2 * linux/arch/arm/mach-omap2/pm.c
4 * OMAP Power Management Common Routines
6 * Copyright (C) 2005 Texas Instruments, Inc.
7 * Copyright (C) 2006-2008 Nokia Corporation
10 * Richard Woodruff <r-woodruff2@ti.com>
13 * Amit Kucheria <amit.kucheria@nokia.com>
14 * Igor Stoppa <igor.stoppa@nokia.com>
17 * Based on pm.c for omap1
19 * This program is free software; you can redistribute it and/or modify
20 * it under the terms of the GNU General Public License version 2 as
21 * published by the Free Software Foundation.
24 #include <linux/suspend.h>
25 #include <linux/time.h>
26 #include <linux/platform_device.h>
27 #include <linux/device.h>
30 #include <asm/mach/time.h>
31 #include <asm/atomic.h>
33 #include <plat/powerdomain.h>
34 #include <plat/omapdev.h>
35 #include <plat/resource.h>
36 #include <plat/omap34xx.h>
38 #include "prm-regbits-34xx.h"
41 atomic_t sleep_block
= ATOMIC_INIT(0);
43 static ssize_t
idle_show(struct kobject
*, struct kobj_attribute
*, char *);
44 static ssize_t
idle_store(struct kobject
*k
, struct kobj_attribute
*,
45 const char *buf
, size_t n
);
47 #ifdef CONFIG_OMAP_PM_SRF
48 static ssize_t
vdd_opp_show(struct kobject
*, struct kobj_attribute
*, char *);
49 static ssize_t
vdd_opp_store(struct kobject
*k
, struct kobj_attribute
*,
50 const char *buf
, size_t n
);
51 static struct kobj_attribute vdd1_opp_attr
=
52 __ATTR(vdd1_opp
, 0644, vdd_opp_show
, vdd_opp_store
);
54 static struct kobj_attribute vdd2_opp_attr
=
55 __ATTR(vdd2_opp
, 0644, vdd_opp_show
, vdd_opp_store
);
56 static struct kobj_attribute vdd1_lock_attr
=
57 __ATTR(vdd1_lock
, 0644, vdd_opp_show
, vdd_opp_store
);
58 static struct kobj_attribute vdd2_lock_attr
=
59 __ATTR(vdd2_lock
, 0644, vdd_opp_show
, vdd_opp_store
);
63 static ssize_t
idle_show(struct kobject
*kobj
, struct kobj_attribute
*attr
,
69 static ssize_t
idle_store(struct kobject
*kobj
, struct kobj_attribute
*attr
,
70 const char *buf
, size_t n
)
74 if (sscanf(buf
, "%hu", &value
) != 1 ||
75 (value
!= 0 && value
!= 1)) {
76 printk(KERN_ERR
"idle_store: Invalid value\n");
83 #ifdef CONFIG_OMAP_PM_SRF
84 #include <plat/omap34xx.h>
85 static int vdd1_locked
;
86 static int vdd2_locked
;
88 static ssize_t
vdd_opp_show(struct kobject
*kobj
, struct kobj_attribute
*attr
,
91 if (attr
== &vdd1_opp_attr
)
92 return sprintf(buf
, "%hu\n", resource_get_level("vdd1_opp"));
93 else if (attr
== &vdd2_opp_attr
)
94 return sprintf(buf
, "%hu\n", resource_get_level("vdd2_opp"));
95 else if (attr
== &vdd1_lock_attr
)
96 return sprintf(buf
, "%hu\n", resource_get_opp_lock(VDD1_OPP
));
97 else if (attr
== &vdd2_lock_attr
)
98 return sprintf(buf
, "%hu\n", resource_get_opp_lock(VDD2_OPP
));
103 static ssize_t
vdd_opp_store(struct kobject
*kobj
, struct kobj_attribute
*attr
,
104 const char *buf
, size_t n
)
106 unsigned short value
;
109 if (sscanf(buf
, "%hu", &value
) != 1)
113 if (attr
== &vdd1_lock_attr
) {
114 flags
= OPP_IGNORE_LOCK
;
115 attr
= &vdd1_opp_attr
;
116 if (vdd1_locked
&& value
== 0) {
117 resource_unlock_opp(VDD1_OPP
);
122 if (vdd1_locked
== 0 && value
!= 0) {
123 resource_lock_opp(VDD1_OPP
);
126 } else if (attr
== &vdd2_lock_attr
) {
127 flags
= OPP_IGNORE_LOCK
;
128 attr
= &vdd2_opp_attr
;
129 if (vdd2_locked
&& value
== 0) {
130 resource_unlock_opp(VDD2_OPP
);
135 if (vdd2_locked
== 0 && value
!= 0) {
136 resource_lock_opp(VDD2_OPP
);
141 if (attr
== &vdd1_opp_attr
) {
142 if (value
< 1 || value
> 5) {
143 printk(KERN_ERR
"vdd_opp_store: Invalid value\n");
146 resource_set_opp_level(VDD1_OPP
, value
, flags
);
147 } else if (attr
== &vdd2_opp_attr
) {
148 if (value
< 1 || value
> 3) {
149 printk(KERN_ERR
"vdd_opp_store: Invalid value\n");
152 resource_set_opp_level(VDD2_OPP
, value
, flags
);
160 void omap2_block_sleep(void)
162 atomic_inc(&sleep_block
);
165 void omap2_allow_sleep(void)
169 i
= atomic_dec_return(&sleep_block
);
173 unsigned get_last_off_on_transaction_id(struct device
*dev
)
175 struct platform_device
*pdev
= to_platform_device(dev
);
176 struct omapdev
*odev
= omapdev_find_pdev(pdev
);
177 struct powerdomain
*pwrdm
;
180 pwrdm
= omapdev_get_pwrdm(odev
);
182 return pwrdm
->state_counter
[0];
188 static int __init
omap_pm_init(void)
192 #ifdef CONFIG_OMAP_PM_SRF
193 error
= sysfs_create_file(power_kobj
,
194 &vdd1_opp_attr
.attr
);
196 printk(KERN_ERR
"sysfs_create_file failed: %d\n", error
);
199 error
= sysfs_create_file(power_kobj
,
200 &vdd2_opp_attr
.attr
);
202 printk(KERN_ERR
"sysfs_create_file failed: %d\n", error
);
206 error
= sysfs_create_file(power_kobj
, &vdd1_lock_attr
.attr
);
208 printk(KERN_ERR
"sysfs_create_file failed: %d\n", error
);
212 error
= sysfs_create_file(power_kobj
, &vdd2_lock_attr
.attr
);
214 printk(KERN_ERR
"sysfs_create_file failed: %d\n", error
);
221 late_initcall(omap_pm_init
);