2 * arch/sh/kernel/cpu/shmobile/pm_runtime.c
4 * Runtime PM support code for SuperH Mobile
6 * Copyright (C) 2009 Magnus Damm
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
12 #include <linux/init.h>
13 #include <linux/kernel.h>
15 #include <linux/pm_runtime.h>
16 #include <linux/platform_device.h>
17 #include <linux/mutex.h>
18 #include <asm/hwblk.h>
20 static DEFINE_SPINLOCK(hwblk_lock
);
21 static LIST_HEAD(hwblk_idle_list
);
22 static struct work_struct hwblk_work
;
24 extern struct hwblk_info
*hwblk_info
;
26 static void platform_pm_runtime_not_idle(struct platform_device
*pdev
)
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
);
36 spin_unlock_irqrestore(&hwblk_lock
, flags
);
39 static int __platform_pm_runtime_resume(struct platform_device
*pdev
)
41 struct device
*d
= &pdev
->dev
;
42 struct pdev_archdata
*ad
= &pdev
->archdata
;
43 int hwblk
= ad
->hwblk_id
;
46 dev_dbg(d
, "__platform_pm_runtime_resume() [%d]\n", hwblk
);
49 hwblk_enable(hwblk_info
, hwblk
);
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
);
57 clear_bit(PDEV_ARCHDATA_FLAG_SUSP
, &ad
->flags
);
59 hwblk_disable(hwblk_info
, hwblk
);
63 dev_dbg(d
, "__platform_pm_runtime_resume() [%d] - returns %d\n",
69 static int __platform_pm_runtime_suspend(struct platform_device
*pdev
)
71 struct device
*d
= &pdev
->dev
;
72 struct pdev_archdata
*ad
= &pdev
->archdata
;
73 int hwblk
= ad
->hwblk_id
;
76 dev_dbg(d
, "__platform_pm_runtime_suspend() [%d]\n", hwblk
);
79 BUG_ON(!test_bit(PDEV_ARCHDATA_FLAG_IDLE
, &ad
->flags
));
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
);
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
);
95 dev_dbg(d
, "__platform_pm_runtime_suspend() [%d] - returns %d\n",
101 static void platform_pm_runtime_work(struct work_struct
*work
)
103 struct platform_device
*pdev
;
107 /* go through the idle list and suspend one device at a time */
109 spin_lock_irqsave(&hwblk_lock
, flags
);
110 if (list_empty(&hwblk_idle_list
))
113 pdev
= list_first_entry(&hwblk_idle_list
,
114 struct platform_device
,
116 spin_unlock_irqrestore(&hwblk_lock
, flags
);
119 mutex_lock(&pdev
->archdata
.mutex
);
120 ret
= __platform_pm_runtime_suspend(pdev
);
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
126 mutex_unlock(&pdev
->archdata
.mutex
);
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)
137 void platform_pm_runtime_suspend_idle(void)
139 queue_work(pm_wq
, &hwblk_work
);
142 static int default_platform_runtime_suspend(struct device
*dev
)
144 struct platform_device
*pdev
= to_platform_device(dev
);
145 struct pdev_archdata
*ad
= &pdev
->archdata
;
147 int hwblk
= ad
->hwblk_id
;
150 dev_dbg(dev
, "%s() [%d]\n", __func__
, hwblk
);
152 /* ignore off-chip platform devices */
156 /* interrupt context not allowed */
159 /* catch misconfigured drivers not starting with resume */
160 if (test_bit(PDEV_ARCHDATA_FLAG_INIT
, &ad
->flags
)) {
166 mutex_lock(&ad
->mutex
);
169 hwblk_disable(hwblk_info
, hwblk
);
171 /* put device on idle list */
172 spin_lock_irqsave(&hwblk_lock
, flags
);
173 list_add_tail(&ad
->entry
, &hwblk_idle_list
);
174 __set_bit(PDEV_ARCHDATA_FLAG_IDLE
, &ad
->flags
);
175 spin_unlock_irqrestore(&hwblk_lock
, flags
);
177 /* increase idle count */
178 hwblk_cnt_inc(hwblk_info
, hwblk
, HWBLK_CNT_IDLE
);
180 /* at this point the platform device is:
181 * idle: ret = 0, FLAG_IDLE set, clock stopped
183 mutex_unlock(&ad
->mutex
);
186 dev_dbg(dev
, "%s() [%d] returns %d\n",
187 __func__
, hwblk
, ret
);
192 static int default_platform_runtime_resume(struct device
*dev
)
194 struct platform_device
*pdev
= to_platform_device(dev
);
195 struct pdev_archdata
*ad
= &pdev
->archdata
;
196 int hwblk
= ad
->hwblk_id
;
199 dev_dbg(dev
, "%s() [%d]\n", __func__
, hwblk
);
201 /* ignore off-chip platform devices */
205 /* interrupt context not allowed */
209 mutex_lock(&ad
->mutex
);
211 /* make sure device is removed from idle list */
212 platform_pm_runtime_not_idle(pdev
);
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
);
219 /* resume the device if needed */
220 ret
= __platform_pm_runtime_resume(pdev
);
222 /* the driver has been initialized now, so clear the init flag */
223 clear_bit(PDEV_ARCHDATA_FLAG_INIT
, &pdev
->archdata
.flags
);
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
229 mutex_unlock(&ad
->mutex
);
231 dev_dbg(dev
, "%s() [%d] returns %d\n",
232 __func__
, hwblk
, ret
);
237 static int default_platform_runtime_idle(struct device
*dev
)
239 struct platform_device
*pdev
= to_platform_device(dev
);
240 int hwblk
= pdev
->archdata
.hwblk_id
;
243 dev_dbg(dev
, "%s() [%d]\n", __func__
, hwblk
);
245 /* ignore off-chip platform devices */
249 /* interrupt context not allowed, use pm_runtime_put()! */
252 /* suspend synchronously to disable clocks immediately */
253 ret
= pm_runtime_suspend(dev
);
255 dev_dbg(dev
, "%s() [%d] done!\n", __func__
, hwblk
);
259 static struct dev_pm_domain default_pm_domain
= {
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
268 static int platform_bus_notify(struct notifier_block
*nb
,
269 unsigned long action
, void *data
)
271 struct device
*dev
= data
;
272 struct platform_device
*pdev
= to_platform_device(dev
);
273 int hwblk
= pdev
->archdata
.hwblk_id
;
275 /* ignore off-chip platform devices */
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
->pm_domain
= &default_pm_domain
;
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
);
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
);
301 case BUS_NOTIFY_DEL_DEVICE
:
302 dev
->pm_domain
= NULL
;
308 static struct notifier_block platform_bus_notifier
= {
309 .notifier_call
= platform_bus_notify
312 static int __init
sh_pm_runtime_init(void)
314 INIT_WORK(&hwblk_work
, platform_pm_runtime_work
);
316 bus_register_notifier(&platform_bus_type
, &platform_bus_notifier
);
319 core_initcall(sh_pm_runtime_init
);