162306a36Sopenharmony_ci/* SPDX-License-Identifier: GPL-2.0 */
262306a36Sopenharmony_ci#ifndef __ASM_VDSO_GETTIMEOFDAY_H
362306a36Sopenharmony_ci#define __ASM_VDSO_GETTIMEOFDAY_H
462306a36Sopenharmony_ci
562306a36Sopenharmony_ci#ifndef __ASSEMBLY__
662306a36Sopenharmony_ci
762306a36Sopenharmony_ci#include <asm/barrier.h>
862306a36Sopenharmony_ci#include <asm/unistd.h>
962306a36Sopenharmony_ci#include <asm/csr.h>
1062306a36Sopenharmony_ci#include <uapi/linux/time.h>
1162306a36Sopenharmony_ci
1262306a36Sopenharmony_ci/*
1362306a36Sopenharmony_ci * 32-bit land is lacking generic time vsyscalls as well as the legacy 32-bit
1462306a36Sopenharmony_ci * time syscalls like gettimeofday. Skip these definitions since on 32-bit.
1562306a36Sopenharmony_ci */
1662306a36Sopenharmony_ci#ifdef CONFIG_GENERIC_TIME_VSYSCALL
1762306a36Sopenharmony_ci
1862306a36Sopenharmony_ci#define VDSO_HAS_CLOCK_GETRES	1
1962306a36Sopenharmony_ci
2062306a36Sopenharmony_cistatic __always_inline
2162306a36Sopenharmony_ciint gettimeofday_fallback(struct __kernel_old_timeval *_tv,
2262306a36Sopenharmony_ci			  struct timezone *_tz)
2362306a36Sopenharmony_ci{
2462306a36Sopenharmony_ci	register struct __kernel_old_timeval *tv asm("a0") = _tv;
2562306a36Sopenharmony_ci	register struct timezone *tz asm("a1") = _tz;
2662306a36Sopenharmony_ci	register long ret asm("a0");
2762306a36Sopenharmony_ci	register long nr asm("a7") = __NR_gettimeofday;
2862306a36Sopenharmony_ci
2962306a36Sopenharmony_ci	asm volatile ("ecall\n"
3062306a36Sopenharmony_ci		      : "=r" (ret)
3162306a36Sopenharmony_ci		      : "r"(tv), "r"(tz), "r"(nr)
3262306a36Sopenharmony_ci		      : "memory");
3362306a36Sopenharmony_ci
3462306a36Sopenharmony_ci	return ret;
3562306a36Sopenharmony_ci}
3662306a36Sopenharmony_ci
3762306a36Sopenharmony_cistatic __always_inline
3862306a36Sopenharmony_cilong clock_gettime_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
3962306a36Sopenharmony_ci{
4062306a36Sopenharmony_ci	register clockid_t clkid asm("a0") = _clkid;
4162306a36Sopenharmony_ci	register struct __kernel_timespec *ts asm("a1") = _ts;
4262306a36Sopenharmony_ci	register long ret asm("a0");
4362306a36Sopenharmony_ci	register long nr asm("a7") = __NR_clock_gettime;
4462306a36Sopenharmony_ci
4562306a36Sopenharmony_ci	asm volatile ("ecall\n"
4662306a36Sopenharmony_ci		      : "=r" (ret)
4762306a36Sopenharmony_ci		      : "r"(clkid), "r"(ts), "r"(nr)
4862306a36Sopenharmony_ci		      : "memory");
4962306a36Sopenharmony_ci
5062306a36Sopenharmony_ci	return ret;
5162306a36Sopenharmony_ci}
5262306a36Sopenharmony_ci
5362306a36Sopenharmony_cistatic __always_inline
5462306a36Sopenharmony_ciint clock_getres_fallback(clockid_t _clkid, struct __kernel_timespec *_ts)
5562306a36Sopenharmony_ci{
5662306a36Sopenharmony_ci	register clockid_t clkid asm("a0") = _clkid;
5762306a36Sopenharmony_ci	register struct __kernel_timespec *ts asm("a1") = _ts;
5862306a36Sopenharmony_ci	register long ret asm("a0");
5962306a36Sopenharmony_ci	register long nr asm("a7") = __NR_clock_getres;
6062306a36Sopenharmony_ci
6162306a36Sopenharmony_ci	asm volatile ("ecall\n"
6262306a36Sopenharmony_ci		      : "=r" (ret)
6362306a36Sopenharmony_ci		      : "r"(clkid), "r"(ts), "r"(nr)
6462306a36Sopenharmony_ci		      : "memory");
6562306a36Sopenharmony_ci
6662306a36Sopenharmony_ci	return ret;
6762306a36Sopenharmony_ci}
6862306a36Sopenharmony_ci
6962306a36Sopenharmony_ci#endif /* CONFIG_GENERIC_TIME_VSYSCALL */
7062306a36Sopenharmony_ci
7162306a36Sopenharmony_cistatic __always_inline u64 __arch_get_hw_counter(s32 clock_mode,
7262306a36Sopenharmony_ci						 const struct vdso_data *vd)
7362306a36Sopenharmony_ci{
7462306a36Sopenharmony_ci	/*
7562306a36Sopenharmony_ci	 * The purpose of csr_read(CSR_TIME) is to trap the system into
7662306a36Sopenharmony_ci	 * M-mode to obtain the value of CSR_TIME. Hence, unlike other
7762306a36Sopenharmony_ci	 * architecture, no fence instructions surround the csr_read()
7862306a36Sopenharmony_ci	 */
7962306a36Sopenharmony_ci	return csr_read(CSR_TIME);
8062306a36Sopenharmony_ci}
8162306a36Sopenharmony_ci
8262306a36Sopenharmony_cistatic __always_inline const struct vdso_data *__arch_get_vdso_data(void)
8362306a36Sopenharmony_ci{
8462306a36Sopenharmony_ci	return _vdso_data;
8562306a36Sopenharmony_ci}
8662306a36Sopenharmony_ci
8762306a36Sopenharmony_ci#ifdef CONFIG_TIME_NS
8862306a36Sopenharmony_cistatic __always_inline
8962306a36Sopenharmony_ciconst struct vdso_data *__arch_get_timens_vdso_data(const struct vdso_data *vd)
9062306a36Sopenharmony_ci{
9162306a36Sopenharmony_ci	return _timens_data;
9262306a36Sopenharmony_ci}
9362306a36Sopenharmony_ci#endif
9462306a36Sopenharmony_ci#endif /* !__ASSEMBLY__ */
9562306a36Sopenharmony_ci
9662306a36Sopenharmony_ci#endif /* __ASM_VDSO_GETTIMEOFDAY_H */
97