• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
1 /* SPDX-License-Identifier: (GPL-2.0-only OR BSD-3-Clause) */
2 /*
3  * This file is provided under a dual BSD/GPLv2 license.  When using or
4  * redistributing this file, you may do so under either license.
5  *
6  * Copyright(c) 2018 Intel Corporation. All rights reserved.
7  *
8  * Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
9  */
10 
11 #ifndef __SOUND_SOC_SOF_IO_H
12 #define __SOUND_SOC_SOF_IO_H
13 
14 #include <linux/device.h>
15 #include <linux/interrupt.h>
16 #include <linux/kernel.h>
17 #include <linux/types.h>
18 #include <sound/pcm.h>
19 #include "sof-priv.h"
20 
21 #define sof_ops(sdev) \
22 	((sdev)->pdata->desc->ops)
23 
24 /* Mandatory operations are verified during probing */
25 
26 /* init */
snd_sof_probe(struct snd_sof_dev * sdev)27 static inline int snd_sof_probe(struct snd_sof_dev *sdev)
28 {
29 	return sof_ops(sdev)->probe(sdev);
30 }
31 
snd_sof_remove(struct snd_sof_dev * sdev)32 static inline int snd_sof_remove(struct snd_sof_dev *sdev)
33 {
34 	if (sof_ops(sdev)->remove)
35 		return sof_ops(sdev)->remove(sdev);
36 
37 	return 0;
38 }
39 
snd_sof_shutdown(struct snd_sof_dev * sdev)40 static inline int snd_sof_shutdown(struct snd_sof_dev *sdev)
41 {
42 	if (sof_ops(sdev)->shutdown)
43 		return sof_ops(sdev)->shutdown(sdev);
44 
45 	return 0;
46 }
47 
48 /* control */
49 
50 /*
51  * snd_sof_dsp_run returns the core mask of the cores that are available
52  * after successful fw boot
53  */
snd_sof_dsp_run(struct snd_sof_dev * sdev)54 static inline int snd_sof_dsp_run(struct snd_sof_dev *sdev)
55 {
56 	return sof_ops(sdev)->run(sdev);
57 }
58 
snd_sof_dsp_stall(struct snd_sof_dev * sdev,unsigned int core_mask)59 static inline int snd_sof_dsp_stall(struct snd_sof_dev *sdev, unsigned int core_mask)
60 {
61 	if (sof_ops(sdev)->stall)
62 		return sof_ops(sdev)->stall(sdev, core_mask);
63 
64 	return 0;
65 }
66 
snd_sof_dsp_reset(struct snd_sof_dev * sdev)67 static inline int snd_sof_dsp_reset(struct snd_sof_dev *sdev)
68 {
69 	if (sof_ops(sdev)->reset)
70 		return sof_ops(sdev)->reset(sdev);
71 
72 	return 0;
73 }
74 
75 /* dsp core power up/power down */
snd_sof_dsp_core_power_up(struct snd_sof_dev * sdev,unsigned int core_mask)76 static inline int snd_sof_dsp_core_power_up(struct snd_sof_dev *sdev,
77 					    unsigned int core_mask)
78 {
79 	int ret = 0;
80 
81 	core_mask &= ~sdev->enabled_cores_mask;
82 	if (sof_ops(sdev)->core_power_up && core_mask) {
83 		ret = sof_ops(sdev)->core_power_up(sdev, core_mask);
84 		if (!ret)
85 			sdev->enabled_cores_mask |= core_mask;
86 	}
87 
88 	return ret;
89 }
90 
snd_sof_dsp_core_power_down(struct snd_sof_dev * sdev,unsigned int core_mask)91 static inline int snd_sof_dsp_core_power_down(struct snd_sof_dev *sdev,
92 					      unsigned int core_mask)
93 {
94 	int ret = 0;
95 
96 	core_mask &= sdev->enabled_cores_mask;
97 	if (sof_ops(sdev)->core_power_down && core_mask) {
98 		ret = sof_ops(sdev)->core_power_down(sdev, core_mask);
99 		if (!ret)
100 			sdev->enabled_cores_mask &= ~core_mask;
101 	}
102 
103 	return ret;
104 }
105 
106 /* pre/post fw load */
snd_sof_dsp_pre_fw_run(struct snd_sof_dev * sdev)107 static inline int snd_sof_dsp_pre_fw_run(struct snd_sof_dev *sdev)
108 {
109 	if (sof_ops(sdev)->pre_fw_run)
110 		return sof_ops(sdev)->pre_fw_run(sdev);
111 
112 	return 0;
113 }
114 
snd_sof_dsp_post_fw_run(struct snd_sof_dev * sdev)115 static inline int snd_sof_dsp_post_fw_run(struct snd_sof_dev *sdev)
116 {
117 	if (sof_ops(sdev)->post_fw_run)
118 		return sof_ops(sdev)->post_fw_run(sdev);
119 
120 	return 0;
121 }
122 
123 /* parse platform specific extended manifest */
snd_sof_dsp_parse_platform_ext_manifest(struct snd_sof_dev * sdev,const struct sof_ext_man_elem_header * hdr)124 static inline int snd_sof_dsp_parse_platform_ext_manifest(struct snd_sof_dev *sdev,
125 							  const struct sof_ext_man_elem_header *hdr)
126 {
127 	if (sof_ops(sdev)->parse_platform_ext_manifest)
128 		return sof_ops(sdev)->parse_platform_ext_manifest(sdev, hdr);
129 
130 	return 0;
131 }
132 
133 /* misc */
134 
135 /**
136  * snd_sof_dsp_get_bar_index - Maps a section type with a BAR index
137  *
138  * @sdev: sof device
139  * @type: section type as described by snd_sof_fw_blk_type
140  *
141  * Returns the corresponding BAR index (a positive integer) or -EINVAL
142  * in case there is no mapping
143  */
snd_sof_dsp_get_bar_index(struct snd_sof_dev * sdev,u32 type)144 static inline int snd_sof_dsp_get_bar_index(struct snd_sof_dev *sdev, u32 type)
145 {
146 	if (sof_ops(sdev)->get_bar_index)
147 		return sof_ops(sdev)->get_bar_index(sdev, type);
148 
149 	return sdev->mmio_bar;
150 }
151 
snd_sof_dsp_get_mailbox_offset(struct snd_sof_dev * sdev)152 static inline int snd_sof_dsp_get_mailbox_offset(struct snd_sof_dev *sdev)
153 {
154 	if (sof_ops(sdev)->get_mailbox_offset)
155 		return sof_ops(sdev)->get_mailbox_offset(sdev);
156 
157 	dev_err(sdev->dev, "error: %s not defined\n", __func__);
158 	return -ENOTSUPP;
159 }
160 
snd_sof_dsp_get_window_offset(struct snd_sof_dev * sdev,u32 id)161 static inline int snd_sof_dsp_get_window_offset(struct snd_sof_dev *sdev,
162 						u32 id)
163 {
164 	if (sof_ops(sdev)->get_window_offset)
165 		return sof_ops(sdev)->get_window_offset(sdev, id);
166 
167 	dev_err(sdev->dev, "error: %s not defined\n", __func__);
168 	return -ENOTSUPP;
169 }
170 /* power management */
snd_sof_dsp_resume(struct snd_sof_dev * sdev)171 static inline int snd_sof_dsp_resume(struct snd_sof_dev *sdev)
172 {
173 	if (sof_ops(sdev)->resume)
174 		return sof_ops(sdev)->resume(sdev);
175 
176 	return 0;
177 }
178 
snd_sof_dsp_suspend(struct snd_sof_dev * sdev,u32 target_state)179 static inline int snd_sof_dsp_suspend(struct snd_sof_dev *sdev,
180 				      u32 target_state)
181 {
182 	if (sof_ops(sdev)->suspend)
183 		return sof_ops(sdev)->suspend(sdev, target_state);
184 
185 	return 0;
186 }
187 
snd_sof_dsp_runtime_resume(struct snd_sof_dev * sdev)188 static inline int snd_sof_dsp_runtime_resume(struct snd_sof_dev *sdev)
189 {
190 	if (sof_ops(sdev)->runtime_resume)
191 		return sof_ops(sdev)->runtime_resume(sdev);
192 
193 	return 0;
194 }
195 
snd_sof_dsp_runtime_suspend(struct snd_sof_dev * sdev)196 static inline int snd_sof_dsp_runtime_suspend(struct snd_sof_dev *sdev)
197 {
198 	if (sof_ops(sdev)->runtime_suspend)
199 		return sof_ops(sdev)->runtime_suspend(sdev);
200 
201 	return 0;
202 }
203 
snd_sof_dsp_runtime_idle(struct snd_sof_dev * sdev)204 static inline int snd_sof_dsp_runtime_idle(struct snd_sof_dev *sdev)
205 {
206 	if (sof_ops(sdev)->runtime_idle)
207 		return sof_ops(sdev)->runtime_idle(sdev);
208 
209 	return 0;
210 }
211 
snd_sof_dsp_hw_params_upon_resume(struct snd_sof_dev * sdev)212 static inline int snd_sof_dsp_hw_params_upon_resume(struct snd_sof_dev *sdev)
213 {
214 	if (sof_ops(sdev)->set_hw_params_upon_resume)
215 		return sof_ops(sdev)->set_hw_params_upon_resume(sdev);
216 	return 0;
217 }
218 
snd_sof_dsp_set_clk(struct snd_sof_dev * sdev,u32 freq)219 static inline int snd_sof_dsp_set_clk(struct snd_sof_dev *sdev, u32 freq)
220 {
221 	if (sof_ops(sdev)->set_clk)
222 		return sof_ops(sdev)->set_clk(sdev, freq);
223 
224 	return 0;
225 }
226 
227 static inline int
snd_sof_dsp_set_power_state(struct snd_sof_dev * sdev,const struct sof_dsp_power_state * target_state)228 snd_sof_dsp_set_power_state(struct snd_sof_dev *sdev,
229 			    const struct sof_dsp_power_state *target_state)
230 {
231 	int ret = 0;
232 
233 	mutex_lock(&sdev->power_state_access);
234 
235 	if (sof_ops(sdev)->set_power_state)
236 		ret = sof_ops(sdev)->set_power_state(sdev, target_state);
237 
238 	mutex_unlock(&sdev->power_state_access);
239 
240 	return ret;
241 }
242 
243 /* debug */
snd_sof_dsp_dbg_dump(struct snd_sof_dev * sdev,u32 flags)244 static inline void snd_sof_dsp_dbg_dump(struct snd_sof_dev *sdev, u32 flags)
245 {
246 	if (sof_ops(sdev)->dbg_dump)
247 		sof_ops(sdev)->dbg_dump(sdev, flags);
248 }
249 
snd_sof_ipc_dump(struct snd_sof_dev * sdev)250 static inline void snd_sof_ipc_dump(struct snd_sof_dev *sdev)
251 {
252 	if (sof_ops(sdev)->ipc_dump)
253 		sof_ops(sdev)->ipc_dump(sdev);
254 }
255 
256 /* register IO */
snd_sof_dsp_write(struct snd_sof_dev * sdev,u32 bar,u32 offset,u32 value)257 static inline void snd_sof_dsp_write(struct snd_sof_dev *sdev, u32 bar,
258 				     u32 offset, u32 value)
259 {
260 	if (sof_ops(sdev)->write) {
261 		sof_ops(sdev)->write(sdev, sdev->bar[bar] + offset, value);
262 		return;
263 	}
264 
265 	dev_err_ratelimited(sdev->dev, "error: %s not defined\n", __func__);
266 }
267 
snd_sof_dsp_write64(struct snd_sof_dev * sdev,u32 bar,u32 offset,u64 value)268 static inline void snd_sof_dsp_write64(struct snd_sof_dev *sdev, u32 bar,
269 				       u32 offset, u64 value)
270 {
271 	if (sof_ops(sdev)->write64) {
272 		sof_ops(sdev)->write64(sdev, sdev->bar[bar] + offset, value);
273 		return;
274 	}
275 
276 	dev_err_ratelimited(sdev->dev, "error: %s not defined\n", __func__);
277 }
278 
snd_sof_dsp_read(struct snd_sof_dev * sdev,u32 bar,u32 offset)279 static inline u32 snd_sof_dsp_read(struct snd_sof_dev *sdev, u32 bar,
280 				   u32 offset)
281 {
282 	if (sof_ops(sdev)->read)
283 		return sof_ops(sdev)->read(sdev, sdev->bar[bar] + offset);
284 
285 	dev_err(sdev->dev, "error: %s not defined\n", __func__);
286 	return -ENOTSUPP;
287 }
288 
snd_sof_dsp_read64(struct snd_sof_dev * sdev,u32 bar,u32 offset)289 static inline u64 snd_sof_dsp_read64(struct snd_sof_dev *sdev, u32 bar,
290 				     u32 offset)
291 {
292 	if (sof_ops(sdev)->read64)
293 		return sof_ops(sdev)->read64(sdev, sdev->bar[bar] + offset);
294 
295 	dev_err(sdev->dev, "error: %s not defined\n", __func__);
296 	return -ENOTSUPP;
297 }
298 
299 /* block IO */
snd_sof_dsp_block_read(struct snd_sof_dev * sdev,u32 bar,u32 offset,void * dest,size_t bytes)300 static inline void snd_sof_dsp_block_read(struct snd_sof_dev *sdev, u32 bar,
301 					  u32 offset, void *dest, size_t bytes)
302 {
303 	sof_ops(sdev)->block_read(sdev, bar, offset, dest, bytes);
304 }
305 
snd_sof_dsp_block_write(struct snd_sof_dev * sdev,u32 bar,u32 offset,void * src,size_t bytes)306 static inline void snd_sof_dsp_block_write(struct snd_sof_dev *sdev, u32 bar,
307 					   u32 offset, void *src, size_t bytes)
308 {
309 	sof_ops(sdev)->block_write(sdev, bar, offset, src, bytes);
310 }
311 
312 /* ipc */
snd_sof_dsp_send_msg(struct snd_sof_dev * sdev,struct snd_sof_ipc_msg * msg)313 static inline int snd_sof_dsp_send_msg(struct snd_sof_dev *sdev,
314 				       struct snd_sof_ipc_msg *msg)
315 {
316 	return sof_ops(sdev)->send_msg(sdev, msg);
317 }
318 
319 /* host DMA trace */
snd_sof_dma_trace_init(struct snd_sof_dev * sdev,u32 * stream_tag)320 static inline int snd_sof_dma_trace_init(struct snd_sof_dev *sdev,
321 					 u32 *stream_tag)
322 {
323 	if (sof_ops(sdev)->trace_init)
324 		return sof_ops(sdev)->trace_init(sdev, stream_tag);
325 
326 	return 0;
327 }
328 
snd_sof_dma_trace_release(struct snd_sof_dev * sdev)329 static inline int snd_sof_dma_trace_release(struct snd_sof_dev *sdev)
330 {
331 	if (sof_ops(sdev)->trace_release)
332 		return sof_ops(sdev)->trace_release(sdev);
333 
334 	return 0;
335 }
336 
snd_sof_dma_trace_trigger(struct snd_sof_dev * sdev,int cmd)337 static inline int snd_sof_dma_trace_trigger(struct snd_sof_dev *sdev, int cmd)
338 {
339 	if (sof_ops(sdev)->trace_trigger)
340 		return sof_ops(sdev)->trace_trigger(sdev, cmd);
341 
342 	return 0;
343 }
344 
345 /* host PCM ops */
346 static inline int
snd_sof_pcm_platform_open(struct snd_sof_dev * sdev,struct snd_pcm_substream * substream)347 snd_sof_pcm_platform_open(struct snd_sof_dev *sdev,
348 			  struct snd_pcm_substream *substream)
349 {
350 	if (sof_ops(sdev) && sof_ops(sdev)->pcm_open)
351 		return sof_ops(sdev)->pcm_open(sdev, substream);
352 
353 	return 0;
354 }
355 
356 /* disconnect pcm substream to a host stream */
357 static inline int
snd_sof_pcm_platform_close(struct snd_sof_dev * sdev,struct snd_pcm_substream * substream)358 snd_sof_pcm_platform_close(struct snd_sof_dev *sdev,
359 			   struct snd_pcm_substream *substream)
360 {
361 	if (sof_ops(sdev) && sof_ops(sdev)->pcm_close)
362 		return sof_ops(sdev)->pcm_close(sdev, substream);
363 
364 	return 0;
365 }
366 
367 /* host stream hw params */
368 static inline int
snd_sof_pcm_platform_hw_params(struct snd_sof_dev * sdev,struct snd_pcm_substream * substream,struct snd_pcm_hw_params * params,struct sof_ipc_stream_params * ipc_params)369 snd_sof_pcm_platform_hw_params(struct snd_sof_dev *sdev,
370 			       struct snd_pcm_substream *substream,
371 			       struct snd_pcm_hw_params *params,
372 			       struct sof_ipc_stream_params *ipc_params)
373 {
374 	if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_params)
375 		return sof_ops(sdev)->pcm_hw_params(sdev, substream,
376 						    params, ipc_params);
377 
378 	return 0;
379 }
380 
381 /* host stream hw free */
382 static inline int
snd_sof_pcm_platform_hw_free(struct snd_sof_dev * sdev,struct snd_pcm_substream * substream)383 snd_sof_pcm_platform_hw_free(struct snd_sof_dev *sdev,
384 			     struct snd_pcm_substream *substream)
385 {
386 	if (sof_ops(sdev) && sof_ops(sdev)->pcm_hw_free)
387 		return sof_ops(sdev)->pcm_hw_free(sdev, substream);
388 
389 	return 0;
390 }
391 
392 /* host stream trigger */
393 static inline int
snd_sof_pcm_platform_trigger(struct snd_sof_dev * sdev,struct snd_pcm_substream * substream,int cmd)394 snd_sof_pcm_platform_trigger(struct snd_sof_dev *sdev,
395 			     struct snd_pcm_substream *substream, int cmd)
396 {
397 	if (sof_ops(sdev) && sof_ops(sdev)->pcm_trigger)
398 		return sof_ops(sdev)->pcm_trigger(sdev, substream, cmd);
399 
400 	return 0;
401 }
402 
403 /* host DSP message data */
snd_sof_ipc_msg_data(struct snd_sof_dev * sdev,struct snd_pcm_substream * substream,void * p,size_t sz)404 static inline void snd_sof_ipc_msg_data(struct snd_sof_dev *sdev,
405 					struct snd_pcm_substream *substream,
406 					void *p, size_t sz)
407 {
408 	sof_ops(sdev)->ipc_msg_data(sdev, substream, p, sz);
409 }
410 
411 /* host configure DSP HW parameters */
412 static inline int
snd_sof_ipc_pcm_params(struct snd_sof_dev * sdev,struct snd_pcm_substream * substream,const struct sof_ipc_pcm_params_reply * reply)413 snd_sof_ipc_pcm_params(struct snd_sof_dev *sdev,
414 		       struct snd_pcm_substream *substream,
415 		       const struct sof_ipc_pcm_params_reply *reply)
416 {
417 	return sof_ops(sdev)->ipc_pcm_params(sdev, substream, reply);
418 }
419 
420 /* host stream pointer */
421 static inline snd_pcm_uframes_t
snd_sof_pcm_platform_pointer(struct snd_sof_dev * sdev,struct snd_pcm_substream * substream)422 snd_sof_pcm_platform_pointer(struct snd_sof_dev *sdev,
423 			     struct snd_pcm_substream *substream)
424 {
425 	if (sof_ops(sdev) && sof_ops(sdev)->pcm_pointer)
426 		return sof_ops(sdev)->pcm_pointer(sdev, substream);
427 
428 	return 0;
429 }
430 
431 #if IS_ENABLED(CONFIG_SND_SOC_SOF_DEBUG_PROBES)
432 static inline int
snd_sof_probe_compr_assign(struct snd_sof_dev * sdev,struct snd_compr_stream * cstream,struct snd_soc_dai * dai)433 snd_sof_probe_compr_assign(struct snd_sof_dev *sdev,
434 		struct snd_compr_stream *cstream, struct snd_soc_dai *dai)
435 {
436 	return sof_ops(sdev)->probe_assign(sdev, cstream, dai);
437 }
438 
439 static inline int
snd_sof_probe_compr_free(struct snd_sof_dev * sdev,struct snd_compr_stream * cstream,struct snd_soc_dai * dai)440 snd_sof_probe_compr_free(struct snd_sof_dev *sdev,
441 		struct snd_compr_stream *cstream, struct snd_soc_dai *dai)
442 {
443 	return sof_ops(sdev)->probe_free(sdev, cstream, dai);
444 }
445 
446 static inline int
snd_sof_probe_compr_set_params(struct snd_sof_dev * sdev,struct snd_compr_stream * cstream,struct snd_compr_params * params,struct snd_soc_dai * dai)447 snd_sof_probe_compr_set_params(struct snd_sof_dev *sdev,
448 		struct snd_compr_stream *cstream,
449 		struct snd_compr_params *params, struct snd_soc_dai *dai)
450 {
451 	return sof_ops(sdev)->probe_set_params(sdev, cstream, params, dai);
452 }
453 
454 static inline int
snd_sof_probe_compr_trigger(struct snd_sof_dev * sdev,struct snd_compr_stream * cstream,int cmd,struct snd_soc_dai * dai)455 snd_sof_probe_compr_trigger(struct snd_sof_dev *sdev,
456 		struct snd_compr_stream *cstream, int cmd,
457 		struct snd_soc_dai *dai)
458 {
459 	return sof_ops(sdev)->probe_trigger(sdev, cstream, cmd, dai);
460 }
461 
462 static inline int
snd_sof_probe_compr_pointer(struct snd_sof_dev * sdev,struct snd_compr_stream * cstream,struct snd_compr_tstamp * tstamp,struct snd_soc_dai * dai)463 snd_sof_probe_compr_pointer(struct snd_sof_dev *sdev,
464 		struct snd_compr_stream *cstream,
465 		struct snd_compr_tstamp *tstamp, struct snd_soc_dai *dai)
466 {
467 	if (sof_ops(sdev) && sof_ops(sdev)->probe_pointer)
468 		return sof_ops(sdev)->probe_pointer(sdev, cstream, tstamp, dai);
469 
470 	return 0;
471 }
472 #endif
473 
474 /* machine driver */
475 static inline int
snd_sof_machine_register(struct snd_sof_dev * sdev,void * pdata)476 snd_sof_machine_register(struct snd_sof_dev *sdev, void *pdata)
477 {
478 	if (sof_ops(sdev) && sof_ops(sdev)->machine_register)
479 		return sof_ops(sdev)->machine_register(sdev, pdata);
480 
481 	return 0;
482 }
483 
484 static inline void
snd_sof_machine_unregister(struct snd_sof_dev * sdev,void * pdata)485 snd_sof_machine_unregister(struct snd_sof_dev *sdev, void *pdata)
486 {
487 	if (sof_ops(sdev) && sof_ops(sdev)->machine_unregister)
488 		sof_ops(sdev)->machine_unregister(sdev, pdata);
489 }
490 
491 static inline void
snd_sof_machine_select(struct snd_sof_dev * sdev)492 snd_sof_machine_select(struct snd_sof_dev *sdev)
493 {
494 	if (sof_ops(sdev) && sof_ops(sdev)->machine_select)
495 		sof_ops(sdev)->machine_select(sdev);
496 }
497 
498 static inline void
snd_sof_set_mach_params(const struct snd_soc_acpi_mach * mach,struct snd_sof_dev * sdev)499 snd_sof_set_mach_params(const struct snd_soc_acpi_mach *mach,
500 			struct snd_sof_dev *sdev)
501 {
502 	if (sof_ops(sdev) && sof_ops(sdev)->set_mach_params)
503 		sof_ops(sdev)->set_mach_params(mach, sdev);
504 }
505 
506 static inline const struct snd_sof_dsp_ops
sof_get_ops(const struct sof_dev_desc * d,const struct sof_ops_table mach_ops[],int asize)507 *sof_get_ops(const struct sof_dev_desc *d,
508 	     const struct sof_ops_table mach_ops[], int asize)
509 {
510 	int i;
511 
512 	for (i = 0; i < asize; i++) {
513 		if (d == mach_ops[i].desc)
514 			return mach_ops[i].ops;
515 	}
516 
517 	/* not found */
518 	return NULL;
519 }
520 
521 /**
522  * snd_sof_dsp_register_poll_timeout - Periodically poll an address
523  * until a condition is met or a timeout occurs
524  * @op: accessor function (takes @addr as its only argument)
525  * @addr: Address to poll
526  * @val: Variable to read the value into
527  * @cond: Break condition (usually involving @val)
528  * @sleep_us: Maximum time to sleep between reads in us (0
529  *            tight-loops).  Should be less than ~20ms since usleep_range
530  *            is used (see Documentation/timers/timers-howto.rst).
531  * @timeout_us: Timeout in us, 0 means never timeout
532  *
533  * Returns 0 on success and -ETIMEDOUT upon a timeout. In either
534  * case, the last read value at @addr is stored in @val. Must not
535  * be called from atomic context if sleep_us or timeout_us are used.
536  *
537  * This is modelled after the readx_poll_timeout macros in linux/iopoll.h.
538  */
539 #define snd_sof_dsp_read_poll_timeout(sdev, bar, offset, val, cond, sleep_us, timeout_us) \
540 ({ \
541 	u64 __timeout_us = (timeout_us); \
542 	unsigned long __sleep_us = (sleep_us); \
543 	ktime_t __timeout = ktime_add_us(ktime_get(), __timeout_us); \
544 	might_sleep_if((__sleep_us) != 0); \
545 	for (;;) {							\
546 		(val) = snd_sof_dsp_read(sdev, bar, offset);		\
547 		if (cond) { \
548 			dev_dbg(sdev->dev, \
549 				"FW Poll Status: reg[%#x]=%#x successful\n", \
550 				(offset), (val)); \
551 			break; \
552 		} \
553 		if (__timeout_us && \
554 		    ktime_compare(ktime_get(), __timeout) > 0) { \
555 			(val) = snd_sof_dsp_read(sdev, bar, offset); \
556 			dev_dbg(sdev->dev, \
557 				"FW Poll Status: reg[%#x]=%#x timedout\n", \
558 				(offset), (val)); \
559 			break; \
560 		} \
561 		if (__sleep_us) \
562 			usleep_range((__sleep_us >> 2) + 1, __sleep_us); \
563 	} \
564 	(cond) ? 0 : -ETIMEDOUT; \
565 })
566 
567 /* This is for registers bits with attribute RWC */
568 bool snd_sof_pci_update_bits(struct snd_sof_dev *sdev, u32 offset,
569 			     u32 mask, u32 value);
570 
571 bool snd_sof_dsp_update_bits_unlocked(struct snd_sof_dev *sdev, u32 bar,
572 				      u32 offset, u32 mask, u32 value);
573 
574 bool snd_sof_dsp_update_bits64_unlocked(struct snd_sof_dev *sdev, u32 bar,
575 					u32 offset, u64 mask, u64 value);
576 
577 bool snd_sof_dsp_update_bits(struct snd_sof_dev *sdev, u32 bar, u32 offset,
578 			     u32 mask, u32 value);
579 
580 bool snd_sof_dsp_update_bits64(struct snd_sof_dev *sdev, u32 bar,
581 			       u32 offset, u64 mask, u64 value);
582 
583 void snd_sof_dsp_update_bits_forced(struct snd_sof_dev *sdev, u32 bar,
584 				    u32 offset, u32 mask, u32 value);
585 
586 int snd_sof_dsp_register_poll(struct snd_sof_dev *sdev, u32 bar, u32 offset,
587 			      u32 mask, u32 target, u32 timeout_ms,
588 			      u32 interval_us);
589 
590 void snd_sof_dsp_panic(struct snd_sof_dev *sdev, u32 offset);
591 #endif
592