Re: [RFT PATCH 1/2] i2c: tegra: update CONFIG_LOAD for new conifiguration
Wolfram, On Thursday 09 July 2015 02:06 AM, Stephen Warren wrote: On 06/30/2015 04:54 AM, Laxman Dewangan wrote: Once the new configuration is set on the conifg register of I2C controller, it is require to update the CONFIG_LOAD register to transfer the new SW configuration to actual HW internal registers that would be used in the actual logic. Can you please review this series? Thanks, Laxman -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [RFT PATCH 1/2] i2c: tegra: update CONFIG_LOAD for new conifiguration
On Thursday 09 July 2015 02:06 AM, Stephen Warren wrote: On 06/30/2015 04:54 AM, Laxman Dewangan wrote: Signed-off-by: Laxman Dewangan ldewan...@nvidia.com Signed-off-by: Chaitanya Bandi ban...@nvidia.com I'm not sure why Chaitanya's S-o-b is there and listed last if he's not the patch author. If he wrote the patch, he should be the git author and his S-o-b should be first. If he didn't and you simply based this patch on work by Chaitanya, then his S-o-b probably shouldn't be present, and yours would be last since you're submitting the patch. The patch I created is based on Chaitanya's work, edited on his work to match with mainline. --- Stephen/Andrew, I need help on testing this on other platform. I tested this on T210. I'm puzzled how this was tested on T210, since it isn't supported upstream yet. We tested this as: - K318 kernel release + i2c subsystem from linux-next in downstream boards. - Chrome-OS team on smaug with their tree. The series, Tested-by: Stephen Warren swar...@nvidia.com Thanks for testing. -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[RFT PATCH 1/2] i2c: tegra: update CONFIG_LOAD for new conifiguration
Once the new configuration is set on the conifg register of I2C controller, it is require to update the CONFIG_LOAD register to transfer the new SW configuration to actual HW internal registers that would be used in the actual logic. It is like, SW is programming only shadow registers through regular configuration and when these load_config bit fields are set to 1, it causes the regular/shadows registers configuration transferred to the HW internal active registers. So SW has to set these bit fields at the end of all regular registers configuration. And these config_load bits are HW auto-clear bits. HW clears these bit fields once the register configuration is moved to HW internal active registers. So SW has to wait until these bits are auto-cleared before going for any further programming This mechanism is supported on T124 and after this SoCs. This is based on change done by Chaitanya Bandi ban...@nvidia.com Signed-off-by: Laxman Dewangan ldewan...@nvidia.com Signed-off-by: Chaitanya Bandi ban...@nvidia.com --- Stephen/Andrew, I need help on testing this on other platform. I tested this on T210. drivers/i2c/busses/i2c-tegra.c | 35 +++ 1 file changed, 35 insertions(+) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 1bcd75e..53f816b 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -100,6 +100,12 @@ #define I2C_HEADER_CONTINUE_XFER (115) #define I2C_HEADER_MASTER_ADDR_SHIFT 12 #define I2C_HEADER_SLAVE_ADDR_SHIFT1 + +#define I2C_CONFIG_LOAD0x08C +#define I2C_MSTR_CONFIG_LOAD (1 0) +#define I2C_SLV_CONFIG_LOAD(1 1) +#define I2C_TIMEOUT_CONFIG_LOAD(1 2) + /* * msg_end_type: The bus control which need to be send at end of transfer. * @MSG_END_STOP: Send stop pulse at end of transfer. @@ -121,6 +127,8 @@ enum msg_end_type { * @has_single_clk_source: The i2c controller has single clock source. Tegra30 * and earlier Socs has two clock sources i.e. div-clk and * fast-clk. + * @has_config_load_reg: Has the config load register to load the new + * configuration. * @clk_divisor_hs_mode: Clock divisor in HS mode. * @clk_divisor_std_fast_mode: Clock divisor in standard/fast mode. It is * applicable if there is no fast clock source i.e. single clock @@ -131,6 +139,7 @@ struct tegra_i2c_hw_feature { bool has_continue_xfer_support; bool has_per_pkt_xfer_complete_irq; bool has_single_clk_source; + bool has_config_load_reg; int clk_divisor_hs_mode; int clk_divisor_std_fast_mode; }; @@ -410,6 +419,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) u32 val; int err = 0; u32 clk_divisor; + unsigned long timeout = jiffies + HZ; err = tegra_i2c_clock_enable(i2c_dev); if (err 0) { @@ -451,6 +461,18 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) if (tegra_i2c_flush_fifos(i2c_dev)) err = -ETIMEDOUT; + if (i2c_dev-hw-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 waiting for config load\n); + return -ETIMEDOUT; + } + msleep(1); + } + } + tegra_i2c_clock_disable(i2c_dev); if (i2c_dev-irq_disabled) { @@ -675,6 +697,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = { .has_single_clk_source = false, .clk_divisor_hs_mode = 3, .clk_divisor_std_fast_mode = 0, + .has_config_load_reg = false, }; static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { @@ -683,6 +706,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { .has_single_clk_source = false, .clk_divisor_hs_mode = 3, .clk_divisor_std_fast_mode = 0, + .has_config_load_reg = false, }; static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { @@ -691,10 +715,21 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { .has_single_clk_source = true, .clk_divisor_hs_mode = 1, .clk_divisor_std_fast_mode = 0x19, + .has_config_load_reg = false, +}; + +static const struct tegra_i2c_hw_feature tegra124_i2c_hw = { + .has_continue_xfer_support = true, + .has_per_pkt_xfer_complete_irq = true, + .has_single_clk_source = true, + .clk_divisor_hs_mode = 1, + .clk_divisor_std_fast_mode = 0x19, + .has_config_load_reg = true, }; /* Match table for of_platform binding */ static const
[RFT PATCH 2/2] i2c: tegra: add support for fast plus (FM+) mode clock rate
Tegra I2C controller required to configure the clock divisor register inside controller to different value based on the clock speed. The recommended clock divisor for the I2C controller for standard/fast mode is 0x19 and for fast-mode plus is 0x10. Add support to configure clock divisor register of I2C controller based on bus clock rate. This clock divisor is supported form T114 onwards. This is based on change done by Chaitanya Bandi ban...@nvidia.com Signed-off-by: Laxman Dewangan ldewan...@nvidia.com Signed-off-by: Chaitanya Bandi ban...@nvidia.com --- Stephen/Andrew, I need help on testing this on other platform. I tested this on T210. drivers/i2c/busses/i2c-tegra.c | 17 +++-- 1 file changed, 15 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 53f816b..6a77a93 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -142,6 +142,7 @@ struct tegra_i2c_hw_feature { bool has_config_load_reg; int clk_divisor_hs_mode; int clk_divisor_std_fast_mode; + u16 clk_divisor_fast_plus_mode; }; /** @@ -181,6 +182,7 @@ struct tegra_i2c_dev { size_t msg_buf_remaining; int msg_read; u32 bus_clk_rate; + u16 clk_divisor_non_hs_mode; bool is_suspended; }; @@ -441,7 +443,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) /* Make sure clock divisor programmed correctly */ clk_divisor = i2c_dev-hw-clk_divisor_hs_mode; - clk_divisor |= i2c_dev-hw-clk_divisor_std_fast_mode + clk_divisor |= i2c_dev-clk_divisor_non_hs_mode I2C_CLK_DIVISOR_STD_FAST_MODE_SHIFT; i2c_writel(i2c_dev, clk_divisor, I2C_CLK_DIVISOR); @@ -697,6 +699,7 @@ static const struct tegra_i2c_hw_feature tegra20_i2c_hw = { .has_single_clk_source = false, .clk_divisor_hs_mode = 3, .clk_divisor_std_fast_mode = 0, + .clk_divisor_fast_plus_mode = 0, .has_config_load_reg = false, }; @@ -706,6 +709,7 @@ static const struct tegra_i2c_hw_feature tegra30_i2c_hw = { .has_single_clk_source = false, .clk_divisor_hs_mode = 3, .clk_divisor_std_fast_mode = 0, + .clk_divisor_fast_plus_mode = 0, .has_config_load_reg = false, }; @@ -715,6 +719,7 @@ static const struct tegra_i2c_hw_feature tegra114_i2c_hw = { .has_single_clk_source = true, .clk_divisor_hs_mode = 1, .clk_divisor_std_fast_mode = 0x19, + .clk_divisor_fast_plus_mode = 0x10, .has_config_load_reg = false, }; @@ -724,6 +729,7 @@ static const struct tegra_i2c_hw_feature tegra124_i2c_hw = { .has_single_clk_source = true, .clk_divisor_hs_mode = 1, .clk_divisor_std_fast_mode = 0x19, + .clk_divisor_fast_plus_mode = 0x10, .has_config_load_reg = true, }; @@ -821,7 +827,14 @@ static int tegra_i2c_probe(struct platform_device *pdev) } } - clk_multiplier *= (i2c_dev-hw-clk_divisor_std_fast_mode + 1); + i2c_dev-clk_divisor_non_hs_mode = + i2c_dev-hw-clk_divisor_std_fast_mode; + if (i2c_dev-hw-clk_divisor_fast_plus_mode + (i2c_dev-bus_clk_rate == 100)) + i2c_dev-clk_divisor_non_hs_mode = + i2c_dev-hw-clk_divisor_fast_plus_mode; + + clk_multiplier *= (i2c_dev-clk_divisor_non_hs_mode + 1); ret = clk_set_rate(i2c_dev-div_clk, i2c_dev-bus_clk_rate * clk_multiplier); if (ret) { -- 2.1.4 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] i2c-mux-pca954x: allow downstream bus numbers to be specified in the dts
On Thursday 17 April 2014 09:16 PM, Laurent Pinchart wrote: + u32 fixed_bus_numbers[PCA954X_MAX_NCHANS] = { 0 }; int ret; if (!i2c_check_functionality(adap, I2C_FUNC_SMBUS_BYTE)) @@ -214,6 +215,17 @@ static int pca954x_probe(struct i2c_client *client, if (ret 0) return ret; } + + /* Get fixed bus numbers */ + ret = of_property_read_u32_array(np, fixed-bus-numbers, + fixed_bus_numbers, chips[id-driver_data].nchans); + if (ret == -EINVAL) + ret = 0;/* missing dtb node is not an error */ + if (ret 0) { + dev_err(client-dev, fixed-bus-numbers: + invalid format\n); + return ret; + } } Hi Frank, Why not you use aliases on DTS instead of changing driver? You can alias the bus number with the child node name. On the following, the bus will be registerd as 6, 7, 8 and 9. i2c-core already support this. aliases { i2c6 = pca9546_i2c0; i2c7 = pca9546_i2c1; i2c8 = pca9546_i2c2; i2c9 = pca9546_i2c3; }; --- This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. --- -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] i2c: tegra: remove warning dump if timeout happen in transfer
If timeout error occurs in the i2c transfer then it was dumping warning of call stack. Remove the warning dump as there is may be possibility that some slave devices are busy and not responding the i2c communication. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- The patch is generated based on discussion happen between Stephena and Wolfram on the patch: i2c: add bcm2835 driver drivers/i2c/busses/i2c-tegra.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index ae2e027..36704e3 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -587,7 +587,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, ret = wait_for_completion_timeout(i2c_dev-msg_complete, TEGRA_I2C_TIMEOUT); tegra_i2c_mask_irq(i2c_dev, int_mask); - if (WARN_ON(ret == 0)) { + if (ret == 0) { dev_err(i2c_dev-dev, i2c transfer timed out\n); tegra_i2c_init(i2c_dev); -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] i2c: tegra: remove warning dump if timeout happen in transfer
If timeout error occurs in the i2c transfer then it was dumping warning of call stack. Remove the warning dump as there is may be possibility that some slave devices are busy and not responding the i2c communication. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- The patch is generated based on discussion happen between Stephena and Wolfram on the patch: i2c: add bcm2835 driver resending patch as Wolfram's email id has been changed. drivers/i2c/busses/i2c-tegra.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index ae2e027..36704e3 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -587,7 +587,7 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, ret = wait_for_completion_timeout(i2c_dev-msg_complete, TEGRA_I2C_TIMEOUT); tegra_i2c_mask_irq(i2c_dev, int_mask); - if (WARN_ON(ret == 0)) { + if (ret == 0) { dev_err(i2c_dev-dev, i2c transfer timed out\n); tegra_i2c_init(i2c_dev); -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH RESEND] i2c: tegra: add support for Tegra114 SoC
NVIDIA's Tegra114 has following enhanced feature in i2c controller: - Enable/disable control for per packet transfer complete interrupt. Earlier SoCs could not disable this. - Single clock source for standard/fast and HS mode clock speed. The clock divisor for fast/standard mode is added into the i2c controller to meet the HS and standard/fast mode of clock speed from single source. Add support for the above feature to make it functional on T114 SOCs. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com Reviewed-by: Stephen Warren swar...@nvidia.com --- Just resending if this is missed in long holiday. Adding reviewed-by: Stephen as he has already given his score. drivers/i2c/busses/i2c-tegra.c | 77 --- 1 files changed, 63 insertions(+), 14 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 7b38877..2dadb96 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -71,6 +71,8 @@ #define I2C_INT_TX_FIFO_DATA_REQ (11) #define I2C_INT_RX_FIFO_DATA_REQ (10) #define I2C_CLK_DIVISOR0x06c +#define I2C_CLK_DIVISOR_STD_FAST_MODE_SHIFT16 +#define I2C_CLK_MULTIPLIER_STD_FAST_MODE 8 #define DVC_CTRL_REG1 0x000 #define DVC_CTRL_REG1_INTR_EN (110) @@ -117,10 +119,23 @@ enum msg_end_type { /** * struct tegra_i2c_hw_feature : Different HW support on Tegra * @has_continue_xfer_support: Continue transfer supports. + * @has_per_pkt_xfer_complete_irq: Has enable/disable capability for transfer + * complete interrupt per packet basis. + * @has_single_clk_source: The i2c controller has single clock source. Tegra30 + * and earlier Socs has two clock sources i.e. div-clk and + * fast-clk. + * @clk_divisor_hs_mode: Clock divisor in HS mode. + * @clk_divisor_std_fast_mode: Clock divisor in standard/fast mode. It is + * applicable if there is no fast clock source i.e. single clock + * source. */ struct tegra_i2c_hw_feature { bool has_continue_xfer_support; + bool has_per_pkt_xfer_complete_irq; + bool has_single_clk_source; + int clk_divisor_hs_mode; + int clk_divisor_std_fast_mode; }; /** @@ -366,11 +381,13 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev) static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev) { int ret; - ret = clk_prepare_enable(i2c_dev-fast_clk); - if (ret 0) { - dev_err(i2c_dev-dev, - Enabling fast clk failed, err %d\n, ret); - return ret; + if (!i2c_dev-hw-has_single_clk_source) { + ret = clk_prepare_enable(i2c_dev-fast_clk); + if (ret 0) { + dev_err(i2c_dev-dev, + Enabling fast clk failed, err %d\n, ret); + return ret; + } } ret = clk_prepare_enable(i2c_dev-div_clk); if (ret 0) { @@ -384,13 +401,16 @@ static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev) static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev) { clk_disable_unprepare(i2c_dev-div_clk); - clk_disable_unprepare(i2c_dev-fast_clk); + if (!i2c_dev-hw-has_single_clk_source) + clk_disable_unprepare(i2c_dev-fast_clk); } static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) { u32 val; int err = 0; + int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE; + u32 clk_divisor; tegra_i2c_clock_enable(i2c_dev); @@ -405,7 +425,15 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) (0x2 I2C_CNFG_DEBOUNCE_CNT_SHIFT); i2c_writel(i2c_dev, val, I2C_CNFG); i2c_writel(i2c_dev, 0, I2C_INT_MASK); - clk_set_rate(i2c_dev-div_clk, i2c_dev-bus_clk_rate * 8); + + clk_multiplier *= (i2c_dev-hw-clk_divisor_std_fast_mode + 1); + clk_set_rate(i2c_dev-div_clk, i2c_dev-bus_clk_rate * clk_multiplier); + + /* Make sure clock divisor programmed correctly */ + clk_divisor = i2c_dev-hw-clk_divisor_hs_mode; + clk_divisor |= i2c_dev-hw-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); @@ -547,6 +575,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, tegra_i2c_fill_tx_fifo(i2c_dev); int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST; + if (i2c_dev-hw-has_per_pkt_xfer_complete_irq) + int_mask |= I2C_INT_PACKET_XFER_COMPLETE; if (msg-flags I2C_M_RD) int_mask |= I2C_INT_RX_FIFO_DATA_REQ; else if (i2c_dev
[PATCH] i2c: tegra: add support for Tegra114 SoC
NVIDIA's Tegra114 has following enhanced feature in i2c controller: - Enable/disable control for per packet transfer complete interrupt. Earlier SoCs could not disable this. - Single clock source for standard/fast and HS mode clock speed. The clock divisor for fast/standard mode is added into the i2c controller to meet the HS and standard/fast mode of clock speed from single source. Add support for the above feature to make it functional on T114 SOCs. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- drivers/i2c/busses/i2c-tegra.c | 77 --- 1 files changed, 63 insertions(+), 14 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 7b38877..2dadb96 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -71,6 +71,8 @@ #define I2C_INT_TX_FIFO_DATA_REQ (11) #define I2C_INT_RX_FIFO_DATA_REQ (10) #define I2C_CLK_DIVISOR0x06c +#define I2C_CLK_DIVISOR_STD_FAST_MODE_SHIFT16 +#define I2C_CLK_MULTIPLIER_STD_FAST_MODE 8 #define DVC_CTRL_REG1 0x000 #define DVC_CTRL_REG1_INTR_EN (110) @@ -117,10 +119,23 @@ enum msg_end_type { /** * struct tegra_i2c_hw_feature : Different HW support on Tegra * @has_continue_xfer_support: Continue transfer supports. + * @has_per_pkt_xfer_complete_irq: Has enable/disable capability for transfer + * complete interrupt per packet basis. + * @has_single_clk_source: The i2c controller has single clock source. Tegra30 + * and earlier Socs has two clock sources i.e. div-clk and + * fast-clk. + * @clk_divisor_hs_mode: Clock divisor in HS mode. + * @clk_divisor_std_fast_mode: Clock divisor in standard/fast mode. It is + * applicable if there is no fast clock source i.e. single clock + * source. */ struct tegra_i2c_hw_feature { bool has_continue_xfer_support; + bool has_per_pkt_xfer_complete_irq; + bool has_single_clk_source; + int clk_divisor_hs_mode; + int clk_divisor_std_fast_mode; }; /** @@ -366,11 +381,13 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev) static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev) { int ret; - ret = clk_prepare_enable(i2c_dev-fast_clk); - if (ret 0) { - dev_err(i2c_dev-dev, - Enabling fast clk failed, err %d\n, ret); - return ret; + if (!i2c_dev-hw-has_single_clk_source) { + ret = clk_prepare_enable(i2c_dev-fast_clk); + if (ret 0) { + dev_err(i2c_dev-dev, + Enabling fast clk failed, err %d\n, ret); + return ret; + } } ret = clk_prepare_enable(i2c_dev-div_clk); if (ret 0) { @@ -384,13 +401,16 @@ static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev) static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev) { clk_disable_unprepare(i2c_dev-div_clk); - clk_disable_unprepare(i2c_dev-fast_clk); + if (!i2c_dev-hw-has_single_clk_source) + clk_disable_unprepare(i2c_dev-fast_clk); } static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) { u32 val; int err = 0; + int clk_multiplier = I2C_CLK_MULTIPLIER_STD_FAST_MODE; + u32 clk_divisor; tegra_i2c_clock_enable(i2c_dev); @@ -405,7 +425,15 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) (0x2 I2C_CNFG_DEBOUNCE_CNT_SHIFT); i2c_writel(i2c_dev, val, I2C_CNFG); i2c_writel(i2c_dev, 0, I2C_INT_MASK); - clk_set_rate(i2c_dev-div_clk, i2c_dev-bus_clk_rate * 8); + + clk_multiplier *= (i2c_dev-hw-clk_divisor_std_fast_mode + 1); + clk_set_rate(i2c_dev-div_clk, i2c_dev-bus_clk_rate * clk_multiplier); + + /* Make sure clock divisor programmed correctly */ + clk_divisor = i2c_dev-hw-clk_divisor_hs_mode; + clk_divisor |= i2c_dev-hw-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); @@ -547,6 +575,8 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, tegra_i2c_fill_tx_fifo(i2c_dev); int_mask = I2C_INT_NO_ACK | I2C_INT_ARBITRATION_LOST; + if (i2c_dev-hw-has_per_pkt_xfer_complete_irq) + int_mask |= I2C_INT_PACKET_XFER_COMPLETE; if (msg-flags I2C_M_RD) int_mask |= I2C_INT_RX_FIFO_DATA_REQ; else if (i2c_dev-msg_buf_remaining) @@ -634,15 +664,32 @@ static const struct i2c_algorithm tegra_i2c_algo = { static const struct tegra_i2c_hw_feature tegra20_i2c_hw
[PATCH REPOST] i2c: tegra: set irq name as device name
When watching the irqs name of tegra i2c, all instances irq name shows as tegra_i2c. Passing the device name properly to have the irq names with instance like tegra-i2c.0, tegra-i2c.1 etc. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com Acked-by: Jean Delvare kh...@linux-fr.org --- Reposting patch in case of it missed. drivers/i2c/busses/i2c-tegra.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index f981ac4..dcea77b 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) } ret = devm_request_irq(pdev-dev, i2c_dev-irq, - tegra_i2c_isr, 0, pdev-name, i2c_dev); + tegra_i2c_isr, 0, dev_name(pdev-dev), i2c_dev); if (ret) { dev_err(pdev-dev, Failed to request irq %i\n, i2c_dev-irq); return ret; -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] i2c: tegra: set irq name as device name
When watching the irqs name of tegra i2c, all instances irq name shows as tegra_i2c. Passing the device name properly to have the irq names with instance like tegra-i2c.0, tegra-i2c.1 etc. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- drivers/i2c/busses/i2c-tegra.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index f981ac4..dcea77b 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -742,7 +742,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) } ret = devm_request_irq(pdev-dev, i2c_dev-irq, - tegra_i2c_isr, 0, pdev-name, i2c_dev); + tegra_i2c_isr, 0, dev_name(pdev-dev), i2c_dev); if (ret) { dev_err(pdev-dev, Failed to request irq %i\n, i2c_dev-irq); return ret; -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH V2 1/2] i2c: tegra: I2_M_NOSTART functionality not supported in Tegra20
On Monday 20 August 2012 10:45 PM, Stephen Warren wrote: On 08/18/2012 01:17 PM, Laxman Dewangan wrote: 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. Thanks, applied the series to Tegra's for-3.7/drivers-i2c branch. Note that I had to fix up patch 1 to remove const on the tegra*_i2c_hw variable declarations to avoid compiler warnings when assigning pointers into tegra_i2c_of_match[].data. Thanks for correction but I did not get this warning and when saw the structure, it is declared as const type only.. struct of_device_id { charname[32]; chartype[32]; charcompatible[128]; #ifdef __KERNEL__ const void *data; #else kernel_ulong_t data; #endif }; -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2] i2c: tegra: protect suspend/resume callbacks with CONFIG_PM_SLEEP
The CONFIG_PM doesn't actually enable any of the PM callbacks, it only allows to enable CONFIG_PM_SLEEP and CONFIG_PM_RUNTIME. This means if CONFIG_PM is used to protect system sleep callbacks then it may end up unreferenced if only runtime PM is enabled. Hence protecting sleep callbacks with CONFIG_PM_SLEEP. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- This patch will remove the compilation warning if CONFIG_PM_SLEEP is not enabled. Change from V1 -V2: provide more details in description as per Mark's response. drivers/i2c/busses/i2c-tegra.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 66eb53f..9a08c57 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -712,7 +712,7 @@ static int __devexit tegra_i2c_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int tegra_i2c_suspend(struct device *dev) { struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH REBASE 1/2] i2c: tegra: I2_M_NOSTART functionality not supported in Tegra20
Thanks for review. On Saturday 18 August 2012 06:17 PM, Wolfram Sang wrote: * PGP Signed by an unknown key On Sat, Aug 18, 2012 at 12:32:34AM +0530, Laxman Dewangan wrote: + bool has_continue_xfer_support; I wonder if it makes sense to carry a pointer here to the tegra_i2c_hw_feature in use instead of copying all entries by hand, since they might get more and more. Ok, we can store the hw pointer in device structure. I will send the new patch. }; static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg) @@ -563,7 +574,17 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (i2c_dev-is_suspended) return -EBUSY; - clk_prepare_enable(i2c_dev-div_clk); + /* 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-has_continue_xfer_support) { + dev_err(i2c_dev-dev, + mesg %d have illegal flag\n, i + 1); + return -EINVAL; + } + } Drivers are requested to explicitly check for features of the I2C bus (like M_NOSTART) before using them, so I'd skip this extra check. Ok, I kept this as part of flag checking so illegal flag should not be passed. I will remove this on next version patch. + + clk_prepare_enable(i2c_dev-clk); From a glimpse, this change looks unrelated at least. Even wrong, no? It was already there, just before above check. Due to insertion of check, this code shifted, otherwise it is not a new code. -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 1/2] 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 ldewan...@nvidia.com --- Changes from V1: - make the hw feature structure as part of tegra device structure in place of copying the member. - Remove check for extra M_NOSTART flag if it is not supported in xfer function. Please note that this should go on tegra common clock source tree to avoid conflicts. drivers/i2c/busses/i2c-tegra.c | 61 ++- 1 files changed, 47 insertions(+), 14 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 7149625..2f74236 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -27,6 +27,7 @@ #include linux/slab.h #include linux/i2c-tegra.h #include linux/of_i2c.h +#include linux/of_device.h #include linux/module.h #include asm/unaligned.h @@ -114,8 +115,18 @@ enum msg_end_type { }; /** + * 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_dev- per device i2c context * @dev: device reference for power management + * @hw: Tegra i2c hw feature. * @adapter: core i2c layer adapter information * @div_clk: clock reference for div clock of i2c controller. * @fast_clk: clock reference for fast clock of i2c controller. @@ -133,6 +144,7 @@ enum msg_end_type { */ struct tegra_i2c_dev { struct device *dev; + const struct tegra_i2c_hw_feature *hw; struct i2c_adapter adapter; struct clk *div_clk; struct clk *fast_clk; @@ -582,8 +594,13 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], static u32 tegra_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | - I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_NOSTART; + struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); + u32 ret = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | + I2C_FUNC_PROTOCOL_MANGLING; + + if (i2c_dev-hw-has_continue_xfer_support) + ret |= I2C_FUNC_NOSTART; + return ret; } static const struct i2c_algorithm tegra_i2c_algo = { @@ -591,6 +608,25 @@ static const struct i2c_algorithm tegra_i2c_algo = { .functionality = tegra_i2c_func, }; +static const struct tegra_i2c_hw_feature tegra20_i2c_hw = { + .has_continue_xfer_support = false, +}; + +static const 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,tegra30-i2c, .data = tegra30_i2c_hw, }, + { .compatible = nvidia,tegra20-i2c, .data = tegra20_i2c_hw, }, + { .compatible = nvidia,tegra20-i2c-dvc, .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; @@ -659,11 +695,18 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) i2c_dev-bus_clk_rate = be32_to_cpup(prop); } - if (pdev-dev.of_node) + i2c_dev-hw = tegra20_i2c_hw; + + if (pdev-dev.of_node) { + const struct of_device_id *match; + match = of_match_device(of_match_ptr(tegra_i2c_of_match), + pdev-dev); + i2c_dev-hw = match-data; i2c_dev-is_dvc = of_device_is_compatible(pdev-dev.of_node, nvidia,tegra20-i2c-dvc); - else if (pdev-id == 3) + } else if (pdev-id == 3) { i2c_dev-is_dvc = 1; + } init_completion(i2c_dev-msg_complete); platform_set_drvdata(pdev, i2c_dev); @@ -751,16 +794,6 @@ static SIMPLE_DEV_PM_OPS(tegra_i2c_pm, tegra_i2c_suspend, tegra_i2c_resume); #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, }, - { .compatible = nvidia,tegra20-i2c-dvc, }, - {}, -}; -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), -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http
[PATCH V2 2/2] i2c: tegra: dynamically control fast clk
Tegra I2C driver enables the fast clock during initialization and does not disable till driver removed. Enable this clock before transfer and disable after transfer done. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com Reviewed-by: Wolfram Sang w.s...@pengutronix.de --- Changes from V1: - Rebased again on patch 1. drivers/i2c/busses/i2c-tegra.c | 35 --- 1 files changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 2f74236..20c35fa 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -363,12 +363,36 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev) dvc_writel(i2c_dev, val, DVC_CTRL_REG1); } +static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev) +{ + int ret; + ret = clk_prepare_enable(i2c_dev-fast_clk); + if (ret 0) { + dev_err(i2c_dev-dev, + Enabling fast clk failed, err %d\n, ret); + return ret; + } + ret = clk_prepare_enable(i2c_dev-div_clk); + if (ret 0) { + dev_err(i2c_dev-dev, + Enabling div clk failed, err %d\n, ret); + clk_disable_unprepare(i2c_dev-fast_clk); + } + return ret; +} + +static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev) +{ + clk_disable_unprepare(i2c_dev-div_clk); + clk_disable_unprepare(i2c_dev-fast_clk); +} + static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) { u32 val; int err = 0; - clk_prepare_enable(i2c_dev-div_clk); + tegra_i2c_clock_enable(i2c_dev); tegra_periph_reset_assert(i2c_dev-div_clk); udelay(2); @@ -399,7 +423,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) if (tegra_i2c_flush_fifos(i2c_dev)) err = -ETIMEDOUT; - clk_disable_unprepare(i2c_dev-div_clk); + tegra_i2c_clock_disable(i2c_dev); if (i2c_dev-irq_disabled) { i2c_dev-irq_disabled = 0; @@ -575,7 +599,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (i2c_dev-is_suspended) return -EBUSY; - clk_prepare_enable(i2c_dev-div_clk); + tegra_i2c_clock_enable(i2c_dev); for (i = 0; i num; i++) { enum msg_end_type end_type = MSG_END_STOP; if (i (num - 1)) { @@ -588,7 +612,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (ret) break; } - clk_disable_unprepare(i2c_dev-div_clk); + tegra_i2c_clock_disable(i2c_dev); return ret ?: i; } @@ -724,8 +748,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) return ret; } - clk_prepare_enable(i2c_dev-fast_clk); - i2c_set_adapdata(i2c_dev-adapter, i2c_dev); i2c_dev-adapter.owner = THIS_MODULE; i2c_dev-adapter.class = I2C_CLASS_HWMON; @@ -739,7 +761,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) ret = i2c_add_numbered_adapter(i2c_dev-adapter); if (ret) { dev_err(pdev-dev, Failed to add I2C adapter\n); - clk_disable_unprepare(i2c_dev-fast_clk); return ret; } -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] i2c: tegra: dynamically control fast clk
Tegra I2C driver enables the fast clock during initialization and does not disable till driver removed. Enable this clock before transfer and disable after transfer done. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- This patch is on top of the clock chnages which is in Tegra sub system and based on i2c: tegra: I2_M_NOSTART functionality not supported in Tegra20 So recommend to go on tegra sub-system. drivers/i2c/busses/i2c-tegra.c | 35 --- 1 files changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 554f713..24f7cee 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -362,12 +362,36 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev) dvc_writel(i2c_dev, val, DVC_CTRL_REG1); } +static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev) +{ + int ret; + ret = clk_prepare_enable(i2c_dev-fast_clk); + if (ret 0) { + dev_err(i2c_dev-dev, + Enabling fast clk failed, err %d\n, ret); + return ret; + } + ret = clk_prepare_enable(i2c_dev-div_clk); + if (ret 0) { + dev_err(i2c_dev-dev, + Enabling div clk failed, err %d\n, ret); + clk_disable_unprepare(i2c_dev-fast_clk); + } + return ret; +} + +static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev) +{ + clk_disable_unprepare(i2c_dev-div_clk); + clk_disable_unprepare(i2c_dev-fast_clk); +} + static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) { u32 val; int err = 0; - clk_prepare_enable(i2c_dev-div_clk); + tegra_i2c_clock_enable(i2c_dev); tegra_periph_reset_assert(i2c_dev-div_clk); udelay(2); @@ -398,7 +422,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) if (tegra_i2c_flush_fifos(i2c_dev)) err = -ETIMEDOUT; - clk_disable_unprepare(i2c_dev-div_clk); + tegra_i2c_clock_disable(i2c_dev); if (i2c_dev-irq_disabled) { i2c_dev-irq_disabled = 0; @@ -584,7 +608,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], } } - clk_prepare_enable(i2c_dev-clk); + tegra_i2c_clock_enable(i2c_dev); for (i = 0; i num; i++) { enum msg_end_type end_type = MSG_END_STOP; if (i (num - 1)) { @@ -597,7 +621,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (ret) break; } - clk_disable_unprepare(i2c_dev-div_clk); + tegra_i2c_clock_disable(i2c_dev); return ret ?: i; } @@ -734,8 +758,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) return ret; } - clk_prepare_enable(i2c_dev-fast_clk); - i2c_set_adapdata(i2c_dev-adapter, i2c_dev); i2c_dev-adapter.owner = THIS_MODULE; i2c_dev-adapter.class = I2C_CLASS_HWMON; @@ -749,7 +771,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) ret = i2c_add_numbered_adapter(i2c_dev-adapter); if (ret) { dev_err(pdev-dev, Failed to add I2C adapter\n); - clk_disable_unprepare(i2c_dev-fast_clk); return ret; } -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] i2c: tegra: dynamically control fast clk
On Saturday 18 August 2012 12:11 AM, Stephen Warren wrote: On 08/17/2012 01:48 AM, Laxman Dewangan wrote: Tegra I2C driver enables the fast clock during initialization and does not disable till driver removed. Enable this clock before transfer and disable after transfer done. Signed-off-by: Laxman Dewanganldewan...@nvidia.com --- This patch is on top of the clock chnages which is in Tegra sub system and based on i2c: tegra: I2_M_NOSTART functionality not supported in Tegra20 So recommend to go on tegra sub-system. What exactly is this patch based on? I checked out Tegra's for-3.7/drivers-i2c, cherry-picked the M_NOSTART patch you mentioned, and attempted to apply this patch. It doesn't apply. Same if I don't cherry-pick the M_NOSTART patch, and same for next-20120816 with/without the M_NOSTART patch. Then It seems I need to create the patch again and send it. The M_NOSTART patch was on tot before clock related change and that is the reason it is not applying. Should I re-send these two patches together as 1/2 and 2/2 to maintain sequence? I can create based on your clock tree. -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH REBASE 1/2] 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 for Tegra20. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- This is rebased on linux-next-20120816. drivers/i2c/busses/i2c-tegra.c | 73 +++ 1 files changed, 58 insertions(+), 15 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 7149625..554f713 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -27,6 +27,7 @@ #include linux/slab.h #include linux/i2c-tegra.h #include linux/of_i2c.h +#include linux/of_device.h #include linux/module.h #include asm/unaligned.h @@ -114,6 +115,15 @@ enum msg_end_type { }; /** + * 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_dev- per device i2c context * @dev: device reference for power management * @adapter: core i2c layer adapter information @@ -148,6 +158,7 @@ struct tegra_i2c_dev { int msg_read; unsigned long bus_clk_rate; bool is_suspended; + bool has_continue_xfer_support; }; static void dvc_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg) @@ -563,7 +574,17 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (i2c_dev-is_suspended) return -EBUSY; - clk_prepare_enable(i2c_dev-div_clk); + /* 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-has_continue_xfer_support) { + dev_err(i2c_dev-dev, + mesg %d have illegal flag\n, i + 1); + return -EINVAL; + } + } + + clk_prepare_enable(i2c_dev-clk); for (i = 0; i num; i++) { enum msg_end_type end_type = MSG_END_STOP; if (i (num - 1)) { @@ -582,8 +603,13 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], static u32 tegra_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | - I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_NOSTART; + struct tegra_i2c_dev *i2c_dev = i2c_get_adapdata(adap); + u32 ret = I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | + I2C_FUNC_PROTOCOL_MANGLING; + + if (i2c_dev-has_continue_xfer_support) + ret |= I2C_FUNC_NOSTART; + return ret; } static const struct i2c_algorithm tegra_i2c_algo = { @@ -591,6 +617,25 @@ 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,tegra30-i2c, .data = tegra30_i2c_hw, }, + { .compatible = nvidia,tegra20-i2c, .data = tegra20_i2c_hw, }, + { .compatible = nvidia,tegra20-i2c-dvc, .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; @@ -600,6 +645,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) struct clk *fast_clk; const unsigned int *prop; void __iomem *base; + const struct tegra_i2c_hw_feature *hw = tegra20_i2c_hw; int irq; int ret = 0; @@ -659,11 +705,18 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) i2c_dev-bus_clk_rate = be32_to_cpup(prop); } - if (pdev-dev.of_node) + if (pdev-dev.of_node) { + const struct of_device_id *match; + match = of_match_device(of_match_ptr(tegra_i2c_of_match), + pdev-dev); + hw = match-data; i2c_dev-is_dvc = of_device_is_compatible(pdev-dev.of_node, nvidia,tegra20-i2c-dvc); - else if (pdev-id == 3) + } else if (pdev-id == 3) { i2c_dev-is_dvc = 1; + } + + i2c_dev-has_continue_xfer_support = hw-has_continue_xfer_support; init_completion(i2c_dev-msg_complete); platform_set_drvdata(pdev, i2c_dev); @@ -751,16 +804,6 @@ static SIMPLE_DEV_PM_OPS(tegra_i2c_pm
[PATCH REBASE 2/2] i2c: tegra: dynamically control fast clk
Tegra I2C driver enables the fast clock during initialization and does not disable till driver removed. Enable this clock before transfer and disable after transfer done. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- This is rebased on linux-next-20120816. drivers/i2c/busses/i2c-tegra.c | 35 --- 1 files changed, 28 insertions(+), 7 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 554f713..24f7cee 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -362,12 +362,36 @@ static void tegra_dvc_init(struct tegra_i2c_dev *i2c_dev) dvc_writel(i2c_dev, val, DVC_CTRL_REG1); } +static inline int tegra_i2c_clock_enable(struct tegra_i2c_dev *i2c_dev) +{ + int ret; + ret = clk_prepare_enable(i2c_dev-fast_clk); + if (ret 0) { + dev_err(i2c_dev-dev, + Enabling fast clk failed, err %d\n, ret); + return ret; + } + ret = clk_prepare_enable(i2c_dev-div_clk); + if (ret 0) { + dev_err(i2c_dev-dev, + Enabling div clk failed, err %d\n, ret); + clk_disable_unprepare(i2c_dev-fast_clk); + } + return ret; +} + +static inline void tegra_i2c_clock_disable(struct tegra_i2c_dev *i2c_dev) +{ + clk_disable_unprepare(i2c_dev-div_clk); + clk_disable_unprepare(i2c_dev-fast_clk); +} + static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) { u32 val; int err = 0; - clk_prepare_enable(i2c_dev-div_clk); + tegra_i2c_clock_enable(i2c_dev); tegra_periph_reset_assert(i2c_dev-div_clk); udelay(2); @@ -398,7 +422,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) if (tegra_i2c_flush_fifos(i2c_dev)) err = -ETIMEDOUT; - clk_disable_unprepare(i2c_dev-div_clk); + tegra_i2c_clock_disable(i2c_dev); if (i2c_dev-irq_disabled) { i2c_dev-irq_disabled = 0; @@ -584,7 +608,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], } } - clk_prepare_enable(i2c_dev-clk); + tegra_i2c_clock_enable(i2c_dev); for (i = 0; i num; i++) { enum msg_end_type end_type = MSG_END_STOP; if (i (num - 1)) { @@ -597,7 +621,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (ret) break; } - clk_disable_unprepare(i2c_dev-div_clk); + tegra_i2c_clock_disable(i2c_dev); return ret ?: i; } @@ -734,8 +758,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) return ret; } - clk_prepare_enable(i2c_dev-fast_clk); - i2c_set_adapdata(i2c_dev-adapter, i2c_dev); i2c_dev-adapter.owner = THIS_MODULE; i2c_dev-adapter.class = I2C_CLASS_HWMON; @@ -749,7 +771,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) ret = i2c_add_numbered_adapter(i2c_dev-adapter); if (ret) { dev_err(pdev-dev, Failed to add I2C adapter\n); - clk_disable_unprepare(i2c_dev-fast_clk); return ret; } -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] i2c: tegra: I2_M_NOSTART functionality not supported in Tegra20
On Tuesday 14 August 2012 10:19 PM, Stephen Warren wrote: On 08/14/2012 03:19 AM, Laxman Dewangan wrote: 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 for Tegra20. Signed-off-by: Laxman Dewanganldewan...@nvidia.com Reported-by: Stephen Warrenswar...@nvidia.com Tested-by: Stephen Warrenswar...@wwwdotorg.org Note that if I take Laxman's I2C driver clock patches through the Tegra tree, and Wolfram takes this patch through the I2C tree, there will be a very slight conflict, since adjacent lines are touched. However, the resolution is simple and obvious, so I think that's fine. Stephen/Wolfram, I have 2 more change to implement runtime PM and dynamic clock control for fast clock which I have planned for 3.7. I think it will be better if this also goes on same tree where the clock related change are available to avoid the merge conflict. -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/4] ARM: tegra: clock: add i2c fast clock entry in clock table
Tegra's i2c controller require two clock sources named as div-clk and fast-clk for proper operation. Currently, the entry of fast-clk is missing in tegra30 clock table and it is incorrectly named in the tegra20 clock table. Adds aliases to enable lookups for fast-clk to succeed. A later patch will remove the incorrectly named clock, once the driver is modified to use the new name. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- arch/arm/mach-tegra/tegra20_clocks_data.c |4 arch/arm/mach-tegra/tegra30_clocks_data.c |5 + 2 files changed, 9 insertions(+), 0 deletions(-) diff --git a/arch/arm/mach-tegra/tegra20_clocks_data.c b/arch/arm/mach-tegra/tegra20_clocks_data.c index b5c518e..7312ecd 100644 --- a/arch/arm/mach-tegra/tegra20_clocks_data.c +++ b/arch/arm/mach-tegra/tegra20_clocks_data.c @@ -1028,6 +1028,10 @@ static struct clk_duplicate tegra_clk_duplicates[] = { CLK_DUPLICATE(cop,tegra-avp,cop), CLK_DUPLICATE(vde,tegra-aes,vde), CLK_DUPLICATE(cclk, NULL, cpu), + CLK_DUPLICATE(pll_p_out3, tegra-i2c.0, fast-clk), + CLK_DUPLICATE(pll_p_out3, tegra-i2c.1, fast-clk), + CLK_DUPLICATE(pll_p_out3, tegra-i2c.2, fast-clk), + CLK_DUPLICATE(pll_p_out3, tegra-i2c.3, fast-clk), }; #define CLK(dev, con, ck) \ diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c index c924240..eae85b7 100644 --- a/arch/arm/mach-tegra/tegra30_clocks_data.c +++ b/arch/arm/mach-tegra/tegra30_clocks_data.c @@ -1287,6 +1287,11 @@ struct clk_duplicate tegra_clk_duplicates[] = { CLK_DUPLICATE(dam1, NULL, dam1), CLK_DUPLICATE(dam2, NULL, dam2), CLK_DUPLICATE(spdif_in, NULL, spdif_in), + CLK_DUPLICATE(pll_p_out3, tegra-i2c.0, fast-clk), + CLK_DUPLICATE(pll_p_out3, tegra-i2c.1, fast-clk), + CLK_DUPLICATE(pll_p_out3, tegra-i2c.2, fast-clk), + CLK_DUPLICATE(pll_p_out3, tegra-i2c.3, fast-clk), + CLK_DUPLICATE(pll_p_out3, tegra-i2c.4, fast-clk), }; struct clk *tegra_ptr_clks[] = { -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/4] i2c: tegra: required clock support for controller
The Tegra's i2c controller required two clock sources for proper operation named as div-clk and fast-clk. Adding support to make sure that driver will get these clocks and enable before any transfer and disable after transfer completed. Patch 1 add the entry of fast clock in clock table. Patch 2 modify i2c driver to get the div and fast clock. Patch 3 name the connection of the clock entry. Patch 4 removes non-required entry from tegra20 clock table. Laxman Dewangan (4): ARM: tegra: clock: add i2c fast clock entry in clock table i2c: tegra: pass proper name for getting clock ARM: tegra: clock: add connection name in i2c clock entry ARM: tegra: clock: remove unused clock entry for i2c arch/arm/mach-tegra/tegra20_clocks_data.c | 20 +--- arch/arm/mach-tegra/tegra30_clocks_data.c | 15 ++--- drivers/i2c/busses/i2c-tegra.c| 46 ++-- 3 files changed, 41 insertions(+), 40 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/4] ARM: tegra: clock: add connection name in i2c clock entry
Add connection name div-clk for the i2c clock entry. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- arch/arm/mach-tegra/tegra20_clocks_data.c |8 arch/arm/mach-tegra/tegra30_clocks_data.c | 10 +- 2 files changed, 9 insertions(+), 9 deletions(-) diff --git a/arch/arm/mach-tegra/tegra20_clocks_data.c b/arch/arm/mach-tegra/tegra20_clocks_data.c index 7312ecd..c1318c2 100644 --- a/arch/arm/mach-tegra/tegra20_clocks_data.c +++ b/arch/arm/mach-tegra/tegra20_clocks_data.c @@ -889,10 +889,10 @@ PERIPH_CLK(la,la, NULL, 76, 0x1f8, 2600, mux_pllp_pllc_pllm_clkm, MUX PERIPH_CLK(owr,tegra_w1, NULL, 71, 0x1cc, 2600, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); PERIPH_CLK(nor,nor, NULL, 42, 0x1d0, 9200, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* requires min voltage */ PERIPH_CLK(mipi, mipi, NULL, 50, 0x174, 6000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* scales with voltage */ -PERIPH_CLK(i2c1, tegra-i2c.0, NULL, 12, 0x124, 2600, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); -PERIPH_CLK(i2c2, tegra-i2c.1, NULL, 54, 0x198, 2600, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); -PERIPH_CLK(i2c3, tegra-i2c.2, NULL, 67, 0x1b8, 2600, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); -PERIPH_CLK(dvc,tegra-i2c.3, NULL, 47, 0x128, 2600, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); +PERIPH_CLK(i2c1, tegra-i2c.0, div-clk, 12, 0x124, 2600, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); +PERIPH_CLK(i2c2, tegra-i2c.1, div-clk, 54, 0x198, 2600, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); +PERIPH_CLK(i2c3, tegra-i2c.2, div-clk, 67, 0x1b8, 2600, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); +PERIPH_CLK(dvc,tegra-i2c.3, div-clk, 47, 0x128, 2600, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); PERIPH_CLK(i2c1_i2c, tegra-i2c.0, i2c, 0, 0, 7200, mux_pllp_out3, 0); PERIPH_CLK(i2c2_i2c, tegra-i2c.1, i2c, 0, 0, 7200, mux_pllp_out3, 0); PERIPH_CLK(i2c3_i2c, tegra-i2c.2, i2c, 0, 0, 7200, mux_pllp_out3, 0); diff --git a/arch/arm/mach-tegra/tegra30_clocks_data.c b/arch/arm/mach-tegra/tegra30_clocks_data.c index eae85b7..45da437 100644 --- a/arch/arm/mach-tegra/tegra30_clocks_data.c +++ b/arch/arm/mach-tegra/tegra30_clocks_data.c @@ -1070,11 +1070,11 @@ PERIPH_CLK(la, la, NULL, 76, 0x1f8, 2600, mux_pllp_pllc_pllm_clkm, MUX PERIPH_CLK(owr,tegra_w1, NULL, 71, 0x1cc, 2600, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB); PERIPH_CLK(nor,nor, NULL, 42, 0x1d0, 12700, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71); /* requires min voltage */ PERIPH_CLK(mipi, mipi, NULL, 50, 0x174, 6000, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | PERIPH_ON_APB); /* scales with voltage */ -PERIPH_CLK(i2c1, tegra-i2c.0, NULL, 12, 0x124, 2600, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); -PERIPH_CLK(i2c2, tegra-i2c.1, NULL, 54, 0x198, 2600, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); -PERIPH_CLK(i2c3, tegra-i2c.2, NULL, 67, 0x1b8, 2600, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); -PERIPH_CLK(i2c4, tegra-i2c.3, NULL, 103,0x3c4, 2600, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); -PERIPH_CLK(i2c5, tegra-i2c.4, NULL, 47, 0x128, 2600, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); +PERIPH_CLK(i2c1, tegra-i2c.0, div-clk, 12, 0x124, 2600, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); +PERIPH_CLK(i2c2, tegra-i2c.1, div-clk, 54, 0x198, 2600, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); +PERIPH_CLK(i2c3, tegra-i2c.2, div-clk, 67, 0x1b8, 2600, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); +PERIPH_CLK(i2c4, tegra-i2c.3, div-clk, 103, 0x3c4, 2600, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); +PERIPH_CLK(i2c5, tegra-i2c.4, div-clk, 47, 0x128, 2600, mux_pllp_clkm, MUX | DIV_U16 | PERIPH_ON_APB); PERIPH_CLK(uarta, tegra-uart.0, NULL, 6, 0x178, 8, mux_pllp_pllc_pllm_clkm, MUX | DIV_U71 | DIV_U71_UART | PERIPH_ON_APB); PERIPH_CLK(uartb, tegra-uart.1, NULL, 7, 0x17c, 8
[PATCH 4/4] ARM: tegra: clock: remove unused clock entry for i2c
Tegra20 clock table have the entry for clock (tegra_i2c.x, i2c) which is no more require as driver acquire clock with name of div-clk and fast-clk. Remove these entries from table. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- arch/arm/mach-tegra/tegra20_clocks_data.c |8 1 files changed, 0 insertions(+), 8 deletions(-) diff --git a/arch/arm/mach-tegra/tegra20_clocks_data.c b/arch/arm/mach-tegra/tegra20_clocks_data.c index c1318c2..6516beb 100644 --- a/arch/arm/mach-tegra/tegra20_clocks_data.c +++ b/arch/arm/mach-tegra/tegra20_clocks_data.c @@ -893,10 +893,6 @@ PERIPH_CLK(i2c1, tegra-i2c.0, div-clk, 12, 0x124, 2600, mux_pllp_pllc_ PERIPH_CLK(i2c2, tegra-i2c.1, div-clk, 54, 0x198, 2600, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); PERIPH_CLK(i2c3, tegra-i2c.2, div-clk, 67, 0x1b8, 2600, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); PERIPH_CLK(dvc,tegra-i2c.3, div-clk, 47, 0x128, 2600, mux_pllp_pllc_pllm_clkm, MUX | DIV_U16); -PERIPH_CLK(i2c1_i2c, tegra-i2c.0, i2c, 0, 0, 7200, mux_pllp_out3, 0); -PERIPH_CLK(i2c2_i2c, tegra-i2c.1, i2c, 0, 0, 7200, mux_pllp_out3, 0); -PERIPH_CLK(i2c3_i2c, tegra-i2c.2, i2c, 0, 0, 7200, mux_pllp_out3, 0); -PERIPH_CLK(dvc_i2c,tegra-i2c.3, i2c, 0, 0, 7200, mux_pllp_out3, 0); PERIPH_CLK(uarta, tegra-uart.0, NULL, 6, 0x178, 6, mux_pllp_pllc_pllm_clkm, MUX); PERIPH_CLK(uartb, tegra-uart.1, NULL, 7, 0x17c, 6, mux_pllp_pllc_pllm_clkm, MUX); PERIPH_CLK(uartc, tegra-uart.2, NULL, 55, 0x1a0, 6, mux_pllp_pllc_pllm_clkm, MUX); @@ -962,10 +958,6 @@ static struct clk *tegra_list_clks[] = { tegra_i2c2, tegra_i2c3, tegra_dvc, - tegra_i2c1_i2c, - tegra_i2c2_i2c, - tegra_i2c3_i2c, - tegra_dvc_i2c, tegra_uarta, tegra_uartb, tegra_uartc, -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/4] i2c: tegra: pass proper name for getting clock
Tegra's i2c controller require two clock sources named as div_clk and fast_clk. This change make sure that driver pass the correct clock's name when it acquires clock handle. Also change the variable name to reflect the correct clock handles. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- drivers/i2c/busses/i2c-tegra.c | 46 1 files changed, 23 insertions(+), 23 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 66eb53f..7149625 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -117,8 +117,8 @@ enum msg_end_type { * struct tegra_i2c_dev- per device i2c context * @dev: device reference for power management * @adapter: core i2c layer adapter information - * @clk: clock reference for i2c controller - * @i2c_clk: clock reference for i2c bus + * @div_clk: clock reference for div clock of i2c controller. + * @fast_clk: clock reference for fast clock of i2c controller. * @base: ioremapped registers cookie * @cont_id: i2c controller id, used for for packet header * @irq: irq number of transfer complete interrupt @@ -134,8 +134,8 @@ enum msg_end_type { struct tegra_i2c_dev { struct device *dev; struct i2c_adapter adapter; - struct clk *clk; - struct clk *i2c_clk; + struct clk *div_clk; + struct clk *fast_clk; void __iomem *base; int cont_id; int irq; @@ -356,11 +356,11 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) u32 val; int err = 0; - clk_prepare_enable(i2c_dev-clk); + clk_prepare_enable(i2c_dev-div_clk); - tegra_periph_reset_assert(i2c_dev-clk); + tegra_periph_reset_assert(i2c_dev-div_clk); udelay(2); - tegra_periph_reset_deassert(i2c_dev-clk); + tegra_periph_reset_deassert(i2c_dev-div_clk); if (i2c_dev-is_dvc) tegra_dvc_init(i2c_dev); @@ -369,7 +369,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) (0x2 I2C_CNFG_DEBOUNCE_CNT_SHIFT); i2c_writel(i2c_dev, val, I2C_CNFG); i2c_writel(i2c_dev, 0, I2C_INT_MASK); - clk_set_rate(i2c_dev-clk, i2c_dev-bus_clk_rate * 8); + clk_set_rate(i2c_dev-div_clk, i2c_dev-bus_clk_rate * 8); if (!i2c_dev-is_dvc) { u32 sl_cfg = i2c_readl(i2c_dev, I2C_SL_CNFG); @@ -387,7 +387,7 @@ static int tegra_i2c_init(struct tegra_i2c_dev *i2c_dev) if (tegra_i2c_flush_fifos(i2c_dev)) err = -ETIMEDOUT; - clk_disable_unprepare(i2c_dev-clk); + clk_disable_unprepare(i2c_dev-div_clk); if (i2c_dev-irq_disabled) { i2c_dev-irq_disabled = 0; @@ -563,7 +563,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (i2c_dev-is_suspended) return -EBUSY; - clk_prepare_enable(i2c_dev-clk); + clk_prepare_enable(i2c_dev-div_clk); for (i = 0; i num; i++) { enum msg_end_type end_type = MSG_END_STOP; if (i (num - 1)) { @@ -576,7 +576,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], if (ret) break; } - clk_disable_unprepare(i2c_dev-clk); + clk_disable_unprepare(i2c_dev-div_clk); return ret ?: i; } @@ -596,8 +596,8 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) struct tegra_i2c_dev *i2c_dev; struct tegra_i2c_platform_data *pdata = pdev-dev.platform_data; struct resource *res; - struct clk *clk; - struct clk *i2c_clk; + struct clk *div_clk; + struct clk *fast_clk; const unsigned int *prop; void __iomem *base; int irq; @@ -622,16 +622,16 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) } irq = res-start; - clk = devm_clk_get(pdev-dev, NULL); - if (IS_ERR(clk)) { + div_clk = devm_clk_get(pdev-dev, div-clk); + if (IS_ERR(div_clk)) { dev_err(pdev-dev, missing controller clock); - return PTR_ERR(clk); + return PTR_ERR(div_clk); } - i2c_clk = devm_clk_get(pdev-dev, i2c); - if (IS_ERR(i2c_clk)) { + fast_clk = devm_clk_get(pdev-dev, fast-clk); + if (IS_ERR(fast_clk)) { dev_err(pdev-dev, missing bus clock); - return PTR_ERR(i2c_clk); + return PTR_ERR(fast_clk); } i2c_dev = devm_kzalloc(pdev-dev, sizeof(*i2c_dev), GFP_KERNEL); @@ -641,8 +641,8 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) } i2c_dev-base = base; - i2c_dev-clk = clk; - i2c_dev-i2c_clk = i2c_clk; + i2c_dev-div_clk = div_clk; + i2c_dev-fast_clk = fast_clk; i2c_dev-adapter.algo = tegra_i2c_algo; i2c_dev-irq = irq
Re: [PATCH 0/4] i2c: tegra: required clock support for controller
On Wednesday 08 August 2012 01:21 PM, Laxman Dewangan wrote: The Tegra's i2c controller required two clock sources for proper operation named as div-clk and fast-clk. Adding support to make sure that driver will get these clocks and enable before any transfer and disable after transfer completed. Patch 1 add the entry of fast clock in clock table. Patch 2 modify i2c driver to get the div and fast clock. Patch 3 name the connection of the clock entry. Patch 4 removes non-required entry from tegra20 clock table. Hi Wolfram/Stephen, This patch series very much depends on the common clock changes happens on Tegra tree and I think it should go in Tegra common clock tree. Thanks, Laxman -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] i2c: tegra: Fix ifdefs for suspend mode
CONFIG_PM covers runtime only PM. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- This patch will remove the compilation warning if CONFIG_PM_SLEEP is not enabled. drivers/i2c/busses/i2c-tegra.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 66eb53f..9a08c57 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -712,7 +712,7 @@ static int __devexit tegra_i2c_remove(struct platform_device *pdev) return 0; } -#ifdef CONFIG_PM +#ifdef CONFIG_PM_SLEEP static int tegra_i2c_suspend(struct device *dev) { struct tegra_i2c_dev *i2c_dev = dev_get_drvdata(dev); -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 0/7] PM / I2C: Convert platform I2C drivers to PM handling based on struct dev_pm_ops
On Thursday 12 July 2012 12:51 AM, Rafael J. Wysocki wrote: [7/7] i2c-tegra: Use struct dev_pm_ops for power management I did not get the 7/7 on my inbox and hence responding here. Looked change from link https://lkml.org/lkml/2012/7/11/467 This is same as which I sent some days ago: https://lkml.org/lkml/2012/7/10/275 I am fine with the change: Acked-by: Laxman Dewangan ldewan...@nvidia.com -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 5/5] i2c: tegra: convert normal suspend/resume to *_noirq
On Thursday 12 July 2012 04:05 PM, Wolfram Sang wrote: * PGP Signed by an unknown key On Tue, Jul 10, 2012 at 04:50:44PM +0530, Laxman Dewangan wrote: To provide the late suspend and early resume for i2c driver, convert the suspend/resume as suspend- suspend_noirq resume - resume_noirq Signed-off-by: Laxman Dewanganldewan...@nvidia.com Applied to next on top of Rafael's patches. Please have a look if I did the fixup right. Thanks for taking care. Can you please point me your git path so that I can verify it? Thanks, Laxman -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 5/5] i2c: tegra: convert normal suspend/resume to *_noirq
On Thursday 12 July 2012 05:28 PM, Wolfram Sang wrote: * PGP Signed by an unknown key Can you please point me your git path so that I can verify it? git://git.pengutronix.de/git/wsa/linux.git i2c-embedded/for-next or http://git.pengutronix.de/?p=wsa/linux.git;a=shortlog;h=refs/heads/i2c-embedded/for-next The change is fine. No issue here. Thanks, Laxman -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 0/5] i2c: tegra: Code cleanups and suspend/resume related changes
This patch series does: - Code cleanups like removing unused variables, using already define function - Use clock_disable_unprepare in place of clock_disable() - Use dev_pm_ops for suspend/resume inplace of legacy suspend/resume callbacks. - Convert suspend/resume to _noirq version to support late suspend/early resume. Laxman Dewangan (5): i2c: tegra: remove unused member variable i2c: tegra: use clk_disable_unprepare in place of clk_disable i2c: tegra: use of_match_ptr() for match_table initialization i2c: tegra: Use struct dev_pm_ops for power management i2c: tegra: convert normal suspend/resume to *_noirq drivers/i2c/busses/i2c-tegra.c | 27 +++ 1 files changed, 15 insertions(+), 12 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 5/5] i2c: tegra: convert normal suspend/resume to *_noirq
To provide the late suspend and early resume for i2c driver, convert the suspend/resume as suspend- suspend_noirq resume - resume_noirq Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- drivers/i2c/busses/i2c-tegra.c |8 1 files changed, 4 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 5f0572d..99e6ae5 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -713,7 +713,7 @@ static int __devexit tegra_i2c_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int tegra_i2c_suspend(struct device *dev) +static int tegra_i2c_suspend_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); @@ -725,7 +725,7 @@ static int tegra_i2c_suspend(struct device *dev) return 0; } -static int tegra_i2c_resume(struct device *dev) +static int tegra_i2c_resume_noirq(struct device *dev) { struct platform_device *pdev = to_platform_device(dev); struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); @@ -748,8 +748,8 @@ static int tegra_i2c_resume(struct device *dev) } static const struct dev_pm_ops tegra_i2c_dev_pm_ops = { - .suspend = tegra_i2c_suspend, - .resume = tegra_i2c_resume, + .suspend_noirq = tegra_i2c_suspend_noirq, + .resume_noirq = tegra_i2c_resume_noirq, }; #define TEGRA_I2C_DEV_PM_OPS (tegra_i2c_dev_pm_ops) #else -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/5] i2c: tegra: Use struct dev_pm_ops for power management
Make the tegra i2c driver define its PM callbacks through struct dev_pm_ops objects rather than by using legacy PM hooks in struct platform_driver. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- drivers/i2c/busses/i2c-tegra.c | 19 +-- 1 files changed, 13 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 0792674..5f0572d 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -713,8 +713,9 @@ static int __devexit tegra_i2c_remove(struct platform_device *pdev) } #ifdef CONFIG_PM -static int tegra_i2c_suspend(struct platform_device *pdev, pm_message_t state) +static int tegra_i2c_suspend(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_lock_adapter(i2c_dev-adapter); @@ -724,8 +725,9 @@ static int tegra_i2c_suspend(struct platform_device *pdev, pm_message_t state) return 0; } -static int tegra_i2c_resume(struct platform_device *pdev) +static int tegra_i2c_resume(struct device *dev) { + struct platform_device *pdev = to_platform_device(dev); struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); int ret; @@ -744,6 +746,14 @@ static int tegra_i2c_resume(struct platform_device *pdev) return 0; } + +static const struct dev_pm_ops tegra_i2c_dev_pm_ops = { + .suspend = tegra_i2c_suspend, + .resume = tegra_i2c_resume, +}; +#define TEGRA_I2C_DEV_PM_OPS (tegra_i2c_dev_pm_ops) +#else +#define TEGRA_I2C_DEV_PM_OPS NULL #endif #if defined(CONFIG_OF) @@ -759,14 +769,11 @@ MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); static struct platform_driver tegra_i2c_driver = { .probe = tegra_i2c_probe, .remove = __devexit_p(tegra_i2c_remove), -#ifdef CONFIG_PM - .suspend = tegra_i2c_suspend, - .resume = tegra_i2c_resume, -#endif .driver = { .name = tegra-i2c, .owner = THIS_MODULE, .of_match_table = of_match_ptr(tegra_i2c_of_match), + .pm = TEGRA_I2C_DEV_PM_OPS, }, }; -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 1/5] i2c: tegra: remove unused member variable
Remove unused member variable iomem of the i2c device structure. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- This patch is resend of earlier patch i2c: tegra: remove unused member variable. and sending it as part fo series. drivers/i2c/busses/i2c-tegra.c |2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index f15cd49..00cdc10 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -119,7 +119,6 @@ enum msg_end_type { * @adapter: core i2c layer adapter information * @clk: clock reference for i2c controller * @i2c_clk: clock reference for i2c bus - * @iomem: memory resource for registers * @base: ioremapped registers cookie * @cont_id: i2c controller id, used for for packet header * @irq: irq number of transfer complete interrupt @@ -137,7 +136,6 @@ struct tegra_i2c_dev { struct i2c_adapter adapter; struct clk *clk; struct clk *i2c_clk; - struct resource *iomem; void __iomem *base; int cont_id; int irq; -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 2/5] i2c: tegra: use clk_disable_unprepare in place of clk_disable
Use clk_disable_unprepare() inplace of clk_disable(). This was missed as part of moving clock enable/disable to prepare/unprepare for using the common clock framework. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- This is already discussed in patch [PATCH] i2c: tegra: use clk_disable_unprepare in place of clk_disable for applying in Wolfram Tree. Resending this as patch series. drivers/i2c/busses/i2c-tegra.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 00cdc10..d071cf0 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -696,7 +696,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) ret = i2c_add_numbered_adapter(i2c_dev-adapter); if (ret) { dev_err(pdev-dev, Failed to add I2C adapter\n); - clk_disable(i2c_dev-i2c_clk); + clk_disable_unprepare(i2c_dev-i2c_clk); return ret; } -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/5] i2c: tegra: use of_match_ptr() for match_table initialization
In place of defining match_table for non-DT based as NULL, use of_match_ptr() for initialzing the of_match_table. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- drivers/i2c/busses/i2c-tegra.c |4 +--- 1 files changed, 1 insertions(+), 3 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index d071cf0..0792674 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -754,8 +754,6 @@ static const struct of_device_id tegra_i2c_of_match[] __devinitconst = { {}, }; MODULE_DEVICE_TABLE(of, tegra_i2c_of_match); -#else -#define tegra_i2c_of_match NULL #endif static struct platform_driver tegra_i2c_driver = { @@ -768,7 +766,7 @@ static struct platform_driver tegra_i2c_driver = { .driver = { .name = tegra-i2c, .owner = THIS_MODULE, - .of_match_table = tegra_i2c_of_match, + .of_match_table = of_match_ptr(tegra_i2c_of_match), }, }; -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 1/5] i2c: tegra: remove unused member variable
Remove unused member variable iomem of the i2c device structure. This variable becomes unused when converted all allocation to devm_* in following change: i2c: tegra: make all resource allocation through devm_* Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- This patch is resend of earlier patch i2c: tegra: remove unused member variable. and sending it as part fo series. Changes from V1: Adding more details in description why this variable becomes unused. No change in code. Remaining patches of this series will be still same, version V1. If require, I will resend the series with new version. drivers/i2c/busses/i2c-tegra.c |2 -- 1 files changed, 0 insertions(+), 2 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index f15cd49..00cdc10 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -119,7 +119,6 @@ enum msg_end_type { * @adapter: core i2c layer adapter information * @clk: clock reference for i2c controller * @i2c_clk: clock reference for i2c bus - * @iomem: memory resource for registers * @base: ioremapped registers cookie * @cont_id: i2c controller id, used for for packet header * @irq: irq number of transfer complete interrupt @@ -137,7 +136,6 @@ struct tegra_i2c_dev { struct i2c_adapter adapter; struct clk *clk; struct clk *i2c_clk; - struct resource *iomem; void __iomem *base; int cont_id; int irq; -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] i2c: tegra: use clk_disable_unprepare in place of clk_disable
On Tuesday 26 June 2012 09:58 PM, Stephen Warren wrote: On 06/26/2012 12:27 AM, Laxman Dewangan wrote: On Monday 25 June 2012 09:25 PM, Stephen Warren wrote: On 06/25/2012 03:46 AM, Laxman Dewangan wrote: Stephen, On Wednesday 20 June 2012 09:57 PM, Stephen Warren wrote: On 06/20/2012 10:26 AM, Stephen Warren wrote: On 06/20/2012 06:56 AM, Laxman Dewangan wrote: Use clk_disable_unprepare() inplace of clk_disable(). This was missed as part of moving clock enable/disable to prepare/unprepare for using the common clock framework. ... I see no reason not to take the second patch in the series through the I2C tree though. Uggh. Ignore that paragraph - the other patch was sent separately not as a series. so are you taking care of this patch or do I need to send the patch based on your tree in place of linux-next? Yes, this patch should be applied through the Tegra tree, since it will be a dependency of the common clock framework switchover there, which I hope to take place this kernel cycle. I did just attempt to apply this patch to the for-3.6/common-clk branch, but it doesn't apply:-( Could you please rebase and resend. Thanks. Looked at your common_clk branch and the related code is not there. The clk_disable() in the particular case is introduced by change i2c: tegra: make all resource allocation through devm_* which is not in your branch. Then later Prashant post the change as i2c: tegra: Add clk_prepare/clk_unprepare and it does not accounted for the above patch. So none of your local tree will have this issue. OK. In that case, it's best if this patch goes through the I2C tree since that's where the code is that it's modifying. This might not be optimal for runtime git bisection depending on the order Linus ends up merging things, but it's probably as good as we can do without inter-twining the I2C and Tegra trees a lot. Then it can go Wolfram's tree along with other patch i2c: tegra: remove unused member variable. as some of previous i2c patches are in his tree. -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH] i2c: tegra: use clk_disable_unprepare in place of clk_disable
On Monday 25 June 2012 09:25 PM, Stephen Warren wrote: On 06/25/2012 03:46 AM, Laxman Dewangan wrote: Stephen, On Wednesday 20 June 2012 09:57 PM, Stephen Warren wrote: On 06/20/2012 10:26 AM, Stephen Warren wrote: On 06/20/2012 06:56 AM, Laxman Dewangan wrote: Use clk_disable_unprepare() inplace of clk_disable(). This was missed as part of moving clock enable/disable to prepare/unprepare for using the common clock framework. ... I see no reason not to take the second patch in the series through the I2C tree though. Uggh. Ignore that paragraph - the other patch was sent separately not as a series. so are you taking care of this patch or do I need to send the patch based on your tree in place of linux-next? Yes, this patch should be applied through the Tegra tree, since it will be a dependency of the common clock framework switchover there, which I hope to take place this kernel cycle. I did just attempt to apply this patch to the for-3.6/common-clk branch, but it doesn't apply:-( Could you please rebase and resend. Thanks. Looked at your common_clk branch and the related code is not there. The clk_disable() in the particular case is introduced by change i2c: tegra: make all resource allocation through devm_* which is not in your branch. Then later Prashant post the change as i2c: tegra: Add clk_prepare/clk_unprepare and it does not accounted for the above patch. So none of your local tree will have this issue. You need to pull some of the change from Wofram's tree to you commn-clk to fix the issue. Suggest to pull the change i2c: tegra: make all resource allocation through devm_* i2c: tegra: support for I2C_M_NOSTART functionality i2c: tegra: add PROTOCOL_MANGLING as supported functionality. i2c: tegra: make sure register writes completes -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH] i2c: tegra: use clk_disable_unprepare in place of clk_disable
Use clk_disable_unprepare() inplace of clk_disable(). This was missed as part of moving clock enable/disable to prepare/unprepare for using the common clock framework. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- drivers/i2c/busses/i2c-tegra.c |2 +- 1 files changed, 1 insertions(+), 1 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 00cdc10..d071cf0 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -696,7 +696,7 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) ret = i2c_add_numbered_adapter(i2c_dev-adapter); if (ret) { dev_err(pdev-dev, Failed to add I2C adapter\n); - clk_disable(i2c_dev-i2c_clk); + clk_disable_unprepare(i2c_dev-i2c_clk); return ret; } -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH V3 1/4] i2c: tegra: make sure register writes completes
On Wednesday 13 June 2012 09:25 PM, Stephen Warren wrote: On 06/13/2012 04:12 AM, Laxman Dewangan wrote: @@ -165,6 +165,10 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg) { writel(val, i2c_dev-base + tegra_i2c_reg_addr(i2c_dev, reg)); + + /* Read back register to make sure that register writes completed */ + if (reg != I2C_TX_FIFO) + readl(i2c_dev-base + tegra_i2c_reg_addr(i2c_dev, reg)); I guess that's fine, but it sure does seem rather heavy-weight. Don't you only need to do the readback if you just wrote to the IRQ status or mask registers, rather than if you wrote to /any/ register other than the FIFO? That's what my second patch but based on your earlier review comment, I did for every register. I think it will not matter much as we dont write all register with every transaction, only during initialization. Then for each transfer we write manly on Tx fifo and interrupt mask/status register and hence not too much overweight. -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v3 0/4] i2c: tegra: Bug fixes, cleanups and M_NOSTART support
This patch series having the: - Handling of late register write due to Tegra PPSB design. - support for I2C_M_NOSTART - Use devm_* for all allocation. Changes from V1: - Using the readback for mask/unmask of irq also. Changes from V2: - Read back is done whenever write happen in i2c register other than TX FIFO. Laxman Dewangan (4): i2c: tegra: make sure register writes completes i2c: tegra: add PROTOCOL_MANGLING as supported functionality. i2c: tegra: support for I2C_M_NOSTART functionality i2c: tegra: make all resource allocation through devm_* drivers/i2c/busses/i2c-tegra.c | 110 ++-- 1 files changed, 60 insertions(+), 50 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V3 3/4] i2c: tegra: support for I2C_M_NOSTART functionality
Adding support for functionality I2C_M_NOSTART. When multiple message transfer request made through i2c and if any message is flagged with I2C_M_NOSTART then it will not send the start/repeat-start and address of that message i.e. sends data directly. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- This is rebased of earlier patch on same support. At this time using the new flag I2C_FUNC_NOSTART. Changes form V1: - Rebased on linux-next. Changes from V2: - Rebased based on Wolfram's tree. drivers/i2c/busses/i2c-tegra.c | 31 ++- 1 files changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 68433ae..c4593a2 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -97,8 +97,21 @@ #define I2C_HEADER_10BIT_ADDR (118) #define I2C_HEADER_IE_ENABLE (117) #define I2C_HEADER_REPEAT_START(116) +#define I2C_HEADER_CONTINUE_XFER (115) #define I2C_HEADER_MASTER_ADDR_SHIFT 12 #define I2C_HEADER_SLAVE_ADDR_SHIFT1 +/* + * msg_end_type: The bus control which need to be send at end of transfer. + * @MSG_END_STOP: Send stop pulse at end of transfer. + * @MSG_END_REPEAT_START: Send repeat start at end of transfer. + * @MSG_END_CONTINUE: The following on message is coming and so do not send + * stop or repeat start. + */ +enum msg_end_type { + MSG_END_STOP, + MSG_END_REPEAT_START, + MSG_END_CONTINUE, +}; /** * struct tegra_i2c_dev- per device i2c context @@ -453,7 +466,7 @@ err: } static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, - struct i2c_msg *msg, int stop) + struct i2c_msg *msg, enum msg_end_type end_state) { u32 packet_header; u32 int_mask; @@ -480,7 +493,9 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); packet_header = I2C_HEADER_IE_ENABLE; - if (!stop) + if (end_state == MSG_END_CONTINUE) + packet_header |= I2C_HEADER_CONTINUE_XFER; + else if (end_state == MSG_END_REPEAT_START) packet_header |= I2C_HEADER_REPEAT_START; if (msg-flags I2C_M_TEN) { packet_header |= msg-addr; @@ -552,8 +567,14 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], clk_enable(i2c_dev-clk); for (i = 0; i num; i++) { - int stop = (i == (num - 1)) ? 1 : 0; - ret = tegra_i2c_xfer_msg(i2c_dev, msgs[i], stop); + enum msg_end_type end_type = MSG_END_STOP; + if (i (num - 1)) { + if (msgs[i + 1].flags I2C_M_NOSTART) + end_type = MSG_END_CONTINUE; + else + end_type = MSG_END_REPEAT_START; + } + ret = tegra_i2c_xfer_msg(i2c_dev, msgs[i], end_type); if (ret) break; } @@ -564,7 +585,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], static u32 tegra_i2c_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | - I2C_FUNC_PROTOCOL_MANGLING; + I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_NOSTART; } static const struct i2c_algorithm tegra_i2c_algo = { -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V3 1/4] i2c: tegra: make sure register writes completes
The Tegra PPSB (an peripheral bus) queues writes transactions. In order to guarantee that writes have completed before a certain time, a read transaction to a register on the same bus must be executed. This is necessary in situations such as when clearing an interrupt status or enable, so that when returning from an interrupt handler, the HW has already de-asserted its interrupt status output, which will avoid spurious interrupts. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- Changes from V1: - Using the readback for mask/unmask of irq also. Changes from V2: - Read back is done whenever write happen in i2c register other than TX FIFO. drivers/i2c/busses/i2c-tegra.c |4 1 files changed, 4 insertions(+), 0 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 8b2e555..785f7f7 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -165,6 +165,10 @@ static void i2c_writel(struct tegra_i2c_dev *i2c_dev, u32 val, unsigned long reg) { writel(val, i2c_dev-base + tegra_i2c_reg_addr(i2c_dev, reg)); + + /* Read back register to make sure that register writes completed */ + if (reg != I2C_TX_FIFO) + readl(i2c_dev-base + tegra_i2c_reg_addr(i2c_dev, reg)); } static u32 i2c_readl(struct tegra_i2c_dev *i2c_dev, unsigned long reg) -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V3 2/4] i2c: tegra: add PROTOCOL_MANGLING as supported functionality.
The Tegra i2c driver supports the I2C_M_IGNORE_NAK and hence returning I2C_FUNC_PROTOCOL_MANGLING as supported functionality. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- No Changes from V1 and V2. drivers/i2c/busses/i2c-tegra.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 785f7f7..68433ae 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -563,7 +563,8 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], static u32 tegra_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | + I2C_FUNC_PROTOCOL_MANGLING; } static const struct i2c_algorithm tegra_i2c_algo = { -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V3 4/4] i2c: tegra: make all resource allocation through devm_*
Use the devm_* for the memory region allocation, interrupt request, clock handler request. By doing this, it does not require to explicitly free it and hence saving some code. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- This is rebased of earlier similar patch and sending as part of this series. Changes form V1: - Rebased on linux-next. Changes from V2: - Rebased based on Wolfram's tree. drivers/i2c/busses/i2c-tegra.c | 62 +++- 1 files changed, 17 insertions(+), 45 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index c4593a2..9f4e22c 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -598,7 +598,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) struct tegra_i2c_dev *i2c_dev; struct tegra_i2c_platform_data *pdata = pdev-dev.platform_data; struct resource *res; - struct resource *iomem; struct clk *clk; struct clk *i2c_clk; const unsigned int *prop; @@ -611,50 +610,41 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) dev_err(pdev-dev, no mem resource\n); return -EINVAL; } - iomem = request_mem_region(res-start, resource_size(res), pdev-name); - if (!iomem) { - dev_err(pdev-dev, I2C region already claimed\n); - return -EBUSY; - } - base = ioremap(iomem-start, resource_size(iomem)); + base = devm_request_and_ioremap(pdev-dev, res); if (!base) { - dev_err(pdev-dev, Cannot ioremap I2C region\n); - return -ENOMEM; + dev_err(pdev-dev, Cannot request/ioremap I2C registers\n); + return -EADDRNOTAVAIL; } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(pdev-dev, no irq resource\n); - ret = -EINVAL; - goto err_iounmap; + return -EINVAL; } irq = res-start; - clk = clk_get(pdev-dev, NULL); + clk = devm_clk_get(pdev-dev, NULL); if (IS_ERR(clk)) { dev_err(pdev-dev, missing controller clock); - ret = PTR_ERR(clk); - goto err_release_region; + return PTR_ERR(clk); } - i2c_clk = clk_get(pdev-dev, i2c); + i2c_clk = devm_clk_get(pdev-dev, i2c); if (IS_ERR(i2c_clk)) { dev_err(pdev-dev, missing bus clock); - ret = PTR_ERR(i2c_clk); - goto err_clk_put; + return PTR_ERR(i2c_clk); } - i2c_dev = kzalloc(sizeof(struct tegra_i2c_dev), GFP_KERNEL); + i2c_dev = devm_kzalloc(pdev-dev, sizeof(*i2c_dev), GFP_KERNEL); if (!i2c_dev) { - ret = -ENOMEM; - goto err_i2c_clk_put; + dev_err(pdev-dev, Could not allocate struct tegra_i2c_dev); + return -ENOMEM; } i2c_dev-base = base; i2c_dev-clk = clk; i2c_dev-i2c_clk = i2c_clk; - i2c_dev-iomem = iomem; i2c_dev-adapter.algo = tegra_i2c_algo; i2c_dev-irq = irq; i2c_dev-cont_id = pdev-id; @@ -683,13 +673,14 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) ret = tegra_i2c_init(i2c_dev); if (ret) { dev_err(pdev-dev, Failed to initialize i2c controller); - goto err_free; + return ret; } - ret = request_irq(i2c_dev-irq, tegra_i2c_isr, 0, pdev-name, i2c_dev); + ret = devm_request_irq(pdev-dev, i2c_dev-irq, + tegra_i2c_isr, 0, pdev-name, i2c_dev); if (ret) { dev_err(pdev-dev, Failed to request irq %i\n, i2c_dev-irq); - goto err_free; + return ret; } clk_enable(i2c_dev-i2c_clk); @@ -707,38 +698,19 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) ret = i2c_add_numbered_adapter(i2c_dev-adapter); if (ret) { dev_err(pdev-dev, Failed to add I2C adapter\n); - goto err_free_irq; + clk_disable(i2c_dev-i2c_clk); + return ret; } of_i2c_register_devices(i2c_dev-adapter); return 0; -err_free_irq: - free_irq(i2c_dev-irq, i2c_dev); -err_free: - kfree(i2c_dev); -err_i2c_clk_put: - clk_put(i2c_clk); -err_clk_put: - clk_put(clk); -err_release_region: - release_mem_region(iomem-start, resource_size(iomem)); -err_iounmap: - iounmap(base); - return ret; } static int __devexit tegra_i2c_remove(struct platform_device *pdev) { struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_del_adapter(i2c_dev-adapter); - free_irq(i2c_dev-irq, i2c_dev); - clk_put(i2c_dev-i2c_clk); - clk_put(i2c_dev-clk
Re: [PATCH 1/4] i2c: tegra: make sure register writes completes
On Tuesday 12 June 2012 01:24 PM, Wolfram Sang wrote: * PGP Signed by an unknown key On Tue, Jun 05, 2012 at 06:39:57PM +0530, Laxman Dewangan wrote: @@ -430,6 +430,13 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) if (i2c_dev-is_dvc) dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); + /* +* Register write get queued in the PPSB bus and write can +* happen later. Read back register to make sure that register +* write is completed. +*/ + i2c_readl(i2c_dev, I2C_INT_STATUS); Does it make sense to put the read into i2c_writel? We can not put in i2c_writel() as we also do fifo write using this and writing and reading back fifo can drainout the fifo. hence putting this here seems more appropriate. + if (status I2C_INT_PACKET_XFER_COMPLETE) { BUG_ON(i2c_dev-msg_buf_remaining); complete(i2c_dev-msg_complete); @@ -444,6 +451,9 @@ err: if (i2c_dev-is_dvc) dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); + /* Read back register to make sure that register writes completed */ + i2c_readl(i2c_dev, I2C_INT_STATUS); + complete(i2c_dev-msg_complete); return IRQ_HANDLED; } @@ -505,6 +515,9 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, ret = wait_for_completion_timeout(i2c_dev-msg_complete, TEGRA_I2C_TIMEOUT); tegra_i2c_mask_irq(i2c_dev, int_mask); + /* Read back register to make sure that register writes completed */ + i2c_readl(i2c_dev, I2C_INT_MASK); + It definately makes sense to put this read into tegra_i2c_mask_irq()? Ok, fine with me. I put the read back logic inside mask_irq() and unmask_irq(). Will send the fix in next patch. if (WARN_ON(ret == 0)) { dev_err(i2c_dev-dev, i2c transfer timed out\n); Regards, Wolfram -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH v2 0/4] i2c: tegra: Bug fixes, cleanups and M_NOSTART support
This patch series having the: - Handling of late register write due to Tegra PPSB design. - support for I2C_M_NOSTART - Use devm_* for all allocation. Changes from V1: Taking care of review comment from Wolfram in patch 1/4. Laxman Dewangan (4): i2c: tegra: make sure register writes completes i2c: tegra: add PROTOCOL_MANGLING as supported functionality. i2c: tegra: support for I2C_M_NOSTART functionality i2c: tegra: make all resource allocation through devm_* drivers/i2c/busses/i2c-tegra.c | 110 ++-- 1 files changed, 60 insertions(+), 50 deletions(-) -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 3/4] i2c: tegra: support for I2C_M_NOSTART functionality
Adding support for functionality I2C_M_NOSTART. When multiple message transfer request made through i2c and if any message is flagged with I2C_M_NOSTART then it will not send the start/repeat-start and address of that message i.e. sends data directly. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- This is rebased of earlier patch on same support. At this time using the new flag I2C_FUNC_NOSTART. No change from V1. drivers/i2c/busses/i2c-tegra.c | 31 ++- 1 files changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index f906487..b093b66 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -97,8 +97,21 @@ #define I2C_HEADER_10BIT_ADDR (118) #define I2C_HEADER_IE_ENABLE (117) #define I2C_HEADER_REPEAT_START(116) +#define I2C_HEADER_CONTINUE_XFER (115) #define I2C_HEADER_MASTER_ADDR_SHIFT 12 #define I2C_HEADER_SLAVE_ADDR_SHIFT1 +/* + * msg_end_type: The bus control which need to be send at end of transfer. + * @MSG_END_STOP: Send stop pulse at end of transfer. + * @MSG_END_REPEAT_START: Send repeat start at end of transfer. + * @MSG_END_CONTINUE: The following on message is coming and so do not send + * stop or repeat start. + */ +enum msg_end_type { + MSG_END_STOP, + MSG_END_REPEAT_START, + MSG_END_CONTINUE, +}; /** * struct tegra_i2c_dev- per device i2c context @@ -465,7 +478,7 @@ err: } static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, - struct i2c_msg *msg, int stop) + struct i2c_msg *msg, enum msg_end_type end_state) { u32 packet_header; u32 int_mask; @@ -492,7 +505,9 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); packet_header = I2C_HEADER_IE_ENABLE; - if (!stop) + if (end_state == MSG_END_CONTINUE) + packet_header |= I2C_HEADER_CONTINUE_XFER; + else if (end_state == MSG_END_REPEAT_START) packet_header |= I2C_HEADER_REPEAT_START; if (msg-flags I2C_M_TEN) { packet_header |= msg-addr; @@ -564,8 +579,14 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], clk_prepare_enable(i2c_dev-clk); for (i = 0; i num; i++) { - int stop = (i == (num - 1)) ? 1 : 0; - ret = tegra_i2c_xfer_msg(i2c_dev, msgs[i], stop); + enum msg_end_type end_type = MSG_END_STOP; + if (i (num - 1)) { + if (msgs[i + 1].flags I2C_M_NOSTART) + end_type = MSG_END_CONTINUE; + else + end_type = MSG_END_REPEAT_START; + } + ret = tegra_i2c_xfer_msg(i2c_dev, msgs[i], end_type); if (ret) break; } @@ -576,7 +597,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], static u32 tegra_i2c_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | - I2C_FUNC_PROTOCOL_MANGLING; + I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_NOSTART; } static const struct i2c_algorithm tegra_i2c_algo = { -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 4/4] i2c: tegra: make all resource allocation through devm_*
Use the devm_* for the memory region allocation, interrupt request, clock handler request. By doing this, it does not require to explicitly free it and hence saving some code. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- This is rebased of earlier similar patch and sending as part of this series. No change from V1. drivers/i2c/busses/i2c-tegra.c | 62 +++- 1 files changed, 17 insertions(+), 45 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index b093b66..2ace6ac 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -610,7 +610,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) struct tegra_i2c_dev *i2c_dev; struct tegra_i2c_platform_data *pdata = pdev-dev.platform_data; struct resource *res; - struct resource *iomem; struct clk *clk; struct clk *i2c_clk; const unsigned int *prop; @@ -623,50 +622,41 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) dev_err(pdev-dev, no mem resource\n); return -EINVAL; } - iomem = request_mem_region(res-start, resource_size(res), pdev-name); - if (!iomem) { - dev_err(pdev-dev, I2C region already claimed\n); - return -EBUSY; - } - base = ioremap(iomem-start, resource_size(iomem)); + base = devm_request_and_ioremap(pdev-dev, res); if (!base) { - dev_err(pdev-dev, Cannot ioremap I2C region\n); - return -ENOMEM; + dev_err(pdev-dev, Cannot request/ioremap I2C registers\n); + return -EADDRNOTAVAIL; } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(pdev-dev, no irq resource\n); - ret = -EINVAL; - goto err_iounmap; + return -EINVAL; } irq = res-start; - clk = clk_get(pdev-dev, NULL); + clk = devm_clk_get(pdev-dev, NULL); if (IS_ERR(clk)) { dev_err(pdev-dev, missing controller clock); - ret = PTR_ERR(clk); - goto err_release_region; + return PTR_ERR(clk); } - i2c_clk = clk_get(pdev-dev, i2c); + i2c_clk = devm_clk_get(pdev-dev, i2c); if (IS_ERR(i2c_clk)) { dev_err(pdev-dev, missing bus clock); - ret = PTR_ERR(i2c_clk); - goto err_clk_put; + return PTR_ERR(i2c_clk); } - i2c_dev = kzalloc(sizeof(struct tegra_i2c_dev), GFP_KERNEL); + i2c_dev = devm_kzalloc(pdev-dev, sizeof(*i2c_dev), GFP_KERNEL); if (!i2c_dev) { - ret = -ENOMEM; - goto err_i2c_clk_put; + dev_err(pdev-dev, Could not allocate struct tegra_i2c_dev); + return -ENOMEM; } i2c_dev-base = base; i2c_dev-clk = clk; i2c_dev-i2c_clk = i2c_clk; - i2c_dev-iomem = iomem; i2c_dev-adapter.algo = tegra_i2c_algo; i2c_dev-irq = irq; i2c_dev-cont_id = pdev-id; @@ -695,13 +685,14 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) ret = tegra_i2c_init(i2c_dev); if (ret) { dev_err(pdev-dev, Failed to initialize i2c controller); - goto err_free; + return ret; } - ret = request_irq(i2c_dev-irq, tegra_i2c_isr, 0, pdev-name, i2c_dev); + ret = devm_request_irq(pdev-dev, i2c_dev-irq, + tegra_i2c_isr, 0, pdev-name, i2c_dev); if (ret) { dev_err(pdev-dev, Failed to request irq %i\n, i2c_dev-irq); - goto err_free; + return ret; } clk_prepare_enable(i2c_dev-i2c_clk); @@ -719,38 +710,19 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) ret = i2c_add_numbered_adapter(i2c_dev-adapter); if (ret) { dev_err(pdev-dev, Failed to add I2C adapter\n); - goto err_free_irq; + clk_disable(i2c_dev-i2c_clk); + return ret; } of_i2c_register_devices(i2c_dev-adapter); return 0; -err_free_irq: - free_irq(i2c_dev-irq, i2c_dev); -err_free: - kfree(i2c_dev); -err_i2c_clk_put: - clk_put(i2c_clk); -err_clk_put: - clk_put(clk); -err_release_region: - release_mem_region(iomem-start, resource_size(iomem)); -err_iounmap: - iounmap(base); - return ret; } static int __devexit tegra_i2c_remove(struct platform_device *pdev) { struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_del_adapter(i2c_dev-adapter); - free_irq(i2c_dev-irq, i2c_dev); - clk_put(i2c_dev-i2c_clk); - clk_put(i2c_dev-clk); - release_mem_region(i2c_dev-iomem-start, - resource_size
[PATCH V2 2/4] i2c: tegra: add PROTOCOL_MANGLING as supported functionality.
The Tegra i2c driver supports the I2C_M_IGNORE_NAK and hence returning I2C_FUNC_PROTOCOL_MANGLING as supported functionality. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- No change from V1, drivers/i2c/busses/i2c-tegra.c |3 ++- 1 files changed, 2 insertions(+), 1 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 753519a..f906487 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -575,7 +575,8 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], static u32 tegra_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | + I2C_FUNC_PROTOCOL_MANGLING; } static const struct i2c_algorithm tegra_i2c_algo = { -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V2 1/4] i2c: tegra: make sure register writes completes
The Tegra PPSB (an peripheral bus) queues writes transactions. In order to guarantee that writes have completed before a certain time, a read transaction to a register on the same bus must be executed. This is necessary in situations such as when clearing an interrupt status or enable, so that when returning from an interrupt handler, the HW has already de-asserted its interrupt status output, which will avoid spurious interrupts. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- changes from V1: Taken care of Wolfram's review comment. drivers/i2c/busses/i2c-tegra.c | 16 1 files changed, 16 insertions(+), 0 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 3da7ee3..753519a 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -189,6 +189,9 @@ static void tegra_i2c_mask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask) u32 int_mask = i2c_readl(i2c_dev, I2C_INT_MASK); int_mask = ~mask; i2c_writel(i2c_dev, int_mask, I2C_INT_MASK); + + /* Read back register to make sure that register writes completed */ + i2c_readl(i2c_dev, I2C_INT_MASK); } static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask) @@ -196,6 +199,9 @@ static void tegra_i2c_unmask_irq(struct tegra_i2c_dev *i2c_dev, u32 mask) u32 int_mask = i2c_readl(i2c_dev, I2C_INT_MASK); int_mask |= mask; i2c_writel(i2c_dev, int_mask, I2C_INT_MASK); + + /* Read back register to make sure that register writes completed */ + i2c_readl(i2c_dev, I2C_INT_MASK); } static int tegra_i2c_flush_fifos(struct tegra_i2c_dev *i2c_dev) @@ -430,6 +436,13 @@ static irqreturn_t tegra_i2c_isr(int irq, void *dev_id) if (i2c_dev-is_dvc) dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); + /* +* Register write get queued in the PPSB bus and write can +* happen later. Read back register to make sure that register +* write is completed. +*/ + i2c_readl(i2c_dev, I2C_INT_STATUS); + if (status I2C_INT_PACKET_XFER_COMPLETE) { BUG_ON(i2c_dev-msg_buf_remaining); complete(i2c_dev-msg_complete); @@ -444,6 +457,9 @@ err: if (i2c_dev-is_dvc) dvc_writel(i2c_dev, DVC_STATUS_I2C_DONE_INTR, DVC_STATUS); + /* Read back register to make sure that register writes completed */ + i2c_readl(i2c_dev, I2C_INT_STATUS); + complete(i2c_dev-msg_complete); return IRQ_HANDLED; } -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 3/4] i2c: tegra: support for I2C_M_NOSTART functionality
Adding support for functionality I2C_M_NOSTART. When multiple message transfer request made through i2c and if any message is flagged with I2C_M_NOSTART then it will not send the start/repeat-start and address of that message i.e. sends data directly. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- This is rebased of earlier patch on same support. At this time using the new flag I2C_FUNC_NOSTART. drivers/i2c/busses/i2c-tegra.c | 31 ++- 1 files changed, 26 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 36d8725..4cc9594 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -97,8 +97,21 @@ #define I2C_HEADER_10BIT_ADDR (118) #define I2C_HEADER_IE_ENABLE (117) #define I2C_HEADER_REPEAT_START(116) +#define I2C_HEADER_CONTINUE_XFER (115) #define I2C_HEADER_MASTER_ADDR_SHIFT 12 #define I2C_HEADER_SLAVE_ADDR_SHIFT1 +/* + * msg_end_type: The bus control which need to be send at end of transfer. + * @MSG_END_STOP: Send stop pulse at end of transfer. + * @MSG_END_REPEAT_START: Send repeat start at end of transfer. + * @MSG_END_CONTINUE: The following on message is coming and so do not send + * stop or repeat start. + */ +enum msg_end_type { + MSG_END_STOP, + MSG_END_REPEAT_START, + MSG_END_CONTINUE, +}; /** * struct tegra_i2c_dev- per device i2c context @@ -459,7 +472,7 @@ err: } static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, - struct i2c_msg *msg, int stop) + struct i2c_msg *msg, enum msg_end_type end_state) { u32 packet_header; u32 int_mask; @@ -486,7 +499,9 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); packet_header = I2C_HEADER_IE_ENABLE; - if (!stop) + if (end_state == MSG_END_CONTINUE) + packet_header |= I2C_HEADER_CONTINUE_XFER; + else if (end_state == MSG_END_REPEAT_START) packet_header |= I2C_HEADER_REPEAT_START; if (msg-flags I2C_M_TEN) { packet_header |= msg-addr; @@ -561,8 +576,14 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], clk_enable(i2c_dev-clk); for (i = 0; i num; i++) { - int stop = (i == (num - 1)) ? 1 : 0; - ret = tegra_i2c_xfer_msg(i2c_dev, msgs[i], stop); + enum msg_end_type end_type = MSG_END_STOP; + if (i (num - 1)) { + if (msgs[i + 1].flags I2C_M_NOSTART) + end_type = MSG_END_CONTINUE; + else + end_type = MSG_END_REPEAT_START; + } + ret = tegra_i2c_xfer_msg(i2c_dev, msgs[i], end_type); if (ret) break; } @@ -573,7 +594,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], static u32 tegra_i2c_func(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | - I2C_FUNC_PROTOCOL_MANGLING; + I2C_FUNC_PROTOCOL_MANGLING | I2C_FUNC_NOSTART; } static const struct i2c_algorithm tegra_i2c_algo = { -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH 4/4] i2c: tegra: make all resource allocation through devm_*
Use the devm_* for the memory region allocation, interrupt request, clock handler request. By doing this, it does not require to explicitly free it and hence saving some code. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- This is rebased of earlier similar patch and sending as part of this series. drivers/i2c/busses/i2c-tegra.c | 62 +++- 1 files changed, 17 insertions(+), 45 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 4cc9594..6745631 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -607,7 +607,6 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) struct tegra_i2c_dev *i2c_dev; struct tegra_i2c_platform_data *pdata = pdev-dev.platform_data; struct resource *res; - struct resource *iomem; struct clk *clk; struct clk *i2c_clk; const unsigned int *prop; @@ -620,50 +619,41 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) dev_err(pdev-dev, no mem resource\n); return -EINVAL; } - iomem = request_mem_region(res-start, resource_size(res), pdev-name); - if (!iomem) { - dev_err(pdev-dev, I2C region already claimed\n); - return -EBUSY; - } - base = ioremap(iomem-start, resource_size(iomem)); + base = devm_request_and_ioremap(pdev-dev, res); if (!base) { - dev_err(pdev-dev, Cannot ioremap I2C region\n); - return -ENOMEM; + dev_err(pdev-dev, Cannot request/ioremap I2C registers\n); + return -EADDRNOTAVAIL; } res = platform_get_resource(pdev, IORESOURCE_IRQ, 0); if (!res) { dev_err(pdev-dev, no irq resource\n); - ret = -EINVAL; - goto err_iounmap; + return -EINVAL; } irq = res-start; - clk = clk_get(pdev-dev, NULL); + clk = devm_clk_get(pdev-dev, NULL); if (IS_ERR(clk)) { dev_err(pdev-dev, missing controller clock); - ret = PTR_ERR(clk); - goto err_release_region; + return PTR_ERR(clk); } - i2c_clk = clk_get(pdev-dev, i2c); + i2c_clk = devm_clk_get(pdev-dev, i2c); if (IS_ERR(i2c_clk)) { dev_err(pdev-dev, missing bus clock); - ret = PTR_ERR(i2c_clk); - goto err_clk_put; + return PTR_ERR(i2c_clk); } - i2c_dev = kzalloc(sizeof(struct tegra_i2c_dev), GFP_KERNEL); + i2c_dev = devm_kzalloc(pdev-dev, sizeof(*i2c_dev), GFP_KERNEL); if (!i2c_dev) { - ret = -ENOMEM; - goto err_i2c_clk_put; + dev_err(pdev-dev, Could not allocate struct tegra_i2c_dev); + return -ENOMEM; } i2c_dev-base = base; i2c_dev-clk = clk; i2c_dev-i2c_clk = i2c_clk; - i2c_dev-iomem = iomem; i2c_dev-adapter.algo = tegra_i2c_algo; i2c_dev-irq = irq; i2c_dev-cont_id = pdev-id; @@ -692,13 +682,14 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) ret = tegra_i2c_init(i2c_dev); if (ret) { dev_err(pdev-dev, Failed to initialize i2c controller); - goto err_free; + return ret; } - ret = request_irq(i2c_dev-irq, tegra_i2c_isr, 0, pdev-name, i2c_dev); + ret = devm_request_irq(pdev-dev, i2c_dev-irq, + tegra_i2c_isr, 0, pdev-name, i2c_dev); if (ret) { dev_err(pdev-dev, Failed to request irq %i\n, i2c_dev-irq); - goto err_free; + return ret; } clk_enable(i2c_dev-i2c_clk); @@ -716,38 +707,19 @@ static int __devinit tegra_i2c_probe(struct platform_device *pdev) ret = i2c_add_numbered_adapter(i2c_dev-adapter); if (ret) { dev_err(pdev-dev, Failed to add I2C adapter\n); - goto err_free_irq; + clk_disable(i2c_dev-i2c_clk); + return ret; } of_i2c_register_devices(i2c_dev-adapter); return 0; -err_free_irq: - free_irq(i2c_dev-irq, i2c_dev); -err_free: - kfree(i2c_dev); -err_i2c_clk_put: - clk_put(i2c_clk); -err_clk_put: - clk_put(clk); -err_release_region: - release_mem_region(iomem-start, resource_size(iomem)); -err_iounmap: - iounmap(base); - return ret; } static int __devexit tegra_i2c_remove(struct platform_device *pdev) { struct tegra_i2c_dev *i2c_dev = platform_get_drvdata(pdev); i2c_del_adapter(i2c_dev-adapter); - free_irq(i2c_dev-irq, i2c_dev); - clk_put(i2c_dev-i2c_clk); - clk_put(i2c_dev-clk); - release_mem_region(i2c_dev-iomem-start, - resource_size(i2c_dev-iomem
Re: [PATCH 0/4] i2c: tegra: Bug fixes, cleanups and M_NOSTART support
On Tuesday 05 June 2012 09:44 PM, Stephen Warren wrote: On 06/05/2012 07:09 AM, Laxman Dewangan wrote: This patch series having the: - Handling of late register write due to Tegra PPSB design. - support for I2C_M_NOSTART - Use devm_* for all allocation. The series, Acked-by: Stephen Warrenswar...@wwwdotorg.org Note that patch 4 touches context adjacent to Prashant's i2c: tegra: Add clk_prepare/clk_unprepare patch, which I hope to take through the Tegra tree since it's a requirement for the Tegra common clock conversion. I don't think this will cause any significant conflict, but perhaps it's worth resolving it explicitly. Wolfram, perhaps we should put these 4 patches and Prashan'ts into their own topic branch so that you can merge it into the I2C tree, and I can merge it into the Tegra tree too? Or, I can take everything through Tegra if you want, and ack it. Laxman, do you expect any more I2C-related changes this kernel cycle? I have two more changes in plan: -I2c controller require two clock source and the fixes towards that. This can go on Tegra tree as changes are require in mach-tegra/tegra30_clock.c, tegra20_clock.c files also. - Run time PM support but can be done later. -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH V1 1/2] i2c: tegra: fix 10bit address configuration
On Thursday 03 May 2012 01:48 PM, Wolfram Sang wrote: * PGP Signed by an unknown key On Thu, May 03, 2012 at 11:43:14AM +0530, Laxman Dewangan wrote: On Tuesday 24 April 2012 02:28 PM, Jean Delvare wrote: On Tue, 24 Apr 2012 12:49:35 +0530, Laxman Dewangan wrote: The slave address of device to be configured in packet header as follows: 7 bit address: PacketHeader3[7:1] 10 bit address: PacketHeader3[9:0] Fixing the code to make packet header3 properly. Signed-off-by: Laxman Dewanganldewan...@nvidia.com --- Looks good. Acked-by: Jean Delvarekh...@linux-fr.org Can it be apply? This is independent of other change in this series which is under discussion/review. Applied to next. Or do you need it in 3.4? I dont need it on 3.4. It is fine to apply for next only. -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 01/11] dma: imx-sdma: make channel0 operations atomic
On Friday 27 April 2012 05:03 PM, Russell King - ARM Linux wrote: On Fri, Apr 27, 2012 at 07:26:56PM +0800, Richard Zhao wrote: Sure, I mean, can you doc in include/linux/dmaengine.h that dmaengine_prep_xxx may sleep? Incorrect. They may _not_ sleep. But I have seen that we are using the kzalloc in the dmaengine_prep_xxx and kzalloc is sleeping call. -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V1 1/2] i2c: tegra: fix 10bit address configuration
The slave address of device to be configured in packet header as follows: 7 bit address: PacketHeader3[7:1] 10 bit address: PacketHeader3[9:0] Fixing the code to make packet header3 properly. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- drivers/i2c/busses/i2c-tegra.c | 11 +++ 1 files changed, 7 insertions(+), 4 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 55e5ea6..18067b3 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -476,12 +476,15 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, packet_header = msg-len - 1; i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); - packet_header = msg-addr I2C_HEADER_SLAVE_ADDR_SHIFT; - packet_header |= I2C_HEADER_IE_ENABLE; + packet_header = I2C_HEADER_IE_ENABLE; if (!stop) packet_header |= I2C_HEADER_REPEAT_START; - if (msg-flags I2C_M_TEN) + if (msg-flags I2C_M_TEN) { + packet_header |= msg-addr; packet_header |= I2C_HEADER_10BIT_ADDR; + } else { + packet_header |= msg-addr I2C_HEADER_SLAVE_ADDR_SHIFT; + } if (msg-flags I2C_M_IGNORE_NAK) packet_header |= I2C_HEADER_CONT_ON_NAK; if (msg-flags I2C_M_RD) @@ -557,7 +560,7 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], static u32 tegra_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; } static const struct i2c_algorithm tegra_i2c_algo = { -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V1 2/2] i2c: tegra: support for I2C_M_NOSTART protocol mangling
Adding support for protocol mangling I2C_M_NOSTART. When multiple message transfer request made through i2c and if any message is flagged with I2C_M_NOSTART then it will not send the start/repeat start/address of that message i.e. send the data directly. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- drivers/i2c/busses/i2c-tegra.c | 32 +++- 1 files changed, 27 insertions(+), 5 deletions(-) diff --git a/drivers/i2c/busses/i2c-tegra.c b/drivers/i2c/busses/i2c-tegra.c index 18067b3..a50e4c4 100644 --- a/drivers/i2c/busses/i2c-tegra.c +++ b/drivers/i2c/busses/i2c-tegra.c @@ -97,8 +97,21 @@ #define I2C_HEADER_10BIT_ADDR (118) #define I2C_HEADER_IE_ENABLE (117) #define I2C_HEADER_REPEAT_START(116) +#define I2C_HEADER_CONTINUE_XFER (115) #define I2C_HEADER_MASTER_ADDR_SHIFT 12 #define I2C_HEADER_SLAVE_ADDR_SHIFT1 +/* + * msg_end_type: The bus control which need to be send at end of transfer. + * @MSG_END_STOP: Send stop pulse at end of transfer. + * @MSG_END_REPEAT_START: Send repeat start at end of transfer. + * @MSG_END_CONTINUE: The following on message is coming and so do not send + * stop or repeat start. + */ +enum msg_end_type { + MSG_END_STOP, + MSG_END_REPEAT_START, + MSG_END_CONTINUE, +}; /** * struct tegra_i2c_dev- per device i2c context @@ -450,7 +463,7 @@ err: } static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, - struct i2c_msg *msg, int stop) + struct i2c_msg *msg, enum msg_end_type end_state) { u32 packet_header; u32 int_mask; @@ -477,7 +490,9 @@ static int tegra_i2c_xfer_msg(struct tegra_i2c_dev *i2c_dev, i2c_writel(i2c_dev, packet_header, I2C_TX_FIFO); packet_header = I2C_HEADER_IE_ENABLE; - if (!stop) + if (end_state == MSG_END_CONTINUE) + packet_header |= I2C_HEADER_CONTINUE_XFER; + else if (end_state == MSG_END_REPEAT_START) packet_header |= I2C_HEADER_REPEAT_START; if (msg-flags I2C_M_TEN) { packet_header |= msg-addr; @@ -549,8 +564,14 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], clk_enable(i2c_dev-clk); for (i = 0; i num; i++) { - int stop = (i == (num - 1)) ? 1 : 0; - ret = tegra_i2c_xfer_msg(i2c_dev, msgs[i], stop); + enum msg_end_type end_type = MSG_END_STOP; + if (i (num - 1)) { + if (msgs[i + 1].flags I2C_M_NOSTART) + end_type = MSG_END_CONTINUE; + else + end_type = MSG_END_REPEAT_START; + } + ret = tegra_i2c_xfer_msg(i2c_dev, msgs[i], end_type); if (ret) break; } @@ -560,7 +581,8 @@ static int tegra_i2c_xfer(struct i2c_adapter *adap, struct i2c_msg msgs[], static u32 tegra_i2c_func(struct i2c_adapter *adap) { - return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR; + return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL | I2C_FUNC_10BIT_ADDR | + I2C_FUNC_PROTOCOL_MANGLING; } static const struct i2c_algorithm tegra_i2c_algo = { -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
[PATCH V1] i2c: gpio: Use open drain support from gpio driver
The gpio core driver (gpio library) supports the open drain pin handling. Therefore, it is not require it to handle in the i2c-gpio driver, just require to pass the OPEN_DRAIN type flag when requesting the gpio. Remove the handling of open drain pin in the i2c-gpio driver. Signed-off-by: Laxman Dewangan ldewan...@nvidia.com --- drivers/i2c/busses/i2c-gpio.c | 78 ++-- 1 files changed, 27 insertions(+), 51 deletions(-) diff --git a/drivers/i2c/busses/i2c-gpio.c b/drivers/i2c/busses/i2c-gpio.c index 69fbfae..662a747 100644 --- a/drivers/i2c/busses/i2c-gpio.c +++ b/drivers/i2c/busses/i2c-gpio.c @@ -16,22 +16,7 @@ #include linux/platform_device.h #include linux/gpio.h -/* Toggle SDA by changing the direction of the pin */ -static void i2c_gpio_setsda_dir(void *data, int state) -{ - struct i2c_gpio_platform_data *pdata = data; - - if (state) - gpio_direction_input(pdata-sda_pin); - else - gpio_direction_output(pdata-sda_pin, 0); -} - -/* - * Toggle SDA by changing the output value of the pin. This is only - * valid for pins configured as open drain (i.e. setting the value - * high effectively turns off the output driver.) - */ +/* Toggle SDA by setting value, gpio library take care of open drain pins.*/ static void i2c_gpio_setsda_val(void *data, int state) { struct i2c_gpio_platform_data *pdata = data; @@ -39,23 +24,7 @@ static void i2c_gpio_setsda_val(void *data, int state) gpio_set_value(pdata-sda_pin, state); } -/* Toggle SCL by changing the direction of the pin. */ -static void i2c_gpio_setscl_dir(void *data, int state) -{ - struct i2c_gpio_platform_data *pdata = data; - - if (state) - gpio_direction_input(pdata-scl_pin); - else - gpio_direction_output(pdata-scl_pin, 0); -} - -/* - * Toggle SCL by changing the output value of the pin. This is used - * for pins that are configured as open drain and for output-only - * pins. The latter case will break the i2c protocol, but it will - * often work in practice. - */ + /* Toggle SCL by setting value, gpio library take care of open drain pins.*/ static void i2c_gpio_setscl_val(void *data, int state) { struct i2c_gpio_platform_data *pdata = data; @@ -83,6 +52,8 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev) struct i2c_algo_bit_data *bit_data; struct i2c_adapter *adap; int ret; + unsigned long sda_gpio_flags; + unsigned long scl_gpio_flags; pdata = pdev-dev.platform_data; if (!pdata) @@ -96,28 +67,33 @@ static int __devinit i2c_gpio_probe(struct platform_device *pdev) if (!bit_data) goto err_alloc_bit_data; - ret = gpio_request(pdata-sda_pin, sda); - if (ret) + /* Initially, SCL and SDA pin should be HIGH */ + sda_gpio_flags = GPIOF_OUT_INIT_HIGH; + scl_gpio_flags = GPIOF_OUT_INIT_HIGH; + + if (pdata-sda_is_open_drain) + sda_gpio_flags |= GPIOF_OPEN_DRAIN; + + if (pdata-scl_is_open_drain !pdata-scl_is_output_only) + scl_gpio_flags |= GPIOF_OPEN_DRAIN; + + + + ret = gpio_request_one(pdata-sda_pin, sda_gpio_flags, sda); + if (ret) { + pr_err(%s(): Error in requesting sda gpio%d, ret %d\n, + __func__, pdata-sda_pin, ret); goto err_request_sda; - ret = gpio_request(pdata-scl_pin, scl); - if (ret) + } + ret = gpio_request_one(pdata-scl_pin, scl_gpio_flags, scl); + if (ret) { + pr_err(%s(): Error in requesting scl gpio%d, ret %d\n, + __func__, pdata-scl_pin, ret); goto err_request_scl; - - if (pdata-sda_is_open_drain) { - gpio_direction_output(pdata-sda_pin, 1); - bit_data-setsda = i2c_gpio_setsda_val; - } else { - gpio_direction_input(pdata-sda_pin); - bit_data-setsda = i2c_gpio_setsda_dir; } - if (pdata-scl_is_open_drain || pdata-scl_is_output_only) { - gpio_direction_output(pdata-scl_pin, 1); - bit_data-setscl = i2c_gpio_setscl_val; - } else { - gpio_direction_input(pdata-scl_pin); - bit_data-setscl = i2c_gpio_setscl_dir; - } + bit_data-setsda = i2c_gpio_setsda_val; + bit_data-setscl = i2c_gpio_setscl_val; if (!pdata-scl_is_output_only) bit_data-getscl = i2c_gpio_getscl; -- 1.7.1.1 -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH V1] i2c: gpio: Use open drain support from gpio driver
The open drain support is already available from next-20120306. I was waiting for the change to be in tree before sending this patch. Hope I am not missing anything here. On Wednesday 07 March 2012 11:14 PM, Mark Brown wrote: * PGP Signed by an unknown key On Wed, Mar 07, 2012 at 06:39:22PM +0100, Wolfram Sang wrote: On Wed, Mar 07, 2012 at 05:31:57PM +, Mark Brown wrote: Reviwed-by: Mark Brownbroo...@opensource.wolfsonmicro.com Typo ;) Not at all, it's a direct demonstration of the quick review I did! :P * Unknown Key * 0x6E30FDDD -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2] i2c/designware: Provide optional i2c bus recovery function
On Tuesday 28 February 2012 06:53 PM, viresh kumar wrote: This patch also adds in generic bus recovery routines gpio or scl line based which can be used by bus controller. In addition controller driver may provide its own version of the bus recovery routine. Signed-off-by: Viresh Kumarviresh.ku...@st.com --- drivers/i2c/i2c-core.c | 56 include/linux/i2c.h| 22 ++ 2 files changed, 78 insertions(+), 0 deletions(-) diff --git a/drivers/i2c/i2c-core.c b/drivers/i2c/i2c-core.c index e9c1893..c9f0daf 100644 --- a/drivers/i2c/i2c-core.c +++ b/drivers/i2c/i2c-core.c @@ -26,7 +26,9 @@ #includelinux/module.h #includelinux/kernel.h +#includelinux/delay.h #includelinux/errno.h +#includelinux/gpio.h #includelinux/slab.h #includelinux/i2c.h #includelinux/init.h @@ -103,6 +105,47 @@ static int i2c_device_uevent(struct device *dev, struct kobj_uevent_env *env) #define i2c_device_uevent NULL #endif/* CONFIG_HOTPLUG */ +/* i2c bus recovery routines */ +static int i2c_gpio_recover_bus(struct i2c_adapter *adap) +{ + int tmp, val = 1; + unsigned long delay = 100; + + tmp = gpio_request_one(adap-scl_gpio, GPIOF_DIR_OUT | + GPIOF_INIT_LOW, i2c-bus-recover); Should rename tmp to ret or status. tmp does not looks appropriate. + if (tmp 0) { + dev_warn(adap-dev, gpio request one fail: %d\n, + adap-scl_gpio); + return tmp; + } + + delay /= adap-clock_rate * 2; Here delay is turning as micor sec and function used as the nano sec. + + for (tmp = 0; tmp adap-clock_cnt * 2; tmp++, val = !val) { + ndelay(delay); should be udelay()? + gpio_set_value(adap-scl_gpio, val); I think it should check for the sda line for coming out of the loop. There may be possibility that we may not need 9 clock pulses. + } + + gpio_free(adap-clock_cnt); + + return 0; +} + +static int i2c_scl_recover_bus(struct i2c_adapter *adap) +{ + int i, val = 0; + unsigned long delay = 100; + + delay /= adap-clock_rate * 2; + + for (i = 0; i adap-clock_cnt * 2; i++, val = !val) { + adap-set_scl(adap, val); + ndelay(delay); udelay()?? + } + + return 0; +} + static int i2c_device_probe(struct device *dev) { struct i2c_client *client = i2c_verify_client(dev); @@ -861,6 +904,19 @@ static int i2c_register_adapter(struct i2c_adapter *adap) Failed to create compatibility class link\n); #endif + /* bus recovery specific initialization */ + if (!adap-recover_bus) { + if (!adap-clock_cnt || !adap-clock_rate) + goto warn_no_recovery; + else if (adap-is_gpio_recovery) + adap-recover_bus = i2c_gpio_recover_bus; + else if (adap-set_scl) + adap-recover_bus = i2c_scl_recover_bus; + +warn_no_recovery: Always generated warning.. + dev_warn(adap-dev, doesn't have recovery method\n); + } + /* create pre-declared device nodes */ if (adap-nr __i2c_first_dynamic_bus_num) i2c_scan_static_board_info(adap); diff --git a/include/linux/i2c.h b/include/linux/i2c.h index 8e25a91..b2a6d97 100644 --- a/include/linux/i2c.h +++ b/include/linux/i2c.h @@ -388,6 +388,28 @@ struct i2c_adapter { struct mutex userspace_clients_lock; struct list_head userspace_clients; + + /* +* bus recovery specific fields: Either pass driver's recover_bus() +* routine, or pass it NULL to use generic ones. There are two type of +* generic one's available: +* - controlling scl line as gpio, pass is_gpio_recovery as true +* and valid scl_gpio number +* - controlling scl line directly via controller, pass +* is_gpio_recovery as false and valid set_scl routine's pointer +* +* Both schemes require valid values of +* - clock_cnt: total number of dummy clocks to be generated +* - clock_rate: rate of dummy clock +* +* scl_gpio. +*/ + int (*recover_bus)(struct i2c_adapter *); + void (*set_scl)(struct i2c_adapter *, int val); + bool is_gpio_recovery; + u8 scl_gpio; gpio can be more than 256. better to use int. Take scl_gpio_flag and use in the gpio_request_one. + u8 clock_cnt; + u32 clock_rate; /* In KHz */ }; #define to_i2c_adapter(d) container_of(d, struct i2c_adapter, dev) -- viresh --- This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is
Re: [PATCH 2/2] i2c/designware: Provide optional i2c bus recovery function
On Wednesday 29 February 2012 05:28 PM, Viresh Kumar wrote: + if (tmp 0) { + dev_warn(adap-dev, gpio request one fail: %d\n, + adap-scl_gpio); + return tmp; + } + + delay /= adap-clock_rate * 2; Here delay is turning as micor sec and function used as the nano sec. clock_rate is in KHz, mentioned in comment of clock_rate. Makes sense now or am i missing something? Oops, my bad.. better to name the variable as clock_rate_khz kind of to avoid the error when we use in our driver. I think it should check for the sda line for coming out of the loop. There may be possibility that we may not need 9 clock pulses. I asked this in another mail, how to be sure that it will work. We observed that sometimes it does not require 9 clocks. So you can poll for given amount of clock time. Once the device who was holding the SDA line to low, release the bus, it can comeout from the loop. Not sure this is as per specs or not but this was our observations. --- This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. --- -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 2/2] i2c/designware: Provide optional i2c bus recovery function
On Monday 27 February 2012 12:51 PM, Shubhrajyoti Datta wrote: On Fri, Feb 24, 2012 at 5:01 PM, Viresh Kumarviresh.ku...@st.com wrote: From: Vincenzo Frascinovincenzo.frasc...@st.com Add optional i2c_recover_bus() function to the Synopsys DesignWare I2C adapter driver that performs i2c bus recovery after timeout. The scope of this routine is to define i2c bus recovery procedure as specified in the i2c protocol Rev. 03 section 3.16 titled Bus clear. What do you do in the function ? Could we have it in the driver file itself? I think bus recovery mechanism is to send extra clock on SCL line by toggling the pin (using gpio apis) and keep watching of sda line whether it becomes high or not. We can put this algorithms in the some common file (i2c/algos/) and so if any i2c bus driver want to use, they can use it. Little background: I am working on tegra i2c controller and we have similar logic in tegra-i2c driver which we want to upstream. If similar function is in common place, we can use this and need not to duplicating it on every bus driver. --- This email message is for the sole use of the intended recipient(s) and may contain confidential information. Any unauthorized review, use, disclosure or distribution is prohibited. If you are not the intended recipient, please contact the sender by reply email and destroy all copies of the original message. --- -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
Re: [PATCH 1/2] i2c: tegra: Remove unnecessary clk_get
On Thursday 16 February 2012 12:13 AM, Stephen Warren wrote: This appears to apply to modules lfsr, dsi, csi, i2c1/2/3, uart1/2/3/4/5, but apparently not the DVC I2C controller according to the TRM. Laxman, can you confirm that the DVC I2C controller doesn't take a clock from pll_p_out3? DVC i2C is also require this 2nd clock. P.S. this patch I posted is in our downstream 2.6.39 and 3.1 kernels. Given this thread, I assume it should be reverted there... Yes, I have pushed the change in our downstream tree K3.1 and it is under testing/promotion.. -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html
RE: [PATCH] i2c: tegra: Add delay before reset the controller
-Original Message- From: Alok Chauhan Hi, (Adding Laxman Dewangan) This change causes problems systems with some models of i2c TPMs, since the first transaction to them will always time out (TPM quirk), and the delay means that the tpm will have time to go back to sleep and thus timeout even on the retry. So you'll never make progress. Working on this. -Alok -Original Message- From: Olof Johansson [mailto:o...@lixom.net] Sent: Friday, December 23, 2011 2:48 AM To: Alok Chauhan Cc: kh...@linux-fr.org; ben-li...@fluff.org; Stephen Warren; bo...@secretlab.ca; paul.gortma...@windriver.com; linux-i2c@vger.kernel.org; linux-ker...@vger.kernel.org; linux-te...@vger.kernel.org; dgr...@google.com Subject: Re: [PATCH] i2c: tegra: Add delay before reset the controller Hi, (Adding linux-tegra and Dylan Reid who was debugging this before) On Thu, Dec 22, 2011 at 2:41 AM, Alok Chauhan al...@nvidia.com wrote: From: Alok Chauhan al...@nvidia.com In NACK error condition, I2C controller violates clock-to-data setup time before stop. In Software, because of this reset of controller is happening before I2C controller could complete STOP condition. Added worst case delay of 1 ms (assuming lowest clock frequency will be 1 KHZ) before reset the controller in case of NACK error. This change causes problems systems with some models of i2c TPMs, since the first transaction to them will always time out (TPM quirk), and the delay means that the tpm will have time to go back to sleep and thus timeout even on the retry. So you'll never make progress. In other words: this patch will break some systems and thus shouldn't be applied. I think the delay should be calculated based on speed. So if it is 100KHz, then delay is 10mcro second for 1 bit. We should wait for 2 bit (ack clock to be complete and stop pulse to be transmitted). This patch will make sure that i2c driver will not break the specs i.e. in case of NACK error, the stop signal should be completed by i2c controller before resetting controller. I will prefer of having the udelay(2*100/speed). -Olof -- To unsubscribe from this list: send the line unsubscribe linux-i2c in the body of a message to majord...@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html