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