linux-tegra.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
* [PATCH] timekeeping: Move persistent clock registration code from ARM to kernel
@ 2014-11-07 19:34 Anatol Pomozov
       [not found] ` <1415388855-35074-1-git-send-email-anatol.pomozov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
  0 siblings, 1 reply; 20+ messages in thread
From: Anatol Pomozov @ 2014-11-07 19:34 UTC (permalink / raw)
  To: swarren-3lzwWm7+Weoh9ZMKESR00Q,
	daniel.lezcano-QSEj5FYQhm4dnm+yROfE0A,
	linux-lFZ/pmaqli7XmaaqVzeoHQ, tglx-hfZtesqFncYOwBW4kG4KsQ
  Cc: linux-kernel-u79uwXL29TY76Z2rM5mHXA,
	linux-tegra-u79uwXL29TY76Z2rM5mHXA, tony-4v6yS6AI5VpBDgjK7y7TUQ,
	thierry.reding-Re5JQEeQqe8AvxtiuMwx3w, mark.rutland-5wv7dgnIgG8,
	Anatol Pomozov

ARM timekeeping functionality allows to register persistent/boot clock dynamically.
This code is arch-independent and can be useful on other plaforms as well.

As a byproduct of this change, tegra20_timer becomes ARM64 compatible.

Tested: backported the change to chromeos-3.14 kernel ran on tegra 64bit
board, made sure high-resolution clock works.

Signed-off-by: Anatol Pomozov <anatol.pomozov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
---
 arch/arm/include/asm/mach/time.h    |  5 -----
 arch/arm/kernel/time.c              | 36 -------------------------------
 arch/arm/plat-omap/counter_32k.c    |  9 +++++---
 drivers/clocksource/tegra20_timer.c | 10 +++++----
 include/linux/timekeeping.h         | 11 ++++++++++
 kernel/time/timekeeping.c           | 43 +++++++++++++++++++++++++++++++++----
 6 files changed, 62 insertions(+), 52 deletions(-)

diff --git a/arch/arm/include/asm/mach/time.h b/arch/arm/include/asm/mach/time.h
index 90c12e1..3cbcafc 100644
--- a/arch/arm/include/asm/mach/time.h
+++ b/arch/arm/include/asm/mach/time.h
@@ -12,9 +12,4 @@
 
 extern void timer_tick(void);
 
-struct timespec;
-typedef void (*clock_access_fn)(struct timespec *);
-extern int register_persistent_clock(clock_access_fn read_boot,
-				     clock_access_fn read_persistent);
-
 #endif
diff --git a/arch/arm/kernel/time.c b/arch/arm/kernel/time.c
index 0cc7e58..0aa1dcd 100644
--- a/arch/arm/kernel/time.c
+++ b/arch/arm/kernel/time.c
@@ -76,42 +76,6 @@ void timer_tick(void)
 }
 #endif
 
-static void dummy_clock_access(struct timespec *ts)
-{
-	ts->tv_sec = 0;
-	ts->tv_nsec = 0;
-}
-
-static clock_access_fn __read_persistent_clock = dummy_clock_access;
-static clock_access_fn __read_boot_clock = dummy_clock_access;;
-
-void read_persistent_clock(struct timespec *ts)
-{
-	__read_persistent_clock(ts);
-}
-
-void read_boot_clock(struct timespec *ts)
-{
-	__read_boot_clock(ts);
-}
-
-int __init register_persistent_clock(clock_access_fn read_boot,
-				     clock_access_fn read_persistent)
-{
-	/* Only allow the clockaccess functions to be registered once */
-	if (__read_persistent_clock == dummy_clock_access &&
-	    __read_boot_clock == dummy_clock_access) {
-		if (read_boot)
-			__read_boot_clock = read_boot;
-		if (read_persistent)
-			__read_persistent_clock = read_persistent;
-
-		return 0;
-	}
-
-	return -EINVAL;
-}
-
 void __init time_init(void)
 {
 	if (machine_desc->init_time) {
diff --git a/arch/arm/plat-omap/counter_32k.c b/arch/arm/plat-omap/counter_32k.c
index 61b4d70..0dbfffd 100644
--- a/arch/arm/plat-omap/counter_32k.c
+++ b/arch/arm/plat-omap/counter_32k.c
@@ -18,10 +18,9 @@
 #include <linux/err.h>
 #include <linux/io.h>
 #include <linux/clocksource.h>
+#include <linux/time.h>
 #include <linux/sched_clock.h>
 
-#include <asm/mach/time.h>
-
 #include <plat/counter-32k.h>
 
 /* OMAP2_32KSYNCNT_CR_OFF: offset of 32ksync counter register */
@@ -76,6 +75,10 @@ static void omap_read_persistent_clock(struct timespec *ts)
 	spin_unlock_irqrestore(&read_persistent_clock_lock, flags);
 }
 
+static const struct persistent_clock_ops omap_persistent_clock = {
+	.read = omap_read_persistent_clock
+};
+
 /**
  * omap_init_clocksource_32k - setup and register counter 32k as a
  * kernel clocksource
@@ -116,7 +119,7 @@ int __init omap_init_clocksource_32k(void __iomem *vbase)
 	}
 
 	sched_clock_register(omap_32k_read_sched_clock, 32, 32768);
-	register_persistent_clock(NULL, omap_read_persistent_clock);
+	register_persistent_clock(&omap_persistent_clock);
 	pr_info("OMAP clocksource: 32k_counter at 32768 Hz\n");
 
 	return 0;
diff --git a/drivers/clocksource/tegra20_timer.c b/drivers/clocksource/tegra20_timer.c
index d2616ef..210130e 100644
--- a/drivers/clocksource/tegra20_timer.c
+++ b/drivers/clocksource/tegra20_timer.c
@@ -28,9 +28,7 @@
 #include <linux/of_irq.h>
 #include <linux/sched_clock.h>
 #include <linux/delay.h>
-
-#include <asm/mach/time.h>
-#include <asm/smp_twd.h>
+#include <linux/timekeeping.h>
 
 #define RTC_SECONDS            0x08
 #define RTC_SHADOW_SECONDS     0x0c
@@ -142,6 +140,10 @@ static void tegra_read_persistent_clock(struct timespec *ts)
 	*ts = *tsp;
 }
 
+static const struct persistent_clock_ops tegra_persistent_clock = {
+	.read = tegra_read_persistent_clock
+};
+
 static unsigned long tegra_delay_timer_read_counter_long(void)
 {
 	return readl(timer_reg_base + TIMERUS_CNTR_1US);
@@ -252,7 +254,7 @@ static void __init tegra20_init_rtc(struct device_node *np)
 	else
 		clk_prepare_enable(clk);
 
-	register_persistent_clock(NULL, tegra_read_persistent_clock);
+	register_persistent_clock(&tegra_persistent_clock);
 }
 CLOCKSOURCE_OF_DECLARE(tegra20_rtc, "nvidia,tegra20-rtc", tegra20_init_rtc);
 
diff --git a/include/linux/timekeeping.h b/include/linux/timekeeping.h
index 1caa6b0..02023f7 100644
--- a/include/linux/timekeeping.h
+++ b/include/linux/timekeeping.h
@@ -201,6 +201,17 @@ static inline bool has_persistent_clock(void)
 	return persistent_clock_exist;
 }
 
+struct persistent_clock_ops {
+	void (*read)(struct timespec *ts);
+	int (*update)(const struct timespec ts);
+};
+
+struct boot_clock_ops {
+	void (*read)(struct timespec *ts);
+};
+
+extern void register_persistent_clock(const struct persistent_clock_ops *clock);
+extern void register_boot_clock(const struct boot_clock_ops *clock);
 extern void read_persistent_clock(struct timespec *ts);
 extern void read_boot_clock(struct timespec *ts);
 extern int update_persistent_clock(struct timespec now);
diff --git a/kernel/time/timekeeping.c b/kernel/time/timekeeping.c
index fb4a9c2..414c172 100644
--- a/kernel/time/timekeeping.c
+++ b/kernel/time/timekeeping.c
@@ -66,6 +66,9 @@ int __read_mostly timekeeping_suspended;
 /* Flag for if there is a persistent clock on this platform */
 bool __read_mostly persistent_clock_exist = false;
 
+const struct persistent_clock_ops __read_mostly *persistent_clock = NULL;
+const struct boot_clock_ops __read_mostly *boot_clock = NULL;
+
 static inline void tk_normalize_xtime(struct timekeeper *tk)
 {
 	while (tk->tkr.xtime_nsec >= ((u64)NSEC_PER_SEC << tk->tkr.shift)) {
@@ -956,6 +959,30 @@ u64 timekeeping_max_deferment(void)
 	return ret;
 }
 
+extern void register_persistent_clock(const struct persistent_clock_ops *clock)
+{
+	BUG_ON(!clock);
+	BUG_ON(!clock->read);
+
+	if (persistent_clock) {
+		pr_warn("Ignore extra persistent clock registration");
+		return;
+	}
+	persistent_clock = clock;
+}
+
+extern void register_boot_clock(const struct boot_clock_ops *clock)
+{
+	BUG_ON(!clock);
+	BUG_ON(!clock->read);
+
+	if (boot_clock) {
+		pr_warn("Ignore extra boot clock registration");
+		return;
+	}
+	boot_clock = clock;
+}
+
 /**
  * read_persistent_clock -  Return time from the persistent clock.
  *
@@ -967,8 +994,12 @@ u64 timekeeping_max_deferment(void)
  */
 void __weak read_persistent_clock(struct timespec *ts)
 {
-	ts->tv_sec = 0;
-	ts->tv_nsec = 0;
+	if (persistent_clock) {
+		persistent_clock->read(ts);
+	} else {
+		ts->tv_sec = 0;
+		ts->tv_nsec = 0;
+	}
 }
 
 /**
@@ -982,8 +1013,12 @@ void __weak read_persistent_clock(struct timespec *ts)
  */
 void __weak read_boot_clock(struct timespec *ts)
 {
-	ts->tv_sec = 0;
-	ts->tv_nsec = 0;
+	if (boot_clock) {
+		boot_clock->read(ts);
+	} else {
+		ts->tv_sec = 0;
+		ts->tv_nsec = 0;
+	}
 }
 
 /*
-- 
2.1.0.rc2.206.gedb03e5

^ permalink raw reply related	[flat|nested] 20+ messages in thread

end of thread, other threads:[~2015-01-09 19:48 UTC | newest]

Thread overview: 20+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-07 19:34 [PATCH] timekeeping: Move persistent clock registration code from ARM to kernel Anatol Pomozov
     [not found] ` <1415388855-35074-1-git-send-email-anatol.pomozov-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org>
2014-11-07 19:42   ` Anatol Pomozov
2014-11-10  9:53   ` Thierry Reding
2014-11-10 19:26     ` Anatol Pomozov
     [not found]       ` <CAOMFOmXpAm5iKCLFyorTW+n9YmgZMmrDGGe736tJX8C6BYQv-A-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-13 22:46         ` Thomas Gleixner
2014-11-13 23:21           ` John Stultz
     [not found]             ` <CALAqxLXYVLXZafNH_ag3WDFHkhMe5t23zLbvg7Sq+4_rTfy+Kw-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-14  0:26               ` Thomas Gleixner
2015-01-09  9:43             ` Thierry Reding
2015-01-09 19:18               ` John Stultz
2014-11-14 22:03           ` Anatol Pomozov
     [not found]             ` <CAOMFOmVziftM=pWGG-L9J-E6AHYAK7k9bmBcpS1adPboLciX9g-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-15  0:18               ` Thomas Gleixner
2014-11-15  0:51                 ` Anatol Pomozov
     [not found]                   ` <CAOMFOmV5=tes6Ak1eUKb2qircp8ba6jt6v-bg66Kp_-jYk9m2w-JsoAwUIsXosN+BqQ9rBEUg@public.gmane.org>
2014-11-15  1:09                     ` Thomas Gleixner
2014-11-15  1:38                       ` Thomas Gleixner
2015-01-09  9:49                         ` Thierry Reding
2015-01-09 13:59                           ` Mark Rutland
2015-01-09 14:09                             ` Thierry Reding
     [not found]                               ` <20150109140902.GA7526-AwZRO8vwLAwmlAP/+Wk3EA@public.gmane.org>
2015-01-09 19:48                                 ` Paul Walmsley
2015-01-09 13:30                   ` Daniel Lezcano
2014-11-15  1:07               ` Stephen Warren

This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).