/* SPDX-License-Identifier: GPL-2.0-only */ /* * Clock utilities for s390 * * Authors: * Thomas Huth * * Copied from the s390/intercept test by: * Pierre Morel */ #ifndef _ASMS390X_TIME_H_ #define _ASMS390X_TIME_H_ #define S390_CLOCK_SHIFT_US (63 - 51) #define STCK_SHIFT_US S390_CLOCK_SHIFT_US #define STCK_MAX ((1UL << 52) - 1) #define CPU_TIMER_SHIFT_US S390_CLOCK_SHIFT_US static inline int sck(uint64_t *time) { int cc; asm volatile( " sck %[time]\n" " ipm %[cc]\n" " srl %[cc],28\n" : [cc] "=d"(cc) : [time] "Q"(*time) : "cc" ); return cc; } static inline int stck(uint64_t *time) { int cc; asm volatile( " stck %[time]\n" " ipm %[cc]\n" " srl %[cc],28\n" : [cc] "=d" (cc), [time] "=Q" (*time) : : "cc" ); return cc; } static inline int stckf(uint64_t *time) { int cc; asm volatile( " stckf %[time]\n" " ipm %[cc]\n" " srl %[cc],28\n" : [cc] "=d" (cc), [time] "=Q" (*time) : : "cc" ); return cc; } static inline uint64_t get_clock_us(void) { uint64_t clk; stck(&clk); return clk >> STCK_SHIFT_US; } static inline uint64_t get_clock_ms(void) { return get_clock_us() / 1000; } static inline void udelay(unsigned long us) { unsigned long startclk = get_clock_us(); unsigned long c; do { c = get_clock_us(); if (c < startclk) c += STCK_MAX; } while (c < startclk + us); } static inline void mdelay(unsigned long ms) { udelay(ms * 1000); } static inline void cpu_timer_set_ms(int64_t timeout_ms) { int64_t timer_value = (timeout_ms * 1000) << CPU_TIMER_SHIFT_US; asm volatile ( "spt %[timer_value]\n" : : [timer_value] "Q" (timer_value) ); } #endif