linux-mips
[Top] [All Lists]

[PATCH -v5 02/11] MIPS: add mips_timecounter_read() to get high precisio

To: linux-mips@linux-mips.org, linux-kernel@vger.kernel.org
Subject: [PATCH -v5 02/11] MIPS: add mips_timecounter_read() to get high precision timestamp
From: Wu Zhangjin <wuzhangjin@gmail.com>
Date: Sun, 25 Oct 2009 23:16:53 +0800
Cc: Wu Zhangjin <wuzhangjin@gmail.com>, rostedt@goodmis.org, Thomas Gleixner <tglx@linutronix.de>, Ralf Baechle <ralf@linux-mips.org>, Nicholas Mc Guire <der.herr@hofr.at>, Richard Sandiford <rdsandiford@googlemail.com>, David Daney <ddaney@caviumnetworks.com>, Adam Nemet <anemet@caviumnetworks.com>, Patrik Kluba <kpajko79@gmail.com>
Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=gamma; h=domainkey-signature:received:received:from:to:cc:subject:date :message-id:x-mailer:in-reply-to:references:in-reply-to:references; bh=xHNoUVL7jtuVw5VH1oK05eQwhoXWhhpyxOfnqPDCLL4=; b=wKe5MGjKCVbppTDYoH0VQ5e9oXU3WULsigeRwrKNEPQZkK/QOsFV9rzxBXIJ+vqDbs dPrYbWCTqrL0R13xlk9ilhRLXHP2OHrR/qhdgCbhORM/6b1XprCUp482+MzYk7yRTCJy ueUa4wfE7PZ3cYMTyJKy1tQIJsv9kNkCTfqbY=
Domainkey-signature: a=rsa-sha1; c=nofws; d=gmail.com; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=QQJBpkuFjJB3CYpSV0aFxXCmKB0Bsd+80B53g43Ik1w66ud8FFT7tV5ilFWOOIqEyt GjK05BDWUDo9f1jTk8MjQa9Vv6Jw4F/QkPNQVTY6n4aI5BoEfwsOcFomGtRbKMS7x4f8 0yJGJDoDneZg7fOTkqnFO8vQDnIK+6y2R3Cho=
In-reply-to: <028867b99ec532b84963a35e7d552becc783cafc.1256483735.git.wuzhangjin@gmail.com>
In-reply-to: <cover.1256483735.git.wuzhangjin@gmail.com>
Original-recipient: rfc822;linux-mips@linux-mips.org
References: <cover.1256482555.git.wuzhangjin@gmail.com> <028867b99ec532b84963a35e7d552becc783cafc.1256483735.git.wuzhangjin@gmail.com>
References: <cover.1256483735.git.wuzhangjin@gmail.com>
Sender: linux-mips-bounce@linux-mips.org
This patch implement a mips_timecounter_read(), which can be used to get
high precision timestamp without extra lock.

It is based on the clock counter register and the
timecounter/cyclecounter abstraction layer of kernel.

Signed-off-by: Wu Zhangjin <wuzhangjin@gmail.com>
---
 arch/mips/include/asm/time.h |   19 +++++++++++++++++++
 arch/mips/kernel/csrc-r4k.c  |   41 +++++++++++++++++++++++++++++++++++++++++
 arch/mips/kernel/time.c      |    2 ++
 3 files changed, 62 insertions(+), 0 deletions(-)

diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h
index df6a430..b8af7fa 100644
--- a/arch/mips/include/asm/time.h
+++ b/arch/mips/include/asm/time.h
@@ -73,8 +73,18 @@ static inline int mips_clockevent_init(void)
  */
 #ifdef CONFIG_CSRC_R4K_LIB
 extern int init_r4k_clocksource(void);
+extern int init_r4k_timecounter(void);
+extern u64 r4k_timecounter_read(void);
 #endif
 
+static inline u64 mips_timecounter_read(void)
+{
+#ifdef CONFIG_CSRC_R4K
+       return r4k_timecounter_read();
+#else
+       return sched_clock();
+#endif
+}
 static inline int init_mips_clocksource(void)
 {
 #ifdef CONFIG_CSRC_R4K
@@ -84,6 +94,15 @@ static inline int init_mips_clocksource(void)
 #endif
 }
 
+static inline int init_mips_timecounter(void)
+{
+#ifdef CONFIG_CSRC_R4K
+       return init_r4k_timecounter();
+#else
+       return 0;
+#endif
+}
+
 extern void clocksource_set_clock(struct clocksource *cs, unsigned int clock);
 extern void clockevent_set_clock(struct clock_event_device *cd,
                unsigned int clock);
diff --git a/arch/mips/kernel/csrc-r4k.c b/arch/mips/kernel/csrc-r4k.c
index e95a3cd..4e7705f 100644
--- a/arch/mips/kernel/csrc-r4k.c
+++ b/arch/mips/kernel/csrc-r4k.c
@@ -7,6 +7,7 @@
  */
 #include <linux/clocksource.h>
 #include <linux/init.h>
+#include <linux/sched.h>
 
 #include <asm/time.h>
 
@@ -36,3 +37,43 @@ int __init init_r4k_clocksource(void)
 
        return 0;
 }
+
+static struct timecounter r4k_tc = {
+       .cc = NULL,
+};
+
+static cycle_t r4k_cc_read(const struct cyclecounter *cc)
+{
+       return read_c0_count();
+}
+
+static struct cyclecounter r4k_cc = {
+       .read = r4k_cc_read,
+       .mask = CLOCKSOURCE_MASK(32),
+       .shift = 32,
+};
+
+int __init init_r4k_timecounter(void)
+{
+       if (!cpu_has_counter || !mips_hpt_frequency)
+               return -ENXIO;
+
+       r4k_cc.mult = div_sc((unsigned long)mips_hpt_frequency, NSEC_PER_SEC,
+                       32);
+
+       timecounter_init(&r4k_tc, &r4k_cc, sched_clock());
+
+       return 0;
+}
+
+u64 r4k_timecounter_read(void)
+{
+       u64 clock;
+
+       if (r4k_tc.cc != NULL)
+               clock = timecounter_read(&r4k_tc);
+       else
+               clock = sched_clock();
+
+       return clock;
+}
diff --git a/arch/mips/kernel/time.c b/arch/mips/kernel/time.c
index 1f467d5..e38cca1 100644
--- a/arch/mips/kernel/time.c
+++ b/arch/mips/kernel/time.c
@@ -156,4 +156,6 @@ void __init time_init(void)
 
        if (!mips_clockevent_init() || !cpu_has_mfc0_count_bug())
                init_mips_clocksource();
+       if (!cpu_has_mfc0_count_bug())
+               init_mips_timecounter();
 }
-- 
1.6.2.1


<Prev in Thread] Current Thread [Next in Thread>