You can not select more than 25 topics Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.

i386_timer.c 4.4KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194
  1. /* A couple of routines to implement a low-overhead timer for drivers */
  2. /*
  3. * This program is free software; you can redistribute it and/or
  4. * modify it under the terms of the GNU General Public License as
  5. * published by the Free Software Foundation; either version 2, or (at
  6. * your option) any later version.
  7. */
  8. #include "etherboot.h"
  9. #include "timer.h"
  10. #include "latch.h"
  11. #include "init.h"
  12. void __load_timer2(unsigned int ticks)
  13. {
  14. /*
  15. * Now let's take care of PPC channel 2
  16. *
  17. * Set the Gate high, program PPC channel 2 for mode 0,
  18. * (interrupt on terminal count mode), binary count,
  19. * load 5 * LATCH count, (LSB and MSB) to begin countdown.
  20. *
  21. * Note some implementations have a bug where the high bits byte
  22. * of channel 2 is ignored.
  23. */
  24. /* Set up the timer gate, turn off the speaker */
  25. /* Set the Gate high, disable speaker */
  26. outb((inb(PPC_PORTB) & ~PPCB_SPKR) | PPCB_T2GATE, PPC_PORTB);
  27. /* binary, mode 0, LSB/MSB, Ch 2 */
  28. outb(TIMER2_SEL|WORD_ACCESS|MODE0|BINARY_COUNT, TIMER_MODE_PORT);
  29. /* LSB of ticks */
  30. outb(ticks & 0xFF, TIMER2_PORT);
  31. /* MSB of ticks */
  32. outb(ticks >> 8, TIMER2_PORT);
  33. }
  34. static int __timer2_running(void)
  35. {
  36. return ((inb(PPC_PORTB) & PPCB_T2OUT) == 0);
  37. }
  38. #if !defined(CONFIG_TSC_CURRTICKS)
  39. static void setup_timers(void)
  40. {
  41. return;
  42. }
  43. void load_timer2(unsigned int ticks)
  44. {
  45. return __load_timer2(ticks);
  46. }
  47. int timer2_running(void)
  48. {
  49. return __timer2_running();
  50. }
  51. void ndelay(unsigned int nsecs)
  52. {
  53. waiton_timer2((nsecs * CLOCK_TICK_RATE)/1000000000);
  54. }
  55. void udelay(unsigned int usecs)
  56. {
  57. waiton_timer2((usecs * TICKS_PER_MS)/1000);
  58. }
  59. #endif /* !defined(CONFIG_TSC_CURRTICKS) */
  60. #if defined(CONFIG_TSC_CURRTICKS)
  61. #define rdtsc(low,high) \
  62. __asm__ __volatile__("rdtsc" : "=a" (low), "=d" (high))
  63. #define rdtscll(val) \
  64. __asm__ __volatile__ ("rdtsc" : "=A" (val))
  65. /* Number of clock ticks to time with the rtc */
  66. #define LATCH 0xFF
  67. #define LATCHES_PER_SEC ((CLOCK_TICK_RATE + (LATCH/2))/LATCH)
  68. #define TICKS_PER_LATCH ((LATCHES_PER_SEC + (TICKS_PER_SEC/2))/TICKS_PER_SEC)
  69. static void sleep_latch(void)
  70. {
  71. __load_timer2(LATCH);
  72. while(__timer2_running());
  73. }
  74. /* ------ Calibrate the TSC -------
  75. * Time how long it takes to excute a loop that runs in known time.
  76. * And find the convertion needed to get to CLOCK_TICK_RATE
  77. */
  78. static unsigned long long calibrate_tsc(void)
  79. {
  80. unsigned long startlow, starthigh;
  81. unsigned long endlow, endhigh;
  82. rdtsc(startlow,starthigh);
  83. sleep_latch();
  84. rdtsc(endlow,endhigh);
  85. /* 64-bit subtract - gcc just messes up with long longs */
  86. __asm__("subl %2,%0\n\t"
  87. "sbbl %3,%1"
  88. :"=a" (endlow), "=d" (endhigh)
  89. :"g" (startlow), "g" (starthigh),
  90. "0" (endlow), "1" (endhigh));
  91. /* Error: ECPUTOOFAST */
  92. if (endhigh)
  93. goto bad_ctc;
  94. endlow *= TICKS_PER_LATCH;
  95. return endlow;
  96. /*
  97. * The CTC wasn't reliable: we got a hit on the very first read,
  98. * or the CPU was so fast/slow that the quotient wouldn't fit in
  99. * 32 bits..
  100. */
  101. bad_ctc:
  102. printf("bad_ctc\n");
  103. return 0;
  104. }
  105. static unsigned long clocks_per_tick;
  106. static void setup_timers(void)
  107. {
  108. if (!clocks_per_tick) {
  109. clocks_per_tick = calibrate_tsc();
  110. /* Display the CPU Mhz to easily test if the calibration was bad */
  111. printf("CPU %ld Mhz\n", (clocks_per_tick/1000 * TICKS_PER_SEC)/1000);
  112. }
  113. }
  114. unsigned long currticks(void)
  115. {
  116. unsigned long clocks_high, clocks_low;
  117. unsigned long currticks;
  118. /* Read the Time Stamp Counter */
  119. rdtsc(clocks_low, clocks_high);
  120. /* currticks = clocks / clocks_per_tick; */
  121. __asm__("divl %1"
  122. :"=a" (currticks)
  123. :"r" (clocks_per_tick), "0" (clocks_low), "d" (clocks_high));
  124. return currticks;
  125. }
  126. static unsigned long long timer_timeout;
  127. static int __timer_running(void)
  128. {
  129. unsigned long long now;
  130. rdtscll(now);
  131. return now < timer_timeout;
  132. }
  133. void udelay(unsigned int usecs)
  134. {
  135. unsigned long long now;
  136. rdtscll(now);
  137. timer_timeout = now + usecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000));
  138. while(__timer_running());
  139. }
  140. void ndelay(unsigned int nsecs)
  141. {
  142. unsigned long long now;
  143. rdtscll(now);
  144. timer_timeout = now + nsecs * ((clocks_per_tick * TICKS_PER_SEC)/(1000*1000*1000));
  145. while(__timer_running());
  146. }
  147. void load_timer2(unsigned int timer2_ticks)
  148. {
  149. unsigned long long now;
  150. unsigned long clocks;
  151. rdtscll(now);
  152. clocks = timer2_ticks * ((clocks_per_tick * TICKS_PER_SEC)/CLOCK_TICK_RATE);
  153. timer_timeout = now + clocks;
  154. }
  155. int timer2_running(void)
  156. {
  157. return __timer_running();
  158. }
  159. #endif /* RTC_CURRTICKS */
  160. INIT_FN ( INIT_TIMERS, setup_timers, NULL, NULL );