120e2fc42SVincenzo Frascino /* SPDX-License-Identifier: GPL-2.0 */
220e2fc42SVincenzo Frascino /*
320e2fc42SVincenzo Frascino  * Copyright (C) 2018 ARM Limited
420e2fc42SVincenzo Frascino  */
520e2fc42SVincenzo Frascino #ifndef __ASM_VDSO_GETTIMEOFDAY_H
620e2fc42SVincenzo Frascino #define __ASM_VDSO_GETTIMEOFDAY_H
720e2fc42SVincenzo Frascino 
820e2fc42SVincenzo Frascino #ifndef __ASSEMBLY__
920e2fc42SVincenzo Frascino 
1020e2fc42SVincenzo Frascino #include <asm/barrier.h>
1120e2fc42SVincenzo Frascino #include <asm/cp15.h>
1220e2fc42SVincenzo Frascino #include <asm/unistd.h>
1320e2fc42SVincenzo Frascino #include <uapi/linux/time.h>
1420e2fc42SVincenzo Frascino 
15052e76a3SVincenzo Frascino #define VDSO_HAS_CLOCK_GETRES		1
16052e76a3SVincenzo Frascino 
1720e2fc42SVincenzo Frascino extern struct vdso_data *__get_datapage(void);
1820e2fc42SVincenzo Frascino 
1920e2fc42SVincenzo Frascino static __always_inline int gettimeofday_fallback(
2020e2fc42SVincenzo Frascino 				struct __kernel_old_timeval *_tv,
2120e2fc42SVincenzo Frascino 				struct timezone *_tz)
2220e2fc42SVincenzo Frascino {
2320e2fc42SVincenzo Frascino 	register struct timezone *tz asm("r1") = _tz;
2420e2fc42SVincenzo Frascino 	register struct __kernel_old_timeval *tv asm("r0") = _tv;
2520e2fc42SVincenzo Frascino 	register long ret asm ("r0");
2620e2fc42SVincenzo Frascino 	register long nr asm("r7") = __NR_gettimeofday;
2720e2fc42SVincenzo Frascino 
2820e2fc42SVincenzo Frascino 	asm volatile(
2920e2fc42SVincenzo Frascino 	"	swi #0\n"
3020e2fc42SVincenzo Frascino 	: "=r" (ret)
3120e2fc42SVincenzo Frascino 	: "r" (tv), "r" (tz), "r" (nr)
3220e2fc42SVincenzo Frascino 	: "memory");
3320e2fc42SVincenzo Frascino 
3420e2fc42SVincenzo Frascino 	return ret;
3520e2fc42SVincenzo Frascino }
3620e2fc42SVincenzo Frascino 
3720e2fc42SVincenzo Frascino static __always_inline long clock_gettime_fallback(
3820e2fc42SVincenzo Frascino 					clockid_t _clkid,
3920e2fc42SVincenzo Frascino 					struct __kernel_timespec *_ts)
4020e2fc42SVincenzo Frascino {
4120e2fc42SVincenzo Frascino 	register struct __kernel_timespec *ts asm("r1") = _ts;
4220e2fc42SVincenzo Frascino 	register clockid_t clkid asm("r0") = _clkid;
4320e2fc42SVincenzo Frascino 	register long ret asm ("r0");
4420e2fc42SVincenzo Frascino 	register long nr asm("r7") = __NR_clock_gettime64;
4520e2fc42SVincenzo Frascino 
4620e2fc42SVincenzo Frascino 	asm volatile(
4720e2fc42SVincenzo Frascino 	"	swi #0\n"
4820e2fc42SVincenzo Frascino 	: "=r" (ret)
4920e2fc42SVincenzo Frascino 	: "r" (clkid), "r" (ts), "r" (nr)
5020e2fc42SVincenzo Frascino 	: "memory");
5120e2fc42SVincenzo Frascino 
5220e2fc42SVincenzo Frascino 	return ret;
5320e2fc42SVincenzo Frascino }
5420e2fc42SVincenzo Frascino 
55715f23b6SThomas Gleixner static __always_inline long clock_gettime32_fallback(
56715f23b6SThomas Gleixner 					clockid_t _clkid,
57715f23b6SThomas Gleixner 					struct old_timespec32 *_ts)
58715f23b6SThomas Gleixner {
59715f23b6SThomas Gleixner 	register struct old_timespec32 *ts asm("r1") = _ts;
60715f23b6SThomas Gleixner 	register clockid_t clkid asm("r0") = _clkid;
61715f23b6SThomas Gleixner 	register long ret asm ("r0");
62715f23b6SThomas Gleixner 	register long nr asm("r7") = __NR_clock_gettime;
63715f23b6SThomas Gleixner 
64715f23b6SThomas Gleixner 	asm volatile(
65715f23b6SThomas Gleixner 	"	swi #0\n"
66715f23b6SThomas Gleixner 	: "=r" (ret)
67715f23b6SThomas Gleixner 	: "r" (clkid), "r" (ts), "r" (nr)
68715f23b6SThomas Gleixner 	: "memory");
69715f23b6SThomas Gleixner 
70715f23b6SThomas Gleixner 	return ret;
71715f23b6SThomas Gleixner }
72715f23b6SThomas Gleixner 
73052e76a3SVincenzo Frascino static __always_inline int clock_getres_fallback(
74052e76a3SVincenzo Frascino 					clockid_t _clkid,
75052e76a3SVincenzo Frascino 					struct __kernel_timespec *_ts)
76052e76a3SVincenzo Frascino {
77052e76a3SVincenzo Frascino 	register struct __kernel_timespec *ts asm("r1") = _ts;
78052e76a3SVincenzo Frascino 	register clockid_t clkid asm("r0") = _clkid;
79052e76a3SVincenzo Frascino 	register long ret asm ("r0");
80052e76a3SVincenzo Frascino 	register long nr asm("r7") = __NR_clock_getres_time64;
81052e76a3SVincenzo Frascino 
82052e76a3SVincenzo Frascino 	asm volatile(
83052e76a3SVincenzo Frascino 	"       swi #0\n"
84052e76a3SVincenzo Frascino 	: "=r" (ret)
85052e76a3SVincenzo Frascino 	: "r" (clkid), "r" (ts), "r" (nr)
86052e76a3SVincenzo Frascino 	: "memory");
87052e76a3SVincenzo Frascino 
88052e76a3SVincenzo Frascino 	return ret;
89052e76a3SVincenzo Frascino }
90052e76a3SVincenzo Frascino 
91715f23b6SThomas Gleixner static __always_inline int clock_getres32_fallback(
92715f23b6SThomas Gleixner 					clockid_t _clkid,
93715f23b6SThomas Gleixner 					struct old_timespec32 *_ts)
94715f23b6SThomas Gleixner {
95715f23b6SThomas Gleixner 	register struct old_timespec32 *ts asm("r1") = _ts;
96715f23b6SThomas Gleixner 	register clockid_t clkid asm("r0") = _clkid;
97715f23b6SThomas Gleixner 	register long ret asm ("r0");
98715f23b6SThomas Gleixner 	register long nr asm("r7") = __NR_clock_getres;
99715f23b6SThomas Gleixner 
100715f23b6SThomas Gleixner 	asm volatile(
101715f23b6SThomas Gleixner 	"       swi #0\n"
102715f23b6SThomas Gleixner 	: "=r" (ret)
103715f23b6SThomas Gleixner 	: "r" (clkid), "r" (ts), "r" (nr)
104715f23b6SThomas Gleixner 	: "memory");
105715f23b6SThomas Gleixner 
106715f23b6SThomas Gleixner 	return ret;
107715f23b6SThomas Gleixner }
108715f23b6SThomas Gleixner 
10920e2fc42SVincenzo Frascino static __always_inline u64 __arch_get_hw_counter(int clock_mode)
11020e2fc42SVincenzo Frascino {
11120e2fc42SVincenzo Frascino #ifdef CONFIG_ARM_ARCH_TIMER
11220e2fc42SVincenzo Frascino 	u64 cycle_now;
11320e2fc42SVincenzo Frascino 
11404bb9642SVincenzo Frascino 	if (!clock_mode)
11504bb9642SVincenzo Frascino 		return -EINVAL;
11604bb9642SVincenzo Frascino 
11720e2fc42SVincenzo Frascino 	isb();
11820e2fc42SVincenzo Frascino 	cycle_now = read_sysreg(CNTVCT);
11920e2fc42SVincenzo Frascino 
12020e2fc42SVincenzo Frascino 	return cycle_now;
12120e2fc42SVincenzo Frascino #else
12220e2fc42SVincenzo Frascino 	return -EINVAL; /* use fallback */
12320e2fc42SVincenzo Frascino #endif
12420e2fc42SVincenzo Frascino }
12520e2fc42SVincenzo Frascino 
12620e2fc42SVincenzo Frascino static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
12720e2fc42SVincenzo Frascino {
12820e2fc42SVincenzo Frascino 	return __get_datapage();
12920e2fc42SVincenzo Frascino }
13020e2fc42SVincenzo Frascino 
13120e2fc42SVincenzo Frascino #endif /* !__ASSEMBLY__ */
13220e2fc42SVincenzo Frascino 
13320e2fc42SVincenzo Frascino #endif /* __ASM_VDSO_GETTIMEOFDAY_H */
134