19afdf402SMateusz Kulikowski /* 29afdf402SMateusz Kulikowski * Wait for bit with timeout and ctrlc 39afdf402SMateusz Kulikowski * 49afdf402SMateusz Kulikowski * (C) Copyright 2015 Mateusz Kulikowski <mateusz.kulikowski@gmail.com> 59afdf402SMateusz Kulikowski * 69afdf402SMateusz Kulikowski * SPDX-License-Identifier: GPL-2.0+ 79afdf402SMateusz Kulikowski */ 89afdf402SMateusz Kulikowski 99afdf402SMateusz Kulikowski #ifndef __WAIT_BIT_H 109afdf402SMateusz Kulikowski #define __WAIT_BIT_H 119afdf402SMateusz Kulikowski 129afdf402SMateusz Kulikowski #include <common.h> 139afdf402SMateusz Kulikowski #include <console.h> 143cd42180SMichal Simek #include <watchdog.h> 151221ce45SMasahiro Yamada #include <linux/errno.h> 169afdf402SMateusz Kulikowski #include <asm/io.h> 179afdf402SMateusz Kulikowski 189afdf402SMateusz Kulikowski /** 19*b491b498SJon Lin * wait_for_bit_x() waits for bit set/cleared in register 209afdf402SMateusz Kulikowski * 219afdf402SMateusz Kulikowski * Function polls register waiting for specific bit(s) change 229afdf402SMateusz Kulikowski * (either 0->1 or 1->0). It can fail under two conditions: 239afdf402SMateusz Kulikowski * - Timeout 249afdf402SMateusz Kulikowski * - User interaction (CTRL-C) 259afdf402SMateusz Kulikowski * Function succeeds only if all bits of masked register are set/cleared 269afdf402SMateusz Kulikowski * (depending on set option). 279afdf402SMateusz Kulikowski * 28*b491b498SJon Lin * @param reg Register that will be read (using read_x()) 299afdf402SMateusz Kulikowski * @param mask Bit(s) of register that must be active 309afdf402SMateusz Kulikowski * @param set Selects wait condition (bit set or clear) 31*b491b498SJon Lin * @param timeout_ms Timeout (in milliseconds) 329afdf402SMateusz Kulikowski * @param breakable Enables CTRL-C interruption 339afdf402SMateusz Kulikowski * @return 0 on success, -ETIMEDOUT or -EINTR on failure 349afdf402SMateusz Kulikowski */ 359afdf402SMateusz Kulikowski 36*b491b498SJon Lin #define BUILD_WAIT_FOR_BIT(sfx, type, read) \ 37*b491b498SJon Lin \ 38*b491b498SJon Lin static inline int wait_for_bit_##sfx(const void *reg, \ 39*b491b498SJon Lin const type mask, \ 40*b491b498SJon Lin const bool set, \ 41*b491b498SJon Lin const unsigned int timeout_ms, \ 42*b491b498SJon Lin const bool breakable) \ 43*b491b498SJon Lin { \ 44*b491b498SJon Lin type val; \ 45*b491b498SJon Lin unsigned long start = get_timer(0); \ 46*b491b498SJon Lin \ 47*b491b498SJon Lin while (1) { \ 48*b491b498SJon Lin val = read(reg); \ 49*b491b498SJon Lin \ 50*b491b498SJon Lin if (!set) \ 51*b491b498SJon Lin val = ~val; \ 52*b491b498SJon Lin \ 53*b491b498SJon Lin if ((val & mask) == mask) \ 54*b491b498SJon Lin return 0; \ 55*b491b498SJon Lin \ 56*b491b498SJon Lin if (get_timer(start) > timeout_ms) \ 57*b491b498SJon Lin break; \ 58*b491b498SJon Lin \ 59*b491b498SJon Lin if (breakable && ctrlc()) { \ 60*b491b498SJon Lin puts("Abort\n"); \ 61*b491b498SJon Lin return -EINTR; \ 62*b491b498SJon Lin } \ 63*b491b498SJon Lin \ 64*b491b498SJon Lin udelay(1); \ 65*b491b498SJon Lin WATCHDOG_RESET(); \ 66*b491b498SJon Lin } \ 67*b491b498SJon Lin \ 68*b491b498SJon Lin debug("%s: Timeout (reg=%p mask=%x wait_set=%i)\n", __func__, \ 69*b491b498SJon Lin reg, mask, set); \ 70*b491b498SJon Lin \ 71*b491b498SJon Lin return -ETIMEDOUT; \ 729afdf402SMateusz Kulikowski } 739afdf402SMateusz Kulikowski 74*b491b498SJon Lin BUILD_WAIT_FOR_BIT(8, u8, readb) 75*b491b498SJon Lin BUILD_WAIT_FOR_BIT(le16, u16, readw) 76*b491b498SJon Lin #ifdef readw_be 77*b491b498SJon Lin BUILD_WAIT_FOR_BIT(be16, u16, readw_be) 78*b491b498SJon Lin #endif 79*b491b498SJon Lin BUILD_WAIT_FOR_BIT(le32, u32, readl) 80*b491b498SJon Lin #ifdef readl_be 81*b491b498SJon Lin BUILD_WAIT_FOR_BIT(be32, u32, readl_be) 82*b491b498SJon Lin #endif 839afdf402SMateusz Kulikowski 849afdf402SMateusz Kulikowski #endif 85