aa20865b288b01a58b1a4c9d1e879e1fe56ef6a3
[linux-2.6-microblaze.git] / arch / mips / include / asm / vdso / gettimeofday.h
1 /*
2  * Copyright (C) 2018 ARM Limited
3  * Copyright (C) 2015 Imagination Technologies
4  * Author: Alex Smith <alex.smith@imgtec.com>
5  *
6  * This program is free software; you can redistribute it and/or modify it
7  * under the terms of the GNU General Public License as published by the
8  * Free Software Foundation;  either version 2 of the  License, or (at your
9  * option) any later version.
10  */
11 #ifndef __ASM_VDSO_GETTIMEOFDAY_H
12 #define __ASM_VDSO_GETTIMEOFDAY_H
13
14 #ifndef __ASSEMBLY__
15
16 #include <linux/compiler.h>
17 #include <linux/time.h>
18
19 #include <asm/vdso/vdso.h>
20 #include <asm/clocksource.h>
21 #include <asm/io.h>
22 #include <asm/unistd.h>
23 #include <asm/vdso.h>
24
25 #ifdef CONFIG_MIPS_CLOCK_VSYSCALL
26
27 static __always_inline long gettimeofday_fallback(
28                                 struct __kernel_old_timeval *_tv,
29                                 struct timezone *_tz)
30 {
31         register struct timezone *tz asm("a1") = _tz;
32         register struct __kernel_old_timeval *tv asm("a0") = _tv;
33         register long ret asm("v0");
34         register long nr asm("v0") = __NR_gettimeofday;
35         register long error asm("a3");
36
37         asm volatile(
38         "       syscall\n"
39         : "=r" (ret), "=r" (error)
40         : "r" (tv), "r" (tz), "r" (nr)
41         : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
42           "$14", "$15", "$24", "$25", "hi", "lo", "memory");
43
44         return error ? -ret : ret;
45 }
46
47 #else
48
49 static __always_inline long gettimeofday_fallback(
50                                 struct __kernel_old_timeval *_tv,
51                                 struct timezone *_tz)
52 {
53         return -1;
54 }
55
56 #endif
57
58 static __always_inline long clock_gettime_fallback(
59                                         clockid_t _clkid,
60                                         struct __kernel_timespec *_ts)
61 {
62         register struct __kernel_timespec *ts asm("a1") = _ts;
63         register clockid_t clkid asm("a0") = _clkid;
64         register long ret asm("v0");
65 #if _MIPS_SIM == _MIPS_SIM_ABI64
66         register long nr asm("v0") = __NR_clock_gettime;
67 #else
68         register long nr asm("v0") = __NR_clock_gettime64;
69 #endif
70         register long error asm("a3");
71
72         asm volatile(
73         "       syscall\n"
74         : "=r" (ret), "=r" (error)
75         : "r" (clkid), "r" (ts), "r" (nr)
76         : "$1", "$3", "$8", "$9", "$10", "$11", "$12", "$13",
77           "$14", "$15", "$24", "$25", "hi", "lo", "memory");
78
79         return error ? -ret : ret;
80 }
81
82 #ifdef CONFIG_CSRC_R4K
83
84 static __always_inline u64 read_r4k_count(void)
85 {
86         unsigned int count;
87
88         __asm__ __volatile__(
89         "       .set push\n"
90         "       .set mips32r2\n"
91         "       rdhwr   %0, $2\n"
92         "       .set pop\n"
93         : "=r" (count));
94
95         return count;
96 }
97
98 #endif
99
100 #ifdef CONFIG_CLKSRC_MIPS_GIC
101
102 static __always_inline u64 read_gic_count(const struct vdso_data *data)
103 {
104         void __iomem *gic = get_gic(data);
105         u32 hi, hi2, lo;
106
107         do {
108                 hi = __raw_readl(gic + sizeof(lo));
109                 lo = __raw_readl(gic);
110                 hi2 = __raw_readl(gic + sizeof(lo));
111         } while (hi2 != hi);
112
113         return (((u64)hi) << 32) + lo;
114 }
115
116 #endif
117
118 static __always_inline u64 __arch_get_hw_counter(s32 clock_mode)
119 {
120 #ifdef CONFIG_CLKSRC_MIPS_GIC
121         const struct vdso_data *data = get_vdso_data();
122 #endif
123         u64 cycle_now;
124
125         switch (clock_mode) {
126 #ifdef CONFIG_CSRC_R4K
127         case VDSO_CLOCK_R4K:
128                 cycle_now = read_r4k_count();
129                 break;
130 #endif
131 #ifdef CONFIG_CLKSRC_MIPS_GIC
132         case VDSO_CLOCK_GIC:
133                 cycle_now = read_gic_count(data);
134                 break;
135 #endif
136         default:
137                 cycle_now = 0;
138                 break;
139         }
140
141         return cycle_now;
142 }
143
144 static __always_inline const struct vdso_data *__arch_get_vdso_data(void)
145 {
146         return get_vdso_data();
147 }
148
149 #endif /* !__ASSEMBLY__ */
150
151 #endif /* __ASM_VDSO_GETTIMEOFDAY_H */