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