First Support on Ginger and OMAP TI
[linux-ginger.git] / arch / arm / mach-omap2 / pm.c
blobc84621c7f24e18de327dc7b716782a635bab7bd5
1 /*
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
9 * Written by:
10 * Richard Woodruff <r-woodruff2@ti.com>
11 * Tony Lindgren
12 * Juha Yrjola
13 * Amit Kucheria <amit.kucheria@nokia.com>
14 * Igor Stoppa <igor.stoppa@nokia.com>
15 * Jouni Hogander
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>
29 #include <plat/cpu.h>
30 #include <asm/mach/time.h>
31 #include <asm/atomic.h>
33 #include <plat/powerdomain.h>
34 #include <plat/resource.h>
35 #include <plat/omap34xx.h>
37 #include "prm-regbits-34xx.h"
38 #include "pm.h"
40 atomic_t sleep_block = ATOMIC_INIT(0);
42 #ifdef CONFIG_OMAP_PM_SRF
43 static ssize_t vdd_opp_show(struct kobject *, struct kobj_attribute *, char *);
44 static ssize_t vdd_opp_store(struct kobject *k, struct kobj_attribute *,
45 const char *buf, size_t n);
46 static struct kobj_attribute vdd1_opp_attr =
47 __ATTR(vdd1_opp, 0644, vdd_opp_show, vdd_opp_store);
49 static struct kobj_attribute vdd2_opp_attr =
50 __ATTR(vdd2_opp, 0644, vdd_opp_show, vdd_opp_store);
51 static struct kobj_attribute vdd1_lock_attr =
52 __ATTR(vdd1_lock, 0644, vdd_opp_show, vdd_opp_store);
53 static struct kobj_attribute vdd2_lock_attr =
54 __ATTR(vdd2_lock, 0644, vdd_opp_show, vdd_opp_store);
56 #endif
58 #ifdef CONFIG_OMAP_PM_SRF
59 #include <plat/omap34xx.h>
60 static int vdd1_locked;
61 static int vdd2_locked;
63 static ssize_t vdd_opp_show(struct kobject *kobj, struct kobj_attribute *attr,
64 char *buf)
66 if (attr == &vdd1_opp_attr)
67 return sprintf(buf, "%hu\n", resource_get_level("vdd1_opp"));
68 else if (attr == &vdd2_opp_attr)
69 return sprintf(buf, "%hu\n", resource_get_level("vdd2_opp"));
70 else if (attr == &vdd1_lock_attr)
71 return sprintf(buf, "%hu\n", resource_get_opp_lock(VDD1_OPP));
72 else if (attr == &vdd2_lock_attr)
73 return sprintf(buf, "%hu\n", resource_get_opp_lock(VDD2_OPP));
74 else
75 return -EINVAL;
78 static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr,
79 const char *buf, size_t n)
81 unsigned short value;
82 int flags = 0;
84 if (sscanf(buf, "%hu", &value) != 1)
85 return -EINVAL;
87 /* Check locks */
88 if (attr == &vdd1_lock_attr) {
89 flags = OPP_IGNORE_LOCK;
90 attr = &vdd1_opp_attr;
91 if (vdd1_locked && value == 0) {
92 resource_unlock_opp(VDD1_OPP);
93 resource_refresh();
94 vdd1_locked = 0;
95 return n;
97 if (vdd1_locked == 0 && value != 0) {
98 resource_lock_opp(VDD1_OPP);
99 vdd1_locked = 1;
101 } else if (attr == &vdd2_lock_attr) {
102 flags = OPP_IGNORE_LOCK;
103 attr = &vdd2_opp_attr;
104 if (vdd2_locked && value == 0) {
105 resource_unlock_opp(VDD2_OPP);
106 resource_refresh();
107 vdd2_locked = 0;
108 return n;
110 if (vdd2_locked == 0 && value != 0) {
111 resource_lock_opp(VDD2_OPP);
112 vdd2_locked = 1;
116 if (attr == &vdd1_opp_attr) {
117 if (value < 1 || value > 5) {
118 printk(KERN_ERR "vdd_opp_store: Invalid value\n");
119 return -EINVAL;
121 resource_set_opp_level(VDD1_OPP, value, flags);
122 } else if (attr == &vdd2_opp_attr) {
123 if (value < 2 || value > 3) {
124 printk(KERN_ERR "vdd_opp_store: Invalid value\n");
125 return -EINVAL;
127 resource_set_opp_level(VDD2_OPP, value, flags);
128 } else {
129 return -EINVAL;
131 return n;
133 #endif
135 void omap2_block_sleep(void)
137 atomic_inc(&sleep_block);
140 void omap2_allow_sleep(void)
142 int i;
144 i = atomic_dec_return(&sleep_block);
145 BUG_ON(i < 0);
148 static int __init omap_pm_init(void)
150 int error = -1;
152 #ifdef CONFIG_OMAP_PM_SRF
153 error = sysfs_create_file(power_kobj,
154 &vdd1_opp_attr.attr);
155 if (error) {
156 printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
157 return error;
159 error = sysfs_create_file(power_kobj,
160 &vdd2_opp_attr.attr);
161 if (error) {
162 printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
163 return error;
166 error = sysfs_create_file(power_kobj, &vdd1_lock_attr.attr);
167 if (error) {
168 printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
169 return error;
172 error = sysfs_create_file(power_kobj, &vdd2_lock_attr.attr);
173 if (error) {
174 printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
175 return error;
177 #endif
179 return error;
181 late_initcall(omap_pm_init);