[Top] [All Lists]

[PATCH v3 1/3] MIPS: add a common mips_cyc2ns()

To: Ralf Baechle <>
Subject: [PATCH v3 1/3] MIPS: add a common mips_cyc2ns()
From: Wu Zhangjin <>
Date: Sat, 10 Apr 2010 14:49:57 +0800
Cc: Wu Zhangjin <>, David Daney <>, Ralf Rösch <>,
Dkim-signature: v=1; a=rsa-sha256; c=relaxed/relaxed;; 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=sUGNdKEpG7sGQVVJ3fXkT300NAgm2L1rK7C72sHBRXk=; b=Zs9hRiRuTAVOVfhpEu9bA4RuGQu39n62xoQj4VovOmPNrgeLNQNz8H9/zc4QRVQpKX fDq4nk9NgniPGhFJd1m/apMKMz/a1676WVuVOY2tRjOa9flk/fB6CccPOezHqwPO2ilo dv5MS8dV19PXs3SYIMXZ+3PI3DN74Iy8Z+LJw=
Domainkey-signature: a=rsa-sha1; c=nofws;; s=gamma; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; b=tGm6XNJ887GQFjxpdbXxet78vNjQcdio1EpW7VNYwt7whPDnD/mG/TOyjXxme0fBTX c29ZQNbu2llR435x2TuVUb5mUDJ+qYT2J2QCgoPlfVJrBycrVLaC9sq/hy+LeArpwbAn ybgANJnc22kJEa10eE//ARWbaCwaADWq+UkCI=
In-reply-to: <>
In-reply-to: <>
Original-recipient: rfc822;
References: <>
References: <>
From: Wu Zhangjin <>


v2 -> v3:

  o use 32bit instead of 64bit for mult and shift as the 'struct
  clocksource' does, which saves several instructions for the 32bit
  version of mips_cyc2ns().
  o removes the 'easy way' of 128bit arithmatic for it not work with
  some compilers. (feedback from David)

v1 -> v2:

  o change the old mips_sched_clock() to mips_cyc2ns() and modify the
  arguments to support 32bit.
  o add 32bit support: use a smaller shift to avoid the quick overflow
  of 64bit arithmatic and balance the overhead of the 128bit arithmatic
  and the precision lost with the smaller shift.


Because the high resolution sched_clock() for r4k has the same overflow
problem and solution mentioned in "MIPS: Octeon: Use non-overflowing
arithmetic in sched_clock".

    "With typical mult and shift values, the calculation for Octeon's
    sched_clock overflows when using 64-bit arithmetic.  Use 128-bit
    calculations instead."

To reduce the duplication, This patch abstracts the solution into an
inline funciton mips_cyc2ns() into arch/mips/include/asm/time.h from

Two patches for Cavium and R4K will be sent out respectively to use this
common function.

Signed-off-by: Wu Zhangjin <>
 arch/mips/include/asm/time.h |   34 ++++++++++++++++++++++++++++++++++
 1 files changed, 34 insertions(+), 0 deletions(-)

diff --git a/arch/mips/include/asm/time.h b/arch/mips/include/asm/time.h
index c7f1bfe..f0ee643 100644
--- a/arch/mips/include/asm/time.h
+++ b/arch/mips/include/asm/time.h
@@ -96,4 +96,38 @@ static inline void clockevent_set_clock(struct 
clock_event_device *cd,
        clockevents_calc_mult_shift(cd, clock, 4);
+static inline unsigned long long mips_cyc2ns(u64 cyc, u32 __mult, u32 __shift)
+#ifdef CONFIG_32BIT
+       /*
+        * To balance the overhead of 128bit-arithematic and the precision
+        * lost, we choose a smaller shift to avoid the quick overflow as the
+        * X86 & ARM does. please refer to arch/x86/kernel/tsc.c and
+        * arch/arm/plat-orion/time.c
+        */
+       return (cyc * __mult) >> __shift;
+#else /* CONFIG_64BIT */
+       /* 64-bit arithmatic can overflow, so use 128-bit */
+       u64 t1, t2, t3;
+       unsigned long long rv;
+       u64 mult, shift;
+       mult = __mult;
+       shift = __shift;
+       asm (
+               "dmultu\t%[cyc],%[mult]\n\t"
+               "nor\t%[t1],$0,%[shift]\n\t"
+               "mfhi\t%[t2]\n\t"
+               "mflo\t%[t3]\n\t"
+               "dsll\t%[t2],%[t2],1\n\t"
+               "dsrlv\t%[rv],%[t3],%[shift]\n\t"
+               "dsllv\t%[t1],%[t2],%[t1]\n\t"
+               "or\t%[rv],%[t1],%[rv]\n\t"
+               : [rv] "=&r" (rv), [t1] "=&r" (t1), [t2] "=&r" (t2), [t3] "=&r" 
+               : [cyc] "r" (cyc), [mult] "r" (mult), [shift] "r" (shift)
+               : "hi", "lo");
+       return rv;
 #endif /* _ASM_TIME_H */

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