]>
Commit | Line | Data |
---|---|---|
83d290c5 | 1 | /* SPDX-License-Identifier: GPL-2.0+ */ |
9afdf402 MK |
2 | /* |
3 | * Wait for bit with timeout and ctrlc | |
4 | * | |
5 | * (C) Copyright 2015 Mateusz Kulikowski <[email protected]> | |
9afdf402 MK |
6 | */ |
7 | ||
8 | #ifndef __WAIT_BIT_H | |
9 | #define __WAIT_BIT_H | |
10 | ||
9afdf402 | 11 | #include <console.h> |
f7ae49fc SG |
12 | #include <log.h> |
13 | #include <time.h> | |
3cd42180 | 14 | #include <watchdog.h> |
f7ae49fc | 15 | #include <linux/delay.h> |
1221ce45 | 16 | #include <linux/errno.h> |
9afdf402 MK |
17 | #include <asm/io.h> |
18 | ||
91fe458b ÁFR |
19 | /** |
20 | * wait_for_bit_x() waits for bit set/cleared in register | |
21 | * | |
22 | * Function polls register waiting for specific bit(s) change | |
23 | * (either 0->1 or 1->0). It can fail under two conditions: | |
24 | * - Timeout | |
25 | * - User interaction (CTRL-C) | |
26 | * Function succeeds only if all bits of masked register are set/cleared | |
27 | * (depending on set option). | |
28 | * | |
29 | * @param reg Register that will be read (using read_x()) | |
30 | * @param mask Bit(s) of register that must be active | |
31 | * @param set Selects wait condition (bit set or clear) | |
32 | * @param timeout_ms Timeout (in milliseconds) | |
33 | * @param breakable Enables CTRL-C interruption | |
34 | * @return 0 on success, -ETIMEDOUT or -EINTR on failure | |
35 | */ | |
36 | ||
37 | #define BUILD_WAIT_FOR_BIT(sfx, type, read) \ | |
38 | \ | |
39 | static inline int wait_for_bit_##sfx(const void *reg, \ | |
40 | const type mask, \ | |
41 | const bool set, \ | |
42 | const unsigned int timeout_ms, \ | |
43 | const bool breakable) \ | |
44 | { \ | |
45 | type val; \ | |
46 | unsigned long start = get_timer(0); \ | |
47 | \ | |
48 | while (1) { \ | |
49 | val = read(reg); \ | |
50 | \ | |
51 | if (!set) \ | |
52 | val = ~val; \ | |
53 | \ | |
54 | if ((val & mask) == mask) \ | |
55 | return 0; \ | |
56 | \ | |
57 | if (get_timer(start) > timeout_ms) \ | |
58 | break; \ | |
59 | \ | |
60 | if (breakable && ctrlc()) { \ | |
61 | puts("Abort\n"); \ | |
62 | return -EINTR; \ | |
63 | } \ | |
64 | \ | |
65 | udelay(1); \ | |
66 | WATCHDOG_RESET(); \ | |
67 | } \ | |
68 | \ | |
69 | debug("%s: Timeout (reg=%p mask=%x wait_set=%i)\n", __func__, \ | |
70 | reg, mask, set); \ | |
71 | \ | |
72 | return -ETIMEDOUT; \ | |
73 | } | |
74 | ||
75 | BUILD_WAIT_FOR_BIT(8, u8, readb) | |
76 | BUILD_WAIT_FOR_BIT(le16, u16, readw) | |
c50d670c | 77 | BUILD_WAIT_FOR_BIT(16, u16, readw) |
91fe458b ÁFR |
78 | #ifdef readw_be |
79 | BUILD_WAIT_FOR_BIT(be16, u16, readw_be) | |
80 | #endif | |
81 | BUILD_WAIT_FOR_BIT(le32, u32, readl) | |
c50d670c | 82 | BUILD_WAIT_FOR_BIT(32, u32, readl) |
91fe458b ÁFR |
83 | #ifdef readl_be |
84 | BUILD_WAIT_FOR_BIT(be32, u32, readl_be) | |
85 | #endif | |
9afdf402 MK |
86 | |
87 | #endif |