blob: ad689b098eaba97ea90fa0f6d3772f372fde047f [file] [log] [blame]
/* 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