From: Rabin Vincent <rabin.vincent@xxxxxxxxxxxxxx> Use the pm_runtime API for pins control. Signed-off-by: Rabin Vincent <rabin.vincent@xxxxxxxxxxxxxx> Reviewed-by: Srinidhi Kasagar <srinidhi.kasagar@xxxxxxxxxxxxxx> Reviewed-by: Jonas Aberg <jonas.aberg@xxxxxxxxxxxxxx> Signed-off-by: Linus Walleij <linus.walleij@xxxxxxxxxx> --- drivers/i2c/busses/i2c-nomadik.c | 51 +++++++++++++++++++++++++++++++++---- 1 files changed, 45 insertions(+), 6 deletions(-) diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index c8bf81a..f3a0af0 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c @@ -23,6 +23,7 @@ #include <linux/clk.h> #include <linux/io.h> #include <linux/regulator/consumer.h> +#include <linux/pm_runtime.h> #include <plat/i2c.h> @@ -576,6 +577,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, if (dev->regulator) regulator_enable(dev->regulator); + pm_runtime_get_sync(&dev->pdev->dev); status = init_hw(dev); if (status) @@ -634,6 +636,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, out: clk_disable(dev->clk); out2: + pm_runtime_put_sync(&dev->pdev->dev); if (dev->regulator) regulator_disable(dev->regulator); @@ -839,19 +842,50 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) #ifdef CONFIG_PM -static int nmk_i2c_suspend(struct platform_device *pdev, pm_message_t mesg) +static int nmk_i2c_suspend(struct device *dev) { - struct nmk_i2c_dev *dev = platform_get_drvdata(pdev); + struct platform_device *pdev = to_platform_device(dev); + struct nmk_i2c_dev *nmk_i2c = platform_get_drvdata(pdev); - if (dev->busy) + if (nmk_i2c->busy) return -EBUSY; - else - return 0; + + /* + * During system suspend, runtime suspend transitions are disabled. + * This check and direct call are here so that even if some driver + * performs i2c transactions in its suspend rountine, we would properly + * runtime suspend the i2c driver. + */ + if (!pm_runtime_suspended(dev)) + if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_suspend) + dev->bus->pm->runtime_suspend(dev); + + return 0; +} + +static int nmk_i2c_resume(struct device *dev) +{ + if (!pm_runtime_suspended(dev)) + if (dev->bus && dev->bus->pm && dev->bus->pm->runtime_resume) + dev->bus->pm->runtime_resume(dev); + + return 0; } #else #define nmk_i2c_suspend NULL +#define nmk_i2c_resume NULL #endif +/* + * We use noirq so that we suspend late and resume before the wakeup interrupt + * to ensure that we do the !pm_runtime_suspended() check in resume before + * there has been a regular pm runtime resume (via pm_runtime_get_sync()). + */ +static const struct dev_pm_ops nmk_i2c_pm = { + .suspend_noirq = nmk_i2c_suspend, + .resume_noirq = nmk_i2c_resume, +}; + static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) { return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; @@ -913,6 +947,9 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) dev->regulator = NULL; } + pm_suspend_ignore_children(&pdev->dev, true); + pm_runtime_enable(&pdev->dev); + dev->clk = clk_get(&pdev->dev, NULL); if (IS_ERR(dev->clk)) { dev_err(&pdev->dev, "could not get i2c clock\n"); @@ -958,6 +995,7 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) err_no_clk: if (dev->regulator) regulator_put(dev->regulator); + pm_runtime_disable(&pdev->dev); free_irq(dev->irq, dev); err_irq: iounmap(dev->virtbase); @@ -990,6 +1028,7 @@ static int __devexit nmk_i2c_remove(struct platform_device *pdev) clk_put(dev->clk); if (dev->regulator) regulator_put(dev->regulator); + pm_runtime_disable(&pdev->dev); platform_set_drvdata(pdev, NULL); kfree(dev); @@ -1000,10 +1039,10 @@ static struct platform_driver nmk_i2c_driver = { .driver = { .owner = THIS_MODULE, .name = DRIVER_NAME, + .pm = &nmk_i2c_pm, }, .probe = nmk_i2c_probe, .remove = __devexit_p(nmk_i2c_remove), - .suspend = nmk_i2c_suspend, }; static int __init nmk_i2c_init(void) -- 1.7.5.1 -- To unsubscribe from this list: send the line "unsubscribe linux-i2c" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html