diff options
| -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) |
