124640f23SVincenzo Frascino /* 224640f23SVincenzo Frascino * Copyright (C) 2018 ARM Limited 324640f23SVincenzo Frascino * Copyright (C) 2015 Imagination Technologies 424640f23SVincenzo Frascino * Author: Alex Smith <alex.smith@imgtec.com> 524640f23SVincenzo Frascino * 624640f23SVincenzo Frascino * This program is free software; you can redistribute it and/or modify it 724640f23SVincenzo Frascino * under the terms of the GNU General Public License as published by the 824640f23SVincenzo Frascino * Free Software Foundation; either version 2 of the License, or (at your 924640f23SVincenzo Frascino * option) any later version. 1024640f23SVincenzo Frascino */ 1124640f23SVincenzo Frascino #ifndef __ASM_VDSO_GETTIMEOFDAY_H 1224640f23SVincenzo Frascino #define __ASM_VDSO_GETTIMEOFDAY_H 1324640f23SVincenzo Frascino 1424640f23SVincenzo Frascino #ifndef __ASSEMBLY__ 1524640f23SVincenzo Frascino 1624640f23SVincenzo Frascino #include <linux/compiler.h> 1724640f23SVincenzo Frascino #include <linux/time.h> 1824640f23SVincenzo Frascino 1924640f23SVincenzo Frascino #include <asm/vdso/vdso.h> 2024640f23SVincenzo Frascino #include <asm/clocksource.h> 2124640f23SVincenzo Frascino #include <asm/io.h> 2224640f23SVincenzo Frascino #include <asm/unistd.h> 2324640f23SVincenzo Frascino #include <asm/vdso.h> 2424640f23SVincenzo Frascino 25abed3d82SVincenzo Frascino #define VDSO_HAS_CLOCK_GETRES 1 26abed3d82SVincenzo Frascino 2724640f23SVincenzo Frascino #ifdef CONFIG_MIPS_CLOCK_VSYSCALL 2824640f23SVincenzo Frascino 2924640f23SVincenzo Frascino static __always_inline long gettimeofday_fallback( 3024640f23SVincenzo Frascino struct __kernel_old_timeval *_tv, 3124640f23SVincenzo Frascino struct timezone *_tz) 3224640f23SVincenzo Frascino { 3324640f23SVincenzo Frascino register struct timezone *tz asm("a1") = _tz; 3424640f23SVincenzo Frascino register struct __kernel_old_timeval *tv asm("a0") = _tv; 3524640f23SVincenzo Frascino register long ret asm("v0"); 3624640f23SVincenzo Frascino register long nr asm("v0") = __NR_gettimeofday; 3724640f23SVincenzo Frascino register long error asm("a3"); 3824640f23SVincenzo Frascino 3924640f23SVincenzo Frascino asm volatile( 4024640f23SVincenzo Frascino " syscall\n" 4124640f23SVincenzo Frascino : "=r" (ret), "=r" (error) 4224640f23SVincenzo Frascino : "r" (tv), "r" (tz), "r" (nr) 4324640f23SVincenzo Frascino : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", 4424640f23SVincenzo Frascino "$14", "$15", "$24", "$25", "hi", "lo", "memory"); 4524640f23SVincenzo Frascino 4624640f23SVincenzo Frascino return error ? -ret : ret; 4724640f23SVincenzo Frascino } 4824640f23SVincenzo Frascino 4924640f23SVincenzo Frascino #else 5024640f23SVincenzo Frascino 5124640f23SVincenzo Frascino static __always_inline long gettimeofday_fallback( 5224640f23SVincenzo Frascino struct __kernel_old_timeval *_tv, 5324640f23SVincenzo Frascino struct timezone *_tz) 5424640f23SVincenzo Frascino { 5524640f23SVincenzo Frascino return -1; 5624640f23SVincenzo Frascino } 5724640f23SVincenzo Frascino 5824640f23SVincenzo Frascino #endif 5924640f23SVincenzo Frascino 6024640f23SVincenzo Frascino static __always_inline long clock_gettime_fallback( 6124640f23SVincenzo Frascino clockid_t _clkid, 6224640f23SVincenzo Frascino struct __kernel_timespec *_ts) 6324640f23SVincenzo Frascino { 6424640f23SVincenzo Frascino register struct __kernel_timespec *ts asm("a1") = _ts; 6524640f23SVincenzo Frascino register clockid_t clkid asm("a0") = _clkid; 6624640f23SVincenzo Frascino register long ret asm("v0"); 6724640f23SVincenzo Frascino #if _MIPS_SIM == _MIPS_SIM_ABI64 6824640f23SVincenzo Frascino register long nr asm("v0") = __NR_clock_gettime; 6924640f23SVincenzo Frascino #else 7024640f23SVincenzo Frascino register long nr asm("v0") = __NR_clock_gettime64; 7124640f23SVincenzo Frascino #endif 7224640f23SVincenzo Frascino register long error asm("a3"); 7324640f23SVincenzo Frascino 7424640f23SVincenzo Frascino asm volatile( 7524640f23SVincenzo Frascino " syscall\n" 7624640f23SVincenzo Frascino : "=r" (ret), "=r" (error) 7724640f23SVincenzo Frascino : "r" (clkid), "r" (ts), "r" (nr) 7824640f23SVincenzo Frascino : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", 7924640f23SVincenzo Frascino "$14", "$15", "$24", "$25", "hi", "lo", "memory"); 8024640f23SVincenzo Frascino 8124640f23SVincenzo Frascino return error ? -ret : ret; 8224640f23SVincenzo Frascino } 8324640f23SVincenzo Frascino 84abed3d82SVincenzo Frascino static __always_inline int clock_getres_fallback( 85abed3d82SVincenzo Frascino clockid_t _clkid, 86abed3d82SVincenzo Frascino struct __kernel_timespec *_ts) 87abed3d82SVincenzo Frascino { 88abed3d82SVincenzo Frascino register struct __kernel_timespec *ts asm("a1") = _ts; 89abed3d82SVincenzo Frascino register clockid_t clkid asm("a0") = _clkid; 90abed3d82SVincenzo Frascino register long ret asm("v0"); 91abed3d82SVincenzo Frascino #if _MIPS_SIM == _MIPS_SIM_ABI64 92abed3d82SVincenzo Frascino register long nr asm("v0") = __NR_clock_getres; 93abed3d82SVincenzo Frascino #else 94abed3d82SVincenzo Frascino register long nr asm("v0") = __NR_clock_getres_time64; 95abed3d82SVincenzo Frascino #endif 96abed3d82SVincenzo Frascino register long error asm("a3"); 97abed3d82SVincenzo Frascino 98abed3d82SVincenzo Frascino asm volatile( 99abed3d82SVincenzo Frascino " syscall\n" 100abed3d82SVincenzo Frascino : "=r" (ret), "=r" (error) 101abed3d82SVincenzo Frascino : "r" (clkid), "r" (ts), "r" (nr) 102abed3d82SVincenzo Frascino : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", 103abed3d82SVincenzo Frascino "$14", "$15", "$24", "$25", "hi", "lo", "memory"); 104abed3d82SVincenzo Frascino 105abed3d82SVincenzo Frascino return error ? -ret : ret; 106abed3d82SVincenzo Frascino } 107abed3d82SVincenzo Frascino 108*932bb934SVincenzo Frascino #if _MIPS_SIM != _MIPS_SIM_ABI64 109*932bb934SVincenzo Frascino 110*932bb934SVincenzo Frascino #define VDSO_HAS_32BIT_FALLBACK 1 111*932bb934SVincenzo Frascino 112*932bb934SVincenzo Frascino static __always_inline long clock_gettime32_fallback( 113*932bb934SVincenzo Frascino clockid_t _clkid, 114*932bb934SVincenzo Frascino struct old_timespec32 *_ts) 115*932bb934SVincenzo Frascino { 116*932bb934SVincenzo Frascino register struct old_timespec32 *ts asm("a1") = _ts; 117*932bb934SVincenzo Frascino register clockid_t clkid asm("a0") = _clkid; 118*932bb934SVincenzo Frascino register long ret asm("v0"); 119*932bb934SVincenzo Frascino register long nr asm("v0") = __NR_clock_gettime; 120*932bb934SVincenzo Frascino register long error asm("a3"); 121*932bb934SVincenzo Frascino 122*932bb934SVincenzo Frascino asm volatile( 123*932bb934SVincenzo Frascino " syscall\n" 124*932bb934SVincenzo Frascino : "=r" (ret), "=r" (error) 125*932bb934SVincenzo Frascino : "r" (clkid), "r" (ts), "r" (nr) 126*932bb934SVincenzo Frascino : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", 127*932bb934SVincenzo Frascino "$14", "$15", "$24", "$25", "hi", "lo", "memory"); 128*932bb934SVincenzo Frascino 129*932bb934SVincenzo Frascino return error ? -ret : ret; 130*932bb934SVincenzo Frascino } 131*932bb934SVincenzo Frascino 132*932bb934SVincenzo Frascino static __always_inline int clock_getres32_fallback( 133*932bb934SVincenzo Frascino clockid_t _clkid, 134*932bb934SVincenzo Frascino struct old_timespec32 *_ts) 135*932bb934SVincenzo Frascino { 136*932bb934SVincenzo Frascino register struct old_timespec32 *ts asm("a1") = _ts; 137*932bb934SVincenzo Frascino register clockid_t clkid asm("a0") = _clkid; 138*932bb934SVincenzo Frascino register long ret asm("v0"); 139*932bb934SVincenzo Frascino register long nr asm("v0") = __NR_clock_getres; 140*932bb934SVincenzo Frascino register long error asm("a3"); 141*932bb934SVincenzo Frascino 142*932bb934SVincenzo Frascino asm volatile( 143*932bb934SVincenzo Frascino " syscall\n" 144*932bb934SVincenzo Frascino : "=r" (ret), "=r" (error) 145*932bb934SVincenzo Frascino : "r" (clkid), "r" (ts), "r" (nr) 146*932bb934SVincenzo Frascino : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13", 147*932bb934SVincenzo Frascino "$14", "$15", "$24", "$25", "hi", "lo", "memory"); 148*932bb934SVincenzo Frascino 149*932bb934SVincenzo Frascino return error ? -ret : ret; 150*932bb934SVincenzo Frascino } 151*932bb934SVincenzo Frascino #endif 152*932bb934SVincenzo Frascino 15324640f23SVincenzo Frascino #ifdef CONFIG_CSRC_R4K 15424640f23SVincenzo Frascino 15524640f23SVincenzo Frascino static __always_inline u64 read_r4k_count(void) 15624640f23SVincenzo Frascino { 15724640f23SVincenzo Frascino unsigned int count; 15824640f23SVincenzo Frascino 15924640f23SVincenzo Frascino __asm__ __volatile__( 16024640f23SVincenzo Frascino " .set push\n" 16124640f23SVincenzo Frascino " .set mips32r2\n" 16224640f23SVincenzo Frascino " rdhwr %0, $2\n" 16324640f23SVincenzo Frascino " .set pop\n" 16424640f23SVincenzo Frascino : "=r" (count)); 16524640f23SVincenzo Frascino 16624640f23SVincenzo Frascino return count; 16724640f23SVincenzo Frascino } 16824640f23SVincenzo Frascino 16924640f23SVincenzo Frascino #endif 17024640f23SVincenzo Frascino 17124640f23SVincenzo Frascino #ifdef CONFIG_CLKSRC_MIPS_GIC 17224640f23SVincenzo Frascino 17324640f23SVincenzo Frascino static __always_inline u64 read_gic_count(const struct vdso_data *data) 17424640f23SVincenzo Frascino { 17524640f23SVincenzo Frascino void __iomem *gic = get_gic(data); 17624640f23SVincenzo Frascino u32 hi, hi2, lo; 17724640f23SVincenzo Frascino 17824640f23SVincenzo Frascino do { 17924640f23SVincenzo Frascino hi = __raw_readl(gic + sizeof(lo)); 18024640f23SVincenzo Frascino lo = __raw_readl(gic); 18124640f23SVincenzo Frascino hi2 = __raw_readl(gic + sizeof(lo)); 18224640f23SVincenzo Frascino } while (hi2 != hi); 18324640f23SVincenzo Frascino 18424640f23SVincenzo Frascino return (((u64)hi) << 32) + lo; 18524640f23SVincenzo Frascino } 18624640f23SVincenzo Frascino 18724640f23SVincenzo Frascino #endif 18824640f23SVincenzo Frascino 18924640f23SVincenzo Frascino static __always_inline u64 __arch_get_hw_counter(s32 clock_mode) 19024640f23SVincenzo Frascino { 19124640f23SVincenzo Frascino #ifdef CONFIG_CLKSRC_MIPS_GIC 19224640f23SVincenzo Frascino const struct vdso_data *data = get_vdso_data(); 19324640f23SVincenzo Frascino #endif 19424640f23SVincenzo Frascino u64 cycle_now; 19524640f23SVincenzo Frascino 19624640f23SVincenzo Frascino switch (clock_mode) { 19724640f23SVincenzo Frascino #ifdef CONFIG_CSRC_R4K 19824640f23SVincenzo Frascino case VDSO_CLOCK_R4K: 19924640f23SVincenzo Frascino cycle_now = read_r4k_count(); 20024640f23SVincenzo Frascino break; 20124640f23SVincenzo Frascino #endif 20224640f23SVincenzo Frascino #ifdef CONFIG_CLKSRC_MIPS_GIC 20324640f23SVincenzo Frascino case VDSO_CLOCK_GIC: 20424640f23SVincenzo Frascino cycle_now = read_gic_count(data); 20524640f23SVincenzo Frascino break; 20624640f23SVincenzo Frascino #endif 20724640f23SVincenzo Frascino default: 20824640f23SVincenzo Frascino cycle_now = 0; 20924640f23SVincenzo Frascino break; 21024640f23SVincenzo Frascino } 21124640f23SVincenzo Frascino 21224640f23SVincenzo Frascino return cycle_now; 21324640f23SVincenzo Frascino } 21424640f23SVincenzo Frascino 21524640f23SVincenzo Frascino static __always_inline const struct vdso_data *__arch_get_vdso_data(void) 21624640f23SVincenzo Frascino { 21724640f23SVincenzo Frascino return get_vdso_data(); 21824640f23SVincenzo Frascino } 21924640f23SVincenzo Frascino 22024640f23SVincenzo Frascino #endif /* !__ASSEMBLY__ */ 22124640f23SVincenzo Frascino 22224640f23SVincenzo Frascino #endif /* __ASM_VDSO_GETTIMEOFDAY_H */ 223