aboutsummaryrefslogtreecommitdiff
path: root/arch/s390/include/asm/timex.h
diff options
context:
space:
mode:
Diffstat (limited to 'arch/s390/include/asm/timex.h')
-rw-r--r--arch/s390/include/asm/timex.h106
1 files changed, 76 insertions, 30 deletions
diff --git a/arch/s390/include/asm/timex.h b/arch/s390/include/asm/timex.h
index 68d9fea34b4..8beee1cceba 100644
--- a/arch/s390/include/asm/timex.h
+++ b/arch/s390/include/asm/timex.h
@@ -1,8 +1,6 @@
/*
- * include/asm-s390/timex.h
- *
* S390 version
- * Copyright (C) 1999 IBM Deutschland Entwicklung GmbH, IBM Corporation
+ * Copyright IBM Corp. 1999
*
* Derived from "include/asm-i386/timex.h"
* Copyright (C) 1992, Linus Torvalds
@@ -11,77 +9,97 @@
#ifndef _ASM_S390_TIMEX_H
#define _ASM_S390_TIMEX_H
+#include <asm/lowcore.h>
+
/* The value of the TOD clock for 1.1.1970. */
#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
/* Inline functions for clock register access. */
-static inline int set_clock(__u64 time)
+static inline int set_tod_clock(__u64 time)
{
int cc;
asm volatile(
- " sck 0(%2)\n"
+ " sck %1\n"
" ipm %0\n"
" srl %0,28\n"
- : "=d" (cc) : "m" (time), "a" (&time) : "cc");
+ : "=d" (cc) : "Q" (time) : "cc");
return cc;
}
-static inline int store_clock(__u64 *time)
+static inline int store_tod_clock(__u64 *time)
{
int cc;
asm volatile(
- " stck 0(%2)\n"
+ " stck %1\n"
" ipm %0\n"
" srl %0,28\n"
- : "=d" (cc), "=m" (*time) : "a" (time) : "cc");
+ : "=d" (cc), "=Q" (*time) : : "cc");
return cc;
}
static inline void set_clock_comparator(__u64 time)
{
- asm volatile("sckc 0(%1)" : : "m" (time), "a" (&time));
+ asm volatile("sckc %0" : : "Q" (time));
}
static inline void store_clock_comparator(__u64 *time)
{
- asm volatile("stckc 0(%1)" : "=m" (*time) : "a" (time));
+ asm volatile("stckc %0" : "=Q" (*time));
+}
+
+void clock_comparator_work(void);
+
+static inline unsigned long long local_tick_disable(void)
+{
+ unsigned long long old;
+
+ old = S390_lowcore.clock_comparator;
+ S390_lowcore.clock_comparator = -1ULL;
+ set_clock_comparator(S390_lowcore.clock_comparator);
+ return old;
+}
+
+static inline void local_tick_enable(unsigned long long comp)
+{
+ S390_lowcore.clock_comparator = comp;
+ set_clock_comparator(S390_lowcore.clock_comparator);
}
#define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
typedef unsigned long long cycles_t;
-static inline unsigned long long get_clock (void)
+static inline void get_tod_clock_ext(char clk[16])
{
- unsigned long long clk;
+ typedef struct { char _[sizeof(clk)]; } addrtype;
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
- asm volatile("stck %0" : "=Q" (clk) : : "cc");
-#else /* __GNUC__ */
- asm volatile("stck 0(%1)" : "=m" (clk) : "a" (&clk) : "cc");
-#endif /* __GNUC__ */
- return clk;
+ asm volatile("stcke %0" : "=Q" (*(addrtype *) clk) : : "cc");
}
-static inline unsigned long long get_clock_xt(void)
+static inline unsigned long long get_tod_clock(void)
{
unsigned char clk[16];
+ get_tod_clock_ext(clk);
+ return *((unsigned long long *)&clk[1]);
+}
-#if __GNUC__ > 3 || (__GNUC__ == 3 && __GNUC_MINOR__ > 2)
- asm volatile("stcke %0" : "=Q" (clk) : : "cc");
-#else /* __GNUC__ */
- asm volatile("stcke 0(%1)" : "=m" (clk)
- : "a" (clk) : "cc");
-#endif /* __GNUC__ */
+static inline unsigned long long get_tod_clock_fast(void)
+{
+#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
+ unsigned long long clk;
- return *((unsigned long long *)&clk[1]);
+ asm volatile("stckf %0" : "=Q" (clk) : : "cc");
+ return clk;
+#else
+ return get_tod_clock();
+#endif
}
static inline cycles_t get_cycles(void)
{
- return (cycles_t) get_clock() >> 2;
+ return (cycles_t) get_tod_clock() >> 2;
}
int get_sync_clock(unsigned long long *clock);
@@ -107,9 +125,37 @@ extern u64 sched_clock_base_cc;
* function, otherwise the returned value is not guaranteed to
* be monotonic.
*/
-static inline unsigned long long get_clock_monotonic(void)
+static inline unsigned long long get_tod_clock_monotonic(void)
{
- return get_clock_xt() - sched_clock_base_cc;
+ return get_tod_clock() - sched_clock_base_cc;
+}
+
+/**
+ * tod_to_ns - convert a TOD format value to nanoseconds
+ * @todval: to be converted TOD format value
+ * Returns: number of nanoseconds that correspond to the TOD format value
+ *
+ * Converting a 64 Bit TOD format value to nanoseconds means that the value
+ * must be divided by 4.096. In order to achieve that we multiply with 125
+ * and divide by 512:
+ *
+ * ns = (todval * 125) >> 9;
+ *
+ * In order to avoid an overflow with the multiplication we can rewrite this.
+ * With a split todval == 2^32 * th + tl (th upper 32 bits, tl lower 32 bits)
+ * we end up with
+ *
+ * ns = ((2^32 * th + tl) * 125 ) >> 9;
+ * -> ns = (2^23 * th * 125) + ((tl * 125) >> 9);
+ *
+ */
+static inline unsigned long long tod_to_ns(unsigned long long todval)
+{
+ unsigned long long ns;
+
+ ns = ((todval >> 32) << 23) * 125;
+ ns += ((todval & 0xffffffff) * 125) >> 9;
+ return ns;
}
#endif