mirror of
https://mirrors.bfsu.edu.cn/git/linux.git
synced 2024-11-15 16:24:13 +08:00
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>
This commit is contained in:
parent
f92a6b0875
commit
54954a6d6b
@ -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 *= 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);
|
||||
}
|
||||
|
||||
|
Loading…
Reference in New Issue
Block a user