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