2 * Copyright 2012 Tilera Corporation. All Rights Reserved.
4 * This program is free software; you can redistribute it and/or
5 * modify it under the terms of the GNU General Public License
6 * as published by the Free Software Foundation, version 2.
8 * This program is distributed in the hope that it will be useful, but
9 * WITHOUT ANY WARRANTY; without even the implied warranty of
10 * MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE, GOOD TITLE or
11 * NON INFRINGEMENT. See the GNU General Public License for
15 #define VDSO_BUILD /* avoid some shift warnings for -m32 in <asm/page.h> */
16 #include <linux/time.h>
17 #include <asm/timex.h>
20 #if CHIP_HAS_SPLIT_CYCLE()
21 static inline cycles_t
get_cycles_inline(void)
23 unsigned int high
= __insn_mfspr(SPR_CYCLE_HIGH
);
24 unsigned int low
= __insn_mfspr(SPR_CYCLE_LOW
);
25 unsigned int high2
= __insn_mfspr(SPR_CYCLE_HIGH
);
27 while (unlikely(high
!= high2
)) {
28 low
= __insn_mfspr(SPR_CYCLE_LOW
);
30 high2
= __insn_mfspr(SPR_CYCLE_HIGH
);
33 return (((cycles_t
)high
) << 32) | low
;
35 #define get_cycles get_cycles_inline
39 * Find out the vDSO data page address in the process address space.
41 inline unsigned long get_datapage(void)
45 /* vdso data page located in the 2nd vDSO page. */
46 asm volatile ("lnk %0" : "=r"(ret
));
47 ret
&= ~(PAGE_SIZE
- 1);
53 int __vdso_gettimeofday(struct timeval
*tv
, struct timezone
*tz
)
56 unsigned long count
, sec
, ns
;
57 volatile struct vdso_data
*vdso_data
;
59 vdso_data
= (struct vdso_data
*)get_datapage();
60 /* The use of the timezone is obsolete, normally tz is NULL. */
61 if (unlikely(tz
!= NULL
)) {
63 /* Spin until the update finish. */
64 count
= vdso_data
->tz_update_count
;
68 tz
->tz_minuteswest
= vdso_data
->tz_minuteswest
;
69 tz
->tz_dsttime
= vdso_data
->tz_dsttime
;
71 /* Check whether updated, read again if so. */
72 if (count
== vdso_data
->tz_update_count
)
77 if (unlikely(tv
== NULL
))
81 /* Spin until the update finish. */
82 count
= vdso_data
->tb_update_count
;
86 cycles
= (get_cycles() - vdso_data
->xtime_tod_stamp
);
87 ns
= (cycles
* vdso_data
->mult
) >> vdso_data
->shift
;
88 sec
= vdso_data
->xtime_clock_sec
;
89 ns
+= vdso_data
->xtime_clock_nsec
;
90 if (ns
>= NSEC_PER_SEC
) {
95 /* Check whether updated, read again if so. */
96 if (count
== vdso_data
->tb_update_count
)
101 tv
->tv_usec
= ns
/ 1000;
106 int gettimeofday(struct timeval
*tv
, struct timezone
*tz
)
107 __attribute__((weak
, alias("__vdso_gettimeofday")));