Merge branch 'core-iommu-for-linus' of git://git.kernel.org/pub/scm/linux/kernel...
[pandora-kernel.git] / arch / sh / kernel / cpu / shmobile / pm_runtime.c
1 /*
2  * arch/sh/kernel/cpu/shmobile/pm_runtime.c
3  *
4  * Runtime PM support code for SuperH Mobile
5  *
6  *  Copyright (C) 2009 Magnus Damm
7  *
8  * This file is subject to the terms and conditions of the GNU General Public
9  * License.  See the file "COPYING" in the main directory of this archive
10  * for more details.
11  */
12 #include <linux/init.h>
13 #include <linux/kernel.h>
14 #include <linux/io.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/platform_device.h>
17 #include <linux/mutex.h>
18 #include <asm/hwblk.h>
19
20 static DEFINE_SPINLOCK(hwblk_lock);
21 static LIST_HEAD(hwblk_idle_list);
22 static struct work_struct hwblk_work;
23
24 extern struct hwblk_info *hwblk_info;
25
26 static void platform_pm_runtime_not_idle(struct platform_device *pdev)
27 {
28         unsigned long flags;
29
30         /* remove device from idle list */
31         spin_lock_irqsave(&hwblk_lock, flags);
32         if (test_bit(PDEV_ARCHDATA_FLAG_IDLE, &pdev->archdata.flags)) {
33                 list_del(&pdev->archdata.entry);
34                 __clear_bit(PDEV_ARCHDATA_FLAG_IDLE, &pdev->archdata.flags);
35         }
36         spin_unlock_irqrestore(&hwblk_lock, flags);
37 }
38
39 static int __platform_pm_runtime_resume(struct platform_device *pdev)
40 {
41         struct device *d = &pdev->dev;
42         struct pdev_archdata *ad = &pdev->archdata;
43         int hwblk = ad->hwblk_id;
44         int ret = -ENOSYS;
45
46         dev_dbg(d, "__platform_pm_runtime_resume() [%d]\n", hwblk);
47
48         if (d->driver) {
49                 hwblk_enable(hwblk_info, hwblk);
50                 ret = 0;
51
52                 if (test_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags)) {
53                         if (d->driver->pm && d->driver->pm->runtime_resume)
54                                 ret = d->driver->pm->runtime_resume(d);
55
56                         if (!ret)
57                                 clear_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags);
58                         else
59                                 hwblk_disable(hwblk_info, hwblk);
60                 }
61         }
62
63         dev_dbg(d, "__platform_pm_runtime_resume() [%d] - returns %d\n",
64                 hwblk, ret);
65
66         return ret;
67 }
68
69 static int __platform_pm_runtime_suspend(struct platform_device *pdev)
70 {
71         struct device *d = &pdev->dev;
72         struct pdev_archdata *ad = &pdev->archdata;
73         int hwblk = ad->hwblk_id;
74         int ret = -ENOSYS;
75
76         dev_dbg(d, "__platform_pm_runtime_suspend() [%d]\n", hwblk);
77
78         if (d->driver) {
79                 BUG_ON(!test_bit(PDEV_ARCHDATA_FLAG_IDLE, &ad->flags));
80                 ret = 0;
81
82                 if (d->driver->pm && d->driver->pm->runtime_suspend) {
83                         hwblk_enable(hwblk_info, hwblk);
84                         ret = d->driver->pm->runtime_suspend(d);
85                         hwblk_disable(hwblk_info, hwblk);
86                 }
87
88                 if (!ret) {
89                         set_bit(PDEV_ARCHDATA_FLAG_SUSP, &ad->flags);
90                         platform_pm_runtime_not_idle(pdev);
91                         hwblk_cnt_dec(hwblk_info, hwblk, HWBLK_CNT_IDLE);
92                 }
93         }
94
95         dev_dbg(d, "__platform_pm_runtime_suspend() [%d] - returns %d\n",
96                 hwblk, ret);
97
98         return ret;
99 }
100
101 static void platform_pm_runtime_work(struct work_struct *work)
102 {
103         struct platform_device *pdev;
104         unsigned long flags;
105         int ret;
106
107         /* go through the idle list and suspend one device at a time */
108         do {
109                 spin_lock_irqsave(&hwblk_lock, flags);
110                 if (list_empty(&hwblk_idle_list))
111                         pdev = NULL;
112                 else
113                         pdev = list_first_entry(&hwblk_idle_list,
114                                                 struct platform_device,
115                                                 archdata.entry);
116                 spin_unlock_irqrestore(&hwblk_lock, flags);
117
118                 if (pdev) {
119                         mutex_lock(&pdev->archdata.mutex);
120                         ret = __platform_pm_runtime_suspend(pdev);
121
122                         /* at this point the platform device may be:
123                          * suspended: ret = 0, FLAG_SUSP set, clock stopped
124                          * failed: ret < 0, FLAG_IDLE set, clock stopped
125                          */
126                         mutex_unlock(&pdev->archdata.mutex);
127                 } else {
128                         ret = -ENODEV;
129                 }
130         } while (!ret);
131 }
132
133 /* this function gets called from cpuidle context when all devices in the
134  * main power domain are unused but some are counted as idle, ie the hwblk
135  * counter values are (HWBLK_CNT_USAGE == 0) && (HWBLK_CNT_IDLE != 0)
136  */
137 void platform_pm_runtime_suspend_idle(void)
138 {
139         queue_work(pm_wq, &hwblk_work);
140 }
141
142 static int default_platform_runtime_suspend(struct device *dev)
143 {
144         struct platform_device *pdev = to_platform_device(dev);
145         struct pdev_archdata *ad = &pdev->archdata;
146         unsigned long flags;
147         int hwblk = ad->hwblk_id;
148         int ret = 0;
149
150         dev_dbg(dev, "%s() [%d]\n", __func__, hwblk);
151
152         /* ignore off-chip platform devices */
153         if (!hwblk)
154                 goto out;
155
156         /* interrupt context not allowed */
157         might_sleep();
158
159         /* catch misconfigured drivers not starting with resume */
160         if (test_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags)) {
161                 ret = -EINVAL;
162                 goto out;
163         }
164
165         /* serialize */
166         mutex_lock(&ad->mutex);
167
168         /* disable clock */
169         hwblk_disable(hwblk_info, hwblk);
170
171         /* put device on idle list */
172         spin_lock_irqsave(&hwblk_lock, flags);
173         list_add_tail(&pdev->archdata.entry, &hwblk_idle_list);
174         __set_bit(PDEV_ARCHDATA_FLAG_IDLE, &pdev->archdata.flags);
175         spin_unlock_irqrestore(&hwblk_lock, flags);
176
177         /* increase idle count */
178         hwblk_cnt_inc(hwblk_info, hwblk, HWBLK_CNT_IDLE);
179
180         /* at this point the platform device is:
181          * idle: ret = 0, FLAG_IDLE set, clock stopped
182          */
183         mutex_unlock(&ad->mutex);
184
185 out:
186         dev_dbg(dev, "%s() [%d] returns %d\n",
187                  __func__, hwblk, ret);
188
189         return ret;
190 }
191
192 static int default_platform_runtime_resume(struct device *dev)
193 {
194         struct platform_device *pdev = to_platform_device(dev);
195         struct pdev_archdata *ad = &pdev->archdata;
196         int hwblk = ad->hwblk_id;
197         int ret = 0;
198
199         dev_dbg(dev, "%s() [%d]\n", __func__, hwblk);
200
201         /* ignore off-chip platform devices */
202         if (!hwblk)
203                 goto out;
204
205         /* interrupt context not allowed */
206         might_sleep();
207
208         /* serialize */
209         mutex_lock(&ad->mutex);
210
211         /* make sure device is removed from idle list */
212         platform_pm_runtime_not_idle(pdev);
213
214         /* decrease idle count */
215         if (!test_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags) &&
216             !test_bit(PDEV_ARCHDATA_FLAG_SUSP, &pdev->archdata.flags))
217                 hwblk_cnt_dec(hwblk_info, hwblk, HWBLK_CNT_IDLE);
218
219         /* resume the device if needed */
220         ret = __platform_pm_runtime_resume(pdev);
221
222         /* the driver has been initialized now, so clear the init flag */
223         clear_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
224
225         /* at this point the platform device may be:
226          * resumed: ret = 0, flags = 0, clock started
227          * failed: ret < 0, FLAG_SUSP set, clock stopped
228          */
229         mutex_unlock(&ad->mutex);
230 out:
231         dev_dbg(dev, "%s() [%d] returns %d\n",
232                 __func__, hwblk, ret);
233
234         return ret;
235 }
236
237 static int default_platform_runtime_idle(struct device *dev)
238 {
239         struct platform_device *pdev = to_platform_device(dev);
240         int hwblk = pdev->archdata.hwblk_id;
241         int ret = 0;
242
243         dev_dbg(dev, "%s() [%d]\n", __func__, hwblk);
244
245         /* ignore off-chip platform devices */
246         if (!hwblk)
247                 goto out;
248
249         /* interrupt context not allowed, use pm_runtime_put()! */
250         might_sleep();
251
252         /* suspend synchronously to disable clocks immediately */
253         ret = pm_runtime_suspend(dev);
254 out:
255         dev_dbg(dev, "%s() [%d] done!\n", __func__, hwblk);
256         return ret;
257 }
258
259 static struct dev_power_domain default_power_domain = {
260         .ops = {
261                 .runtime_suspend = default_platform_runtime_suspend,
262                 .runtime_resume = default_platform_runtime_resume,
263                 .runtime_idle = default_platform_runtime_idle,
264                 USE_PLATFORM_PM_SLEEP_OPS
265         },
266 };
267
268 static int platform_bus_notify(struct notifier_block *nb,
269                                unsigned long action, void *data)
270 {
271         struct device *dev = data;
272         struct platform_device *pdev = to_platform_device(dev);
273         int hwblk = pdev->archdata.hwblk_id;
274
275         /* ignore off-chip platform devices */
276         if (!hwblk)
277                 return 0;
278
279         switch (action) {
280         case BUS_NOTIFY_ADD_DEVICE:
281                 INIT_LIST_HEAD(&pdev->archdata.entry);
282                 mutex_init(&pdev->archdata.mutex);
283                 /* platform devices without drivers should be disabled */
284                 hwblk_enable(hwblk_info, hwblk);
285                 hwblk_disable(hwblk_info, hwblk);
286                 /* make sure driver re-inits itself once */
287                 __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
288                 dev->pwr_domain = &default_power_domain;
289                 break;
290         /* TODO: add BUS_NOTIFY_BIND_DRIVER and increase idle count */
291         case BUS_NOTIFY_BOUND_DRIVER:
292                 /* keep track of number of devices in use per hwblk */
293                 hwblk_cnt_inc(hwblk_info, hwblk, HWBLK_CNT_DEVICES);
294                 break;
295         case BUS_NOTIFY_UNBOUND_DRIVER:
296                 /* keep track of number of devices in use per hwblk */
297                 hwblk_cnt_dec(hwblk_info, hwblk, HWBLK_CNT_DEVICES);
298                 /* make sure driver re-inits itself once */
299                 __set_bit(PDEV_ARCHDATA_FLAG_INIT, &pdev->archdata.flags);
300                 break;
301         case BUS_NOTIFY_DEL_DEVICE:
302                 dev->pwr_domain = NULL;
303                 break;
304         }
305         return 0;
306 }
307
308 static struct notifier_block platform_bus_notifier = {
309         .notifier_call = platform_bus_notify
310 };
311
312 static int __init sh_pm_runtime_init(void)
313 {
314         INIT_WORK(&hwblk_work, platform_pm_runtime_work);
315
316         bus_register_notifier(&platform_bus_type, &platform_bus_notifier);
317         return 0;
318 }
319 core_initcall(sh_pm_runtime_init);