1 // SPDX-License-Identifier: BSD-3-Clause
2 //
3 // Copyright(c) 2016 Intel Corporation. All rights reserved.
4 //
5 // Author: Liam Girdwood <liam.r.girdwood@linux.intel.com>
6 
7 /*
8  * Simple wait for event completion and signaling with timeouts.
9  */
10 
11 #include <rtos/clk.h>
12 #include <sof/lib/io.h>
13 #include <sof/lib/uuid.h>
14 #include <rtos/wait.h>
15 #include <sof/platform.h>
16 #include <sof/schedule/schedule.h>
17 #include <sof/trace/trace.h>
18 #include <user/trace.h>
19 #include <errno.h>
20 #include <stdint.h>
21 #include <inttypes.h>
22 
23 LOG_MODULE_REGISTER(wait, CONFIG_SOF_LOG_LEVEL);
24 
25 /* 1028070e-04e8-46ab-8d81-10a0116ce738 */
26 DECLARE_SOF_UUID("wait", wait_uuid, 0x1028070e, 0x04e8, 0x46ab,
27 		 0x8d, 0x81, 0x10, 0xa0, 0x11, 0x6c, 0xe7, 0x38);
28 
29 DECLARE_TR_CTX(wait_tr, SOF_UUID(wait_uuid), LOG_LEVEL_INFO);
30 
31 #define DEFAULT_TRY_TIMES 8
32 
poll_for_register_delay(uint32_t reg,uint32_t mask,uint32_t val,uint64_t us)33 int poll_for_register_delay(uint32_t reg, uint32_t mask,
34 			    uint32_t val, uint64_t us)
35 {
36 	uint64_t tick = k_us_to_cyc_ceil64(us);
37 	uint32_t tries = DEFAULT_TRY_TIMES;
38 	uint64_t delta = tick / tries;
39 
40 	if (!delta) {
41 		/*
42 		 * If we want to wait for less than DEFAULT_TRY_TIMES ticks then
43 		 * delta has to be set to 1 and number of tries to that of number
44 		 * of ticks.
45 		 */
46 		delta = 1;
47 		tries = tick;
48 	}
49 
50 	while ((io_reg_read(reg) & mask) != val) {
51 		if (!tries--) {
52 			tr_err(&wait_tr, "poll timeout reg %u mask %u val %u us %u",
53 			       reg, mask, val, (uint32_t)us);
54 			return -EIO;
55 		}
56 		wait_delay(delta);
57 	}
58 	return 0;
59 }
60 
wait_delay(uint64_t number_of_clks)61 void wait_delay(uint64_t number_of_clks)
62 {
63 	uint64_t timeout = sof_cycle_get_64() + number_of_clks;
64 
65 	while (sof_cycle_get_64() < timeout)
66 		idelay(PLATFORM_DEFAULT_DELAY);
67 }
68 
wait_delay_ms(uint64_t ms)69 void wait_delay_ms(uint64_t ms)
70 {
71 	wait_delay(k_ms_to_cyc_ceil64(ms));
72 }
73 
wait_delay_us(uint64_t us)74 void wait_delay_us(uint64_t us)
75 {
76 	wait_delay(k_us_to_cyc_ceil64(us));
77 }
78