xref: /rk3399_rockchip-uboot/include/wait_bit.h (revision 3cd42180a8f691c68d88b9ef428054348c2f0432)
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