18c2ecf20Sopenharmony_ci/*
28c2ecf20Sopenharmony_ci * Copyright (c) 2017 Oracle and/or its affiliates. All rights reserved.
38c2ecf20Sopenharmony_ci */
48c2ecf20Sopenharmony_ci
58c2ecf20Sopenharmony_ci#ifndef _ASM_SPARC_VVAR_DATA_H
68c2ecf20Sopenharmony_ci#define _ASM_SPARC_VVAR_DATA_H
78c2ecf20Sopenharmony_ci
88c2ecf20Sopenharmony_ci#include <asm/clocksource.h>
98c2ecf20Sopenharmony_ci#include <asm/processor.h>
108c2ecf20Sopenharmony_ci#include <asm/barrier.h>
118c2ecf20Sopenharmony_ci#include <linux/time.h>
128c2ecf20Sopenharmony_ci#include <linux/types.h>
138c2ecf20Sopenharmony_ci
148c2ecf20Sopenharmony_cistruct vvar_data {
158c2ecf20Sopenharmony_ci	unsigned int seq;
168c2ecf20Sopenharmony_ci
178c2ecf20Sopenharmony_ci	int vclock_mode;
188c2ecf20Sopenharmony_ci	struct { /* extract of a clocksource struct */
198c2ecf20Sopenharmony_ci		u64	cycle_last;
208c2ecf20Sopenharmony_ci		u64	mask;
218c2ecf20Sopenharmony_ci		int	mult;
228c2ecf20Sopenharmony_ci		int	shift;
238c2ecf20Sopenharmony_ci	} clock;
248c2ecf20Sopenharmony_ci	/* open coded 'struct timespec' */
258c2ecf20Sopenharmony_ci	u64		wall_time_sec;
268c2ecf20Sopenharmony_ci	u64		wall_time_snsec;
278c2ecf20Sopenharmony_ci	u64		monotonic_time_snsec;
288c2ecf20Sopenharmony_ci	u64		monotonic_time_sec;
298c2ecf20Sopenharmony_ci	u64		monotonic_time_coarse_sec;
308c2ecf20Sopenharmony_ci	u64		monotonic_time_coarse_nsec;
318c2ecf20Sopenharmony_ci	u64		wall_time_coarse_sec;
328c2ecf20Sopenharmony_ci	u64		wall_time_coarse_nsec;
338c2ecf20Sopenharmony_ci
348c2ecf20Sopenharmony_ci	int		tz_minuteswest;
358c2ecf20Sopenharmony_ci	int		tz_dsttime;
368c2ecf20Sopenharmony_ci};
378c2ecf20Sopenharmony_ci
388c2ecf20Sopenharmony_ciextern struct vvar_data *vvar_data;
398c2ecf20Sopenharmony_ciextern int vdso_fix_stick;
408c2ecf20Sopenharmony_ci
418c2ecf20Sopenharmony_cistatic inline unsigned int vvar_read_begin(const struct vvar_data *s)
428c2ecf20Sopenharmony_ci{
438c2ecf20Sopenharmony_ci	unsigned int ret;
448c2ecf20Sopenharmony_ci
458c2ecf20Sopenharmony_cirepeat:
468c2ecf20Sopenharmony_ci	ret = READ_ONCE(s->seq);
478c2ecf20Sopenharmony_ci	if (unlikely(ret & 1)) {
488c2ecf20Sopenharmony_ci		cpu_relax();
498c2ecf20Sopenharmony_ci		goto repeat;
508c2ecf20Sopenharmony_ci	}
518c2ecf20Sopenharmony_ci	smp_rmb(); /* Finish all reads before we return seq */
528c2ecf20Sopenharmony_ci	return ret;
538c2ecf20Sopenharmony_ci}
548c2ecf20Sopenharmony_ci
558c2ecf20Sopenharmony_cistatic inline int vvar_read_retry(const struct vvar_data *s,
568c2ecf20Sopenharmony_ci					unsigned int start)
578c2ecf20Sopenharmony_ci{
588c2ecf20Sopenharmony_ci	smp_rmb(); /* Finish all reads before checking the value of seq */
598c2ecf20Sopenharmony_ci	return unlikely(s->seq != start);
608c2ecf20Sopenharmony_ci}
618c2ecf20Sopenharmony_ci
628c2ecf20Sopenharmony_cistatic inline void vvar_write_begin(struct vvar_data *s)
638c2ecf20Sopenharmony_ci{
648c2ecf20Sopenharmony_ci	++s->seq;
658c2ecf20Sopenharmony_ci	smp_wmb(); /* Makes sure that increment of seq is reflected */
668c2ecf20Sopenharmony_ci}
678c2ecf20Sopenharmony_ci
688c2ecf20Sopenharmony_cistatic inline void vvar_write_end(struct vvar_data *s)
698c2ecf20Sopenharmony_ci{
708c2ecf20Sopenharmony_ci	smp_wmb(); /* Makes the value of seq current before we increment */
718c2ecf20Sopenharmony_ci	++s->seq;
728c2ecf20Sopenharmony_ci}
738c2ecf20Sopenharmony_ci
748c2ecf20Sopenharmony_ci
758c2ecf20Sopenharmony_ci#endif /* _ASM_SPARC_VVAR_DATA_H */
76