Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

i2c: Runtime PM for SuperH Mobile I2C

This patch modifies the SuperH Mobile I2C driver to support
Runtime PM. These changes is all that is needed for proper
Runtime PM support in this driver. Driver callbacks for
Runtime PM are empty because the device registers are always
re-initialized after pm_runtime_get_sync().

Signed-off-by: Magnus Damm <damm@igel.co.jp>
Signed-off-by: Paul Mundt <lethal@linux-sh.org>

authored by

Magnus Damm and committed by
Paul Mundt
f1a3b994 6a93dde1

+37 -2
+37 -2
drivers/i2c/busses/i2c-sh_mobile.c
··· 28 28 #include <linux/interrupt.h> 29 29 #include <linux/i2c.h> 30 30 #include <linux/err.h> 31 + #include <linux/pm_runtime.h> 31 32 #include <linux/clk.h> 32 33 #include <linux/io.h> 33 34 ··· 166 165 u_int32_t denom; 167 166 u_int32_t tmp; 168 167 169 - /* Make sure the clock is enabled */ 168 + /* Wake up device and enable clock */ 169 + pm_runtime_get_sync(pd->dev); 170 170 clk_enable(pd->clk); 171 171 172 172 /* Get clock rate after clock is enabled */ ··· 215 213 /* Disable channel */ 216 214 iowrite8(ioread8(ICCR(pd)) & ~ICCR_ICE, ICCR(pd)); 217 215 218 - /* Disable clock */ 216 + /* Disable clock and mark device as idle */ 219 217 clk_disable(pd->clk); 218 + pm_runtime_put_sync(pd->dev); 220 219 } 221 220 222 221 static unsigned char i2c_op(struct sh_mobile_i2c_data *pd, ··· 575 572 goto err_irq; 576 573 } 577 574 575 + /* Enable Runtime PM for this device. 576 + * 577 + * Also tell the Runtime PM core to ignore children 578 + * for this device since it is valid for us to suspend 579 + * this I2C master driver even though the slave devices 580 + * on the I2C bus may not be suspended. 581 + * 582 + * The state of the I2C hardware bus is unaffected by 583 + * the Runtime PM state. 584 + */ 585 + pm_suspend_ignore_children(&dev->dev, true); 586 + pm_runtime_enable(&dev->dev); 587 + 578 588 /* setup the private data */ 579 589 adap = &pd->adap; 580 590 i2c_set_adapdata(adap, pd); ··· 630 614 iounmap(pd->reg); 631 615 sh_mobile_i2c_hook_irqs(dev, 0); 632 616 clk_put(pd->clk); 617 + pm_runtime_disable(&dev->dev); 633 618 kfree(pd); 634 619 return 0; 635 620 } 621 + 622 + static int sh_mobile_i2c_runtime_nop(struct device *dev) 623 + { 624 + /* Runtime PM callback shared between ->runtime_suspend() 625 + * and ->runtime_resume(). Simply returns success. 626 + * 627 + * This driver re-initializes all registers after 628 + * pm_runtime_get_sync() anyway so there is no need 629 + * to save and restore registers here. 630 + */ 631 + return 0; 632 + } 633 + 634 + static struct dev_pm_ops sh_mobile_i2c_dev_pm_ops = { 635 + .runtime_suspend = sh_mobile_i2c_runtime_nop, 636 + .runtime_resume = sh_mobile_i2c_runtime_nop, 637 + }; 636 638 637 639 static struct platform_driver sh_mobile_i2c_driver = { 638 640 .driver = { 639 641 .name = "i2c-sh_mobile", 640 642 .owner = THIS_MODULE, 643 + .pm = &sh_mobile_i2c_dev_pm_ops, 641 644 }, 642 645 .probe = sh_mobile_i2c_probe, 643 646 .remove = sh_mobile_i2c_remove,