linux/arch/s390/include/asm/timex.h
<<
>>
Prefs
   1/*
   2 *  S390 version
   3 *    Copyright IBM Corp. 1999
   4 *
   5 *  Derived from "include/asm-i386/timex.h"
   6 *    Copyright (C) 1992, Linus Torvalds
   7 */
   8
   9#ifndef _ASM_S390_TIMEX_H
  10#define _ASM_S390_TIMEX_H
  11
  12#include <asm/lowcore.h>
  13
  14/* The value of the TOD clock for 1.1.1970. */
  15#define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
  16
  17/* Inline functions for clock register access. */
  18static inline int set_tod_clock(__u64 time)
  19{
  20        int cc;
  21
  22        asm volatile(
  23                "   sck   %1\n"
  24                "   ipm   %0\n"
  25                "   srl   %0,28\n"
  26                : "=d" (cc) : "Q" (time) : "cc");
  27        return cc;
  28}
  29
  30static inline int store_tod_clock(__u64 *time)
  31{
  32        int cc;
  33
  34        asm volatile(
  35                "   stck  %1\n"
  36                "   ipm   %0\n"
  37                "   srl   %0,28\n"
  38                : "=d" (cc), "=Q" (*time) : : "cc");
  39        return cc;
  40}
  41
  42static inline void set_clock_comparator(__u64 time)
  43{
  44        asm volatile("sckc %0" : : "Q" (time));
  45}
  46
  47static inline void store_clock_comparator(__u64 *time)
  48{
  49        asm volatile("stckc %0" : "=Q" (*time));
  50}
  51
  52void clock_comparator_work(void);
  53
  54static inline unsigned long long local_tick_disable(void)
  55{
  56        unsigned long long old;
  57
  58        old = S390_lowcore.clock_comparator;
  59        S390_lowcore.clock_comparator = -1ULL;
  60        set_clock_comparator(S390_lowcore.clock_comparator);
  61        return old;
  62}
  63
  64static inline void local_tick_enable(unsigned long long comp)
  65{
  66        S390_lowcore.clock_comparator = comp;
  67        set_clock_comparator(S390_lowcore.clock_comparator);
  68}
  69
  70#define CLOCK_TICK_RATE         1193180 /* Underlying HZ */
  71#define STORE_CLOCK_EXT_SIZE    16      /* stcke writes 16 bytes */
  72
  73typedef unsigned long long cycles_t;
  74
  75static inline void get_tod_clock_ext(char *clk)
  76{
  77        typedef struct { char _[STORE_CLOCK_EXT_SIZE]; } addrtype;
  78
  79        asm volatile("stcke %0" : "=Q" (*(addrtype *) clk) : : "cc");
  80}
  81
  82static inline unsigned long long get_tod_clock(void)
  83{
  84        unsigned char clk[STORE_CLOCK_EXT_SIZE];
  85
  86        get_tod_clock_ext(clk);
  87        return *((unsigned long long *)&clk[1]);
  88}
  89
  90static inline unsigned long long get_tod_clock_fast(void)
  91{
  92#ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
  93        unsigned long long clk;
  94
  95        asm volatile("stckf %0" : "=Q" (clk) : : "cc");
  96        return clk;
  97#else
  98        return get_tod_clock();
  99#endif
 100}
 101
 102static inline cycles_t get_cycles(void)
 103{
 104        return (cycles_t) get_tod_clock() >> 2;
 105}
 106
 107int get_sync_clock(unsigned long long *clock);
 108void init_cpu_timer(void);
 109unsigned long long monotonic_clock(void);
 110
 111void tod_to_timeval(__u64, struct timespec *);
 112
 113static inline
 114void stck_to_timespec(unsigned long long stck, struct timespec *ts)
 115{
 116        tod_to_timeval(stck - TOD_UNIX_EPOCH, ts);
 117}
 118
 119extern u64 sched_clock_base_cc;
 120
 121/**
 122 * get_clock_monotonic - returns current time in clock rate units
 123 *
 124 * The caller must ensure that preemption is disabled.
 125 * The clock and sched_clock_base get changed via stop_machine.
 126 * Therefore preemption must be disabled when calling this
 127 * function, otherwise the returned value is not guaranteed to
 128 * be monotonic.
 129 */
 130static inline unsigned long long get_tod_clock_monotonic(void)
 131{
 132        return get_tod_clock() - sched_clock_base_cc;
 133}
 134
 135/**
 136 * tod_to_ns - convert a TOD format value to nanoseconds
 137 * @todval: to be converted TOD format value
 138 * Returns: number of nanoseconds that correspond to the TOD format value
 139 *
 140 * Converting a 64 Bit TOD format value to nanoseconds means that the value
 141 * must be divided by 4.096. In order to achieve that we multiply with 125
 142 * and divide by 512:
 143 *
 144 *    ns = (todval * 125) >> 9;
 145 *
 146 * In order to avoid an overflow with the multiplication we can rewrite this.
 147 * With a split todval == 2^32 * th + tl (th upper 32 bits, tl lower 32 bits)
 148 * we end up with
 149 *
 150 *    ns = ((2^32 * th + tl) * 125 ) >> 9;
 151 * -> ns = (2^23 * th * 125) + ((tl * 125) >> 9);
 152 *
 153 */
 154static inline unsigned long long tod_to_ns(unsigned long long todval)
 155{
 156        unsigned long long ns;
 157
 158        ns = ((todval >> 32) << 23) * 125;
 159        ns += ((todval & 0xffffffff) * 125) >> 9;
 160        return ns;
 161}
 162
 163#endif
 164