diff options
Diffstat (limited to 'arch/mips/include/asm/timex.h')
-rw-r--r-- | arch/mips/include/asm/timex.h | 97 |
1 files changed, 97 insertions, 0 deletions
diff --git a/arch/mips/include/asm/timex.h b/arch/mips/include/asm/timex.h index 6529704aa73..6c150979fa2 100644 --- a/arch/mips/include/asm/timex.h +++ b/arch/mips/include/asm/timex.h @@ -20,6 +20,8 @@ */ #define CLOCK_TICK_RATE 1193182 +extern unsigned int mips_hpt_frequency; + /* * Standard way to access the cycle counter. * Currently only used on SMP for scheduling. @@ -29,14 +31,109 @@ * which isn't an evil thing. * * We know that all SMP capable CPUs have cycle counters. + * + * Mathieu Desnoyers <mathieu.desnoyers@polymtl.ca> + * HAVE_GET_CYCLES makes sure that this case is handled properly : + * + * Ralf Baechle <ralf@linux-mips.org> : + * This avoids us executing an mfc0 c0_count instruction on processors which + * don't have but also on certain R4000 and R4400 versions where reading from + * the count register just in the very moment when its value equals c0_compare + * will result in the timer interrupt getting lost. */ +#ifdef CONFIG_HAVE_GET_CYCLES +# ifdef CONFIG_CPU_CAVIUM_OCTEON +typedef unsigned long cycles_t; + +static inline cycles_t get_cycles(void) +{ + return read_c0_cvmcount(); +} + +static inline void get_cycles_barrier(void) +{ +} + +static inline cycles_t get_cycles_rate(void) +{ + return mips_hpt_frequency; +} + +extern int test_tsc_synchronization(void); +extern int _tsc_is_sync; +static inline int tsc_is_sync(void) +{ + return _tsc_is_sync; +} +# else /* #ifdef CONFIG_CPU_CAVIUM_OCTEON */ +# error "64-bit get_cycles() supported only on Cavium Octeon MIPS architectures" +# endif /* #else #ifdef CONFIG_CPU_CAVIUM_OCTEON */ +#elif defined(CONFIG_HAVE_GET_CYCLES_32) typedef unsigned int cycles_t; static inline cycles_t get_cycles(void) { + return read_c0_count(); +} + +static inline void get_cycles_barrier(void) +{ +} + +static inline cycles_t get_cycles_rate(void) +{ + return mips_hpt_frequency; +} + +extern int test_tsc_synchronization(void); +extern int _tsc_is_sync; +static inline int tsc_is_sync(void) +{ + return _tsc_is_sync; +} +#else +typedef unsigned int cycles_t; + +static inline cycles_t get_cycles(void) +{ + return 0; +} +static inline int test_tsc_synchronization(void) +{ return 0; } +static inline int tsc_is_sync(void) +{ + return 0; +} +#endif + +#define DELAY_INTERRUPT 100 +/* + * Only updates 32 LSB. + */ +static inline void write_tsc(u32 val1, u32 val2) +{ + write_c0_count(val1); + /* Arrange for an interrupt in a short while */ + write_c0_compare(read_c0_count() + DELAY_INTERRUPT); +} + +/* + * Currently unused, should update internal tsc-related timekeeping sources. + */ +static inline void mark_tsc_unstable(char *reason) +{ +} + +/* + * Currently simply use the tsc_is_sync value. + */ +static inline int unsynchronized_tsc(void) +{ + return !tsc_is_sync(); +} #endif /* __KERNEL__ */ |