xref: /linux-6.15/include/linux/pm_wakeup.h (revision 630d55e0)
11a59d1b8SThomas Gleixner /* SPDX-License-Identifier: GPL-2.0-or-later */
29a3df1f7SAlan Stern /*
39a3df1f7SAlan Stern  *  pm_wakeup.h - Power management wakeup interface
49a3df1f7SAlan Stern  *
59a3df1f7SAlan Stern  *  Copyright (C) 2008 Alan Stern
6074037ecSRafael J. Wysocki  *  Copyright (C) 2010 Rafael J. Wysocki, Novell Inc.
79a3df1f7SAlan Stern  */
89a3df1f7SAlan Stern 
99a3df1f7SAlan Stern #ifndef _LINUX_PM_WAKEUP_H
109a3df1f7SAlan Stern #define _LINUX_PM_WAKEUP_H
119a3df1f7SAlan Stern 
129a3df1f7SAlan Stern #ifndef _DEVICE_H_
13a7306f3cSNataniel Farzan # error "Please do not include this file directly."
149a3df1f7SAlan Stern #endif
159a3df1f7SAlan Stern 
16228c54efSDmitry Torokhov #include <linux/types.h>
17228c54efSDmitry Torokhov 
184990d4feSTony Lindgren struct wake_irq;
194990d4feSTony Lindgren 
20074037ecSRafael J. Wysocki /**
21074037ecSRafael J. Wysocki  * struct wakeup_source - Representation of wakeup sources
222430d12cSAlan Stern  *
234990d4feSTony Lindgren  * @name: Name of the wakeup source
24c8377adfSTri Vo  * @id: Wakeup source id
254990d4feSTony Lindgren  * @entry: Wakeup source list entry
264990d4feSTony Lindgren  * @lock: Wakeup source lock
274990d4feSTony Lindgren  * @wakeirq: Optional device specific wakeirq
284990d4feSTony Lindgren  * @timer: Wakeup timer list
294990d4feSTony Lindgren  * @timer_expires: Wakeup timer expiration
30074037ecSRafael J. Wysocki  * @total_time: Total time this wakeup source has been active.
31074037ecSRafael J. Wysocki  * @max_time: Maximum time this wakeup source has been continuously active.
3230e3ce6dSRafael J. Wysocki  * @last_time: Monotonic clock when the wakeup source's was touched last time.
3355850945SRafael J. Wysocki  * @prevent_sleep_time: Total time this source has been preventing autosleep.
34074037ecSRafael J. Wysocki  * @event_count: Number of signaled wakeup events.
351258ca80SChanwoo Choi  * @active_count: Number of times the wakeup source was activated.
361258ca80SChanwoo Choi  * @relax_count: Number of times the wakeup source was deactivated.
3730e3ce6dSRafael J. Wysocki  * @expire_count: Number of times the wakeup source's timeout has expired.
3830e3ce6dSRafael J. Wysocki  * @wakeup_count: Number of times the wakeup source might abort suspend.
39c8377adfSTri Vo  * @dev: Struct device for sysfs statistics about the wakeup source.
40074037ecSRafael J. Wysocki  * @active: Status of the wakeup source.
41e9bea8f9SRafael J. Wysocki  * @autosleep_enabled: Autosleep is active, so update @prevent_sleep_time.
429a3df1f7SAlan Stern  */
43074037ecSRafael J. Wysocki struct wakeup_source {
448671bbc1SRafael J. Wysocki 	const char 		*name;
45c8377adfSTri Vo 	int			id;
46074037ecSRafael J. Wysocki 	struct list_head	entry;
47074037ecSRafael J. Wysocki 	spinlock_t		lock;
484990d4feSTony Lindgren 	struct wake_irq		*wakeirq;
49074037ecSRafael J. Wysocki 	struct timer_list	timer;
50074037ecSRafael J. Wysocki 	unsigned long		timer_expires;
51074037ecSRafael J. Wysocki 	ktime_t total_time;
52074037ecSRafael J. Wysocki 	ktime_t max_time;
53074037ecSRafael J. Wysocki 	ktime_t last_time;
5455850945SRafael J. Wysocki 	ktime_t start_prevent_time;
5555850945SRafael J. Wysocki 	ktime_t prevent_sleep_time;
56074037ecSRafael J. Wysocki 	unsigned long		event_count;
57074037ecSRafael J. Wysocki 	unsigned long		active_count;
58074037ecSRafael J. Wysocki 	unsigned long		relax_count;
5930e3ce6dSRafael J. Wysocki 	unsigned long		expire_count;
6030e3ce6dSRafael J. Wysocki 	unsigned long		wakeup_count;
61c8377adfSTri Vo 	struct device		*dev;
6230e3ce6dSRafael J. Wysocki 	bool			active:1;
6355850945SRafael J. Wysocki 	bool			autosleep_enabled:1;
64074037ecSRafael J. Wysocki };
65074037ecSRafael J. Wysocki 
66b4941adbSRan Wang #define for_each_wakeup_source(ws) \
67b4941adbSRan Wang 	for ((ws) = wakeup_sources_walk_start();	\
68b4941adbSRan Wang 	     (ws);					\
69b4941adbSRan Wang 	     (ws) = wakeup_sources_walk_next((ws)))
70b4941adbSRan Wang 
71074037ecSRafael J. Wysocki #ifdef CONFIG_PM_SLEEP
72074037ecSRafael J. Wysocki 
73074037ecSRafael J. Wysocki /*
74074037ecSRafael J. Wysocki  * Changes to device_may_wakeup take effect on the next pm state change.
75074037ecSRafael J. Wysocki  */
769a3df1f7SAlan Stern 
device_can_wakeup(struct device * dev)77228c54efSDmitry Torokhov static inline bool device_can_wakeup(struct device *dev)
789a3df1f7SAlan Stern {
799a3df1f7SAlan Stern 	return dev->power.can_wakeup;
809a3df1f7SAlan Stern }
819a3df1f7SAlan Stern 
device_may_wakeup(struct device * dev)82228c54efSDmitry Torokhov static inline bool device_may_wakeup(struct device *dev)
839a3df1f7SAlan Stern {
84074037ecSRafael J. Wysocki 	return dev->power.can_wakeup && !!dev->power.wakeup;
859a3df1f7SAlan Stern }
869a3df1f7SAlan Stern 
device_wakeup_path(struct device * dev)874e1d9a73SPatrice Chotard static inline bool device_wakeup_path(struct device *dev)
884e1d9a73SPatrice Chotard {
894e1d9a73SPatrice Chotard 	return dev->power.wakeup_path;
904e1d9a73SPatrice Chotard }
914e1d9a73SPatrice Chotard 
device_set_wakeup_path(struct device * dev)92cf04ce78SUlf Hansson static inline void device_set_wakeup_path(struct device *dev)
93cf04ce78SUlf Hansson {
94cf04ce78SUlf Hansson 	dev->power.wakeup_path = true;
95cf04ce78SUlf Hansson }
96cf04ce78SUlf Hansson 
97074037ecSRafael J. Wysocki /* drivers/base/power/wakeup.c */
98074037ecSRafael J. Wysocki extern struct wakeup_source *wakeup_source_create(const char *name);
99074037ecSRafael J. Wysocki extern void wakeup_source_destroy(struct wakeup_source *ws);
100074037ecSRafael J. Wysocki extern void wakeup_source_add(struct wakeup_source *ws);
101074037ecSRafael J. Wysocki extern void wakeup_source_remove(struct wakeup_source *ws);
102c8377adfSTri Vo extern struct wakeup_source *wakeup_source_register(struct device *dev,
103c8377adfSTri Vo 						    const char *name);
104074037ecSRafael J. Wysocki extern void wakeup_source_unregister(struct wakeup_source *ws);
105b4941adbSRan Wang extern int wakeup_sources_read_lock(void);
106b4941adbSRan Wang extern void wakeup_sources_read_unlock(int idx);
107b4941adbSRan Wang extern struct wakeup_source *wakeup_sources_walk_start(void);
108b4941adbSRan Wang extern struct wakeup_source *wakeup_sources_walk_next(struct wakeup_source *ws);
109074037ecSRafael J. Wysocki extern int device_wakeup_enable(struct device *dev);
110afde996aSDhruva Gole extern void device_wakeup_disable(struct device *dev);
111cb8f51bdSRafael J. Wysocki extern void device_set_wakeup_capable(struct device *dev, bool capable);
112074037ecSRafael J. Wysocki extern int device_set_wakeup_enable(struct device *dev, bool enable);
113074037ecSRafael J. Wysocki extern void __pm_stay_awake(struct wakeup_source *ws);
114074037ecSRafael J. Wysocki extern void pm_stay_awake(struct device *dev);
115074037ecSRafael J. Wysocki extern void __pm_relax(struct wakeup_source *ws);
116074037ecSRafael J. Wysocki extern void pm_relax(struct device *dev);
1178a537eceSRafael J. Wysocki extern void pm_wakeup_ws_event(struct wakeup_source *ws, unsigned int msec, bool hard);
1188a537eceSRafael J. Wysocki extern void pm_wakeup_dev_event(struct device *dev, unsigned int msec, bool hard);
1199a3df1f7SAlan Stern 
120074037ecSRafael J. Wysocki #else /* !CONFIG_PM_SLEEP */
1219a3df1f7SAlan Stern 
device_set_wakeup_capable(struct device * dev,bool capable)122228c54efSDmitry Torokhov static inline void device_set_wakeup_capable(struct device *dev, bool capable)
123228c54efSDmitry Torokhov {
1242430d12cSAlan Stern 	dev->power.can_wakeup = capable;
125228c54efSDmitry Torokhov }
126c300bd2fSStephen Rothwell 
device_can_wakeup(struct device * dev)127228c54efSDmitry Torokhov static inline bool device_can_wakeup(struct device *dev)
1289a3df1f7SAlan Stern {
1299a3df1f7SAlan Stern 	return dev->power.can_wakeup;
1309a3df1f7SAlan Stern }
1319a3df1f7SAlan Stern 
wakeup_source_create(const char * name)132074037ecSRafael J. Wysocki static inline struct wakeup_source *wakeup_source_create(const char *name)
133074037ecSRafael J. Wysocki {
134074037ecSRafael J. Wysocki 	return NULL;
135074037ecSRafael J. Wysocki }
136074037ecSRafael J. Wysocki 
wakeup_source_destroy(struct wakeup_source * ws)137074037ecSRafael J. Wysocki static inline void wakeup_source_destroy(struct wakeup_source *ws) {}
138074037ecSRafael J. Wysocki 
wakeup_source_add(struct wakeup_source * ws)139074037ecSRafael J. Wysocki static inline void wakeup_source_add(struct wakeup_source *ws) {}
140074037ecSRafael J. Wysocki 
wakeup_source_remove(struct wakeup_source * ws)141074037ecSRafael J. Wysocki static inline void wakeup_source_remove(struct wakeup_source *ws) {}
142074037ecSRafael J. Wysocki 
wakeup_source_register(struct device * dev,const char * name)143c8377adfSTri Vo static inline struct wakeup_source *wakeup_source_register(struct device *dev,
144c8377adfSTri Vo 							   const char *name)
145074037ecSRafael J. Wysocki {
146074037ecSRafael J. Wysocki 	return NULL;
147074037ecSRafael J. Wysocki }
148074037ecSRafael J. Wysocki 
wakeup_source_unregister(struct wakeup_source * ws)149074037ecSRafael J. Wysocki static inline void wakeup_source_unregister(struct wakeup_source *ws) {}
150074037ecSRafael J. Wysocki 
device_wakeup_enable(struct device * dev)151074037ecSRafael J. Wysocki static inline int device_wakeup_enable(struct device *dev)
152074037ecSRafael J. Wysocki {
153805bdaecSRafael J. Wysocki 	dev->power.should_wakeup = true;
154805bdaecSRafael J. Wysocki 	return 0;
155074037ecSRafael J. Wysocki }
156074037ecSRafael J. Wysocki 
device_wakeup_disable(struct device * dev)157afde996aSDhruva Gole static inline void device_wakeup_disable(struct device *dev)
158074037ecSRafael J. Wysocki {
159805bdaecSRafael J. Wysocki 	dev->power.should_wakeup = false;
160805bdaecSRafael J. Wysocki }
161805bdaecSRafael J. Wysocki 
device_set_wakeup_enable(struct device * dev,bool enable)162805bdaecSRafael J. Wysocki static inline int device_set_wakeup_enable(struct device *dev, bool enable)
163805bdaecSRafael J. Wysocki {
164805bdaecSRafael J. Wysocki 	dev->power.should_wakeup = enable;
165074037ecSRafael J. Wysocki 	return 0;
166074037ecSRafael J. Wysocki }
167074037ecSRafael J. Wysocki 
device_may_wakeup(struct device * dev)168805bdaecSRafael J. Wysocki static inline bool device_may_wakeup(struct device *dev)
169074037ecSRafael J. Wysocki {
170805bdaecSRafael J. Wysocki 	return dev->power.can_wakeup && dev->power.should_wakeup;
171074037ecSRafael J. Wysocki }
172074037ecSRafael J. Wysocki 
device_wakeup_path(struct device * dev)1734e1d9a73SPatrice Chotard static inline bool device_wakeup_path(struct device *dev)
1744e1d9a73SPatrice Chotard {
1754e1d9a73SPatrice Chotard 	return false;
1764e1d9a73SPatrice Chotard }
1774e1d9a73SPatrice Chotard 
device_set_wakeup_path(struct device * dev)178cf04ce78SUlf Hansson static inline void device_set_wakeup_path(struct device *dev) {}
179cf04ce78SUlf Hansson 
__pm_stay_awake(struct wakeup_source * ws)180074037ecSRafael J. Wysocki static inline void __pm_stay_awake(struct wakeup_source *ws) {}
181074037ecSRafael J. Wysocki 
pm_stay_awake(struct device * dev)182074037ecSRafael J. Wysocki static inline void pm_stay_awake(struct device *dev) {}
183074037ecSRafael J. Wysocki 
__pm_relax(struct wakeup_source * ws)184074037ecSRafael J. Wysocki static inline void __pm_relax(struct wakeup_source *ws) {}
185074037ecSRafael J. Wysocki 
pm_relax(struct device * dev)186074037ecSRafael J. Wysocki static inline void pm_relax(struct device *dev) {}
187074037ecSRafael J. Wysocki 
pm_wakeup_ws_event(struct wakeup_source * ws,unsigned int msec,bool hard)1888a537eceSRafael J. Wysocki static inline void pm_wakeup_ws_event(struct wakeup_source *ws,
1898a537eceSRafael J. Wysocki 				      unsigned int msec, bool hard) {}
190074037ecSRafael J. Wysocki 
pm_wakeup_dev_event(struct device * dev,unsigned int msec,bool hard)1918a537eceSRafael J. Wysocki static inline void pm_wakeup_dev_event(struct device *dev, unsigned int msec,
1928a537eceSRafael J. Wysocki 				       bool hard) {}
193074037ecSRafael J. Wysocki 
194074037ecSRafael J. Wysocki #endif /* !CONFIG_PM_SLEEP */
1959a3df1f7SAlan Stern 
device_awake_path(struct device * dev)19610bb4e4aSUlf Hansson static inline bool device_awake_path(struct device *dev)
19710bb4e4aSUlf Hansson {
19810bb4e4aSUlf Hansson 	return device_wakeup_path(dev);
19910bb4e4aSUlf Hansson }
20010bb4e4aSUlf Hansson 
device_set_awake_path(struct device * dev)20110bb4e4aSUlf Hansson static inline void device_set_awake_path(struct device *dev)
20210bb4e4aSUlf Hansson {
20310bb4e4aSUlf Hansson 	device_set_wakeup_path(dev);
20410bb4e4aSUlf Hansson }
20510bb4e4aSUlf Hansson 
__pm_wakeup_event(struct wakeup_source * ws,unsigned int msec)2068a537eceSRafael J. Wysocki static inline void __pm_wakeup_event(struct wakeup_source *ws, unsigned int msec)
2078a537eceSRafael J. Wysocki {
208*630d55e0SZijun Hu 	pm_wakeup_ws_event(ws, msec, false);
2098a537eceSRafael J. Wysocki }
2108a537eceSRafael J. Wysocki 
pm_wakeup_event(struct device * dev,unsigned int msec)2118a537eceSRafael J. Wysocki static inline void pm_wakeup_event(struct device *dev, unsigned int msec)
2128a537eceSRafael J. Wysocki {
213*630d55e0SZijun Hu 	pm_wakeup_dev_event(dev, msec, false);
2148a537eceSRafael J. Wysocki }
2158a537eceSRafael J. Wysocki 
pm_wakeup_hard_event(struct device * dev)2168a537eceSRafael J. Wysocki static inline void pm_wakeup_hard_event(struct device *dev)
2178a537eceSRafael J. Wysocki {
218*630d55e0SZijun Hu 	pm_wakeup_dev_event(dev, 0, true);
2198a537eceSRafael J. Wysocki }
2208a537eceSRafael J. Wysocki 
22109d3154aSBjorn Helgaas /**
22209d3154aSBjorn Helgaas  * device_init_wakeup - Device wakeup initialization.
22309d3154aSBjorn Helgaas  * @dev: Device to handle.
22409d3154aSBjorn Helgaas  * @enable: Whether or not to enable @dev as a wakeup device.
22509d3154aSBjorn Helgaas  *
22609d3154aSBjorn Helgaas  * By default, most devices should leave wakeup disabled.  The exceptions are
22709d3154aSBjorn Helgaas  * devices that everyone expects to be wakeup sources: keyboards, power buttons,
22809d3154aSBjorn Helgaas  * possibly network interfaces, etc.  Also, devices that don't generate their
22909d3154aSBjorn Helgaas  * own wakeup requests but merely forward requests from one bus to another
23009d3154aSBjorn Helgaas  * (like PCI bridges) should have wakeup enabled by default.
23109d3154aSBjorn Helgaas  */
device_init_wakeup(struct device * dev,bool enable)23209d3154aSBjorn Helgaas static inline int device_init_wakeup(struct device *dev, bool enable)
23309d3154aSBjorn Helgaas {
23409d3154aSBjorn Helgaas 	if (enable) {
23509d3154aSBjorn Helgaas 		device_set_wakeup_capable(dev, true);
23609d3154aSBjorn Helgaas 		return device_wakeup_enable(dev);
2373642c7edSDhruva Gole 	}
23809d3154aSBjorn Helgaas 	device_wakeup_disable(dev);
23909d3154aSBjorn Helgaas 	device_set_wakeup_capable(dev, false);
24009d3154aSBjorn Helgaas 	return 0;
24109d3154aSBjorn Helgaas }
24209d3154aSBjorn Helgaas 
device_disable_wakeup(void * dev)243b3172683SJoe Hattori static void device_disable_wakeup(void *dev)
244b3172683SJoe Hattori {
245b3172683SJoe Hattori 	device_init_wakeup(dev, false);
246b3172683SJoe Hattori }
247b3172683SJoe Hattori 
248b3172683SJoe Hattori /**
249b3172683SJoe Hattori  * devm_device_init_wakeup - Resource managed device wakeup initialization.
250b3172683SJoe Hattori  * @dev: Device to handle.
251b3172683SJoe Hattori  *
252b3172683SJoe Hattori  * This function is the devm managed version of device_init_wakeup(dev, true).
253b3172683SJoe Hattori  */
devm_device_init_wakeup(struct device * dev)254b3172683SJoe Hattori static inline int devm_device_init_wakeup(struct device *dev)
255b3172683SJoe Hattori {
256b3172683SJoe Hattori 	device_init_wakeup(dev, true);
257b3172683SJoe Hattori 	return devm_add_action_or_reset(dev, device_disable_wakeup, dev);
258b3172683SJoe Hattori }
259b3172683SJoe Hattori 
2609a3df1f7SAlan Stern #endif /* _LINUX_PM_WAKEUP_H */
261