OMAP3: PM: Fixed VDD2 control to work from both sysfs and SRF API
[linux-ginger.git] / arch / arm / mach-omap2 / pm.c
blobabc80f70884fb53bbb9d1b531856189543cf5ce8
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/omapdev.h>
35 #include <plat/resource.h>
37 #include "prm-regbits-34xx.h"
38 #include "pm.h"
40 atomic_t sleep_block = ATOMIC_INIT(0);
42 static ssize_t idle_show(struct kobject *, struct kobj_attribute *, char *);
43 static ssize_t idle_store(struct kobject *k, struct kobj_attribute *,
44 const char *buf, size_t n);
46 #ifdef CONFIG_OMAP_PM_SRF
47 static ssize_t vdd_opp_show(struct kobject *, struct kobj_attribute *, char *);
48 static ssize_t vdd_opp_store(struct kobject *k, struct kobj_attribute *,
49 const char *buf, size_t n);
50 static struct kobj_attribute vdd1_opp_attr =
51 __ATTR(vdd1_opp, 0644, vdd_opp_show, vdd_opp_store);
53 static struct kobj_attribute vdd2_opp_attr =
54 __ATTR(vdd2_opp, 0644, vdd_opp_show, vdd_opp_store);
55 #endif
57 static ssize_t idle_show(struct kobject *kobj, struct kobj_attribute *attr,
58 char *buf)
60 return -EINVAL;
63 static ssize_t idle_store(struct kobject *kobj, struct kobj_attribute *attr,
64 const char *buf, size_t n)
66 unsigned short value;
68 if (sscanf(buf, "%hu", &value) != 1 ||
69 (value != 0 && value != 1)) {
70 printk(KERN_ERR "idle_store: Invalid value\n");
71 return -EINVAL;
74 return n;
77 #ifdef CONFIG_OMAP_PM_SRF
78 static ssize_t vdd_opp_show(struct kobject *kobj, struct kobj_attribute *attr,
79 char *buf)
81 if (attr == &vdd1_opp_attr)
82 return sprintf(buf, "%hu\n", resource_get_level("vdd1_opp"));
83 else if (attr == &vdd2_opp_attr)
84 return sprintf(buf, "%hu\n", resource_get_level("vdd2_opp"));
85 else
86 return -EINVAL;
89 static ssize_t vdd_opp_store(struct kobject *kobj, struct kobj_attribute *attr,
90 const char *buf, size_t n)
92 unsigned short value;
94 if (sscanf(buf, "%hu", &value) != 1)
95 return -EINVAL;
97 if (attr == &vdd1_opp_attr) {
98 if (value < 1 || value > 5) {
99 printk(KERN_ERR "vdd_opp_store: Invalid value\n");
100 return -EINVAL;
102 set_opp_level(VDD1_OPP, value);
103 } else if (attr == &vdd2_opp_attr) {
104 if (value < 2 || value > 3) {
105 printk(KERN_ERR "vdd_opp_store: Invalid value\n");
106 return -EINVAL;
108 set_opp_level(VDD2_OPP, value);
109 } else {
110 return -EINVAL;
112 return n;
114 #endif
116 void omap2_block_sleep(void)
118 atomic_inc(&sleep_block);
121 void omap2_allow_sleep(void)
123 int i;
125 i = atomic_dec_return(&sleep_block);
126 BUG_ON(i < 0);
129 unsigned get_last_off_on_transaction_id(struct device *dev)
131 struct platform_device *pdev = to_platform_device(dev);
132 struct omapdev *odev = omapdev_find_pdev(pdev);
133 struct powerdomain *pwrdm;
135 if (odev) {
136 pwrdm = omapdev_get_pwrdm(odev);
137 if (pwrdm)
138 return pwrdm->state_counter[0];
141 return 0;
144 static int __init omap_pm_init(void)
146 int error = -1;
148 #ifdef CONFIG_OMAP_PM_SRF
149 error = sysfs_create_file(power_kobj,
150 &vdd1_opp_attr.attr);
151 if (error) {
152 printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
153 return error;
155 error = sysfs_create_file(power_kobj,
156 &vdd2_opp_attr.attr);
157 if (error) {
158 printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
159 return error;
161 #endif
163 return error;
165 late_initcall(omap_pm_init);