diff options
author | David Daney <ddaney@caviumnetworks.com> | 2010-10-07 19:03:47 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2010-10-29 14:08:38 -0400 |
commit | 54954a6d6ba1c2f44375d2992d50f1db56a8857d (patch) | |
tree | 332959aa2067a9b8819cf9ccd8e735abb78d88cb /arch/mips/cavium-octeon | |
parent | f92a6b0875977132074a696e8d44c95e8472d8ac (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/cavium-octeon')
-rw-r--r-- | 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 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 | */ |
23 | void octeon_init_cvmcount(void) | 28 | void 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) | |||
77 | void __init plat_time_init(void) | 105 | void __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 | ||