| /* SPDX-License-Identifier: GPL-2.0-only */ | |
| /* | |
| * Clock utilities for s390 | |
| * | |
| * Authors: | |
| * Thomas Huth <thuth@redhat.com> | |
| * | |
| * Copied from the s390/intercept test by: | |
| * Pierre Morel <pmorel@linux.ibm.com> | |
| */ | |
| #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 |