]> www.pilppa.org Git - linux-2.6-omap-h63xx.git/blob - arch/arm/mach-omap2/pm.c
f69982661c0227c3101a7537cb74540bf7b46090
[linux-2.6-omap-h63xx.git] / arch / arm / mach-omap2 / pm.c
1 /*
2  * linux/arch/arm/mach-omap2/pm.c
3  *
4  * OMAP Power Management Common Routines
5  *
6  * Copyright (C) 2005 Texas Instruments, Inc.
7  * Copyright (C) 2006-2008 Nokia Corporation
8  *
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
16  *
17  * Based on pm.c for omap1
18  *
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.
22  */
23
24 #include <linux/suspend.h>
25 #include <linux/time.h>
26
27 #include <asm/arch/cpu.h>
28 #include <asm/mach/time.h>
29 #include <asm/atomic.h>
30
31 #include "pm.h"
32
33 unsigned short enable_dyn_sleep;
34 unsigned short clocks_off_while_idle;
35 atomic_t sleep_block = ATOMIC_INIT(0);
36
37 static ssize_t idle_show(struct kobject *, struct kobj_attribute *, char *);
38 static ssize_t idle_store(struct kobject *k, struct kobj_attribute *,
39                           const char *buf, size_t n);
40
41 static struct kobj_attribute sleep_while_idle_attr =
42         __ATTR(sleep_while_idle, 0644, idle_show, idle_store);
43
44 static struct kobj_attribute clocks_off_while_idle_attr =
45         __ATTR(clocks_off_while_idle, 0644, idle_show, idle_store);
46
47 static ssize_t idle_show(struct kobject *kobj, struct kobj_attribute *attr,
48                          char *buf)
49 {
50         if (attr == &sleep_while_idle_attr)
51                 return sprintf(buf, "%hu\n", enable_dyn_sleep);
52         else if (attr == &clocks_off_while_idle_attr)
53                 return sprintf(buf, "%hu\n", clocks_off_while_idle);
54         else
55                 return -EINVAL;
56 }
57
58 static ssize_t idle_store(struct kobject *kobj, struct kobj_attribute *attr,
59                           const char *buf, size_t n)
60 {
61         unsigned short value;
62
63         if (sscanf(buf, "%hu", &value) != 1 ||
64             (value != 0 && value != 1)) {
65                 printk(KERN_ERR "idle_store: Invalid value\n");
66                 return -EINVAL;
67         }
68
69         if (attr == &sleep_while_idle_attr)
70                 enable_dyn_sleep = value;
71         else if (attr == &clocks_off_while_idle_attr)
72                 clocks_off_while_idle = value;
73         else
74                 return -EINVAL;
75
76         return n;
77 }
78
79 void omap2_block_sleep(void)
80 {
81         atomic_inc(&sleep_block);
82 }
83
84 void omap2_allow_sleep(void)
85 {
86         int i;
87
88         i = atomic_dec_return(&sleep_block);
89         BUG_ON(i < 0);
90 }
91
92 static int __init omap_pm_init(void)
93 {
94         int error = -1;
95
96         if (cpu_is_omap24xx())
97                 error = omap2_pm_init();
98         if (cpu_is_omap34xx())
99                 error = omap3_pm_init();
100         if (error) {
101                 printk(KERN_ERR "omap2|3_pm_init failed: %d\n", error);
102                 return error;
103         }
104
105         /* disabled till drivers are fixed */
106         enable_dyn_sleep = 0;
107         error = sysfs_create_file(power_kobj, &sleep_while_idle_attr.attr);
108         if (error)
109                 printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
110         error = sysfs_create_file(power_kobj,
111                                   &clocks_off_while_idle_attr.attr);
112         if (error)
113                 printk(KERN_ERR "sysfs_create_file failed: %d\n", error);
114
115         return error;
116 }
117
118 late_initcall(omap_pm_init);