pm.h 11.5 KB
Newer Older
Linus Torvalds's avatar
Linus Torvalds committed
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
/*
 *  pm.h - Power management interface
 *
 *  Copyright (C) 2000 Andrew Henroid
 *
 *  This program is free software; you can redistribute it and/or modify
 *  it under the terms of the GNU General Public License as published by
 *  the Free Software Foundation; either version 2 of the License, or
 *  (at your option) any later version.
 *
 *  This program is distributed in the hope that it will be useful,
 *  but WITHOUT ANY WARRANTY; without even the implied warranty of
 *  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 *  GNU General Public License for more details.
 *
 *  You should have received a copy of the GNU General Public License
 *  along with this program; if not, write to the Free Software
 *  Foundation, Inc., 59 Temple Place, Suite 330, Boston, MA  02111-1307  USA
 */

#ifndef _LINUX_PM_H
#define _LINUX_PM_H

#ifdef __KERNEL__

#include <linux/list.h>
#include <asm/atomic.h>

/*
 * Power management requests... these are passed to pm_send_all() and friends.
 *
 * these functions are old and deprecated, see below.
 */
typedef int __bitwise pm_request_t;

#define PM_SUSPEND	((__force pm_request_t) 1)	/* enter D1-D3 */
#define PM_RESUME	((__force pm_request_t) 2)	/* enter D0 */


/*
 * Device types... these are passed to pm_register
 */
typedef int __bitwise pm_dev_t;

#define PM_UNKNOWN_DEV	((__force pm_dev_t) 0)	/* generic */
#define PM_SYS_DEV	((__force pm_dev_t) 1)	/* system device (fan, KB controller, ...) */
#define PM_PCI_DEV	((__force pm_dev_t) 2)	/* PCI device */
#define PM_USB_DEV	((__force pm_dev_t) 3)	/* USB device */
#define PM_SCSI_DEV	((__force pm_dev_t) 4)	/* SCSI device */
#define PM_ISA_DEV	((__force pm_dev_t) 5)	/* ISA device */
#define	PM_MTD_DEV	((__force pm_dev_t) 6)	/* Memory Technology Device */

/*
 * System device hardware ID (PnP) values
 */
enum
{
	PM_SYS_UNKNOWN = 0x00000000, /* generic */
	PM_SYS_KBC =	 0x41d00303, /* keyboard controller */
	PM_SYS_COM =	 0x41d00500, /* serial port */
	PM_SYS_IRDA =	 0x41d00510, /* IRDA controller */
	PM_SYS_FDC =	 0x41d00700, /* floppy controller */
	PM_SYS_VGA =	 0x41d00900, /* VGA controller */
	PM_SYS_PCMCIA =	 0x41d00e00, /* PCMCIA controller */
};

/*
 * Device identifier
 */
#define PM_PCI_ID(dev) ((dev)->bus->number << 16 | (dev)->devfn)

/*
 * Request handler callback
 */
struct pm_dev;

typedef int (*pm_callback)(struct pm_dev *dev, pm_request_t rqst, void *data);

/*
 * Dynamic device information
 */
struct pm_dev
{
	pm_dev_t	 type;
	unsigned long	 id;
	pm_callback	 callback;
	void		*data;

	unsigned long	 flags;
	unsigned long	 state;
	unsigned long	 prev_state;

	struct list_head entry;
};

/* Functions above this comment are list-based old-style power
 * managment. Please avoid using them.  */

/*
 * Callbacks for platform drivers to implement.
 */
extern void (*pm_idle)(void);
extern void (*pm_power_off)(void);

typedef int __bitwise suspend_state_t;

#define PM_SUSPEND_ON		((__force suspend_state_t) 0)
#define PM_SUSPEND_STANDBY	((__force suspend_state_t) 1)
#define PM_SUSPEND_MEM		((__force suspend_state_t) 3)
#define PM_SUSPEND_DISK		((__force suspend_state_t) 4)
#define PM_SUSPEND_MAX		((__force suspend_state_t) 5)

typedef int __bitwise suspend_disk_method_t;

115
116
/* invalid must be 0 so struct pm_ops initialisers can leave it out */
#define PM_DISK_INVALID		((__force suspend_disk_method_t) 0)
117
118
119
120
121
122
#define	PM_DISK_PLATFORM	((__force suspend_disk_method_t) 1)
#define	PM_DISK_SHUTDOWN	((__force suspend_disk_method_t) 2)
#define	PM_DISK_REBOOT		((__force suspend_disk_method_t) 3)
#define	PM_DISK_TEST		((__force suspend_disk_method_t) 4)
#define	PM_DISK_TESTPROC	((__force suspend_disk_method_t) 5)
#define	PM_DISK_MAX		((__force suspend_disk_method_t) 6)
Linus Torvalds's avatar
Linus Torvalds committed
123

124
125
126
127
/**
 * struct pm_ops - Callbacks for managing platform dependent suspend states.
 * @valid: Callback to determine whether the given state can be entered.
 * 	If %CONFIG_SOFTWARE_SUSPEND is set then %PM_SUSPEND_DISK is
128
129
130
131
132
133
 *	always valid and never passed to this call. If not assigned,
 *	no suspend states are valid.
 *	Valid states are advertised in /sys/power/state but can still
 *	be rejected by prepare or enter if the conditions aren't right.
 *	There is a %pm_valid_only_mem function available that can be assigned
 *	to this if you only implement mem sleep.
134
135
136
137
138
139
140
141
142
143
 *
 * @prepare: Prepare the platform for the given suspend state. Can return a
 *	negative error code if necessary.
 *
 * @enter: Enter the given suspend state, must be assigned. Can return a
 *	negative error code if necessary.
 *
 * @finish: Called when the system has left the given state and all devices
 *	are resumed. The return value is ignored.
 *
144
145
146
147
148
149
150
151
152
153
 * @pm_disk_mode: The generic code always allows one of the shutdown methods
 *	%PM_DISK_SHUTDOWN, %PM_DISK_REBOOT, %PM_DISK_TEST and
 *	%PM_DISK_TESTPROC. If this variable is set, the mode it is set
 *	to is allowed in addition to those modes and is also made default.
 *	When this mode is sent selected, the @prepare call will be called
 *	before suspending to disk (if present), the @enter call should be
 *	present and will be called after all state has been saved and the
 *	machine is ready to be powered off; the @finish callback is called
 *	after state has been restored. All these calls are called with
 *	%PM_SUSPEND_DISK as the state.
154
 */
Linus Torvalds's avatar
Linus Torvalds committed
155
struct pm_ops {
156
	int (*valid)(suspend_state_t state);
Linus Torvalds's avatar
Linus Torvalds committed
157
158
159
	int (*prepare)(suspend_state_t state);
	int (*enter)(suspend_state_t state);
	int (*finish)(suspend_state_t state);
160
	suspend_disk_method_t pm_disk_mode;
Linus Torvalds's avatar
Linus Torvalds committed
161
162
};

163
164
165
166
167
/**
 * pm_set_ops - set platform dependent power management ops
 * @pm_ops: The new power management operations to set.
 */
extern void pm_set_ops(struct pm_ops *pm_ops);
Alexey Starikovskiy's avatar
Alexey Starikovskiy committed
168
extern struct pm_ops *pm_ops;
Linus Torvalds's avatar
Linus Torvalds committed
169
170
extern int pm_suspend(suspend_state_t state);

171
extern int pm_valid_only_mem(suspend_state_t state);
Linus Torvalds's avatar
Linus Torvalds committed
172

173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
/**
 * arch_suspend_disable_irqs - disable IRQs for suspend
 *
 * Disables IRQs (in the default case). This is a weak symbol in the common
 * code and thus allows architectures to override it if more needs to be
 * done. Not called for suspend to disk.
 */
extern void arch_suspend_disable_irqs(void);

/**
 * arch_suspend_enable_irqs - enable IRQs after suspend
 *
 * Enables IRQs (in the default case). This is a weak symbol in the common
 * code and thus allows architectures to override it if more needs to be
 * done. Not called for suspend to disk.
 */
extern void arch_suspend_enable_irqs(void);

Linus Torvalds's avatar
Linus Torvalds committed
191
192
193
194
195
196
/*
 * Device power management
 */

struct device;

197
198
199
typedef struct pm_message {
	int event;
} pm_message_t;
Linus Torvalds's avatar
Linus Torvalds committed
200
201

/*
David Brownell's avatar
David Brownell committed
202
203
204
205
206
207
 * Several driver power state transitions are externally visible, affecting
 * the state of pending I/O queues and (for drivers that touch hardware)
 * interrupts, wakeups, DMA, and other hardware state.  There may also be
 * internal transitions to various low power modes, which are transparent
 * to the rest of the driver stack (such as a driver that's ON gating off
 * clocks which are not in active use).
Linus Torvalds's avatar
Linus Torvalds committed
208
 *
David Brownell's avatar
David Brownell committed
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
 * One transition is triggered by resume(), after a suspend() call; the
 * message is implicit:
 *
 * ON		Driver starts working again, responding to hardware events
 * 		and software requests.  The hardware may have gone through
 * 		a power-off reset, or it may have maintained state from the
 * 		previous suspend() which the driver will rely on while
 * 		resuming.  On most platforms, there are no restrictions on
 * 		availability of resources like clocks during resume().
 *
 * Other transitions are triggered by messages sent using suspend().  All
 * these transitions quiesce the driver, so that I/O queues are inactive.
 * That commonly entails turning off IRQs and DMA; there may be rules
 * about how to quiesce that are specific to the bus or the device's type.
 * (For example, network drivers mark the link state.)  Other details may
 * differ according to the message:
 *
 * SUSPEND	Quiesce, enter a low power device state appropriate for
 * 		the upcoming system state (such as PCI_D3hot), and enable
 * 		wakeup events as appropriate.
 *
 * FREEZE	Quiesce operations so that a consistent image can be saved;
 * 		but do NOT otherwise enter a low power device state, and do
 * 		NOT emit system wakeup events.
 *
 * PRETHAW	Quiesce as if for FREEZE; additionally, prepare for restoring
 * 		the system from a snapshot taken after an earlier FREEZE.
 * 		Some drivers will need to reset their hardware state instead
 * 		of preserving it, to ensure that it's never mistaken for the
 * 		state which that earlier snapshot had set up.
 *
 * A minimally power-aware driver treats all messages as SUSPEND, fully
 * reinitializes its device during resume() -- whether or not it was reset
 * during the suspend/resume cycle -- and can't issue wakeup events.
 *
 * More power-aware drivers may also use low power states at runtime as
 * well as during system sleep states like PM_SUSPEND_STANDBY.  They may
 * be able to use wakeup events to exit from runtime low-power states,
 * or from system low-power states such as standby or suspend-to-RAM.
Linus Torvalds's avatar
Linus Torvalds committed
248
249
 */

250
251
252
#define PM_EVENT_ON 0
#define PM_EVENT_FREEZE 1
#define PM_EVENT_SUSPEND 2
David Brownell's avatar
David Brownell committed
253
#define PM_EVENT_PRETHAW 3
254
255

#define PMSG_FREEZE	((struct pm_message){ .event = PM_EVENT_FREEZE, })
David Brownell's avatar
David Brownell committed
256
#define PMSG_PRETHAW	((struct pm_message){ .event = PM_EVENT_PRETHAW, })
257
258
#define PMSG_SUSPEND	((struct pm_message){ .event = PM_EVENT_SUSPEND, })
#define PMSG_ON		((struct pm_message){ .event = PM_EVENT_ON, })
Linus Torvalds's avatar
Linus Torvalds committed
259
260
261

struct dev_pm_info {
	pm_message_t		power_state;
262
	unsigned		can_wakeup:1;
Linus Torvalds's avatar
Linus Torvalds committed
263
#ifdef	CONFIG_PM
264
	unsigned		should_wakeup:1;
Linus Torvalds's avatar
Linus Torvalds committed
265
266
267
268
269
270
271
272
273
274
275
276
277
	pm_message_t		prev_state;
	void			* saved_state;
	struct device		* pm_parent;
	struct list_head	entry;
#endif
};

extern void device_pm_set_parent(struct device * dev, struct device * parent);

extern int device_power_down(pm_message_t state);
extern void device_power_up(void);
extern void device_resume(void);

278
#ifdef CONFIG_PM
279
280
extern suspend_disk_method_t pm_disk_mode;

281
extern int device_suspend(pm_message_t state);
282
extern int device_prepare_suspend(pm_message_t state);
283
284
285
286
287
288

#define device_set_wakeup_enable(dev,val) \
	((dev)->power.should_wakeup = !!(val))
#define device_may_wakeup(dev) \
	(device_can_wakeup(dev) && (dev)->power.should_wakeup)

289
290
extern int dpm_runtime_suspend(struct device *, pm_message_t);
extern void dpm_runtime_resume(struct device *);
291
292
293
294
295
296
extern void __suspend_report_result(const char *function, void *fn, int ret);

#define suspend_report_result(fn, ret)					\
	do {								\
		__suspend_report_result(__FUNCTION__, fn, ret);		\
	} while (0)
297

298
299
300
301
302
303
304
305
306
307
308
309
310
311
/*
 * Platform hook to activate device wakeup capability, if that's not already
 * handled by enable_irq_wake() etc.
 * Returns zero on success, else negative errno
 */
extern int (*platform_enable_wakeup)(struct device *dev, int is_on);

static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
{
	if (platform_enable_wakeup)
		return (*platform_enable_wakeup)(dev, is_on);
	return 0;
}

312
313
#else /* !CONFIG_PM */

314
315
316
317
static inline int device_suspend(pm_message_t state)
{
	return 0;
}
318
319
320
321

#define device_set_wakeup_enable(dev,val)	do{}while(0)
#define device_may_wakeup(dev)			(0)

322
323
324
325
326
327
328
329
330
static inline int dpm_runtime_suspend(struct device * dev, pm_message_t state)
{
	return 0;
}

static inline void dpm_runtime_resume(struct device * dev)
{
}

331
332
#define suspend_report_result(fn, ret) do { } while (0)

333
334
335
336
337
static inline int call_platform_enable_wakeup(struct device *dev, int is_on)
{
	return -EIO;
}

338
#endif
Linus Torvalds's avatar
Linus Torvalds committed
339

340
341
342
343
344
345
346
347
348
349
350
/* changes to device_may_wakeup take effect on the next pm state change.
 * by default, devices should wakeup if they can.
 */
#define device_can_wakeup(dev) \
	((dev)->power.can_wakeup)
#define device_init_wakeup(dev,val) \
	do { \
		device_can_wakeup(dev) = !!(val); \
		device_set_wakeup_enable(dev,val); \
	} while(0)

Linus Torvalds's avatar
Linus Torvalds committed
351
352
353
#endif /* __KERNEL__ */

#endif /* _LINUX_PM_H */