1*5113495bSYour Name /*
2*5113495bSYour Name * Copyright (c) 2013-2021 The Linux Foundation. All rights reserved.
3*5113495bSYour Name * Copyright (c) 2022-2023 Qualcomm Innovation Center, Inc. All rights reserved.
4*5113495bSYour Name *
5*5113495bSYour Name * Permission to use, copy, modify, and/or distribute this software for any
6*5113495bSYour Name * purpose with or without fee is hereby granted, provided that the above
7*5113495bSYour Name * copyright notice and this permission notice appear in all copies.
8*5113495bSYour Name
9*5113495bSYour Name * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
10*5113495bSYour Name * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
11*5113495bSYour Name * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR
12*5113495bSYour Name * ANY SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
13*5113495bSYour Name * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN
14*5113495bSYour Name * ACTION OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF
15*5113495bSYour Name * OR IN CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
16*5113495bSYour Name */
17*5113495bSYour Name
18*5113495bSYour Name #ifndef __HIF_RUNTIME_PM_H__
19*5113495bSYour Name #define __HIF_RUNTIME_PM_H__
20*5113495bSYour Name
21*5113495bSYour Name /**
22*5113495bSYour Name * enum hif_rtpm_fill_type - Caller type for Runtime PM stats fill
23*5113495bSYour Name * @HIF_RTPM_FILL_TYPE_SYSFS: Sysfs is caller for Runtime PM stats
24*5113495bSYour Name * @HIF_RTPM_FILL_TYPE_DEBUGFS: Debugfs is caller for Runtime PM stats
25*5113495bSYour Name * @HIF_RTPM_FILL_TYPE_MAX: max value
26*5113495bSYour Name */
27*5113495bSYour Name enum hif_rtpm_fill_type {
28*5113495bSYour Name HIF_RTPM_FILL_TYPE_SYSFS,
29*5113495bSYour Name HIF_RTPM_FILL_TYPE_DEBUGFS,
30*5113495bSYour Name HIF_RTPM_FILL_TYPE_MAX,
31*5113495bSYour Name };
32*5113495bSYour Name
33*5113495bSYour Name #ifdef FEATURE_RUNTIME_PM
34*5113495bSYour Name #include <linux/pm_runtime.h>
35*5113495bSYour Name
36*5113495bSYour Name /**
37*5113495bSYour Name * enum hif_rtpm_state - Driver States for Runtime Power Management
38*5113495bSYour Name * @HIF_RTPM_STATE_NONE: runtime pm is off
39*5113495bSYour Name * @HIF_RTPM_STATE_ON: runtime pm is active and link is active
40*5113495bSYour Name * @HIF_RTPM_STATE_RESUMING: a runtime resume is in progress
41*5113495bSYour Name * @HIF_RTPM_STATE_RESUMING_LINKUP: Link is up during resume
42*5113495bSYour Name * @HIF_RTPM_STATE_SUSPENDING: a runtime suspend is in progress
43*5113495bSYour Name * @HIF_RTPM_STATE_SUSPENDED: the driver is runtime suspended
44*5113495bSYour Name */
45*5113495bSYour Name enum hif_rtpm_state {
46*5113495bSYour Name HIF_RTPM_STATE_NONE,
47*5113495bSYour Name HIF_RTPM_STATE_ON,
48*5113495bSYour Name HIF_RTPM_STATE_RESUMING_LINKUP,
49*5113495bSYour Name HIF_RTPM_STATE_RESUMING,
50*5113495bSYour Name HIF_RTPM_STATE_SUSPENDING,
51*5113495bSYour Name HIF_RTPM_STATE_SUSPENDED,
52*5113495bSYour Name };
53*5113495bSYour Name
54*5113495bSYour Name /**
55*5113495bSYour Name * struct hif_rtpm_state_stats - Runtime PM stats
56*5113495bSYour Name * @resume_count: count of resume calls done
57*5113495bSYour Name * @suspend_count: count of suspend calls done
58*5113495bSYour Name * @suspend_err_count: count of suspend calls failed
59*5113495bSYour Name * @resume_ts: Last resume call timestamp
60*5113495bSYour Name * @suspend_ts: Last suspend call timestamp
61*5113495bSYour Name * @suspend_err_ts: Last suspend call fail timestamp
62*5113495bSYour Name * @last_busy_ts: Last busy timestamp marked
63*5113495bSYour Name * @last_busy_id:
64*5113495bSYour Name * @last_busy_marker:
65*5113495bSYour Name * @request_resume_ts: Last request resume done timestamp
66*5113495bSYour Name * @request_resume_id: Client ID requesting resume
67*5113495bSYour Name * @prevent_suspend:
68*5113495bSYour Name * @allow_suspend:
69*5113495bSYour Name * @runtime_get_err:
70*5113495bSYour Name */
71*5113495bSYour Name struct hif_rtpm_state_stats {
72*5113495bSYour Name uint32_t resume_count;
73*5113495bSYour Name uint32_t suspend_count;
74*5113495bSYour Name uint32_t suspend_err_count;
75*5113495bSYour Name uint64_t resume_ts;
76*5113495bSYour Name uint64_t suspend_ts;
77*5113495bSYour Name uint64_t suspend_err_ts;
78*5113495bSYour Name uint64_t last_busy_ts;
79*5113495bSYour Name uint32_t last_busy_id;
80*5113495bSYour Name void *last_busy_marker;
81*5113495bSYour Name uint64_t request_resume_ts;
82*5113495bSYour Name uint64_t request_resume_id;
83*5113495bSYour Name uint32_t prevent_suspend;
84*5113495bSYour Name uint32_t allow_suspend;
85*5113495bSYour Name uint32_t runtime_get_err;
86*5113495bSYour Name };
87*5113495bSYour Name
88*5113495bSYour Name #define HIF_RTPM_BUSY_HIST_MAX 16
89*5113495bSYour Name #define HIF_RTPM_BUSY_HIST_MASK (HIF_RTPM_BUSY_HIST_MAX - 1)
90*5113495bSYour Name
91*5113495bSYour Name /**
92*5113495bSYour Name * struct hif_rtpm_last_busy_hist - Runtime last busy hist
93*5113495bSYour Name * @last_busy_cnt: count of last busy mark
94*5113495bSYour Name * @last_busy_idx: last busy history index
95*5113495bSYour Name * @last_busy_ts: last busy marked timestamp
96*5113495bSYour Name */
97*5113495bSYour Name struct hif_rtpm_last_busy_hist {
98*5113495bSYour Name unsigned long last_busy_cnt;
99*5113495bSYour Name unsigned long last_busy_idx;
100*5113495bSYour Name uint64_t last_busy_ts[HIF_RTPM_BUSY_HIST_MAX];
101*5113495bSYour Name };
102*5113495bSYour Name
103*5113495bSYour Name /**
104*5113495bSYour Name * struct hif_rtpm_client - Runtime PM client structure
105*5113495bSYour Name * @hif_rtpm_cbk: Callback during resume if get called at suspend and failed
106*5113495bSYour Name * @active_count: current active status of client
107*5113495bSYour Name * @get_count: count of get calls by this client
108*5113495bSYour Name * @put_count: count of put calls by this client
109*5113495bSYour Name * @last_busy_cnt:
110*5113495bSYour Name * @get_ts: Last get called timestamp
111*5113495bSYour Name * @put_ts: Last put called timestamp
112*5113495bSYour Name * @last_busy_ts:
113*5113495bSYour Name */
114*5113495bSYour Name struct hif_rtpm_client {
115*5113495bSYour Name void (*hif_rtpm_cbk)(void);
116*5113495bSYour Name qdf_atomic_t active_count;
117*5113495bSYour Name qdf_atomic_t get_count;
118*5113495bSYour Name qdf_atomic_t put_count;
119*5113495bSYour Name uint32_t last_busy_cnt;
120*5113495bSYour Name uint64_t get_ts;
121*5113495bSYour Name uint64_t put_ts;
122*5113495bSYour Name uint64_t last_busy_ts;
123*5113495bSYour Name };
124*5113495bSYour Name
125*5113495bSYour Name /**
126*5113495bSYour Name * struct hif_rtpm_ctx - Runtime power management context
127*5113495bSYour Name * @enable_rpm:
128*5113495bSYour Name * @dev:
129*5113495bSYour Name * @runtime_lock: Lock to sync state changes with get calls
130*5113495bSYour Name * @runtime_suspend_lock: Suspend lock
131*5113495bSYour Name * @client_count: Number of clients currently registered
132*5113495bSYour Name * @clients: clients registered to use runtime PM module
133*5113495bSYour Name * @prevent_list_lock:
134*5113495bSYour Name * @prevent_list:
135*5113495bSYour Name * @prevent_cnt:
136*5113495bSYour Name * @pm_state: Current runtime pm state
137*5113495bSYour Name * @pending_job: bitmap to set the client job to be called at resume
138*5113495bSYour Name * @monitor_wake_intr: Monitor waking MSI for runtime PM
139*5113495bSYour Name * @stats: Runtime PM stats
140*5113495bSYour Name * @pm_dentry: debug fs entry
141*5113495bSYour Name * @cfg_delay:
142*5113495bSYour Name * @delay:
143*5113495bSYour Name * @busy_hist: busy histogram
144*5113495bSYour Name */
145*5113495bSYour Name struct hif_rtpm_ctx {
146*5113495bSYour Name bool enable_rpm;
147*5113495bSYour Name struct device *dev;
148*5113495bSYour Name qdf_spinlock_t runtime_lock;
149*5113495bSYour Name qdf_spinlock_t runtime_suspend_lock;
150*5113495bSYour Name unsigned int client_count;
151*5113495bSYour Name struct hif_rtpm_client *clients[HIF_RTPM_ID_MAX];
152*5113495bSYour Name qdf_spinlock_t prevent_list_lock;
153*5113495bSYour Name struct list_head prevent_list;
154*5113495bSYour Name uint32_t prevent_cnt;
155*5113495bSYour Name qdf_atomic_t pm_state;
156*5113495bSYour Name unsigned long pending_job;
157*5113495bSYour Name qdf_atomic_t monitor_wake_intr;
158*5113495bSYour Name struct hif_rtpm_state_stats stats;
159*5113495bSYour Name struct dentry *pm_dentry;
160*5113495bSYour Name int cfg_delay;
161*5113495bSYour Name int delay;
162*5113495bSYour Name struct hif_rtpm_last_busy_hist *busy_hist[CE_COUNT_MAX];
163*5113495bSYour Name };
164*5113495bSYour Name
165*5113495bSYour Name #define HIF_RTPM_DELAY_MIN 100
166*5113495bSYour Name #define HIF_RTPM_DELAY_MAX 10000
167*5113495bSYour Name
168*5113495bSYour Name /**
169*5113495bSYour Name * __hif_rtpm_enabled() - Check if runtime pm is enabled from kernel
170*5113495bSYour Name * @dev: device structure
171*5113495bSYour Name *
172*5113495bSYour Name * Return: true if enabled.
173*5113495bSYour Name */
__hif_rtpm_enabled(struct device * dev)174*5113495bSYour Name static inline bool __hif_rtpm_enabled(struct device *dev)
175*5113495bSYour Name {
176*5113495bSYour Name return pm_runtime_enabled(dev);
177*5113495bSYour Name }
178*5113495bSYour Name
179*5113495bSYour Name /**
180*5113495bSYour Name * __hif_rtpm_get() - Increment dev usage count and call resume function
181*5113495bSYour Name * @dev: device structure
182*5113495bSYour Name *
183*5113495bSYour Name * Increments usage count and internally queue resume work
184*5113495bSYour Name *
185*5113495bSYour Name * Return: 1 if state is active. 0 if resume is requested. Error otherwise.
186*5113495bSYour Name */
__hif_rtpm_get(struct device * dev)187*5113495bSYour Name static inline int __hif_rtpm_get(struct device *dev)
188*5113495bSYour Name {
189*5113495bSYour Name return pm_runtime_get(dev);
190*5113495bSYour Name }
191*5113495bSYour Name
192*5113495bSYour Name /**
193*5113495bSYour Name * __hif_rtpm_get_noresume() - Only increment dev usage count
194*5113495bSYour Name * @dev: device structure
195*5113495bSYour Name *
196*5113495bSYour Name * Return: Void
197*5113495bSYour Name */
__hif_rtpm_get_noresume(struct device * dev)198*5113495bSYour Name static inline void __hif_rtpm_get_noresume(struct device *dev)
199*5113495bSYour Name {
200*5113495bSYour Name pm_runtime_get_noresume(dev);
201*5113495bSYour Name }
202*5113495bSYour Name
203*5113495bSYour Name /**
204*5113495bSYour Name * __hif_rtpm_get_sync() - Increment usage count and set state to active
205*5113495bSYour Name * @dev: device structure
206*5113495bSYour Name *
207*5113495bSYour Name * Return: 1 if state is already active, 0 if state active was done.
208*5113495bSYour Name * Error otherwise.
209*5113495bSYour Name */
__hif_rtpm_get_sync(struct device * dev)210*5113495bSYour Name static inline int __hif_rtpm_get_sync(struct device *dev)
211*5113495bSYour Name {
212*5113495bSYour Name return pm_runtime_get_sync(dev);
213*5113495bSYour Name }
214*5113495bSYour Name
215*5113495bSYour Name /**
216*5113495bSYour Name * __hif_rtpm_put_auto() - Decrement usage count and call suspend function
217*5113495bSYour Name * @dev: device structure
218*5113495bSYour Name *
219*5113495bSYour Name * Decrements usage count and queue suspend work if usage count is 0
220*5113495bSYour Name *
221*5113495bSYour Name * Return: 0 if success. Error otherwise.
222*5113495bSYour Name */
__hif_rtpm_put_auto(struct device * dev)223*5113495bSYour Name static inline int __hif_rtpm_put_auto(struct device *dev)
224*5113495bSYour Name {
225*5113495bSYour Name return pm_runtime_put_autosuspend(dev);
226*5113495bSYour Name }
227*5113495bSYour Name
228*5113495bSYour Name /**
229*5113495bSYour Name * __hif_rtpm_put_noidle() - Decrement usage count
230*5113495bSYour Name * @dev: device structure
231*5113495bSYour Name *
232*5113495bSYour Name * Return: void
233*5113495bSYour Name */
__hif_rtpm_put_noidle(struct device * dev)234*5113495bSYour Name static inline void __hif_rtpm_put_noidle(struct device *dev)
235*5113495bSYour Name {
236*5113495bSYour Name pm_runtime_put_noidle(dev);
237*5113495bSYour Name }
238*5113495bSYour Name
239*5113495bSYour Name /**
240*5113495bSYour Name * __hif_rtpm_put_sync_suspend() - Decrement usage count
241*5113495bSYour Name * @dev: device structure
242*5113495bSYour Name *
243*5113495bSYour Name * Decrement usage_count of device and if 0 synchrounsly call suspend function
244*5113495bSYour Name *
245*5113495bSYour Name * Return: 0 if success. Error otherwise
246*5113495bSYour Name */
__hif_rtpm_put_sync_suspend(struct device * dev)247*5113495bSYour Name static inline int __hif_rtpm_put_sync_suspend(struct device *dev)
248*5113495bSYour Name {
249*5113495bSYour Name return pm_runtime_put_sync_suspend(dev);
250*5113495bSYour Name }
251*5113495bSYour Name
252*5113495bSYour Name /**
253*5113495bSYour Name * __hif_rtpm_set_autosuspend_delay() - Set delay to trigger RTPM suspend
254*5113495bSYour Name * @dev: device structure
255*5113495bSYour Name * @delay: delay in ms to be set
256*5113495bSYour Name *
257*5113495bSYour Name * Return: None
258*5113495bSYour Name */
259*5113495bSYour Name static inline
__hif_rtpm_set_autosuspend_delay(struct device * dev,int delay)260*5113495bSYour Name void __hif_rtpm_set_autosuspend_delay(struct device *dev, int delay)
261*5113495bSYour Name {
262*5113495bSYour Name pm_runtime_set_autosuspend_delay(dev, delay);
263*5113495bSYour Name }
264*5113495bSYour Name
265*5113495bSYour Name /**
266*5113495bSYour Name * __hif_rtpm_mark_last_busy() - Mark last busy timestamp
267*5113495bSYour Name * @dev: device structure
268*5113495bSYour Name *
269*5113495bSYour Name * Return: Void
270*5113495bSYour Name */
__hif_rtpm_mark_last_busy(struct device * dev)271*5113495bSYour Name static inline void __hif_rtpm_mark_last_busy(struct device *dev)
272*5113495bSYour Name {
273*5113495bSYour Name pm_runtime_mark_last_busy(dev);
274*5113495bSYour Name }
275*5113495bSYour Name
276*5113495bSYour Name /**
277*5113495bSYour Name * __hif_rtpm_resume() - Do Runtime PM Resume of bus
278*5113495bSYour Name * @dev: device structure
279*5113495bSYour Name *
280*5113495bSYour Name * Return: 0 if success. Error otherwise
281*5113495bSYour Name */
__hif_rtpm_resume(struct device * dev)282*5113495bSYour Name static inline int __hif_rtpm_resume(struct device *dev)
283*5113495bSYour Name {
284*5113495bSYour Name return pm_runtime_resume(dev);
285*5113495bSYour Name }
286*5113495bSYour Name
287*5113495bSYour Name /**
288*5113495bSYour Name * __hif_rtpm_request_resume() - Queue resume work
289*5113495bSYour Name * @dev: device structure
290*5113495bSYour Name *
291*5113495bSYour Name * Return: 1 if already active. 0 if successfully queued. Error otherwise
292*5113495bSYour Name */
__hif_rtpm_request_resume(struct device * dev)293*5113495bSYour Name static inline int __hif_rtpm_request_resume(struct device *dev)
294*5113495bSYour Name {
295*5113495bSYour Name return pm_request_resume(dev);
296*5113495bSYour Name }
297*5113495bSYour Name
298*5113495bSYour Name /**
299*5113495bSYour Name * hif_rtpm_open() - initialize runtime pm
300*5113495bSYour Name * @scn: hif ctx
301*5113495bSYour Name *
302*5113495bSYour Name * Return: None
303*5113495bSYour Name */
304*5113495bSYour Name void hif_rtpm_open(struct hif_softc *scn);
305*5113495bSYour Name
306*5113495bSYour Name /**
307*5113495bSYour Name * hif_rtpm_close() - close runtime pm
308*5113495bSYour Name * @scn: hif ctx
309*5113495bSYour Name *
310*5113495bSYour Name * ensure runtime_pm is stopped before closing the driver
311*5113495bSYour Name *
312*5113495bSYour Name * Return: None
313*5113495bSYour Name */
314*5113495bSYour Name void hif_rtpm_close(struct hif_softc *scn);
315*5113495bSYour Name
316*5113495bSYour Name /**
317*5113495bSYour Name * hif_rtpm_start() - start the runtime pm
318*5113495bSYour Name * @scn: hif context
319*5113495bSYour Name *
320*5113495bSYour Name * After this call, runtime pm will be active.
321*5113495bSYour Name *
322*5113495bSYour Name * Return: None
323*5113495bSYour Name */
324*5113495bSYour Name void hif_rtpm_start(struct hif_softc *scn);
325*5113495bSYour Name
326*5113495bSYour Name /**
327*5113495bSYour Name * hif_rtpm_stop() - stop runtime pm
328*5113495bSYour Name * @scn: hif context
329*5113495bSYour Name *
330*5113495bSYour Name * Turns off runtime pm and frees corresponding resources
331*5113495bSYour Name * that were acquired by hif_rtpm_start().
332*5113495bSYour Name *
333*5113495bSYour Name * Return: None
334*5113495bSYour Name */
335*5113495bSYour Name void hif_rtpm_stop(struct hif_softc *scn);
336*5113495bSYour Name
337*5113495bSYour Name /**
338*5113495bSYour Name * hif_rtpm_log_debug_stats() - fill buffer with runtime pm stats
339*5113495bSYour Name * @s: pointer to buffer to fill status
340*5113495bSYour Name * @type: type of caller
341*5113495bSYour Name *
342*5113495bSYour Name * Fills input buffer with runtime pm stats depending on caller type.
343*5113495bSYour Name *
344*5113495bSYour Name * Return: Num of bytes filled if caller type requires, else 0.
345*5113495bSYour Name */
346*5113495bSYour Name int hif_rtpm_log_debug_stats(void *s, enum hif_rtpm_fill_type type);
347*5113495bSYour Name
348*5113495bSYour Name #else
hif_rtpm_open(struct hif_softc * scn)349*5113495bSYour Name static inline void hif_rtpm_open(struct hif_softc *scn) {}
hif_rtpm_close(struct hif_softc * scn)350*5113495bSYour Name static inline void hif_rtpm_close(struct hif_softc *scn) {}
hif_rtpm_start(struct hif_softc * scn)351*5113495bSYour Name static inline void hif_rtpm_start(struct hif_softc *scn) {}
hif_rtpm_stop(struct hif_softc * scn)352*5113495bSYour Name static inline void hif_rtpm_stop(struct hif_softc *scn) {}
hif_rtpm_log_debug_stats(void * s,enum hif_rtpm_fill_type type)353*5113495bSYour Name static inline int hif_rtpm_log_debug_stats(void *s,
354*5113495bSYour Name enum hif_rtpm_fill_type type)
355*5113495bSYour Name {
356*5113495bSYour Name return 0;
357*5113495bSYour Name }
358*5113495bSYour Name #endif /* FEATURE_RUNTIME_PM */
359*5113495bSYour Name #endif /* __HIF_RUNTIME_PM_H__ */
360