[PATCH 08/14] MIPS: Octeon: Scale Octeon2 clocks in octeon_init_cvmcount()

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



The per-CPU clocks are synchronized from IPD_CLK_COUNT, on cn63XX it
must be scaled by the clock frequency ratio.

Signed-off-by: David Daney <ddaney@xxxxxxxxxxxxxxxxxx>
---
 arch/mips/cavium-octeon/csrc-octeon.c |   34 ++++++++++++++++++++++++++++++--
 1 files changed, 31 insertions(+), 3 deletions(-)

diff --git a/arch/mips/cavium-octeon/csrc-octeon.c b/arch/mips/cavium-octeon/csrc-octeon.c
index b6847c8..c85a681 100644
--- a/arch/mips/cavium-octeon/csrc-octeon.c
+++ b/arch/mips/cavium-octeon/csrc-octeon.c
@@ -4,14 +4,18 @@
  * for more details.
  *
  * Copyright (C) 2007 by Ralf Baechle
+ * Copyright (C) 2009, 2010 Cavium Networks, Inc.
  */
 #include <linux/clocksource.h>
 #include <linux/init.h>
+#include <linux/smp.h>
 
+#include <asm/cpu-info.h>
 #include <asm/time.h>
 
 #include <asm/octeon/octeon.h>
 #include <asm/octeon/cvmx-ipd-defs.h>
+#include <asm/octeon/cvmx-mio-defs.h>
 
 /*
  * Set the current core's cvmcount counter to the value of the
@@ -19,11 +23,23 @@
  * on-line.  This allows for a read from a local cpu register to
  * access a synchronized counter.
  *
+ * On CPU_CAVIUM_OCTEON2 the IPD_CLK_COUNT is scaled by rdiv/sdiv.
  */
 void octeon_init_cvmcount(void)
 {
 	unsigned long flags;
 	unsigned loops = 2;
+	u64 f = 0;
+	u64 rdiv = 0;
+	u64 sdiv = 0;
+	if (current_cpu_type() == CPU_CAVIUM_OCTEON2) {
+		union cvmx_mio_rst_boot rst_boot;
+		rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
+		rdiv = rst_boot.s.c_mul;	/* CPU clock */
+		sdiv = rst_boot.s.pnr_mul;	/* I/O clock */
+		f = (0x8000000000000000ull / sdiv) * 2;
+	}
+
 
 	/* Clobber loops so GCC will not unroll the following while loop. */
 	asm("" : "+r" (loops));
@@ -33,8 +49,20 @@ void octeon_init_cvmcount(void)
 	 * Loop several times so we are executing from the cache,
 	 * which should give more deterministic timing.
 	 */
-	while (loops--)
-		write_c0_cvmcount(cvmx_read_csr(CVMX_IPD_CLK_COUNT));
+	while (loops--) {
+		u64 ipd_clk_count = cvmx_read_csr(CVMX_IPD_CLK_COUNT);
+		if (rdiv != 0) {
+			ipd_clk_count = ipd_clk_count * rdiv;
+			if (f != 0) {
+				asm("dmultu\t%[cnt],%[f]\n\t"
+				    "mfhi\t%[cnt]"
+				    : [cnt] "+r" (ipd_clk_count),
+				      [f] "=r" (f)
+				    : : "hi", "lo");
+			}
+		}
+		write_c0_cvmcount(ipd_clk_count);
+	}
 	local_irq_restore(flags);
 }
 
@@ -77,7 +105,7 @@ unsigned long long notrace sched_clock(void)
 void __init plat_time_init(void)
 {
 	clocksource_mips.rating = 300;
-	clocksource_set_clock(&clocksource_mips, mips_hpt_frequency);
+	clocksource_set_clock(&clocksource_mips, octeon_get_clock_rate());
 	clocksource_register(&clocksource_mips);
 }
 
-- 
1.7.2.3




[Index of Archives]     [Linux MIPS Home]     [LKML Archive]     [Linux ARM Kernel]     [Linux ARM]     [Linux]     [Git]     [Yosemite News]     [Linux SCSI]     [Linux Hams]

  Powered by Linux