diff options
author | David Daney <ddaney@caviumnetworks.com> | 2012-08-21 14:45:05 -0400 |
---|---|---|
committer | David Daney <david.daney@cavium.com> | 2012-08-31 14:48:48 -0400 |
commit | 70a26a219cc0eedae4529c27fe1abfb2a02e373b (patch) | |
tree | 30b51a8344ba6bb97196fcb5c864a2fa2471b1cf /arch/mips/cavium-octeon | |
parent | 2432cbe4f29fbb8d349e481695ac6e88b884bacb (diff) |
MIPS: Octeon: Add octeon_io_clk_delay() function.
Also cleanup and fix octeon_init_cvmcount()
Signed-off-by: David Daney <ddaney@caviumnetworks.com>
Acked-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'arch/mips/cavium-octeon')
-rw-r--r-- | arch/mips/cavium-octeon/csrc-octeon.c | 93 | ||||
-rw-r--r-- | arch/mips/cavium-octeon/setup.c | 3 |
2 files changed, 65 insertions, 31 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 | |||
22 | static u64 f; | ||
23 | static u64 rdiv; | ||
24 | static u64 sdiv; | ||
25 | static u64 octeon_udelay_factor; | ||
26 | static u64 octeon_ndelay_factor; | ||
27 | |||
28 | void __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 | ||
112 | static u64 octeon_udelay_factor; | ||
113 | static u64 octeon_ndelay_factor; | ||
114 | |||
115 | void __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 | |||
127 | void __udelay(unsigned long us) | 128 | void __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 | } |
165 | EXPORT_SYMBOL(__delay); | 166 | EXPORT_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 | */ | ||
177 | void 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 | } | ||
198 | EXPORT_SYMBOL(octeon_io_clk_delay); | ||
diff --git a/arch/mips/cavium-octeon/setup.c b/arch/mips/cavium-octeon/setup.c index 919b0fb7bb1a..04dd8ff0e0d8 100644 --- a/arch/mips/cavium-octeon/setup.c +++ b/arch/mips/cavium-octeon/setup.c | |||
@@ -548,6 +548,8 @@ void __init prom_init(void) | |||
548 | } | 548 | } |
549 | #endif | 549 | #endif |
550 | 550 | ||
551 | octeon_setup_delays(); | ||
552 | |||
551 | /* | 553 | /* |
552 | * BIST should always be enabled when doing a soft reset. L2 | 554 | * BIST should always be enabled when doing a soft reset. L2 |
553 | * Cache locking for instance is not cleared unless BIST is | 555 | * Cache locking for instance is not cleared unless BIST is |
@@ -611,7 +613,6 @@ void __init prom_init(void) | |||
611 | mips_hpt_frequency = octeon_get_clock_rate(); | 613 | mips_hpt_frequency = octeon_get_clock_rate(); |
612 | 614 | ||
613 | octeon_init_cvmcount(); | 615 | octeon_init_cvmcount(); |
614 | octeon_setup_delays(); | ||
615 | 616 | ||
616 | _machine_restart = octeon_restart; | 617 | _machine_restart = octeon_restart; |
617 | _machine_halt = octeon_halt; | 618 | _machine_halt = octeon_halt; |