xref: /linux-6.15/include/asm-generic/delay.h (revision f36eb171)
1b2441318SGreg Kroah-Hartman /* SPDX-License-Identifier: GPL-2.0 */
2aafe4dbeSArnd Bergmann #ifndef __ASM_GENERIC_DELAY_H
3aafe4dbeSArnd Bergmann #define __ASM_GENERIC_DELAY_H
4aafe4dbeSArnd Bergmann 
530ab2b03SJonas Bonn /* Undefined functions to get compile-time errors */
630ab2b03SJonas Bonn extern void __bad_udelay(void);
730ab2b03SJonas Bonn extern void __bad_ndelay(void);
830ab2b03SJonas Bonn 
9aafe4dbeSArnd Bergmann extern void __udelay(unsigned long usecs);
1030ab2b03SJonas Bonn extern void __ndelay(unsigned long nsecs);
1130ab2b03SJonas Bonn extern void __const_udelay(unsigned long xloops);
12aafe4dbeSArnd Bergmann extern void __delay(unsigned long loops);
13aafe4dbeSArnd Bergmann 
14a87e553fSAndrew Morton /*
15*f36eb171SAnna-Maria Behnsen  * Implementation details:
16*f36eb171SAnna-Maria Behnsen  *
17*f36eb171SAnna-Maria Behnsen  * * The weird n/20000 thing suppresses a "comparison is always false due to
18a87e553fSAndrew Morton  *   limited range of data type" warning with non-const 8-bit arguments.
19*f36eb171SAnna-Maria Behnsen  * * 0x10c7 is 2**32 / 1000000 (rounded up) -> udelay
20*f36eb171SAnna-Maria Behnsen  * * 0x5 is 2**32 / 1000000000 (rounded up) -> ndelay
21a87e553fSAndrew Morton  */
22a87e553fSAndrew Morton 
23*f36eb171SAnna-Maria Behnsen /**
24*f36eb171SAnna-Maria Behnsen  * udelay - Inserting a delay based on microseconds with busy waiting
25*f36eb171SAnna-Maria Behnsen  * @usec:	requested delay in microseconds
26*f36eb171SAnna-Maria Behnsen  *
27*f36eb171SAnna-Maria Behnsen  * When delaying in an atomic context ndelay(), udelay() and mdelay() are the
28*f36eb171SAnna-Maria Behnsen  * only valid variants of delaying/sleeping to go with.
29*f36eb171SAnna-Maria Behnsen  *
30*f36eb171SAnna-Maria Behnsen  * When inserting delays in non atomic context which are shorter than the time
31*f36eb171SAnna-Maria Behnsen  * which is required to queue e.g. an hrtimer and to enter then the scheduler,
32*f36eb171SAnna-Maria Behnsen  * it is also valuable to use udelay(). But it is not simple to specify a
33*f36eb171SAnna-Maria Behnsen  * generic threshold for this which will fit for all systems. An approximation
34*f36eb171SAnna-Maria Behnsen  * is a threshold for all delays up to 10 microseconds.
35*f36eb171SAnna-Maria Behnsen  *
36*f36eb171SAnna-Maria Behnsen  * When having a delay which is larger than the architecture specific
37*f36eb171SAnna-Maria Behnsen  * %MAX_UDELAY_MS value, please make sure mdelay() is used. Otherwise a overflow
38*f36eb171SAnna-Maria Behnsen  * risk is given.
39*f36eb171SAnna-Maria Behnsen  *
40*f36eb171SAnna-Maria Behnsen  * Please note that ndelay(), udelay() and mdelay() may return early for several
41*f36eb171SAnna-Maria Behnsen  * reasons (https://lists.openwall.net/linux-kernel/2011/01/09/56):
42*f36eb171SAnna-Maria Behnsen  *
43*f36eb171SAnna-Maria Behnsen  * #. computed loops_per_jiffy too low (due to the time taken to execute the
44*f36eb171SAnna-Maria Behnsen  *    timer interrupt.)
45*f36eb171SAnna-Maria Behnsen  * #. cache behaviour affecting the time it takes to execute the loop function.
46*f36eb171SAnna-Maria Behnsen  * #. CPU clock rate changes.
47*f36eb171SAnna-Maria Behnsen  */
48a87e553fSAndrew Morton #define udelay(n)							\
49a87e553fSAndrew Morton 	({								\
50a87e553fSAndrew Morton 		if (__builtin_constant_p(n)) {				\
51a87e553fSAndrew Morton 			if ((n) / 20000 >= 1)				\
52a87e553fSAndrew Morton 				 __bad_udelay();			\
53a87e553fSAndrew Morton 			else						\
54a87e553fSAndrew Morton 				__const_udelay((n) * 0x10c7ul);		\
55a87e553fSAndrew Morton 		} else {						\
56a87e553fSAndrew Morton 			__udelay(n);					\
57a87e553fSAndrew Morton 		}							\
58a87e553fSAndrew Morton 	})
5930ab2b03SJonas Bonn 
60*f36eb171SAnna-Maria Behnsen /**
61*f36eb171SAnna-Maria Behnsen  * ndelay - Inserting a delay based on nanoseconds with busy waiting
62*f36eb171SAnna-Maria Behnsen  * @nsec:	requested delay in nanoseconds
63*f36eb171SAnna-Maria Behnsen  *
64*f36eb171SAnna-Maria Behnsen  * See udelay() for basic information about ndelay() and it's variants.
65*f36eb171SAnna-Maria Behnsen  */
66a87e553fSAndrew Morton #define ndelay(n)							\
67a87e553fSAndrew Morton 	({								\
68a87e553fSAndrew Morton 		if (__builtin_constant_p(n)) {				\
69a87e553fSAndrew Morton 			if ((n) / 20000 >= 1)				\
70a87e553fSAndrew Morton 				__bad_ndelay();				\
71a87e553fSAndrew Morton 			else						\
72a87e553fSAndrew Morton 				__const_udelay((n) * 5ul);		\
73a87e553fSAndrew Morton 		} else {						\
74a87e553fSAndrew Morton 			__ndelay(n);					\
75a87e553fSAndrew Morton 		}							\
76a87e553fSAndrew Morton 	})
77aafe4dbeSArnd Bergmann 
78aafe4dbeSArnd Bergmann #endif /* __ASM_GENERIC_DELAY_H */
79