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