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> 14*3cd42180SMichal Simek #include <watchdog.h> 151221ce45SMasahiro Yamada #include <linux/errno.h> 169afdf402SMateusz Kulikowski #include <asm/io.h> 179afdf402SMateusz Kulikowski 189afdf402SMateusz Kulikowski /** 199afdf402SMateusz Kulikowski * wait_for_bit() 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 * 289afdf402SMateusz Kulikowski * @param prefix Prefix added to timeout messagge (message visible only 299afdf402SMateusz Kulikowski * with debug enabled) 309afdf402SMateusz Kulikowski * @param reg Register that will be read (using readl()) 319afdf402SMateusz Kulikowski * @param mask Bit(s) of register that must be active 329afdf402SMateusz Kulikowski * @param set Selects wait condition (bit set or clear) 339afdf402SMateusz Kulikowski * @param timeout_ms Timeout (in miliseconds) 349afdf402SMateusz Kulikowski * @param breakable Enables CTRL-C interruption 359afdf402SMateusz Kulikowski * @return 0 on success, -ETIMEDOUT or -EINTR on failure 369afdf402SMateusz Kulikowski */ 379afdf402SMateusz Kulikowski static inline int wait_for_bit(const char *prefix, const u32 *reg, 389afdf402SMateusz Kulikowski const u32 mask, const bool set, 399afdf402SMateusz Kulikowski const unsigned int timeout_ms, 409afdf402SMateusz Kulikowski const bool breakable) 419afdf402SMateusz Kulikowski { 429afdf402SMateusz Kulikowski u32 val; 439afdf402SMateusz Kulikowski unsigned long start = get_timer(0); 449afdf402SMateusz Kulikowski 459afdf402SMateusz Kulikowski while (1) { 469afdf402SMateusz Kulikowski val = readl(reg); 479afdf402SMateusz Kulikowski 489afdf402SMateusz Kulikowski if (!set) 499afdf402SMateusz Kulikowski val = ~val; 509afdf402SMateusz Kulikowski 519afdf402SMateusz Kulikowski if ((val & mask) == mask) 529afdf402SMateusz Kulikowski return 0; 539afdf402SMateusz Kulikowski 549afdf402SMateusz Kulikowski if (get_timer(start) > timeout_ms) 559afdf402SMateusz Kulikowski break; 569afdf402SMateusz Kulikowski 579afdf402SMateusz Kulikowski if (breakable && ctrlc()) { 589afdf402SMateusz Kulikowski puts("Abort\n"); 599afdf402SMateusz Kulikowski return -EINTR; 609afdf402SMateusz Kulikowski } 619afdf402SMateusz Kulikowski 629afdf402SMateusz Kulikowski udelay(1); 63*3cd42180SMichal Simek WATCHDOG_RESET(); 649afdf402SMateusz Kulikowski } 659afdf402SMateusz Kulikowski 669afdf402SMateusz Kulikowski debug("%s: Timeout (reg=%p mask=%08x wait_set=%i)\n", prefix, reg, mask, 679afdf402SMateusz Kulikowski set); 689afdf402SMateusz Kulikowski 699afdf402SMateusz Kulikowski return -ETIMEDOUT; 709afdf402SMateusz Kulikowski } 719afdf402SMateusz Kulikowski 729afdf402SMateusz Kulikowski 739afdf402SMateusz Kulikowski #endif 74