aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/cavium-octeon/csrc-octeon.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/cavium-octeon/csrc-octeon.c')
-rw-r--r--arch/mips/cavium-octeon/csrc-octeon.c93
1 files changed, 63 insertions, 30 deletions
diff --git a/arch/mips/cavium-octeon/csrc-octeon.c b/arch/mips/cavium-octeon/csrc-octeon.c
index ce6483a9302a..02193953eb9e 100644
--- a/arch/mips/cavium-octeon/csrc-octeon.c
+++ b/arch/mips/cavium-octeon/csrc-octeon.c
@@ -4,7 +4,7 @@
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 * Copyright (C) 2009, 2012 Cavium, Inc.
8 */ 8 */
9#include <linux/clocksource.h> 9#include <linux/clocksource.h>
10#include <linux/export.h> 10#include <linux/export.h>
@@ -18,6 +18,33 @@
18#include <asm/octeon/cvmx-ipd-defs.h> 18#include <asm/octeon/cvmx-ipd-defs.h>
19#include <asm/octeon/cvmx-mio-defs.h> 19#include <asm/octeon/cvmx-mio-defs.h>
20 20
21
22static u64 f;
23static u64 rdiv;
24static u64 sdiv;
25static u64 octeon_udelay_factor;
26static u64 octeon_ndelay_factor;
27
28void __init octeon_setup_delays(void)
29{
30 octeon_udelay_factor = octeon_get_clock_rate() / 1000000;
31 /*
32 * For __ndelay we divide by 2^16, so the factor is multiplied
33 * by the same amount.
34 */
35 octeon_ndelay_factor = (octeon_udelay_factor * 0x10000ull) / 1000ull;
36
37 preset_lpj = octeon_get_clock_rate() / HZ;
38
39 if (current_cpu_type() == CPU_CAVIUM_OCTEON2) {
40 union cvmx_mio_rst_boot rst_boot;
41 rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
42 rdiv = rst_boot.s.c_mul; /* CPU clock */
43 sdiv = rst_boot.s.pnr_mul; /* I/O clock */
44 f = (0x8000000000000000ull / sdiv) * 2;
45 }
46}
47
21/* 48/*
22 * Set the current core's cvmcount counter to the value of the 49 * Set the current core's cvmcount counter to the value of the
23 * IPD_CLK_COUNT. We do this on all cores as they are brought 50 * IPD_CLK_COUNT. We do this on all cores as they are brought
@@ -30,17 +57,6 @@ void octeon_init_cvmcount(void)
30{ 57{
31 unsigned long flags; 58 unsigned long flags;
32 unsigned loops = 2; 59 unsigned loops = 2;
33 u64 f = 0;
34 u64 rdiv = 0;
35 u64 sdiv = 0;
36 if (current_cpu_type() == CPU_CAVIUM_OCTEON2) {
37 union cvmx_mio_rst_boot rst_boot;
38 rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
39 rdiv = rst_boot.s.c_mul; /* CPU clock */
40 sdiv = rst_boot.s.pnr_mul; /* I/O clock */
41 f = (0x8000000000000000ull / sdiv) * 2;
42 }
43
44 60
45 /* Clobber loops so GCC will not unroll the following while loop. */ 61 /* Clobber loops so GCC will not unroll the following while loop. */
46 asm("" : "+r" (loops)); 62 asm("" : "+r" (loops));
@@ -57,9 +73,9 @@ void octeon_init_cvmcount(void)
57 if (f != 0) { 73 if (f != 0) {
58 asm("dmultu\t%[cnt],%[f]\n\t" 74 asm("dmultu\t%[cnt],%[f]\n\t"
59 "mfhi\t%[cnt]" 75 "mfhi\t%[cnt]"
60 : [cnt] "+r" (ipd_clk_count), 76 : [cnt] "+r" (ipd_clk_count)
61 [f] "=r" (f) 77 : [f] "r" (f)
62 : : "hi", "lo"); 78 : "hi", "lo");
63 } 79 }
64 } 80 }
65 write_c0_cvmcount(ipd_clk_count); 81 write_c0_cvmcount(ipd_clk_count);
@@ -109,21 +125,6 @@ void __init plat_time_init(void)
109 clocksource_register_hz(&clocksource_mips, octeon_get_clock_rate()); 125 clocksource_register_hz(&clocksource_mips, octeon_get_clock_rate());
110} 126}
111 127
112static u64 octeon_udelay_factor;
113static u64 octeon_ndelay_factor;
114
115void __init octeon_setup_delays(void)
116{
117 octeon_udelay_factor = octeon_get_clock_rate() / 1000000;
118 /*
119 * For __ndelay we divide by 2^16, so the factor is multiplied
120 * by the same amount.
121 */
122 octeon_ndelay_factor = (octeon_udelay_factor * 0x10000ull) / 1000ull;
123
124 preset_lpj = octeon_get_clock_rate() / HZ;
125}
126
127void __udelay(unsigned long us) 128void __udelay(unsigned long us)
128{ 129{
129 u64 cur, end, inc; 130 u64 cur, end, inc;
@@ -163,3 +164,35 @@ void __delay(unsigned long loops)
163 cur = read_c0_cvmcount(); 164 cur = read_c0_cvmcount();
164} 165}
165EXPORT_SYMBOL(__delay); 166EXPORT_SYMBOL(__delay);
167
168
169/**
170 * octeon_io_clk_delay - wait for a given number of io clock cycles to pass.
171 *
172 * We scale the wait by the clock ratio, and then wait for the
173 * corresponding number of core clocks.
174 *
175 * @count: The number of clocks to wait.
176 */
177void octeon_io_clk_delay(unsigned long count)
178{
179 u64 cur, end;
180
181 cur = read_c0_cvmcount();
182 if (rdiv != 0) {
183 end = count * rdiv;
184 if (f != 0) {
185 asm("dmultu\t%[cnt],%[f]\n\t"
186 "mfhi\t%[cnt]"
187 : [cnt] "+r" (end)
188 : [f] "r" (f)
189 : "hi", "lo");
190 }
191 end = cur + end;
192 } else {
193 end = cur + count;
194 }
195 while (end > cur)
196 cur = read_c0_cvmcount();
197}
198EXPORT_SYMBOL(octeon_io_clk_delay);