1 /* SPDX-License-Identifier: GPL-2.0-only */ 2 /* 3 * Clock utilities for s390 4 * 5 * Authors: 6 * Thomas Huth <thuth@redhat.com> 7 * 8 * Copied from the s390/intercept test by: 9 * Pierre Morel <pmorel@linux.ibm.com> 10 */ 11 #ifndef _ASMS390X_TIME_H_ 12 #define _ASMS390X_TIME_H_ 13 14 #define S390_CLOCK_SHIFT_US (63 - 51) 15 16 #define STCK_SHIFT_US S390_CLOCK_SHIFT_US 17 #define STCK_MAX ((1UL << 52) - 1) 18 19 #define CPU_TIMER_SHIFT_US S390_CLOCK_SHIFT_US 20 sck(uint64_t * time)21static inline int sck(uint64_t *time) 22 { 23 int cc; 24 25 asm volatile( 26 " sck %[time]\n" 27 " ipm %[cc]\n" 28 " srl %[cc],28\n" 29 : [cc] "=d"(cc) 30 : [time] "Q"(*time) 31 : "cc" 32 ); 33 34 return cc; 35 } 36 stck(uint64_t * time)37static inline int stck(uint64_t *time) 38 { 39 int cc; 40 41 asm volatile( 42 " stck %[time]\n" 43 " ipm %[cc]\n" 44 " srl %[cc],28\n" 45 : [cc] "=d" (cc), [time] "=Q" (*time) 46 : 47 : "cc" 48 ); 49 50 return cc; 51 } 52 stckf(uint64_t * time)53static inline int stckf(uint64_t *time) 54 { 55 int cc; 56 57 asm volatile( 58 " stckf %[time]\n" 59 " ipm %[cc]\n" 60 " srl %[cc],28\n" 61 : [cc] "=d" (cc), [time] "=Q" (*time) 62 : 63 : "cc" 64 ); 65 66 return cc; 67 } 68 get_clock_us(void)69static inline uint64_t get_clock_us(void) 70 { 71 uint64_t clk; 72 73 stck(&clk); 74 75 return clk >> STCK_SHIFT_US; 76 } 77 get_clock_ms(void)78static inline uint64_t get_clock_ms(void) 79 { 80 return get_clock_us() / 1000; 81 } 82 udelay(unsigned long us)83static inline void udelay(unsigned long us) 84 { 85 unsigned long startclk = get_clock_us(); 86 unsigned long c; 87 88 do { 89 c = get_clock_us(); 90 if (c < startclk) 91 c += STCK_MAX; 92 } while (c < startclk + us); 93 } 94 mdelay(unsigned long ms)95static inline void mdelay(unsigned long ms) 96 { 97 udelay(ms * 1000); 98 } 99 cpu_timer_set_ms(int64_t timeout_ms)100static inline void cpu_timer_set_ms(int64_t timeout_ms) 101 { 102 int64_t timer_value = (timeout_ms * 1000) << CPU_TIMER_SHIFT_US; 103 104 asm volatile ( 105 "spt %[timer_value]\n" 106 : 107 : [timer_value] "Q" (timer_value) 108 ); 109 } 110 111 #endif 112