Commit 90adda98 authored by John Stultz's avatar John Stultz

hrtimer: Add hrtimer support for CLOCK_TAI

Add hrtimer support for CLOCK_TAI, as well as posix timer interfaces.
Signed-off-by: default avatarJohn Stultz <john.stultz@linaro.org>
parent 1ff3c967
...@@ -157,6 +157,7 @@ enum hrtimer_base_type { ...@@ -157,6 +157,7 @@ enum hrtimer_base_type {
HRTIMER_BASE_MONOTONIC, HRTIMER_BASE_MONOTONIC,
HRTIMER_BASE_REALTIME, HRTIMER_BASE_REALTIME,
HRTIMER_BASE_BOOTTIME, HRTIMER_BASE_BOOTTIME,
HRTIMER_BASE_TAI,
HRTIMER_MAX_CLOCK_BASES, HRTIMER_MAX_CLOCK_BASES,
}; };
...@@ -327,7 +328,9 @@ extern ktime_t ktime_get(void); ...@@ -327,7 +328,9 @@ extern ktime_t ktime_get(void);
extern ktime_t ktime_get_real(void); extern ktime_t ktime_get_real(void);
extern ktime_t ktime_get_boottime(void); extern ktime_t ktime_get_boottime(void);
extern ktime_t ktime_get_monotonic_offset(void); extern ktime_t ktime_get_monotonic_offset(void);
extern ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot); extern ktime_t ktime_get_clocktai(void);
extern ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot,
ktime_t *offs_tai);
DECLARE_PER_CPU(struct tick_device, tick_cpu_device); DECLARE_PER_CPU(struct tick_device, tick_cpu_device);
......
...@@ -64,6 +64,8 @@ struct timekeeper { ...@@ -64,6 +64,8 @@ struct timekeeper {
struct timespec raw_time; struct timespec raw_time;
/* The current UTC to TAI offset in seconds */ /* The current UTC to TAI offset in seconds */
s32 tai_offset; s32 tai_offset;
/* Offset clock monotonic -> clock tai */
ktime_t offs_tai;
/* Seqlock for all timekeeper values */ /* Seqlock for all timekeeper values */
seqlock_t lock; seqlock_t lock;
......
...@@ -83,6 +83,12 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) = ...@@ -83,6 +83,12 @@ DEFINE_PER_CPU(struct hrtimer_cpu_base, hrtimer_bases) =
.get_time = &ktime_get_boottime, .get_time = &ktime_get_boottime,
.resolution = KTIME_LOW_RES, .resolution = KTIME_LOW_RES,
}, },
{
.index = HRTIMER_BASE_TAI,
.clockid = CLOCK_TAI,
.get_time = &ktime_get_clocktai,
.resolution = KTIME_LOW_RES,
},
} }
}; };
...@@ -90,6 +96,7 @@ static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = { ...@@ -90,6 +96,7 @@ static const int hrtimer_clock_to_base_table[MAX_CLOCKS] = {
[CLOCK_REALTIME] = HRTIMER_BASE_REALTIME, [CLOCK_REALTIME] = HRTIMER_BASE_REALTIME,
[CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC, [CLOCK_MONOTONIC] = HRTIMER_BASE_MONOTONIC,
[CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME, [CLOCK_BOOTTIME] = HRTIMER_BASE_BOOTTIME,
[CLOCK_TAI] = HRTIMER_BASE_TAI,
}; };
static inline int hrtimer_clockid_to_base(clockid_t clock_id) static inline int hrtimer_clockid_to_base(clockid_t clock_id)
...@@ -106,8 +113,10 @@ static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base) ...@@ -106,8 +113,10 @@ static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base)
{ {
ktime_t xtim, mono, boot; ktime_t xtim, mono, boot;
struct timespec xts, tom, slp; struct timespec xts, tom, slp;
s32 tai_offset;
get_xtime_and_monotonic_and_sleep_offset(&xts, &tom, &slp); get_xtime_and_monotonic_and_sleep_offset(&xts, &tom, &slp);
tai_offset = timekeeping_get_tai_offset();
xtim = timespec_to_ktime(xts); xtim = timespec_to_ktime(xts);
mono = ktime_add(xtim, timespec_to_ktime(tom)); mono = ktime_add(xtim, timespec_to_ktime(tom));
...@@ -115,6 +124,8 @@ static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base) ...@@ -115,6 +124,8 @@ static void hrtimer_get_softirq_time(struct hrtimer_cpu_base *base)
base->clock_base[HRTIMER_BASE_REALTIME].softirq_time = xtim; base->clock_base[HRTIMER_BASE_REALTIME].softirq_time = xtim;
base->clock_base[HRTIMER_BASE_MONOTONIC].softirq_time = mono; base->clock_base[HRTIMER_BASE_MONOTONIC].softirq_time = mono;
base->clock_base[HRTIMER_BASE_BOOTTIME].softirq_time = boot; base->clock_base[HRTIMER_BASE_BOOTTIME].softirq_time = boot;
base->clock_base[HRTIMER_BASE_TAI].softirq_time =
ktime_add(xtim, ktime_set(tai_offset, 0));
} }
/* /*
...@@ -651,8 +662,9 @@ static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base) ...@@ -651,8 +662,9 @@ static inline ktime_t hrtimer_update_base(struct hrtimer_cpu_base *base)
{ {
ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset; ktime_t *offs_real = &base->clock_base[HRTIMER_BASE_REALTIME].offset;
ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset; ktime_t *offs_boot = &base->clock_base[HRTIMER_BASE_BOOTTIME].offset;
ktime_t *offs_tai = &base->clock_base[HRTIMER_BASE_TAI].offset;
return ktime_get_update_offsets(offs_real, offs_boot); return ktime_get_update_offsets(offs_real, offs_boot, offs_tai);
} }
/* /*
......
...@@ -269,6 +269,12 @@ static __init int init_posix_timers(void) ...@@ -269,6 +269,12 @@ static __init int init_posix_timers(void)
struct k_clock clock_tai = { struct k_clock clock_tai = {
.clock_getres = hrtimer_get_res, .clock_getres = hrtimer_get_res,
.clock_get = posix_get_tai, .clock_get = posix_get_tai,
.nsleep = common_nsleep,
.nsleep_restart = hrtimer_nanosleep_restart,
.timer_create = common_timer_create,
.timer_set = common_timer_set,
.timer_get = common_timer_get,
.timer_del = common_timer_del,
}; };
struct k_clock clock_boottime = { struct k_clock clock_boottime = {
.clock_getres = hrtimer_get_res, .clock_getres = hrtimer_get_res,
......
...@@ -67,6 +67,7 @@ static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm) ...@@ -67,6 +67,7 @@ static void tk_set_wall_to_mono(struct timekeeper *tk, struct timespec wtm)
tk->wall_to_monotonic = wtm; tk->wall_to_monotonic = wtm;
set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec); set_normalized_timespec(&tmp, -wtm.tv_sec, -wtm.tv_nsec);
tk->offs_real = timespec_to_ktime(tmp); tk->offs_real = timespec_to_ktime(tmp);
tk->offs_tai = ktime_sub(tk->offs_real, ktime_set(tk->tai_offset, 0));
} }
static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t) static void tk_set_sleep_time(struct timekeeper *tk, struct timespec t)
...@@ -409,6 +410,20 @@ void timekeeping_clocktai(struct timespec *ts) ...@@ -409,6 +410,20 @@ void timekeeping_clocktai(struct timespec *ts)
EXPORT_SYMBOL(timekeeping_clocktai); EXPORT_SYMBOL(timekeeping_clocktai);
/**
* ktime_get_clocktai - Returns the TAI time of day in a ktime
*
* Returns the time of day in a ktime.
*/
ktime_t ktime_get_clocktai(void)
{
struct timespec ts;
timekeeping_clocktai(&ts);
return timespec_to_ktime(ts);
}
EXPORT_SYMBOL(ktime_get_clocktai);
#ifdef CONFIG_NTP_PPS #ifdef CONFIG_NTP_PPS
/** /**
...@@ -569,6 +584,7 @@ s32 timekeeping_get_tai_offset(void) ...@@ -569,6 +584,7 @@ s32 timekeeping_get_tai_offset(void)
void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset) void __timekeeping_set_tai_offset(struct timekeeper *tk, s32 tai_offset)
{ {
tk->tai_offset = tai_offset; tk->tai_offset = tai_offset;
tk->offs_tai = ktime_sub(tk->offs_real, ktime_set(tai_offset, 0));
} }
/** /**
...@@ -1539,7 +1555,8 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim, ...@@ -1539,7 +1555,8 @@ void get_xtime_and_monotonic_and_sleep_offset(struct timespec *xtim,
* Returns current monotonic time and updates the offsets * Returns current monotonic time and updates the offsets
* Called from hrtimer_interupt() or retrigger_next_event() * Called from hrtimer_interupt() or retrigger_next_event()
*/ */
ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot,
ktime_t *offs_tai)
{ {
struct timekeeper *tk = &timekeeper; struct timekeeper *tk = &timekeeper;
ktime_t now; ktime_t now;
...@@ -1554,6 +1571,7 @@ ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot) ...@@ -1554,6 +1571,7 @@ ktime_t ktime_get_update_offsets(ktime_t *offs_real, ktime_t *offs_boot)
*offs_real = tk->offs_real; *offs_real = tk->offs_real;
*offs_boot = tk->offs_boot; *offs_boot = tk->offs_boot;
*offs_tai = tk->offs_tai;
} while (read_seqretry(&tk->lock, seq)); } while (read_seqretry(&tk->lock, seq));
now = ktime_add_ns(ktime_set(secs, 0), nsecs); now = ktime_add_ns(ktime_set(secs, 0), nsecs);
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment