xref: /openbmc/linux/arch/mips/include/asm/delay.h (revision 384740dc49ea651ba350704d13ff6be9976e37fe)
1*384740dcSRalf Baechle /*
2*384740dcSRalf Baechle  * This file is subject to the terms and conditions of the GNU General Public
3*384740dcSRalf Baechle  * License.  See the file "COPYING" in the main directory of this archive
4*384740dcSRalf Baechle  * for more details.
5*384740dcSRalf Baechle  *
6*384740dcSRalf Baechle  * Copyright (C) 1994 by Waldorf Electronics
7*384740dcSRalf Baechle  * Copyright (C) 1995 - 2000, 01, 03 by Ralf Baechle
8*384740dcSRalf Baechle  * Copyright (C) 1999, 2000 Silicon Graphics, Inc.
9*384740dcSRalf Baechle  * Copyright (C) 2007  Maciej W. Rozycki
10*384740dcSRalf Baechle  */
11*384740dcSRalf Baechle #ifndef _ASM_DELAY_H
12*384740dcSRalf Baechle #define _ASM_DELAY_H
13*384740dcSRalf Baechle 
14*384740dcSRalf Baechle #include <linux/param.h>
15*384740dcSRalf Baechle #include <linux/smp.h>
16*384740dcSRalf Baechle 
17*384740dcSRalf Baechle #include <asm/compiler.h>
18*384740dcSRalf Baechle #include <asm/war.h>
19*384740dcSRalf Baechle 
20*384740dcSRalf Baechle static inline void __delay(unsigned long loops)
21*384740dcSRalf Baechle {
22*384740dcSRalf Baechle 	if (sizeof(long) == 4)
23*384740dcSRalf Baechle 		__asm__ __volatile__ (
24*384740dcSRalf Baechle 		"	.set	noreorder				\n"
25*384740dcSRalf Baechle 		"	.align	3					\n"
26*384740dcSRalf Baechle 		"1:	bnez	%0, 1b					\n"
27*384740dcSRalf Baechle 		"	subu	%0, 1					\n"
28*384740dcSRalf Baechle 		"	.set	reorder					\n"
29*384740dcSRalf Baechle 		: "=r" (loops)
30*384740dcSRalf Baechle 		: "0" (loops));
31*384740dcSRalf Baechle 	else if (sizeof(long) == 8 && !DADDI_WAR)
32*384740dcSRalf Baechle 		__asm__ __volatile__ (
33*384740dcSRalf Baechle 		"	.set	noreorder				\n"
34*384740dcSRalf Baechle 		"	.align	3					\n"
35*384740dcSRalf Baechle 		"1:	bnez	%0, 1b					\n"
36*384740dcSRalf Baechle 		"	dsubu	%0, 1					\n"
37*384740dcSRalf Baechle 		"	.set	reorder					\n"
38*384740dcSRalf Baechle 		: "=r" (loops)
39*384740dcSRalf Baechle 		: "0" (loops));
40*384740dcSRalf Baechle 	else if (sizeof(long) == 8 && DADDI_WAR)
41*384740dcSRalf Baechle 		__asm__ __volatile__ (
42*384740dcSRalf Baechle 		"	.set	noreorder				\n"
43*384740dcSRalf Baechle 		"	.align	3					\n"
44*384740dcSRalf Baechle 		"1:	bnez	%0, 1b					\n"
45*384740dcSRalf Baechle 		"	dsubu	%0, %2					\n"
46*384740dcSRalf Baechle 		"	.set	reorder					\n"
47*384740dcSRalf Baechle 		: "=r" (loops)
48*384740dcSRalf Baechle 		: "0" (loops), "r" (1));
49*384740dcSRalf Baechle }
50*384740dcSRalf Baechle 
51*384740dcSRalf Baechle 
52*384740dcSRalf Baechle /*
53*384740dcSRalf Baechle  * Division by multiplication: you don't have to worry about
54*384740dcSRalf Baechle  * loss of precision.
55*384740dcSRalf Baechle  *
56*384740dcSRalf Baechle  * Use only for very small delays ( < 1 msec).  Should probably use a
57*384740dcSRalf Baechle  * lookup table, really, as the multiplications take much too long with
58*384740dcSRalf Baechle  * short delays.  This is a "reasonable" implementation, though (and the
59*384740dcSRalf Baechle  * first constant multiplications gets optimized away if the delay is
60*384740dcSRalf Baechle  * a constant)
61*384740dcSRalf Baechle  */
62*384740dcSRalf Baechle 
63*384740dcSRalf Baechle static inline void __udelay(unsigned long usecs, unsigned long lpj)
64*384740dcSRalf Baechle {
65*384740dcSRalf Baechle 	unsigned long hi, lo;
66*384740dcSRalf Baechle 
67*384740dcSRalf Baechle 	/*
68*384740dcSRalf Baechle 	 * The rates of 128 is rounded wrongly by the catchall case
69*384740dcSRalf Baechle 	 * for 64-bit.  Excessive precission?  Probably ...
70*384740dcSRalf Baechle 	 */
71*384740dcSRalf Baechle #if defined(CONFIG_64BIT) && (HZ == 128)
72*384740dcSRalf Baechle 	usecs *= 0x0008637bd05af6c7UL;		/* 2**64 / (1000000 / HZ) */
73*384740dcSRalf Baechle #elif defined(CONFIG_64BIT)
74*384740dcSRalf Baechle 	usecs *= (0x8000000000000000UL / (500000 / HZ));
75*384740dcSRalf Baechle #else /* 32-bit junk follows here */
76*384740dcSRalf Baechle 	usecs *= (unsigned long) (((0x8000000000000000ULL / (500000 / HZ)) +
77*384740dcSRalf Baechle 	                           0x80000000ULL) >> 32);
78*384740dcSRalf Baechle #endif
79*384740dcSRalf Baechle 
80*384740dcSRalf Baechle 	if (sizeof(long) == 4)
81*384740dcSRalf Baechle 		__asm__("multu\t%2, %3"
82*384740dcSRalf Baechle 		: "=h" (usecs), "=l" (lo)
83*384740dcSRalf Baechle 		: "r" (usecs), "r" (lpj)
84*384740dcSRalf Baechle 		: GCC_REG_ACCUM);
85*384740dcSRalf Baechle 	else if (sizeof(long) == 8 && !R4000_WAR)
86*384740dcSRalf Baechle 		__asm__("dmultu\t%2, %3"
87*384740dcSRalf Baechle 		: "=h" (usecs), "=l" (lo)
88*384740dcSRalf Baechle 		: "r" (usecs), "r" (lpj)
89*384740dcSRalf Baechle 		: GCC_REG_ACCUM);
90*384740dcSRalf Baechle 	else if (sizeof(long) == 8 && R4000_WAR)
91*384740dcSRalf Baechle 		__asm__("dmultu\t%3, %4\n\tmfhi\t%0"
92*384740dcSRalf Baechle 		: "=r" (usecs), "=h" (hi), "=l" (lo)
93*384740dcSRalf Baechle 		: "r" (usecs), "r" (lpj)
94*384740dcSRalf Baechle 		: GCC_REG_ACCUM);
95*384740dcSRalf Baechle 
96*384740dcSRalf Baechle 	__delay(usecs);
97*384740dcSRalf Baechle }
98*384740dcSRalf Baechle 
99*384740dcSRalf Baechle #define __udelay_val cpu_data[raw_smp_processor_id()].udelay_val
100*384740dcSRalf Baechle 
101*384740dcSRalf Baechle #define udelay(usecs) __udelay((usecs), __udelay_val)
102*384740dcSRalf Baechle 
103*384740dcSRalf Baechle /* make sure "usecs *= ..." in udelay do not overflow. */
104*384740dcSRalf Baechle #if HZ >= 1000
105*384740dcSRalf Baechle #define MAX_UDELAY_MS	1
106*384740dcSRalf Baechle #elif HZ <= 200
107*384740dcSRalf Baechle #define MAX_UDELAY_MS	5
108*384740dcSRalf Baechle #else
109*384740dcSRalf Baechle #define MAX_UDELAY_MS	(1000 / HZ)
110*384740dcSRalf Baechle #endif
111*384740dcSRalf Baechle 
112*384740dcSRalf Baechle #endif /* _ASM_DELAY_H */
113