162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0-or-later */
262306a36Sopenharmony_ci/*
362306a36Sopenharmony_ci * Common timebase prototypes and such for all ppc machines.
462306a36Sopenharmony_ci */
562306a36Sopenharmony_ci
662306a36Sopenharmony_ci#ifndef _ASM_POWERPC_VDSO_TIMEBASE_H
762306a36Sopenharmony_ci#define _ASM_POWERPC_VDSO_TIMEBASE_H
862306a36Sopenharmony_ci
962306a36Sopenharmony_ci#include <asm/reg.h>
1062306a36Sopenharmony_ci
1162306a36Sopenharmony_ci/*
1262306a36Sopenharmony_ci * We use __powerpc64__ here because we want the compat VDSO to use the 32-bit
1362306a36Sopenharmony_ci * version below in the else case of the ifdef.
1462306a36Sopenharmony_ci */
1562306a36Sopenharmony_ci#if defined(__powerpc64__) && (defined(CONFIG_PPC_CELL) || defined(CONFIG_PPC_E500))
1662306a36Sopenharmony_ci#define mftb()		({unsigned long rval;				\
1762306a36Sopenharmony_ci			asm volatile(					\
1862306a36Sopenharmony_ci				"90:	mfspr %0, %2;\n"		\
1962306a36Sopenharmony_ci				ASM_FTR_IFSET(				\
2062306a36Sopenharmony_ci					"97:	cmpwi %0,0;\n"		\
2162306a36Sopenharmony_ci					"	beq- 90b;\n", "", %1)	\
2262306a36Sopenharmony_ci			: "=r" (rval) \
2362306a36Sopenharmony_ci			: "i" (CPU_FTR_CELL_TB_BUG), "i" (SPRN_TBRL) : "cr0"); \
2462306a36Sopenharmony_ci			rval;})
2562306a36Sopenharmony_ci#elif defined(CONFIG_PPC_8xx)
2662306a36Sopenharmony_ci#define mftb()		({unsigned long rval;	\
2762306a36Sopenharmony_ci			asm volatile("mftbl %0" : "=r" (rval)); rval;})
2862306a36Sopenharmony_ci#else
2962306a36Sopenharmony_ci#define mftb()		({unsigned long rval;	\
3062306a36Sopenharmony_ci			asm volatile("mfspr %0, %1" : \
3162306a36Sopenharmony_ci				     "=r" (rval) : "i" (SPRN_TBRL)); rval;})
3262306a36Sopenharmony_ci#endif /* !CONFIG_PPC_CELL */
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci#if defined(CONFIG_PPC_8xx)
3562306a36Sopenharmony_ci#define mftbu()		({unsigned long rval;	\
3662306a36Sopenharmony_ci			asm volatile("mftbu %0" : "=r" (rval)); rval;})
3762306a36Sopenharmony_ci#else
3862306a36Sopenharmony_ci#define mftbu()		({unsigned long rval;	\
3962306a36Sopenharmony_ci			asm volatile("mfspr %0, %1" : "=r" (rval) : \
4062306a36Sopenharmony_ci				"i" (SPRN_TBRU)); rval;})
4162306a36Sopenharmony_ci#endif
4262306a36Sopenharmony_ci
4362306a36Sopenharmony_ci#define mttbl(v)	asm volatile("mttbl %0":: "r"(v))
4462306a36Sopenharmony_ci#define mttbu(v)	asm volatile("mttbu %0":: "r"(v))
4562306a36Sopenharmony_ci
4662306a36Sopenharmony_cistatic __always_inline u64 get_tb(void)
4762306a36Sopenharmony_ci{
4862306a36Sopenharmony_ci	unsigned int tbhi, tblo, tbhi2;
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	/*
5162306a36Sopenharmony_ci	 * We use __powerpc64__ here not CONFIG_PPC64 because we want the compat
5262306a36Sopenharmony_ci	 * VDSO to use the 32-bit compatible version in the while loop below.
5362306a36Sopenharmony_ci	 */
5462306a36Sopenharmony_ci	if (__is_defined(__powerpc64__))
5562306a36Sopenharmony_ci		return mftb();
5662306a36Sopenharmony_ci
5762306a36Sopenharmony_ci	do {
5862306a36Sopenharmony_ci		tbhi = mftbu();
5962306a36Sopenharmony_ci		tblo = mftb();
6062306a36Sopenharmony_ci		tbhi2 = mftbu();
6162306a36Sopenharmony_ci	} while (tbhi != tbhi2);
6262306a36Sopenharmony_ci
6362306a36Sopenharmony_ci	return ((u64)tbhi << 32) | tblo;
6462306a36Sopenharmony_ci}
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_cistatic inline void set_tb(unsigned int upper, unsigned int lower)
6762306a36Sopenharmony_ci{
6862306a36Sopenharmony_ci	mtspr(SPRN_TBWL, 0);
6962306a36Sopenharmony_ci	mtspr(SPRN_TBWU, upper);
7062306a36Sopenharmony_ci	mtspr(SPRN_TBWL, lower);
7162306a36Sopenharmony_ci}
7262306a36Sopenharmony_ci
7362306a36Sopenharmony_ci#endif /* _ASM_POWERPC_VDSO_TIMEBASE_H */
74