aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips
diff options
context:
space:
mode:
authorDavid Daney <ddaney@caviumnetworks.com>2010-10-07 19:03:47 -0400
committerRalf Baechle <ralf@linux-mips.org>2010-10-29 14:08:38 -0400
commit54954a6d6ba1c2f44375d2992d50f1db56a8857d (patch)
tree332959aa2067a9b8819cf9ccd8e735abb78d88cb /arch/mips
parentf92a6b0875977132074a696e8d44c95e8472d8ac (diff)
MIPS: Octeon: Scale Octeon2 clocks in octeon_init_cvmcount()
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@caviumnetworks.com> Patchwork: http://patchwork.linux-mips.org/patch/1667/ Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch/mips')
-rw-r--r--arch/mips/cavium-octeon/csrc-octeon.c34
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 b6847c8e0ddd..26bf71130bf8 100644
--- a/arch/mips/cavium-octeon/csrc-octeon.c
+++ b/arch/mips/cavium-octeon/csrc-octeon.c
@@ -4,14 +4,18 @@
4 * for more details. 4 * for more details.
5 * 5 *
6 * Copyright (C) 2007 by Ralf Baechle 6 * Copyright (C) 2007 by Ralf Baechle
7 * Copyright (C) 2009, 2010 Cavium Networks, Inc.
7 */ 8 */
8#include <linux/clocksource.h> 9#include <linux/clocksource.h>
9#include <linux/init.h> 10#include <linux/init.h>
11#include <linux/smp.h>
10 12
13#include <asm/cpu-info.h>
11#include <asm/time.h> 14#include <asm/time.h>
12 15
13#include <asm/octeon/octeon.h> 16#include <asm/octeon/octeon.h>
14#include <asm/octeon/cvmx-ipd-defs.h> 17#include <asm/octeon/cvmx-ipd-defs.h>
18#include <asm/octeon/cvmx-mio-defs.h>
15 19
16/* 20/*
17 * Set the current core's cvmcount counter to the value of the 21 * Set the current core's cvmcount counter to the value of the
@@ -19,11 +23,23 @@
19 * on-line. This allows for a read from a local cpu register to 23 * on-line. This allows for a read from a local cpu register to
20 * access a synchronized counter. 24 * access a synchronized counter.
21 * 25 *
26 * On CPU_CAVIUM_OCTEON2 the IPD_CLK_COUNT is scaled by rdiv/sdiv.
22 */ 27 */
23void octeon_init_cvmcount(void) 28void octeon_init_cvmcount(void)
24{ 29{
25 unsigned long flags; 30 unsigned long flags;
26 unsigned loops = 2; 31 unsigned loops = 2;
32 u64 f = 0;
33 u64 rdiv = 0;
34 u64 sdiv = 0;
35 if (current_cpu_type() == CPU_CAVIUM_OCTEON2) {
36 union cvmx_mio_rst_boot rst_boot;
37 rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
38 rdiv = rst_boot.s.c_mul; /* CPU clock */
39 sdiv = rst_boot.s.pnr_mul; /* I/O clock */
40 f = (0x8000000000000000ull / sdiv) * 2;
41 }
42
27 43
28 /* Clobber loops so GCC will not unroll the following while loop. */ 44 /* Clobber loops so GCC will not unroll the following while loop. */
29 asm("" : "+r" (loops)); 45 asm("" : "+r" (loops));
@@ -33,8 +49,20 @@ void octeon_init_cvmcount(void)
33 * Loop several times so we are executing from the cache, 49 * Loop several times so we are executing from the cache,
34 * which should give more deterministic timing. 50 * which should give more deterministic timing.
35 */ 51 */
36 while (loops--) 52 while (loops--) {
37 write_c0_cvmcount(cvmx_read_csr(CVMX_IPD_CLK_COUNT)); 53 u64 ipd_clk_count = cvmx_read_csr(CVMX_IPD_CLK_COUNT);
54 if (rdiv != 0) {
55 ipd_clk_count *= rdiv;
56 if (f != 0) {
57 asm("dmultu\t%[cnt],%[f]\n\t"
58 "mfhi\t%[cnt]"
59 : [cnt] "+r" (ipd_clk_count),
60 [f] "=r" (f)
61 : : "hi", "lo");
62 }
63 }
64 write_c0_cvmcount(ipd_clk_count);
65 }
38 local_irq_restore(flags); 66 local_irq_restore(flags);
39} 67}
40 68
@@ -77,7 +105,7 @@ unsigned long long notrace sched_clock(void)
77void __init plat_time_init(void) 105void __init plat_time_init(void)
78{ 106{
79 clocksource_mips.rating = 300; 107 clocksource_mips.rating = 300;
80 clocksource_set_clock(&clocksource_mips, mips_hpt_frequency); 108 clocksource_set_clock(&clocksource_mips, octeon_get_clock_rate());
81 clocksource_register(&clocksource_mips); 109 clocksource_register(&clocksource_mips);
82} 110}
83 111