csrc-octeon.c 4.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208
  1. /*
  2. * This file is subject to the terms and conditions of the GNU General Public
  3. * License. See the file "COPYING" in the main directory of this archive
  4. * for more details.
  5. *
  6. * Copyright (C) 2007 by Ralf Baechle
  7. * Copyright (C) 2009, 2012 Cavium, Inc.
  8. */
  9. #include <linux/clocksource.h>
  10. #include <linux/export.h>
  11. #include <linux/init.h>
  12. #include <linux/smp.h>
  13. #include <asm/cpu-info.h>
  14. #include <asm/cpu-type.h>
  15. #include <asm/time.h>
  16. #include <asm/octeon/octeon.h>
  17. #include <asm/octeon/cvmx-ipd-defs.h>
  18. #include <asm/octeon/cvmx-mio-defs.h>
  19. #include <asm/octeon/cvmx-rst-defs.h>
  20. static u64 f;
  21. static u64 rdiv;
  22. static u64 sdiv;
  23. static u64 octeon_udelay_factor;
  24. static u64 octeon_ndelay_factor;
  25. void __init octeon_setup_delays(void)
  26. {
  27. octeon_udelay_factor = octeon_get_clock_rate() / 1000000;
  28. /*
  29. * For __ndelay we divide by 2^16, so the factor is multiplied
  30. * by the same amount.
  31. */
  32. octeon_ndelay_factor = (octeon_udelay_factor * 0x10000ull) / 1000ull;
  33. preset_lpj = octeon_get_clock_rate() / HZ;
  34. if (current_cpu_type() == CPU_CAVIUM_OCTEON2) {
  35. union cvmx_mio_rst_boot rst_boot;
  36. rst_boot.u64 = cvmx_read_csr(CVMX_MIO_RST_BOOT);
  37. rdiv = rst_boot.s.c_mul; /* CPU clock */
  38. sdiv = rst_boot.s.pnr_mul; /* I/O clock */
  39. f = (0x8000000000000000ull / sdiv) * 2;
  40. } else if (current_cpu_type() == CPU_CAVIUM_OCTEON3) {
  41. union cvmx_rst_boot rst_boot;
  42. rst_boot.u64 = cvmx_read_csr(CVMX_RST_BOOT);
  43. rdiv = rst_boot.s.c_mul; /* CPU clock */
  44. sdiv = rst_boot.s.pnr_mul; /* I/O clock */
  45. f = (0x8000000000000000ull / sdiv) * 2;
  46. }
  47. }
  48. /*
  49. * Set the current core's cvmcount counter to the value of the
  50. * IPD_CLK_COUNT. We do this on all cores as they are brought
  51. * on-line. This allows for a read from a local cpu register to
  52. * access a synchronized counter.
  53. *
  54. * On CPU_CAVIUM_OCTEON2 the IPD_CLK_COUNT is scaled by rdiv/sdiv.
  55. */
  56. void octeon_init_cvmcount(void)
  57. {
  58. unsigned long flags;
  59. unsigned loops = 2;
  60. /* Clobber loops so GCC will not unroll the following while loop. */
  61. asm("" : "+r" (loops));
  62. local_irq_save(flags);
  63. /*
  64. * Loop several times so we are executing from the cache,
  65. * which should give more deterministic timing.
  66. */
  67. while (loops--) {
  68. u64 ipd_clk_count = cvmx_read_csr(CVMX_IPD_CLK_COUNT);
  69. if (rdiv != 0) {
  70. ipd_clk_count *= rdiv;
  71. if (f != 0) {
  72. asm("dmultu\t%[cnt],%[f]\n\t"
  73. "mfhi\t%[cnt]"
  74. : [cnt] "+r" (ipd_clk_count)
  75. : [f] "r" (f)
  76. : "hi", "lo");
  77. }
  78. }
  79. write_c0_cvmcount(ipd_clk_count);
  80. }
  81. local_irq_restore(flags);
  82. }
  83. static cycle_t octeon_cvmcount_read(struct clocksource *cs)
  84. {
  85. return read_c0_cvmcount();
  86. }
  87. static struct clocksource clocksource_mips = {
  88. .name = "OCTEON_CVMCOUNT",
  89. .read = octeon_cvmcount_read,
  90. .mask = CLOCKSOURCE_MASK(64),
  91. .flags = CLOCK_SOURCE_IS_CONTINUOUS,
  92. };
  93. unsigned long long notrace sched_clock(void)
  94. {
  95. /* 64-bit arithmatic can overflow, so use 128-bit. */
  96. u64 t1, t2, t3;
  97. unsigned long long rv;
  98. u64 mult = clocksource_mips.mult;
  99. u64 shift = clocksource_mips.shift;
  100. u64 cnt = read_c0_cvmcount();
  101. asm (
  102. "dmultu\t%[cnt],%[mult]\n\t"
  103. "nor\t%[t1],$0,%[shift]\n\t"
  104. "mfhi\t%[t2]\n\t"
  105. "mflo\t%[t3]\n\t"
  106. "dsll\t%[t2],%[t2],1\n\t"
  107. "dsrlv\t%[rv],%[t3],%[shift]\n\t"
  108. "dsllv\t%[t1],%[t2],%[t1]\n\t"
  109. "or\t%[rv],%[t1],%[rv]\n\t"
  110. : [rv] "=&r" (rv), [t1] "=&r" (t1), [t2] "=&r" (t2), [t3] "=&r" (t3)
  111. : [cnt] "r" (cnt), [mult] "r" (mult), [shift] "r" (shift)
  112. : "hi", "lo");
  113. return rv;
  114. }
  115. void __init plat_time_init(void)
  116. {
  117. clocksource_mips.rating = 300;
  118. clocksource_register_hz(&clocksource_mips, octeon_get_clock_rate());
  119. }
  120. void __udelay(unsigned long us)
  121. {
  122. u64 cur, end, inc;
  123. cur = read_c0_cvmcount();
  124. inc = us * octeon_udelay_factor;
  125. end = cur + inc;
  126. while (end > cur)
  127. cur = read_c0_cvmcount();
  128. }
  129. EXPORT_SYMBOL(__udelay);
  130. void __ndelay(unsigned long ns)
  131. {
  132. u64 cur, end, inc;
  133. cur = read_c0_cvmcount();
  134. inc = ((ns * octeon_ndelay_factor) >> 16);
  135. end = cur + inc;
  136. while (end > cur)
  137. cur = read_c0_cvmcount();
  138. }
  139. EXPORT_SYMBOL(__ndelay);
  140. void __delay(unsigned long loops)
  141. {
  142. u64 cur, end;
  143. cur = read_c0_cvmcount();
  144. end = cur + loops;
  145. while (end > cur)
  146. cur = read_c0_cvmcount();
  147. }
  148. EXPORT_SYMBOL(__delay);
  149. /**
  150. * octeon_io_clk_delay - wait for a given number of io clock cycles to pass.
  151. *
  152. * We scale the wait by the clock ratio, and then wait for the
  153. * corresponding number of core clocks.
  154. *
  155. * @count: The number of clocks to wait.
  156. */
  157. void octeon_io_clk_delay(unsigned long count)
  158. {
  159. u64 cur, end;
  160. cur = read_c0_cvmcount();
  161. if (rdiv != 0) {
  162. end = count * rdiv;
  163. if (f != 0) {
  164. asm("dmultu\t%[cnt],%[f]\n\t"
  165. "mfhi\t%[cnt]"
  166. : [cnt] "+r" (end)
  167. : [f] "r" (f)
  168. : "hi", "lo");
  169. }
  170. end = cur + end;
  171. } else {
  172. end = cur + count;
  173. }
  174. while (end > cur)
  175. cur = read_c0_cvmcount();
  176. }
  177. EXPORT_SYMBOL(octeon_io_clk_delay);