Linux kernel mirror (for testing) git.kernel.org/pub/scm/linux/kernel/git/torvalds/linux.git
kernel os linux

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>

authored by

David Daney and committed by
David Daney
70a26a21 2432cbe4

+66 -31
+63 -30
arch/mips/cavium-octeon/csrc-octeon.c
··· 4 4 * for more details. 5 5 * 6 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 9 #include <linux/clocksource.h> 10 10 #include <linux/export.h> ··· 18 18 #include <asm/octeon/cvmx-ipd-defs.h> 19 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 49 * Set the current core's cvmcount counter to the value of the 23 50 * IPD_CLK_COUNT. We do this on all cores as they are brought ··· 57 30 { 58 31 unsigned long flags; 59 32 unsigned loops = 2; 60 - u64 f = 0; 61 - u64 rdiv = 0; 62 - u64 sdiv = 0; 63 - if (current_cpu_type() == CPU_CAVIUM_OCTEON2) { 64 - union cvmx_mio_rst_boot rst_boot; 65 - rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT); 66 - rdiv = rst_boot.s.c_mul; /* CPU clock */ 67 - sdiv = rst_boot.s.pnr_mul; /* I/O clock */ 68 - f = (0x8000000000000000ull / sdiv) * 2; 69 - } 70 - 71 33 72 34 /* Clobber loops so GCC will not unroll the following while loop. */ 73 35 asm("" : "+r" (loops)); ··· 73 57 if (f != 0) { 74 58 asm("dmultu\t%[cnt],%[f]\n\t" 75 59 "mfhi\t%[cnt]" 76 - : [cnt] "+r" (ipd_clk_count), 77 - [f] "=r" (f) 78 - : : "hi", "lo"); 60 + : [cnt] "+r" (ipd_clk_count) 61 + : [f] "r" (f) 62 + : "hi", "lo"); 79 63 } 80 64 } 81 65 write_c0_cvmcount(ipd_clk_count); ··· 125 109 clocksource_register_hz(&clocksource_mips, octeon_get_clock_rate()); 126 110 } 127 111 128 - static u64 octeon_udelay_factor; 129 - static u64 octeon_ndelay_factor; 130 - 131 - void __init octeon_setup_delays(void) 132 - { 133 - octeon_udelay_factor = octeon_get_clock_rate() / 1000000; 134 - /* 135 - * For __ndelay we divide by 2^16, so the factor is multiplied 136 - * by the same amount. 137 - */ 138 - octeon_ndelay_factor = (octeon_udelay_factor * 0x10000ull) / 1000ull; 139 - 140 - preset_lpj = octeon_get_clock_rate() / HZ; 141 - } 142 - 143 112 void __udelay(unsigned long us) 144 113 { 145 114 u64 cur, end, inc; ··· 164 163 cur = read_c0_cvmcount(); 165 164 } 166 165 EXPORT_SYMBOL(__delay); 166 + 167 + 168 + /** 169 + * octeon_io_clk_delay - wait for a given number of io clock cycles to pass. 170 + * 171 + * We scale the wait by the clock ratio, and then wait for the 172 + * corresponding number of core clocks. 173 + * 174 + * @count: The number of clocks to wait. 175 + */ 176 + void octeon_io_clk_delay(unsigned long count) 177 + { 178 + u64 cur, end; 179 + 180 + cur = read_c0_cvmcount(); 181 + if (rdiv != 0) { 182 + end = count * rdiv; 183 + if (f != 0) { 184 + asm("dmultu\t%[cnt],%[f]\n\t" 185 + "mfhi\t%[cnt]" 186 + : [cnt] "+r" (end) 187 + : [f] "r" (f) 188 + : "hi", "lo"); 189 + } 190 + end = cur + end; 191 + } else { 192 + end = cur + count; 193 + } 194 + while (end > cur) 195 + cur = read_c0_cvmcount(); 196 + } 197 + EXPORT_SYMBOL(octeon_io_clk_delay);
+2 -1
arch/mips/cavium-octeon/setup.c
··· 548 548 } 549 549 #endif 550 550 551 + octeon_setup_delays(); 552 + 551 553 /* 552 554 * BIST should always be enabled when doing a soft reset. L2 553 555 * Cache locking for instance is not cleared unless BIST is ··· 613 611 mips_hpt_frequency = octeon_get_clock_rate(); 614 612 615 613 octeon_init_cvmcount(); 616 - octeon_setup_delays(); 617 614 618 615 _machine_restart = octeon_restart; 619 616 _machine_halt = octeon_halt;
+1
arch/mips/include/asm/octeon/octeon.h
··· 52 52 53 53 extern void octeon_init_cvmcount(void); 54 54 extern void octeon_setup_delays(void); 55 + extern void octeon_io_clk_delay(unsigned long); 55 56 56 57 #define OCTEON_ARGV_MAX_ARGS 64 57 58 #define OCTOEN_SERIAL_LEN 20