2005-04-16 15:20:36 -07:00
/*
* S390 version
2012-07-20 11:15:04 +02:00
* Copyright IBM Corp . 1999
2005-04-16 15:20:36 -07:00
*
* Derived from " include/asm-i386/timex.h "
* Copyright ( C ) 1992 , Linus Torvalds
*/
# ifndef _ASM_S390_TIMEX_H
# define _ASM_S390_TIMEX_H
2011-01-05 12:47:26 +01:00
# include <asm/lowcore.h>
2009-04-14 15:36:28 +02:00
/* The value of the TOD clock for 1.1.1970. */
# define TOD_UNIX_EPOCH 0x7d91048bca000000ULL
2007-02-05 21:18:19 +01:00
/* Inline functions for clock register access. */
2013-01-30 09:49:40 +01:00
static inline int set_tod_clock ( __u64 time )
2007-02-05 21:18:19 +01:00
{
int cc ;
asm volatile (
2010-02-26 22:37:31 +01:00
" sck %1 \n "
2007-02-05 21:18:19 +01:00
" ipm %0 \n "
" srl %0,28 \n "
2010-02-26 22:37:31 +01:00
: " =d " ( cc ) : " Q " ( time ) : " cc " ) ;
2007-02-05 21:18:19 +01:00
return cc ;
}
2013-01-30 09:49:40 +01:00
static inline int store_tod_clock ( __u64 * time )
2007-02-05 21:18:19 +01:00
{
int cc ;
asm volatile (
2010-02-26 22:37:31 +01:00
" stck %1 \n "
2007-02-05 21:18:19 +01:00
" ipm %0 \n "
" srl %0,28 \n "
2010-02-26 22:37:31 +01:00
: " =d " ( cc ) , " =Q " ( * time ) : : " cc " ) ;
2007-02-05 21:18:19 +01:00
return cc ;
}
static inline void set_clock_comparator ( __u64 time )
{
2010-02-26 22:37:31 +01:00
asm volatile ( " sckc %0 " : : " Q " ( time ) ) ;
2007-02-05 21:18:19 +01:00
}
static inline void store_clock_comparator ( __u64 * time )
{
2010-02-26 22:37:31 +01:00
asm volatile ( " stckc %0 " : " =Q " ( * time ) ) ;
2007-02-05 21:18:19 +01:00
}
2011-01-05 12:47:26 +01:00
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 ;
2011-01-05 12:47:27 +01:00
set_clock_comparator ( S390_lowcore . clock_comparator ) ;
2011-01-05 12:47:26 +01:00
return old ;
}
static inline void local_tick_enable ( unsigned long long comp )
{
S390_lowcore . clock_comparator = comp ;
2011-01-05 12:47:27 +01:00
set_clock_comparator ( S390_lowcore . clock_comparator ) ;
2011-01-05 12:47:26 +01:00
}
2015-01-01 22:27:32 +08:00
# define CLOCK_TICK_RATE 1193180 /* Underlying HZ */
# define STORE_CLOCK_EXT_SIZE 16 /* stcke writes 16 bytes */
2005-04-16 15:20:36 -07:00
typedef unsigned long long cycles_t ;
2015-01-01 22:27:32 +08:00
static inline void get_tod_clock_ext ( char * clk )
2010-05-17 10:00:20 +02:00
{
2015-01-01 22:27:32 +08:00
typedef struct { char _ [ STORE_CLOCK_EXT_SIZE ] ; } addrtype ;
2013-10-28 11:17:10 +01:00
asm volatile ( " stcke %0 " : " =Q " ( * ( addrtype * ) clk ) : : " cc " ) ;
2010-05-17 10:00:20 +02:00
}
2013-10-17 12:38:17 +02:00
static inline unsigned long long get_tod_clock ( void )
2007-02-05 21:18:22 +01:00
{
2015-01-01 22:27:32 +08:00
unsigned char clk [ STORE_CLOCK_EXT_SIZE ] ;
2013-01-30 09:49:40 +01:00
get_tod_clock_ext ( clk ) ;
2008-04-17 07:46:16 +02:00
return * ( ( unsigned long long * ) & clk [ 1 ] ) ;
2007-02-05 21:18:22 +01:00
}
2013-10-17 12:38:17 +02:00
static inline unsigned long long get_tod_clock_fast ( void )
{
# ifdef CONFIG_HAVE_MARCH_Z9_109_FEATURES
unsigned long long clk ;
asm volatile ( " stckf %0 " : " =Q " ( clk ) : : " cc " ) ;
return clk ;
# else
return get_tod_clock ( ) ;
# endif
}
2006-09-28 16:56:43 +02:00
static inline cycles_t get_cycles ( void )
{
2013-01-30 09:49:40 +01:00
return ( cycles_t ) get_tod_clock ( ) > > 2 ;
2006-09-28 16:56:43 +02:00
}
2007-02-05 21:18:19 +01:00
int get_sync_clock ( unsigned long long * clock ) ;
2007-02-05 21:16:47 +01:00
void init_cpu_timer ( void ) ;
2008-04-17 07:46:26 +02:00
unsigned long long monotonic_clock ( void ) ;
2007-02-05 21:16:47 +01:00
2009-08-18 15:43:31 +02:00
void tod_to_timeval ( __u64 , struct timespec * ) ;
static inline
void stck_to_timespec ( unsigned long long stck , struct timespec * ts )
{
tod_to_timeval ( stck - TOD_UNIX_EPOCH , ts ) ;
}
2009-04-14 15:36:28 +02:00
extern u64 sched_clock_base_cc ;
2009-09-11 10:28:31 +02:00
/**
* get_clock_monotonic - returns current time in clock rate units
*
* The caller must ensure that preemption is disabled .
* The clock and sched_clock_base get changed via stop_machine .
* Therefore preemption must be disabled when calling this
* function , otherwise the returned value is not guaranteed to
* be monotonic .
*/
2013-01-30 09:49:40 +01:00
static inline unsigned long long get_tod_clock_monotonic ( void )
2009-09-11 10:28:31 +02:00
{
2013-10-17 12:38:17 +02:00
return get_tod_clock ( ) - sched_clock_base_cc ;
2009-09-11 10:28:31 +02:00
}
2013-01-14 16:55:55 +01:00
/**
* 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 ;
}
2005-04-16 15:20:36 -07:00
# endif