xref: /rk3399_rockchip-uboot/include/wait_bit.h (revision 1221ce459d04a428f8880f58581f671b736c3c27)
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*1221ce45SMasahiro Yamada #include <linux/errno.h>
159afdf402SMateusz Kulikowski #include <asm/io.h>
169afdf402SMateusz Kulikowski 
179afdf402SMateusz Kulikowski /**
189afdf402SMateusz Kulikowski  * wait_for_bit()	waits for bit set/cleared in register
199afdf402SMateusz Kulikowski  *
209afdf402SMateusz Kulikowski  * Function polls register waiting for specific bit(s) change
219afdf402SMateusz Kulikowski  * (either 0->1 or 1->0). It can fail under two conditions:
229afdf402SMateusz Kulikowski  * - Timeout
239afdf402SMateusz Kulikowski  * - User interaction (CTRL-C)
249afdf402SMateusz Kulikowski  * Function succeeds only if all bits of masked register are set/cleared
259afdf402SMateusz Kulikowski  * (depending on set option).
269afdf402SMateusz Kulikowski  *
279afdf402SMateusz Kulikowski  * @param prefix	Prefix added to timeout messagge (message visible only
289afdf402SMateusz Kulikowski  *			with debug enabled)
299afdf402SMateusz Kulikowski  * @param reg		Register that will be read (using readl())
309afdf402SMateusz Kulikowski  * @param mask		Bit(s) of register that must be active
319afdf402SMateusz Kulikowski  * @param set		Selects wait condition (bit set or clear)
329afdf402SMateusz Kulikowski  * @param timeout_ms	Timeout (in miliseconds)
339afdf402SMateusz Kulikowski  * @param breakable	Enables CTRL-C interruption
349afdf402SMateusz Kulikowski  * @return		0 on success, -ETIMEDOUT or -EINTR on failure
359afdf402SMateusz Kulikowski  */
369afdf402SMateusz Kulikowski static inline int wait_for_bit(const char *prefix, const u32 *reg,
379afdf402SMateusz Kulikowski 			       const u32 mask, const bool set,
389afdf402SMateusz Kulikowski 			       const unsigned int timeout_ms,
399afdf402SMateusz Kulikowski 			       const bool breakable)
409afdf402SMateusz Kulikowski {
419afdf402SMateusz Kulikowski 	u32 val;
429afdf402SMateusz Kulikowski 	unsigned long start = get_timer(0);
439afdf402SMateusz Kulikowski 
449afdf402SMateusz Kulikowski 	while (1) {
459afdf402SMateusz Kulikowski 		val = readl(reg);
469afdf402SMateusz Kulikowski 
479afdf402SMateusz Kulikowski 		if (!set)
489afdf402SMateusz Kulikowski 			val = ~val;
499afdf402SMateusz Kulikowski 
509afdf402SMateusz Kulikowski 		if ((val & mask) == mask)
519afdf402SMateusz Kulikowski 			return 0;
529afdf402SMateusz Kulikowski 
539afdf402SMateusz Kulikowski 		if (get_timer(start) > timeout_ms)
549afdf402SMateusz Kulikowski 			break;
559afdf402SMateusz Kulikowski 
569afdf402SMateusz Kulikowski 		if (breakable && ctrlc()) {
579afdf402SMateusz Kulikowski 			puts("Abort\n");
589afdf402SMateusz Kulikowski 			return -EINTR;
599afdf402SMateusz Kulikowski 		}
609afdf402SMateusz Kulikowski 
619afdf402SMateusz Kulikowski 		udelay(1);
629afdf402SMateusz Kulikowski 	}
639afdf402SMateusz Kulikowski 
649afdf402SMateusz Kulikowski 	debug("%s: Timeout (reg=%p mask=%08x wait_set=%i)\n", prefix, reg, mask,
659afdf402SMateusz Kulikowski 	      set);
669afdf402SMateusz Kulikowski 
679afdf402SMateusz Kulikowski 	return -ETIMEDOUT;
689afdf402SMateusz Kulikowski }
699afdf402SMateusz Kulikowski 
709afdf402SMateusz Kulikowski 
719afdf402SMateusz Kulikowski #endif
72