aboutsummaryrefslogtreecommitdiff
path: root/arch/mips/include/asm/timex.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/include/asm/timex.h')
-rw-r--r--arch/mips/include/asm/timex.h97
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__ */