upload tizen1.0 source
[kernel/linux-2.6.36.git] / arch / arm / plat-samsung / pd.c
1 /* linux/arch/arm/plat-samsung/pd.c
2  *
3  * Copyright (c) 2010 Samsung Electronics Co., Ltd.
4  *              http://www.samsung.com
5  *
6  * Samsung Power domain support
7  *
8  * This program is free software; you can redistribute it and/or modify
9  * it under the terms of the GNU General Public License version 2 as
10  * published by the Free Software Foundation.
11 */
12
13 #include <linux/init.h>
14 #include <linux/module.h>
15 #include <linux/platform_device.h>
16 #include <linux/err.h>
17 #include <linux/pm_runtime.h>
18
19 #include <plat/pd.h>
20
21 static int samsung_pd_probe(struct platform_device *pdev)
22 {
23         struct samsung_pd_info *pdata = pdev->dev.platform_data;
24         struct device *dev = &pdev->dev;
25         int ret;
26
27         if (!pdata) {
28                 dev_err(dev, "no device data specified\n");
29                 return -ENOENT;
30         }
31
32         if (pdata->init) {
33                 ret = pdata->init(dev);
34                 if (ret) {
35                         dev_err(dev, "init fails");
36                         return ret;
37                 }
38         }
39
40         /*
41          * boot_on means that this powerdomain should NOT be turned off
42          * until the user explicitly says so by executing get and then put
43          * By setting set_suspended, this power-domain is NOT
44          * turned off until a driver actually gets it.
45          */
46         if (pdata->boot_on)
47                 pm_runtime_set_suspended(dev);
48         else
49                 pm_runtime_set_active(dev);
50         pm_runtime_enable(dev);
51
52         dev_info(dev, "power domain registered\n");
53         return 0;
54 }
55
56 static int __devexit samsung_pd_remove(struct platform_device *pdev)
57 {
58         struct device *dev = &pdev->dev;
59
60         pm_runtime_disable(dev);
61         return 0;
62 }
63
64 static int samsung_pd_runtime_suspend(struct device *dev)
65 {
66         struct samsung_pd_info *pdata = dev->platform_data;
67         int ret = 0;
68
69         if (pdata->disable)
70                 ret = pdata->disable(dev);
71
72         dev_dbg(dev, "suspended\n");
73         return ret;
74 }
75
76 static int samsung_pd_runtime_resume(struct device *dev)
77 {
78         struct samsung_pd_info *pdata = dev->platform_data;
79         int ret = 0;
80
81         if (pdata->enable)
82                 ret = pdata->enable(dev);
83
84         dev_dbg(dev, "resumed\n");
85         return ret;
86 }
87
88 #ifdef CONFIG_PM
89 static int samsung_pd_suspend(struct device *dev)
90 {
91         /*
92          * Do nothing.
93          * Do not turn it off if there is possibility that
94          * some driver is still using the power-domain at
95          * suspend routines
96          */
97         return 0;
98 }
99
100 static int samsung_pd_resume(struct device *dev)
101 {
102         int ret;
103
104         ret = samsung_pd_runtime_resume(dev);
105         /*
106          * Bring the device to full powered state upon resume
107          * and update the runtime PM status as recommended
108          * in Documentation/power/runtime_pm.txt.
109          */
110         if (!ret) {
111                 pm_runtime_disable(dev);
112                 pm_runtime_set_active(dev);
113                 pm_runtime_enable(dev);
114         }
115         return ret;
116 }
117 #else
118 #define samsung_pd_resume NULL
119 #define samsung_pd_suspend NULL
120 #endif
121
122 static const struct dev_pm_ops samsung_pd_pm_ops = {
123         .runtime_suspend        = samsung_pd_runtime_suspend,
124         .runtime_resume         = samsung_pd_runtime_resume,
125         .suspend                = samsung_pd_suspend,
126         .resume                 = samsung_pd_resume,
127 };
128
129 static struct platform_driver samsung_pd_driver = {
130         .driver         = {
131                 .name           = "samsung-pd",
132                 .owner          = THIS_MODULE,
133                 .pm             = &samsung_pd_pm_ops,
134         },
135         .probe          = samsung_pd_probe,
136         .remove         = __devexit_p(samsung_pd_remove),
137 };
138
139 static int __init samsung_pd_init(void)
140 {
141         int ret;
142
143         ret = platform_driver_register(&samsung_pd_driver);
144         if (ret)
145                 printk(KERN_ERR "%s: failed to add PD driver\n", __func__);
146
147         return ret;
148 }
149 arch_initcall(samsung_pd_init);