diff options
Diffstat (limited to 'drivers/i2c')
-rw-r--r-- | drivers/i2c/busses/i2c-nomadik.c | 37 |
1 files changed, 31 insertions, 6 deletions
diff --git a/drivers/i2c/busses/i2c-nomadik.c b/drivers/i2c/busses/i2c-nomadik.c index c8bf81abcd3c..234e4a9070b8 100644 --- a/drivers/i2c/busses/i2c-nomadik.c +++ b/drivers/i2c/busses/i2c-nomadik.c | |||
@@ -23,6 +23,7 @@ | |||
23 | #include <linux/clk.h> | 23 | #include <linux/clk.h> |
24 | #include <linux/io.h> | 24 | #include <linux/io.h> |
25 | #include <linux/regulator/consumer.h> | 25 | #include <linux/regulator/consumer.h> |
26 | #include <linux/pm_runtime.h> | ||
26 | 27 | ||
27 | #include <plat/i2c.h> | 28 | #include <plat/i2c.h> |
28 | 29 | ||
@@ -576,6 +577,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
576 | 577 | ||
577 | if (dev->regulator) | 578 | if (dev->regulator) |
578 | regulator_enable(dev->regulator); | 579 | regulator_enable(dev->regulator); |
580 | pm_runtime_get_sync(&dev->pdev->dev); | ||
579 | 581 | ||
580 | status = init_hw(dev); | 582 | status = init_hw(dev); |
581 | if (status) | 583 | if (status) |
@@ -634,6 +636,7 @@ static int nmk_i2c_xfer(struct i2c_adapter *i2c_adap, | |||
634 | out: | 636 | out: |
635 | clk_disable(dev->clk); | 637 | clk_disable(dev->clk); |
636 | out2: | 638 | out2: |
639 | pm_runtime_put_sync(&dev->pdev->dev); | ||
637 | if (dev->regulator) | 640 | if (dev->regulator) |
638 | regulator_disable(dev->regulator); | 641 | regulator_disable(dev->regulator); |
639 | 642 | ||
@@ -839,19 +842,36 @@ static irqreturn_t i2c_irq_handler(int irq, void *arg) | |||
839 | 842 | ||
840 | 843 | ||
841 | #ifdef CONFIG_PM | 844 | #ifdef CONFIG_PM |
842 | static int nmk_i2c_suspend(struct platform_device *pdev, pm_message_t mesg) | 845 | static int nmk_i2c_suspend(struct device *dev) |
843 | { | 846 | { |
844 | struct nmk_i2c_dev *dev = platform_get_drvdata(pdev); | 847 | struct platform_device *pdev = to_platform_device(dev); |
848 | struct nmk_i2c_dev *nmk_i2c = platform_get_drvdata(pdev); | ||
845 | 849 | ||
846 | if (dev->busy) | 850 | if (nmk_i2c->busy) |
847 | return -EBUSY; | 851 | return -EBUSY; |
848 | else | 852 | |
849 | return 0; | 853 | return 0; |
854 | } | ||
855 | |||
856 | static int nmk_i2c_resume(struct device *dev) | ||
857 | { | ||
858 | return 0; | ||
850 | } | 859 | } |
851 | #else | 860 | #else |
852 | #define nmk_i2c_suspend NULL | 861 | #define nmk_i2c_suspend NULL |
862 | #define nmk_i2c_resume NULL | ||
853 | #endif | 863 | #endif |
854 | 864 | ||
865 | /* | ||
866 | * We use noirq so that we suspend late and resume before the wakeup interrupt | ||
867 | * to ensure that we do the !pm_runtime_suspended() check in resume before | ||
868 | * there has been a regular pm runtime resume (via pm_runtime_get_sync()). | ||
869 | */ | ||
870 | static const struct dev_pm_ops nmk_i2c_pm = { | ||
871 | .suspend_noirq = nmk_i2c_suspend, | ||
872 | .resume_noirq = nmk_i2c_resume, | ||
873 | }; | ||
874 | |||
855 | static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) | 875 | static unsigned int nmk_i2c_functionality(struct i2c_adapter *adap) |
856 | { | 876 | { |
857 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; | 877 | return I2C_FUNC_I2C | I2C_FUNC_SMBUS_EMUL; |
@@ -913,6 +933,9 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) | |||
913 | dev->regulator = NULL; | 933 | dev->regulator = NULL; |
914 | } | 934 | } |
915 | 935 | ||
936 | pm_suspend_ignore_children(&pdev->dev, true); | ||
937 | pm_runtime_enable(&pdev->dev); | ||
938 | |||
916 | dev->clk = clk_get(&pdev->dev, NULL); | 939 | dev->clk = clk_get(&pdev->dev, NULL); |
917 | if (IS_ERR(dev->clk)) { | 940 | if (IS_ERR(dev->clk)) { |
918 | dev_err(&pdev->dev, "could not get i2c clock\n"); | 941 | dev_err(&pdev->dev, "could not get i2c clock\n"); |
@@ -958,6 +981,7 @@ static int __devinit nmk_i2c_probe(struct platform_device *pdev) | |||
958 | err_no_clk: | 981 | err_no_clk: |
959 | if (dev->regulator) | 982 | if (dev->regulator) |
960 | regulator_put(dev->regulator); | 983 | regulator_put(dev->regulator); |
984 | pm_runtime_disable(&pdev->dev); | ||
961 | free_irq(dev->irq, dev); | 985 | free_irq(dev->irq, dev); |
962 | err_irq: | 986 | err_irq: |
963 | iounmap(dev->virtbase); | 987 | iounmap(dev->virtbase); |
@@ -990,6 +1014,7 @@ static int __devexit nmk_i2c_remove(struct platform_device *pdev) | |||
990 | clk_put(dev->clk); | 1014 | clk_put(dev->clk); |
991 | if (dev->regulator) | 1015 | if (dev->regulator) |
992 | regulator_put(dev->regulator); | 1016 | regulator_put(dev->regulator); |
1017 | pm_runtime_disable(&pdev->dev); | ||
993 | platform_set_drvdata(pdev, NULL); | 1018 | platform_set_drvdata(pdev, NULL); |
994 | kfree(dev); | 1019 | kfree(dev); |
995 | 1020 | ||
@@ -1000,10 +1025,10 @@ static struct platform_driver nmk_i2c_driver = { | |||
1000 | .driver = { | 1025 | .driver = { |
1001 | .owner = THIS_MODULE, | 1026 | .owner = THIS_MODULE, |
1002 | .name = DRIVER_NAME, | 1027 | .name = DRIVER_NAME, |
1028 | .pm = &nmk_i2c_pm, | ||
1003 | }, | 1029 | }, |
1004 | .probe = nmk_i2c_probe, | 1030 | .probe = nmk_i2c_probe, |
1005 | .remove = __devexit_p(nmk_i2c_remove), | 1031 | .remove = __devexit_p(nmk_i2c_remove), |
1006 | .suspend = nmk_i2c_suspend, | ||
1007 | }; | 1032 | }; |
1008 | 1033 | ||
1009 | static int __init nmk_i2c_init(void) | 1034 | static int __init nmk_i2c_init(void) |