Re: [PATCH v2 2/3] i2c: davinci: Add PM Runtime Support

2017-08-21 Thread Sekhar Nori
On Tuesday 22 August 2017 06:47 AM, Franklin S Cooper Jr wrote:
> 
> 
> On 08/21/2017 04:05 AM, Sekhar Nori wrote:
>> On Thursday 17 August 2017 03:47 AM, Franklin S Cooper Jr wrote:
>>
>>> @@ -802,7 +821,6 @@ static int davinci_i2c_probe(struct platform_device 
>>> *pdev)
>>> dev->clk = devm_clk_get(>dev, NULL);
>>> if (IS_ERR(dev->clk))
>>> return PTR_ERR(dev->clk);
>>> -   clk_prepare_enable(dev->clk);
>>>  
>>> mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> dev->base = devm_ioremap_resource(>dev, mem);
>>> @@ -811,6 +829,18 @@ static int davinci_i2c_probe(struct platform_device 
>>> *pdev)
>>> goto err_unuse_clocks;
>>
>> This goto is wrong now. There is no need to unwind the pm_runtime setup
>> on a devm_ioremap_resource() failure. You can just return error here.
> 
> Ok
>>
>>> }
>>>  
>>> +   pm_runtime_set_autosuspend_delay(dev->dev,
>>> +DAVINCI_I2C_PM_TIMEOUT);
>>> +   pm_runtime_use_autosuspend(dev->dev);
>>> +
>>> +   pm_runtime_enable(dev->dev);
>>> +
>>> +   r = pm_runtime_get_sync(dev->dev);
>>> +   if (r < 0) {
>>> +   dev_err(dev->dev, "failed to runtime_get device: %d\n", r);
>>> +   goto err_unuse_clocks;
>>> +   }
>>> +
>>> i2c_davinci_init(dev);
>>>  
>>> r = devm_request_irq(>dev, dev->irq, i2c_davinci_isr, 0,
>>> @@ -849,10 +879,16 @@ static int davinci_i2c_probe(struct platform_device 
>>> *pdev)
>>> if (r)
>>> goto err_unuse_clocks;
>>>  
>>> +   pm_runtime_mark_last_busy(dev->dev);
>>> +   pm_runtime_put_autosuspend(dev->dev);
>>> +
>>> return 0;
>>>  
>>>  err_unuse_clocks:
>>> -   clk_disable_unprepare(dev->clk);
>>> +   pm_runtime_dont_use_autosuspend(dev->dev);
>>> +   pm_runtime_put_sync(dev->dev);
>>> +   pm_runtime_disable(dev->dev);
>>> +
>>> dev->clk = NULL;
>>
>> This null setting of clk seems quite bogus and can be cleaned-up.
> 
> Do you mean that I should just remove this line?

Yes, and I noticed a similar line in at least one more place that can be
removed as well.

Thanks,
Sekhar


Re: [PATCH v2 2/3] i2c: davinci: Add PM Runtime Support

2017-08-21 Thread Sekhar Nori
On Tuesday 22 August 2017 06:47 AM, Franklin S Cooper Jr wrote:
> 
> 
> On 08/21/2017 04:05 AM, Sekhar Nori wrote:
>> On Thursday 17 August 2017 03:47 AM, Franklin S Cooper Jr wrote:
>>
>>> @@ -802,7 +821,6 @@ static int davinci_i2c_probe(struct platform_device 
>>> *pdev)
>>> dev->clk = devm_clk_get(>dev, NULL);
>>> if (IS_ERR(dev->clk))
>>> return PTR_ERR(dev->clk);
>>> -   clk_prepare_enable(dev->clk);
>>>  
>>> mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>> dev->base = devm_ioremap_resource(>dev, mem);
>>> @@ -811,6 +829,18 @@ static int davinci_i2c_probe(struct platform_device 
>>> *pdev)
>>> goto err_unuse_clocks;
>>
>> This goto is wrong now. There is no need to unwind the pm_runtime setup
>> on a devm_ioremap_resource() failure. You can just return error here.
> 
> Ok
>>
>>> }
>>>  
>>> +   pm_runtime_set_autosuspend_delay(dev->dev,
>>> +DAVINCI_I2C_PM_TIMEOUT);
>>> +   pm_runtime_use_autosuspend(dev->dev);
>>> +
>>> +   pm_runtime_enable(dev->dev);
>>> +
>>> +   r = pm_runtime_get_sync(dev->dev);
>>> +   if (r < 0) {
>>> +   dev_err(dev->dev, "failed to runtime_get device: %d\n", r);
>>> +   goto err_unuse_clocks;
>>> +   }
>>> +
>>> i2c_davinci_init(dev);
>>>  
>>> r = devm_request_irq(>dev, dev->irq, i2c_davinci_isr, 0,
>>> @@ -849,10 +879,16 @@ static int davinci_i2c_probe(struct platform_device 
>>> *pdev)
>>> if (r)
>>> goto err_unuse_clocks;
>>>  
>>> +   pm_runtime_mark_last_busy(dev->dev);
>>> +   pm_runtime_put_autosuspend(dev->dev);
>>> +
>>> return 0;
>>>  
>>>  err_unuse_clocks:
>>> -   clk_disable_unprepare(dev->clk);
>>> +   pm_runtime_dont_use_autosuspend(dev->dev);
>>> +   pm_runtime_put_sync(dev->dev);
>>> +   pm_runtime_disable(dev->dev);
>>> +
>>> dev->clk = NULL;
>>
>> This null setting of clk seems quite bogus and can be cleaned-up.
> 
> Do you mean that I should just remove this line?

Yes, and I noticed a similar line in at least one more place that can be
removed as well.

Thanks,
Sekhar


Re: [PATCH v2 2/3] i2c: davinci: Add PM Runtime Support

2017-08-21 Thread Franklin S Cooper Jr


On 08/21/2017 04:05 AM, Sekhar Nori wrote:
> On Thursday 17 August 2017 03:47 AM, Franklin S Cooper Jr wrote:
> 
>> @@ -802,7 +821,6 @@ static int davinci_i2c_probe(struct platform_device 
>> *pdev)
>>  dev->clk = devm_clk_get(>dev, NULL);
>>  if (IS_ERR(dev->clk))
>>  return PTR_ERR(dev->clk);
>> -clk_prepare_enable(dev->clk);
>>  
>>  mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>  dev->base = devm_ioremap_resource(>dev, mem);
>> @@ -811,6 +829,18 @@ static int davinci_i2c_probe(struct platform_device 
>> *pdev)
>>  goto err_unuse_clocks;
> 
> This goto is wrong now. There is no need to unwind the pm_runtime setup
> on a devm_ioremap_resource() failure. You can just return error here.

Ok
> 
>>  }
>>  
>> +pm_runtime_set_autosuspend_delay(dev->dev,
>> + DAVINCI_I2C_PM_TIMEOUT);
>> +pm_runtime_use_autosuspend(dev->dev);
>> +
>> +pm_runtime_enable(dev->dev);
>> +
>> +r = pm_runtime_get_sync(dev->dev);
>> +if (r < 0) {
>> +dev_err(dev->dev, "failed to runtime_get device: %d\n", r);
>> +goto err_unuse_clocks;
>> +}
>> +
>>  i2c_davinci_init(dev);
>>  
>>  r = devm_request_irq(>dev, dev->irq, i2c_davinci_isr, 0,
>> @@ -849,10 +879,16 @@ static int davinci_i2c_probe(struct platform_device 
>> *pdev)
>>  if (r)
>>  goto err_unuse_clocks;
>>  
>> +pm_runtime_mark_last_busy(dev->dev);
>> +pm_runtime_put_autosuspend(dev->dev);
>> +
>>  return 0;
>>  
>>  err_unuse_clocks:
>> -clk_disable_unprepare(dev->clk);
>> +pm_runtime_dont_use_autosuspend(dev->dev);
>> +pm_runtime_put_sync(dev->dev);
>> +pm_runtime_disable(dev->dev);
>> +
>>  dev->clk = NULL;
> 
> This null setting of clk seems quite bogus and can be cleaned-up.

Do you mean that I should just remove this line?
> 
>>  return r;
>>  }
> 
> Thanks,
> Sekhar
> 


Re: [PATCH v2 2/3] i2c: davinci: Add PM Runtime Support

2017-08-21 Thread Franklin S Cooper Jr


On 08/21/2017 04:05 AM, Sekhar Nori wrote:
> On Thursday 17 August 2017 03:47 AM, Franklin S Cooper Jr wrote:
> 
>> @@ -802,7 +821,6 @@ static int davinci_i2c_probe(struct platform_device 
>> *pdev)
>>  dev->clk = devm_clk_get(>dev, NULL);
>>  if (IS_ERR(dev->clk))
>>  return PTR_ERR(dev->clk);
>> -clk_prepare_enable(dev->clk);
>>  
>>  mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>>  dev->base = devm_ioremap_resource(>dev, mem);
>> @@ -811,6 +829,18 @@ static int davinci_i2c_probe(struct platform_device 
>> *pdev)
>>  goto err_unuse_clocks;
> 
> This goto is wrong now. There is no need to unwind the pm_runtime setup
> on a devm_ioremap_resource() failure. You can just return error here.

Ok
> 
>>  }
>>  
>> +pm_runtime_set_autosuspend_delay(dev->dev,
>> + DAVINCI_I2C_PM_TIMEOUT);
>> +pm_runtime_use_autosuspend(dev->dev);
>> +
>> +pm_runtime_enable(dev->dev);
>> +
>> +r = pm_runtime_get_sync(dev->dev);
>> +if (r < 0) {
>> +dev_err(dev->dev, "failed to runtime_get device: %d\n", r);
>> +goto err_unuse_clocks;
>> +}
>> +
>>  i2c_davinci_init(dev);
>>  
>>  r = devm_request_irq(>dev, dev->irq, i2c_davinci_isr, 0,
>> @@ -849,10 +879,16 @@ static int davinci_i2c_probe(struct platform_device 
>> *pdev)
>>  if (r)
>>  goto err_unuse_clocks;
>>  
>> +pm_runtime_mark_last_busy(dev->dev);
>> +pm_runtime_put_autosuspend(dev->dev);
>> +
>>  return 0;
>>  
>>  err_unuse_clocks:
>> -clk_disable_unprepare(dev->clk);
>> +pm_runtime_dont_use_autosuspend(dev->dev);
>> +pm_runtime_put_sync(dev->dev);
>> +pm_runtime_disable(dev->dev);
>> +
>>  dev->clk = NULL;
> 
> This null setting of clk seems quite bogus and can be cleaned-up.

Do you mean that I should just remove this line?
> 
>>  return r;
>>  }
> 
> Thanks,
> Sekhar
> 


Re: [PATCH v2 2/3] i2c: davinci: Add PM Runtime Support

2017-08-21 Thread Sekhar Nori
Hi Wolfram,

On Thursday 17 August 2017 09:54 PM, Wolfram Sang wrote:
> On Wed, Aug 16, 2017 at 05:17:14PM -0500, Franklin S Cooper Jr wrote:
>> 66AK2G has I2C instances that are not apart of the ALWAYS_ON power domain
>> like other Keystone 2 SoCs and OMAPL138. Therefore, pm_runtime
>> is required to insure the power domain used by the specific I2C instance is
>> properly turned on along with its functional clock.
>>
>> Signed-off-by: Franklin S Cooper Jr 
> 
> I'd need a review from the driver maintainers here. Which are Sekhar
> Nori and Kevin Hilman(?) according to MAINTAINERS. Is that still
> correct?

I just finished the review (sent the comments). Thanks for the reminder!

Also, tested the patches using i2cdetect and suspend/resume on OMAP-L138
LCDK board.

Regards,
Sekhar


Re: [PATCH v2 2/3] i2c: davinci: Add PM Runtime Support

2017-08-21 Thread Sekhar Nori
Hi Wolfram,

On Thursday 17 August 2017 09:54 PM, Wolfram Sang wrote:
> On Wed, Aug 16, 2017 at 05:17:14PM -0500, Franklin S Cooper Jr wrote:
>> 66AK2G has I2C instances that are not apart of the ALWAYS_ON power domain
>> like other Keystone 2 SoCs and OMAPL138. Therefore, pm_runtime
>> is required to insure the power domain used by the specific I2C instance is
>> properly turned on along with its functional clock.
>>
>> Signed-off-by: Franklin S Cooper Jr 
> 
> I'd need a review from the driver maintainers here. Which are Sekhar
> Nori and Kevin Hilman(?) according to MAINTAINERS. Is that still
> correct?

I just finished the review (sent the comments). Thanks for the reminder!

Also, tested the patches using i2cdetect and suspend/resume on OMAP-L138
LCDK board.

Regards,
Sekhar


Re: [PATCH v2 2/3] i2c: davinci: Add PM Runtime Support

2017-08-21 Thread Sekhar Nori
On Thursday 17 August 2017 03:47 AM, Franklin S Cooper Jr wrote:

> @@ -802,7 +821,6 @@ static int davinci_i2c_probe(struct platform_device *pdev)
>   dev->clk = devm_clk_get(>dev, NULL);
>   if (IS_ERR(dev->clk))
>   return PTR_ERR(dev->clk);
> - clk_prepare_enable(dev->clk);
>  
>   mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>   dev->base = devm_ioremap_resource(>dev, mem);
> @@ -811,6 +829,18 @@ static int davinci_i2c_probe(struct platform_device 
> *pdev)
>   goto err_unuse_clocks;

This goto is wrong now. There is no need to unwind the pm_runtime setup
on a devm_ioremap_resource() failure. You can just return error here.

>   }
>  
> + pm_runtime_set_autosuspend_delay(dev->dev,
> +  DAVINCI_I2C_PM_TIMEOUT);
> + pm_runtime_use_autosuspend(dev->dev);
> +
> + pm_runtime_enable(dev->dev);
> +
> + r = pm_runtime_get_sync(dev->dev);
> + if (r < 0) {
> + dev_err(dev->dev, "failed to runtime_get device: %d\n", r);
> + goto err_unuse_clocks;
> + }
> +
>   i2c_davinci_init(dev);
>  
>   r = devm_request_irq(>dev, dev->irq, i2c_davinci_isr, 0,
> @@ -849,10 +879,16 @@ static int davinci_i2c_probe(struct platform_device 
> *pdev)
>   if (r)
>   goto err_unuse_clocks;
>  
> + pm_runtime_mark_last_busy(dev->dev);
> + pm_runtime_put_autosuspend(dev->dev);
> +
>   return 0;
>  
>  err_unuse_clocks:
> - clk_disable_unprepare(dev->clk);
> + pm_runtime_dont_use_autosuspend(dev->dev);
> + pm_runtime_put_sync(dev->dev);
> + pm_runtime_disable(dev->dev);
> +
>   dev->clk = NULL;

This null setting of clk seems quite bogus and can be cleaned-up.

>   return r;
>  }

Thanks,
Sekhar


Re: [PATCH v2 2/3] i2c: davinci: Add PM Runtime Support

2017-08-21 Thread Sekhar Nori
On Thursday 17 August 2017 03:47 AM, Franklin S Cooper Jr wrote:

> @@ -802,7 +821,6 @@ static int davinci_i2c_probe(struct platform_device *pdev)
>   dev->clk = devm_clk_get(>dev, NULL);
>   if (IS_ERR(dev->clk))
>   return PTR_ERR(dev->clk);
> - clk_prepare_enable(dev->clk);
>  
>   mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>   dev->base = devm_ioremap_resource(>dev, mem);
> @@ -811,6 +829,18 @@ static int davinci_i2c_probe(struct platform_device 
> *pdev)
>   goto err_unuse_clocks;

This goto is wrong now. There is no need to unwind the pm_runtime setup
on a devm_ioremap_resource() failure. You can just return error here.

>   }
>  
> + pm_runtime_set_autosuspend_delay(dev->dev,
> +  DAVINCI_I2C_PM_TIMEOUT);
> + pm_runtime_use_autosuspend(dev->dev);
> +
> + pm_runtime_enable(dev->dev);
> +
> + r = pm_runtime_get_sync(dev->dev);
> + if (r < 0) {
> + dev_err(dev->dev, "failed to runtime_get device: %d\n", r);
> + goto err_unuse_clocks;
> + }
> +
>   i2c_davinci_init(dev);
>  
>   r = devm_request_irq(>dev, dev->irq, i2c_davinci_isr, 0,
> @@ -849,10 +879,16 @@ static int davinci_i2c_probe(struct platform_device 
> *pdev)
>   if (r)
>   goto err_unuse_clocks;
>  
> + pm_runtime_mark_last_busy(dev->dev);
> + pm_runtime_put_autosuspend(dev->dev);
> +
>   return 0;
>  
>  err_unuse_clocks:
> - clk_disable_unprepare(dev->clk);
> + pm_runtime_dont_use_autosuspend(dev->dev);
> + pm_runtime_put_sync(dev->dev);
> + pm_runtime_disable(dev->dev);
> +
>   dev->clk = NULL;

This null setting of clk seems quite bogus and can be cleaned-up.

>   return r;
>  }

Thanks,
Sekhar


Re: [PATCH v2 2/3] i2c: davinci: Add PM Runtime Support

2017-08-17 Thread Wolfram Sang
On Wed, Aug 16, 2017 at 05:17:14PM -0500, Franklin S Cooper Jr wrote:
> 66AK2G has I2C instances that are not apart of the ALWAYS_ON power domain
> like other Keystone 2 SoCs and OMAPL138. Therefore, pm_runtime
> is required to insure the power domain used by the specific I2C instance is
> properly turned on along with its functional clock.
> 
> Signed-off-by: Franklin S Cooper Jr 

I'd need a review from the driver maintainers here. Which are Sekhar
Nori and Kevin Hilman(?) according to MAINTAINERS. Is that still
correct?

> ---
> Version 2 changes:
> Move initial calls to pm runtime autosuspend before pm_runtime_enable
> 
>  drivers/i2c/busses/i2c-davinci.c | 62 
> ++--
>  1 file changed, 54 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-davinci.c 
> b/drivers/i2c/busses/i2c-davinci.c
> index b8c4353..6b1930d 100644
> --- a/drivers/i2c/busses/i2c-davinci.c
> +++ b/drivers/i2c/busses/i2c-davinci.c
> @@ -36,6 +36,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  /* - global defines --- */
>  
> @@ -122,6 +123,9 @@
>  /* set the SDA GPIO low */
>  #define DAVINCI_I2C_DCLR_PDCLR1  BIT(1)
>  
> +/* timeout for pm runtime autosuspend */
> +#define DAVINCI_I2C_PM_TIMEOUT   1000/* ms */
> +
>  struct davinci_i2c_dev {
>   struct device   *dev;
>   void __iomem*base;
> @@ -541,10 +545,17 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct 
> i2c_msg msgs[], int num)
>  
>   dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
>  
> + ret = pm_runtime_get_sync(dev->dev);
> + if (ret < 0) {
> + dev_err(dev->dev, "Failed to runtime_get device: %d\n", ret);
> + pm_runtime_put_noidle(dev->dev);
> + return ret;
> + }
> +
>   ret = i2c_davinci_wait_bus_not_busy(dev);
>   if (ret < 0) {
>   dev_warn(dev->dev, "timeout waiting for bus ready\n");
> - return ret;
> + goto out;
>   }
>  
>   for (i = 0; i < num; i++) {
> @@ -552,14 +563,19 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct 
> i2c_msg msgs[], int num)
>   dev_dbg(dev->dev, "%s [%d/%d] ret: %d\n", __func__, i + 1, num,
>   ret);
>   if (ret < 0)
> - return ret;
> + goto out;
>   }
>  
> + ret = num;
>  #ifdef CONFIG_CPU_FREQ
>   complete(>xfr_complete);
>  #endif
>  
> - return num;
> +out:
> + pm_runtime_mark_last_busy(dev->dev);
> + pm_runtime_put_autosuspend(dev->dev);
> +
> + return ret;
>  }
>  
>  static u32 i2c_davinci_func(struct i2c_adapter *adap)
> @@ -599,6 +615,9 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void 
> *dev_id)
>   int count = 0;
>   u16 w;
>  
> + if (pm_runtime_suspended(dev->dev))
> + return IRQ_NONE;
> +
>   while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) {
>   dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
>   if (count++ == 100) {
> @@ -802,7 +821,6 @@ static int davinci_i2c_probe(struct platform_device *pdev)
>   dev->clk = devm_clk_get(>dev, NULL);
>   if (IS_ERR(dev->clk))
>   return PTR_ERR(dev->clk);
> - clk_prepare_enable(dev->clk);
>  
>   mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>   dev->base = devm_ioremap_resource(>dev, mem);
> @@ -811,6 +829,18 @@ static int davinci_i2c_probe(struct platform_device 
> *pdev)
>   goto err_unuse_clocks;
>   }
>  
> + pm_runtime_set_autosuspend_delay(dev->dev,
> +  DAVINCI_I2C_PM_TIMEOUT);
> + pm_runtime_use_autosuspend(dev->dev);
> +
> + pm_runtime_enable(dev->dev);
> +
> + r = pm_runtime_get_sync(dev->dev);
> + if (r < 0) {
> + dev_err(dev->dev, "failed to runtime_get device: %d\n", r);
> + goto err_unuse_clocks;
> + }
> +
>   i2c_davinci_init(dev);
>  
>   r = devm_request_irq(>dev, dev->irq, i2c_davinci_isr, 0,
> @@ -849,10 +879,16 @@ static int davinci_i2c_probe(struct platform_device 
> *pdev)
>   if (r)
>   goto err_unuse_clocks;
>  
> + pm_runtime_mark_last_busy(dev->dev);
> + pm_runtime_put_autosuspend(dev->dev);
> +
>   return 0;
>  
>  err_unuse_clocks:
> - clk_disable_unprepare(dev->clk);
> + pm_runtime_dont_use_autosuspend(dev->dev);
> + pm_runtime_put_sync(dev->dev);
> + pm_runtime_disable(dev->dev);
> +
>   dev->clk = NULL;
>   return r;
>  }
> @@ -860,16 +896,26 @@ static int davinci_i2c_probe(struct platform_device 
> *pdev)
>  static int davinci_i2c_remove(struct platform_device *pdev)
>  {
>   struct davinci_i2c_dev *dev = platform_get_drvdata(pdev);
> + int ret;
>  
>   i2c_davinci_cpufreq_deregister(dev);
>  
>   i2c_del_adapter(>adapter);
>  
> - 

Re: [PATCH v2 2/3] i2c: davinci: Add PM Runtime Support

2017-08-17 Thread Wolfram Sang
On Wed, Aug 16, 2017 at 05:17:14PM -0500, Franklin S Cooper Jr wrote:
> 66AK2G has I2C instances that are not apart of the ALWAYS_ON power domain
> like other Keystone 2 SoCs and OMAPL138. Therefore, pm_runtime
> is required to insure the power domain used by the specific I2C instance is
> properly turned on along with its functional clock.
> 
> Signed-off-by: Franklin S Cooper Jr 

I'd need a review from the driver maintainers here. Which are Sekhar
Nori and Kevin Hilman(?) according to MAINTAINERS. Is that still
correct?

> ---
> Version 2 changes:
> Move initial calls to pm runtime autosuspend before pm_runtime_enable
> 
>  drivers/i2c/busses/i2c-davinci.c | 62 
> ++--
>  1 file changed, 54 insertions(+), 8 deletions(-)
> 
> diff --git a/drivers/i2c/busses/i2c-davinci.c 
> b/drivers/i2c/busses/i2c-davinci.c
> index b8c4353..6b1930d 100644
> --- a/drivers/i2c/busses/i2c-davinci.c
> +++ b/drivers/i2c/busses/i2c-davinci.c
> @@ -36,6 +36,7 @@
>  #include 
>  #include 
>  #include 
> +#include 
>  
>  /* - global defines --- */
>  
> @@ -122,6 +123,9 @@
>  /* set the SDA GPIO low */
>  #define DAVINCI_I2C_DCLR_PDCLR1  BIT(1)
>  
> +/* timeout for pm runtime autosuspend */
> +#define DAVINCI_I2C_PM_TIMEOUT   1000/* ms */
> +
>  struct davinci_i2c_dev {
>   struct device   *dev;
>   void __iomem*base;
> @@ -541,10 +545,17 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct 
> i2c_msg msgs[], int num)
>  
>   dev_dbg(dev->dev, "%s: msgs: %d\n", __func__, num);
>  
> + ret = pm_runtime_get_sync(dev->dev);
> + if (ret < 0) {
> + dev_err(dev->dev, "Failed to runtime_get device: %d\n", ret);
> + pm_runtime_put_noidle(dev->dev);
> + return ret;
> + }
> +
>   ret = i2c_davinci_wait_bus_not_busy(dev);
>   if (ret < 0) {
>   dev_warn(dev->dev, "timeout waiting for bus ready\n");
> - return ret;
> + goto out;
>   }
>  
>   for (i = 0; i < num; i++) {
> @@ -552,14 +563,19 @@ i2c_davinci_xfer(struct i2c_adapter *adap, struct 
> i2c_msg msgs[], int num)
>   dev_dbg(dev->dev, "%s [%d/%d] ret: %d\n", __func__, i + 1, num,
>   ret);
>   if (ret < 0)
> - return ret;
> + goto out;
>   }
>  
> + ret = num;
>  #ifdef CONFIG_CPU_FREQ
>   complete(>xfr_complete);
>  #endif
>  
> - return num;
> +out:
> + pm_runtime_mark_last_busy(dev->dev);
> + pm_runtime_put_autosuspend(dev->dev);
> +
> + return ret;
>  }
>  
>  static u32 i2c_davinci_func(struct i2c_adapter *adap)
> @@ -599,6 +615,9 @@ static irqreturn_t i2c_davinci_isr(int this_irq, void 
> *dev_id)
>   int count = 0;
>   u16 w;
>  
> + if (pm_runtime_suspended(dev->dev))
> + return IRQ_NONE;
> +
>   while ((stat = davinci_i2c_read_reg(dev, DAVINCI_I2C_IVR_REG))) {
>   dev_dbg(dev->dev, "%s: stat=0x%x\n", __func__, stat);
>   if (count++ == 100) {
> @@ -802,7 +821,6 @@ static int davinci_i2c_probe(struct platform_device *pdev)
>   dev->clk = devm_clk_get(>dev, NULL);
>   if (IS_ERR(dev->clk))
>   return PTR_ERR(dev->clk);
> - clk_prepare_enable(dev->clk);
>  
>   mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
>   dev->base = devm_ioremap_resource(>dev, mem);
> @@ -811,6 +829,18 @@ static int davinci_i2c_probe(struct platform_device 
> *pdev)
>   goto err_unuse_clocks;
>   }
>  
> + pm_runtime_set_autosuspend_delay(dev->dev,
> +  DAVINCI_I2C_PM_TIMEOUT);
> + pm_runtime_use_autosuspend(dev->dev);
> +
> + pm_runtime_enable(dev->dev);
> +
> + r = pm_runtime_get_sync(dev->dev);
> + if (r < 0) {
> + dev_err(dev->dev, "failed to runtime_get device: %d\n", r);
> + goto err_unuse_clocks;
> + }
> +
>   i2c_davinci_init(dev);
>  
>   r = devm_request_irq(>dev, dev->irq, i2c_davinci_isr, 0,
> @@ -849,10 +879,16 @@ static int davinci_i2c_probe(struct platform_device 
> *pdev)
>   if (r)
>   goto err_unuse_clocks;
>  
> + pm_runtime_mark_last_busy(dev->dev);
> + pm_runtime_put_autosuspend(dev->dev);
> +
>   return 0;
>  
>  err_unuse_clocks:
> - clk_disable_unprepare(dev->clk);
> + pm_runtime_dont_use_autosuspend(dev->dev);
> + pm_runtime_put_sync(dev->dev);
> + pm_runtime_disable(dev->dev);
> +
>   dev->clk = NULL;
>   return r;
>  }
> @@ -860,16 +896,26 @@ static int davinci_i2c_probe(struct platform_device 
> *pdev)
>  static int davinci_i2c_remove(struct platform_device *pdev)
>  {
>   struct davinci_i2c_dev *dev = platform_get_drvdata(pdev);
> + int ret;
>  
>   i2c_davinci_cpufreq_deregister(dev);
>  
>   i2c_del_adapter(>adapter);
>  
> - clk_disable_unprepare(dev->clk);
> + ret =