1 /* SPDX-License-Identifier: GPL-2.0+ */ 2 /* 3 * Wait for bit with timeout and ctrlc 4 * 5 * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com> 6 */ 7 8 #ifndef __WAIT_BIT_H 9 #define __WAIT_BIT_H 10 11 #include <common.h> 12 #include <console.h> 13 #include <watchdog.h> 14 #include <linux/errno.h> 15 #include <asm/io.h> 16 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 82 83 #endif 84