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