2 * arch/arm/mach-shmobile/pm_runtime.c
4 * Runtime PM support code for SuperH Mobile ARM
6 * Copyright (C) 2009-2010 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
13 #include <linux/init.h>
14 #include <linux/kernel.h>
16 #include <linux/pm_runtime.h>
17 #include <linux/platform_device.h>
18 #include <linux/clk.h>
19 #include <linux/sh_clk.h>
20 #include <linux/bitmap.h>
22 #ifdef CONFIG_PM_RUNTIME
25 #define BIT_CLK_ENABLED 2
27 struct pm_runtime_data
{
32 static void __devres_release(struct device
*dev
, void *res
)
34 struct pm_runtime_data
*prd
= res
;
36 dev_dbg(dev
, "__devres_release()\n");
38 if (test_bit(BIT_CLK_ENABLED
, &prd
->flags
))
39 clk_disable(prd
->clk
);
41 if (test_bit(BIT_ACTIVE
, &prd
->flags
))
45 static struct pm_runtime_data
*__to_prd(struct device
*dev
)
47 return devres_find(dev
, __devres_release
, NULL
, NULL
);
50 static void platform_pm_runtime_init(struct device
*dev
,
51 struct pm_runtime_data
*prd
)
53 if (prd
&& !test_and_set_bit(BIT_ONCE
, &prd
->flags
)) {
54 prd
->clk
= clk_get(dev
, NULL
);
55 if (!IS_ERR(prd
->clk
)) {
56 set_bit(BIT_ACTIVE
, &prd
->flags
);
57 dev_info(dev
, "clocks managed by runtime pm\n");
62 static void platform_pm_runtime_bug(struct device
*dev
,
63 struct pm_runtime_data
*prd
)
65 if (prd
&& !test_and_set_bit(BIT_ONCE
, &prd
->flags
))
66 dev_err(dev
, "runtime pm suspend before resume\n");
69 int platform_pm_runtime_suspend(struct device
*dev
)
71 struct pm_runtime_data
*prd
= __to_prd(dev
);
73 dev_dbg(dev
, "platform_pm_runtime_suspend()\n");
75 platform_pm_runtime_bug(dev
, prd
);
77 if (prd
&& test_bit(BIT_ACTIVE
, &prd
->flags
)) {
78 clk_disable(prd
->clk
);
79 clear_bit(BIT_CLK_ENABLED
, &prd
->flags
);
85 int platform_pm_runtime_resume(struct device
*dev
)
87 struct pm_runtime_data
*prd
= __to_prd(dev
);
89 dev_dbg(dev
, "platform_pm_runtime_resume()\n");
91 platform_pm_runtime_init(dev
, prd
);
93 if (prd
&& test_bit(BIT_ACTIVE
, &prd
->flags
)) {
95 set_bit(BIT_CLK_ENABLED
, &prd
->flags
);
101 int platform_pm_runtime_idle(struct device
*dev
)
103 /* suspend synchronously to disable clocks immediately */
104 return pm_runtime_suspend(dev
);
107 static int platform_bus_notify(struct notifier_block
*nb
,
108 unsigned long action
, void *data
)
110 struct device
*dev
= data
;
111 struct pm_runtime_data
*prd
;
113 dev_dbg(dev
, "platform_bus_notify() %ld !\n", action
);
115 if (action
== BUS_NOTIFY_BIND_DRIVER
) {
116 prd
= devres_alloc(__devres_release
, sizeof(*prd
), GFP_KERNEL
);
118 devres_add(dev
, prd
);
120 dev_err(dev
, "unable to alloc memory for runtime pm\n");
126 #else /* CONFIG_PM_RUNTIME */
128 static int platform_bus_notify(struct notifier_block
*nb
,
129 unsigned long action
, void *data
)
131 struct device
*dev
= data
;
134 dev_dbg(dev
, "platform_bus_notify() %ld !\n", action
);
137 case BUS_NOTIFY_BIND_DRIVER
:
138 clk
= clk_get(dev
, NULL
);
142 dev_info(dev
, "runtime pm disabled, clock forced on\n");
145 case BUS_NOTIFY_UNBOUND_DRIVER
:
146 clk
= clk_get(dev
, NULL
);
150 dev_info(dev
, "runtime pm disabled, clock forced off\n");
158 #endif /* CONFIG_PM_RUNTIME */
160 static struct notifier_block platform_bus_notifier
= {
161 .notifier_call
= platform_bus_notify
164 static int __init
sh_pm_runtime_init(void)
166 bus_register_notifier(&platform_bus_type
, &platform_bus_notifier
);
169 core_initcall(sh_pm_runtime_init
);