Annotation of prex-old/dev/power/pm.c, Revision 1.1.1.1
1.1 nbrk 1: /*-
2: * Copyright (c) 2005, Kohsuke Ohtani
3: * All rights reserved.
4: *
5: * Redistribution and use in source and binary forms, with or without
6: * modification, are permitted provided that the following conditions
7: * are met:
8: * 1. Redistributions of source code must retain the above copyright
9: * notice, this list of conditions and the following disclaimer.
10: * 2. Redistributions in binary form must reproduce the above copyright
11: * notice, this list of conditions and the following disclaimer in the
12: * documentation and/or other materials provided with the distribution.
13: * 3. Neither the name of the author nor the names of any co-contributors
14: * may be used to endorse or promote products derived from this software
15: * without specific prior written permission.
16: *
17: * THIS SOFTWARE IS PROVIDED BY THE AUTHOR AND CONTRIBUTORS ``AS IS'' AND
18: * ANY EXPRESS OR IMPLIED WARRANTIES, INCLUDING, BUT NOT LIMITED TO, THE
19: * IMPLIED WARRANTIES OF MERCHANTABILITY AND FITNESS FOR A PARTICULAR PURPOSE
20: * ARE DISCLAIMED. IN NO EVENT SHALL THE AUTHOR OR CONTRIBUTORS BE LIABLE
21: * FOR ANY DIRECT, INDIRECT, INCIDENTAL, SPECIAL, EXEMPLARY, OR CONSEQUENTIAL
22: * DAMAGES (INCLUDING, BUT NOT LIMITED TO, PROCUREMENT OF SUBSTITUTE GOODS
23: * OR SERVICES; LOSS OF USE, DATA, OR PROFITS; OR BUSINESS INTERRUPTION)
24: * HOWEVER CAUSED AND ON ANY THEORY OF LIABILITY, WHETHER IN CONTRACT, STRICT
25: * LIABILITY, OR TORT (INCLUDING NEGLIGENCE OR OTHERWISE) ARISING IN ANY WAY
26: * OUT OF THE USE OF THIS SOFTWARE, EVEN IF ADVISED OF THE POSSIBILITY OF
27: * SUCH DAMAGE.
28: */
29:
30: /*
31: * pm.c - power management driver (hardware independent)
32: */
33:
34: #include <sys/ioctl.h>
35: #include <driver.h>
36: #include <machdep.h>
37: #include <event.h>
38: #include <pm.h>
39: #include "dvs.h"
40:
41: /* #define DEBUG_PM 1 */
42:
43: #ifdef DEBUG_PM
44: #define pm_printf(fmt, args...) printk("pm: " fmt, ## args)
45: #else
46: #define pm_printf(fmt...) do {} while (0)
47: #endif
48:
49:
50: #ifdef CONFIG_PM_POWERSAVE
51: #define DEFAULT_POWER_POLICY PM_POWERSAVE
52: #else
53: #define DEFAULT_POWER_POLICY PM_PERFORMANCE
54: #endif
55:
56: static int pm_open(device_t dev, int mode);
57: static int pm_ioctl(device_t dev, int cmd, u_long arg);
58: static int pm_close(device_t dev);
59: static int pm_init(void);
60:
61: /*
62: * Driver structure
63: */
64: struct driver pm_drv = {
65: /* name */ "Power Management",
66: /* order */ 2,
67: /* init */ pm_init,
68: };
69:
70: static struct devio pm_io = {
71: /* open */ pm_open,
72: /* close */ pm_close,
73: /* read */ NULL,
74: /* write */ NULL,
75: /* ioctl */ pm_ioctl,
76: /* event */ NULL,
77: };
78:
79: static device_t pm_dev; /* Device object */
80: static int nr_open; /* Open count */
81:
82: /*
83: * Power mangement policy
84: */
85: static int power_policy;
86:
87: /*
88: * Idle timer
89: */
90: static struct timer idle_timer;
91: static u_long idle_count; /* Idling counter in sec */
92: static u_long suspend_timeout; /* Time until auto suspend in sec */
93:
94: /*
95: * Set system to suspend state
96: * Call to all devices and architecture depended code.
97: */
98: int
99: pm_suspend(void)
100: {
101: int err;
102:
103: pm_printf("Suspend system\n");
104: err = device_broadcast(EVT_SUSPEND, 1);
105: if (err)
106: return err;
107: machine_suspend();
108: return 0;
109: }
110:
111: /*
112: * Resume
113: */
114: int
115: pm_resume(void)
116: {
117: pm_printf("Resume system\n");
118: device_broadcast(EVT_RESUME, 1);
119: return 0;
120: }
121:
122: /*
123: * Power off system
124: * Call to all devices and architecture depended code.
125: */
126: int
127: pm_poweroff(void)
128: {
129: int err;
130:
131: pm_printf("Power off...\n");
132: err = device_broadcast(EVT_SHUTDOWN, 1);
133: if (err)
134: return err;
135: machine_poweroff();
136: return 0;
137: }
138:
139: /*
140: * Reboot system.
141: */
142: int
143: pm_reboot(void)
144: {
145: int err;
146:
147: pm_printf("rebooting...\n");
148: err = device_broadcast(EVT_SHUTDOWN, 1);
149: if (err)
150: return err;
151:
152: irq_lock();
153:
154: /*
155: * Do reset.
156: */
157: machine_reset();
158: return 0;
159: }
160:
161: /*
162: * Idle timer handler
163: */
164: static void
165: idle_timeout(u_long dummy)
166: {
167:
168: irq_lock();
169: idle_count++;
170: irq_unlock();
171: if (idle_count >= suspend_timeout)
172: pm_suspend();
173: else
174: timer_callout(&idle_timer, idle_timeout, 0, 1000);
175: }
176:
177: /*
178: * Set suspend timer
179: */
180: int
181: pm_settimer(u_long sec)
182: {
183:
184: sched_lock();
185: if (sec)
186: timer_callout(&idle_timer, idle_timeout, 0, 1000);
187: else
188: timer_stop(&idle_timer);
189: idle_count = 0;
190: suspend_timeout = sec;
191: sched_unlock();
192: return 0;
193: }
194:
195: /*
196: * Get power management timer
197: */
198: int
199: pm_gettimer(u_long *sec)
200: {
201:
202: *sec = suspend_timeout;
203: return 0;
204: }
205:
206: /*
207: * Reload idle timer
208: */
209: void
210: pm_active(void)
211: {
212:
213: idle_count = 0;
214: }
215:
216: /*
217: * Set power policy
218: */
219: static int
220: pm_setpolicy(int policy)
221: {
222:
223: if (policy != PM_POWERSAVE && policy != PM_PERFORMANCE)
224: return EINVAL;
225: #ifdef CONFIG_CPUFREQ
226: cpufreq_setpolicy(policy);
227: #endif
228: power_policy = policy;
229: return 0;
230: }
231:
232: /*
233: * Get current power policy
234: */
235: int
236: pm_getpolicy(void)
237: {
238:
239: return power_policy;
240: }
241:
242: /*
243: * Open the pm device.
244: *
245: * The open operation is allowed to only one task. This can protect
246: * the critical ioctl operation from some malicious tasks. For example,
247: * the power off should be done by the privileged task like a process
248: * server.
249: */
250: static int
251: pm_open(device_t dev, int mode)
252: {
253:
254: if (nr_open > 0)
255: return EBUSY;
256: nr_open++;
257: return 0;
258: }
259:
260: static int
261: pm_close(device_t dev)
262: {
263:
264: if (nr_open != 1)
265: return EINVAL;
266: nr_open--;
267: return 0;
268: }
269:
270: static int
271: pm_ioctl(device_t dev, int cmd, u_long arg)
272: {
273: int err = 0;
274: int policy;
275:
276: switch (cmd) {
277: case PMIOC_SET_POWER:
278: switch (arg) {
279: case POWER_SUSPEND:
280: pm_suspend();
281: break;
282: case POWER_OFF:
283: pm_poweroff();
284: break;
285: case POWER_REBOOT:
286: pm_reboot();
287: break;
288: default:
289: return EINVAL;
290: }
291: break;
292: case PMIOC_SET_POLICY:
293: err = pm_setpolicy((int)arg);
294: break;
295: case PMIOC_GET_POLICY:
296: policy = pm_getpolicy();
297: if (umem_copyout(&policy, (int *)arg, sizeof(int)))
298: return EFAULT;
299: break;
300: default:
301: return EINVAL;
302: }
303: return err;
304: }
305:
306: /*
307: * Initialize
308: */
309: static int
310: pm_init(void)
311: {
312:
313: /* Create device object */
314: pm_dev = device_create(&pm_io, "pm", DF_CHR);
315: ASSERT(pm_dev);
316:
317: nr_open = 0;
318: idle_count = 0;
319: suspend_timeout = 0;
320: power_policy = DEFAULT_POWER_POLICY;
321: timer_init(&idle_timer);
322: printk("pm: Default power policy is %s mode\n",
323: (power_policy == PM_POWERSAVE) ? "power save" : "performance");
324: return 0;
325: }
CVSweb