1 /* SPDX-License-Identifier: GPL-2.0-or-later */
2 /*
3  * Common timebase prototypes and such for all ppc machines.
4  */
5 
6 #ifndef _ASM_POWERPC_VDSO_TIMEBASE_H
7 #define _ASM_POWERPC_VDSO_TIMEBASE_H
8 
9 #include <asm/reg.h>
10 
11 /*
12  * We use __powerpc64__ here because we want the compat VDSO to use the 32-bit
13  * version below in the else case of the ifdef.
14  */
15 #if defined(__powerpc64__) && (defined(CONFIG_PPC_CELL) || defined(CONFIG_E500))
16 #define mftb()		({unsigned long rval;				\
17 			asm volatile(					\
18 				"90:	mfspr %0, %2;\n"		\
19 				ASM_FTR_IFSET(				\
20 					"97:	cmpwi %0,0;\n"		\
21 					"	beq- 90b;\n", "", %1)	\
22 			: "=r" (rval) \
23 			: "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL) : "cr0"); \
24 			rval;})
25 #elif defined(CONFIG_PPC_8xx)
26 #define mftb()		({unsigned long rval;	\
27 			asm volatile("mftbl %0" : "=r" (rval)); rval;})
28 #else
29 #define mftb()		({unsigned long rval;	\
30 			asm volatile("mfspr %0, %1" : \
31 				     "=r" (rval) : "i" (SPRN_TBRL)); rval;})
32 #endif /* !CONFIG_PPC_CELL */
33 
34 #if defined(CONFIG_PPC_8xx)
35 #define mftbu()		({unsigned long rval;	\
36 			asm volatile("mftbu %0" : "=r" (rval)); rval;})
37 #else
38 #define mftbu()		({unsigned long rval;	\
39 			asm volatile("mfspr %0, %1" : "=r" (rval) : \
40 				"i" (SPRN_TBRU)); rval;})
41 #endif
42 
43 #define mttbl(v)	asm volatile("mttbl %0":: "r"(v))
44 #define mttbu(v)	asm volatile("mttbu %0":: "r"(v))
45 
46 /* For compatibility, get_tbl() is defined as get_tb() on ppc64 */
47 static inline unsigned long get_tbl(void)
48 {
49 	return mftb();
50 }
51 
52 static __always_inline u64 get_tb(void)
53 {
54 	unsigned int tbhi, tblo, tbhi2;
55 
56 	/*
57 	 * We use __powerpc64__ here not CONFIG_PPC64 because we want the compat
58 	 * VDSO to use the 32-bit compatible version in the while loop below.
59 	 */
60 	if (__is_defined(__powerpc64__))
61 		return mftb();
62 
63 	do {
64 		tbhi = mftbu();
65 		tblo = mftb();
66 		tbhi2 = mftbu();
67 	} while (tbhi != tbhi2);
68 
69 	return ((u64)tbhi << 32) | tblo;
70 }
71 
72 static inline void set_tb(unsigned int upper, unsigned int lower)
73 {
74 	mtspr(SPRN_TBWL, 0);
75 	mtspr(SPRN_TBWU, upper);
76 	mtspr(SPRN_TBWL, lower);
77 }
78 
79 #endif /* _ASM_POWERPC_VDSO_TIMEBASE_H */
80