xref: /openbmc/linux/arch/microblaze/include/asm/delay.h (revision ead5d1f4d877e92c051e1a1ade623d0d30e71619)
1*4726dd60SMichal Simek /* SPDX-License-Identifier: GPL-2.0 */
2216f0348SMichal Simek /*
3216f0348SMichal Simek  * Copyright (C) 2008 Michal Simek
4216f0348SMichal Simek  * Copyright (C) 2007 John Williams
5216f0348SMichal Simek  * Copyright (C) 2006 Atmark Techno, Inc.
6216f0348SMichal Simek  */
7216f0348SMichal Simek 
8216f0348SMichal Simek #ifndef _ASM_MICROBLAZE_DELAY_H
9216f0348SMichal Simek #define _ASM_MICROBLAZE_DELAY_H
10216f0348SMichal Simek 
11ac1566ecSMichal Simek #include <linux/param.h>
12ac1566ecSMichal Simek 
__delay(unsigned long loops)13b6db0a56SMichal Simek static inline void __delay(unsigned long loops)
14216f0348SMichal Simek {
15216f0348SMichal Simek 	asm volatile ("# __delay		\n\t"		\
16216f0348SMichal Simek 			"1: addi	%0, %0, -1\t\n"		\
17216f0348SMichal Simek 			"bneid	%0, 1b		\t\n"		\
18216f0348SMichal Simek 			"nop			\t\n"
19216f0348SMichal Simek 			: "=r" (loops)
20216f0348SMichal Simek 			: "0" (loops));
21216f0348SMichal Simek }
22216f0348SMichal Simek 
23216f0348SMichal Simek /*
24216f0348SMichal Simek  * Note that 19 * 226 == 4294 ==~ 2^32 / 10^6, so
25216f0348SMichal Simek  * loops = (4294 * usecs * loops_per_jiffy * HZ) / 2^32.
26216f0348SMichal Simek  *
27216f0348SMichal Simek  * The mul instruction gives us loops = (a * b) / 2^32.
28216f0348SMichal Simek  * We choose a = usecs * 19 * HZ and b = loops_per_jiffy * 226
29216f0348SMichal Simek  * because this lets us support a wide range of HZ and
30216f0348SMichal Simek  * loops_per_jiffy values without either a or b overflowing 2^32.
31216f0348SMichal Simek  * Thus we need usecs * HZ <= (2^32 - 1) / 19 = 226050910 and
32216f0348SMichal Simek  * loops_per_jiffy <= (2^32 - 1) / 226 = 19004280
33216f0348SMichal Simek  * (which corresponds to ~3800 bogomips at HZ = 100).
34216f0348SMichal Simek  * -- paulus
35216f0348SMichal Simek  */
36216f0348SMichal Simek #define __MAX_UDELAY	(226050910UL/HZ)	/* maximum udelay argument */
37216f0348SMichal Simek #define __MAX_NDELAY	(4294967295UL/HZ)	/* maximum ndelay argument */
38216f0348SMichal Simek 
39216f0348SMichal Simek extern unsigned long loops_per_jiffy;
40216f0348SMichal Simek 
__udelay(unsigned int x)41b6db0a56SMichal Simek static inline void __udelay(unsigned int x)
42216f0348SMichal Simek {
43216f0348SMichal Simek 
44216f0348SMichal Simek 	unsigned long long tmp =
45216f0348SMichal Simek 		(unsigned long long)x * (unsigned long long)loops_per_jiffy \
46216f0348SMichal Simek 			* 226LL;
47216f0348SMichal Simek 	unsigned loops = tmp >> 32;
48216f0348SMichal Simek 
49216f0348SMichal Simek /*
50216f0348SMichal Simek 	__asm__("mulxuu %0,%1,%2" : "=r" (loops) :
51216f0348SMichal Simek 		"r" (x), "r" (loops_per_jiffy * 226));
52216f0348SMichal Simek */
53216f0348SMichal Simek 	__delay(loops);
54216f0348SMichal Simek }
55216f0348SMichal Simek 
56216f0348SMichal Simek extern void __bad_udelay(void);		/* deliberately undefined */
57216f0348SMichal Simek extern void __bad_ndelay(void);		/* deliberately undefined */
58216f0348SMichal Simek 
59ad1d4358SMichal Simek #define udelay(n)						\
60ad1d4358SMichal Simek 	({							\
61ad1d4358SMichal Simek 		if (__builtin_constant_p(n)) {			\
62ad1d4358SMichal Simek 			if ((n) / __MAX_UDELAY >= 1)		\
63ad1d4358SMichal Simek 				__bad_udelay();			\
64ad1d4358SMichal Simek 			else					\
65ad1d4358SMichal Simek 				__udelay((n) * (19 * HZ));	\
66ad1d4358SMichal Simek 		} else {					\
67ad1d4358SMichal Simek 			__udelay((n) * (19 * HZ));		\
68ad1d4358SMichal Simek 		}						\
69ad1d4358SMichal Simek 	})
70216f0348SMichal Simek 
71ad1d4358SMichal Simek #define ndelay(n)						\
72ad1d4358SMichal Simek 	({							\
73ad1d4358SMichal Simek 		if (__builtin_constant_p(n)) {			\
74ad1d4358SMichal Simek 			if ((n) / __MAX_NDELAY >= 1)		\
75ad1d4358SMichal Simek 				__bad_ndelay();			\
76ad1d4358SMichal Simek 			else					\
77ad1d4358SMichal Simek 				__udelay((n) * HZ);		\
78ad1d4358SMichal Simek 		} else {					\
79ad1d4358SMichal Simek 			__udelay((n) * HZ);			\
80ad1d4358SMichal Simek 		}						\
81ad1d4358SMichal Simek 	})
82216f0348SMichal Simek 
83216f0348SMichal Simek #define muldiv(a, b, c)		(((a)*(b))/(c))
84216f0348SMichal Simek 
85216f0348SMichal Simek #endif /* _ASM_MICROBLAZE_DELAY_H */
86