time.h 3.7 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157
  1. /*
  2. * Common time prototypes and such for all ppc machines.
  3. *
  4. * Written by Cort Dougan (cort@fsmlabs.com) to merge
  5. * Paul Mackerras' version and mine for PReP and Pmac.
  6. */
  7. #ifdef __KERNEL__
  8. #ifndef __ASM_TIME_H__
  9. #define __ASM_TIME_H__
  10. #include <linux/config.h>
  11. #include <linux/types.h>
  12. #include <linux/rtc.h>
  13. #include <linux/threads.h>
  14. #include <asm/reg.h>
  15. /* time.c */
  16. extern unsigned tb_ticks_per_jiffy;
  17. extern unsigned tb_to_us;
  18. extern unsigned tb_last_stamp;
  19. extern unsigned long disarm_decr[NR_CPUS];
  20. extern void to_tm(int tim, struct rtc_time * tm);
  21. extern time_t last_rtc_update;
  22. extern void set_dec_cpu6(unsigned int val);
  23. int via_calibrate_decr(void);
  24. /* Accessor functions for the decrementer register.
  25. * The 4xx doesn't even have a decrementer. I tried to use the
  26. * generic timer interrupt code, which seems OK, with the 4xx PIT
  27. * in auto-reload mode. The problem is PIT stops counting when it
  28. * hits zero. If it would wrap, we could use it just like a decrementer.
  29. */
  30. static __inline__ unsigned int get_dec(void)
  31. {
  32. #if defined(CONFIG_40x)
  33. return (mfspr(SPRN_PIT));
  34. #else
  35. return (mfspr(SPRN_DEC));
  36. #endif
  37. }
  38. static __inline__ void set_dec(unsigned int val)
  39. {
  40. #if defined(CONFIG_40x)
  41. return; /* Have to let it auto-reload */
  42. #elif defined(CONFIG_8xx_CPU6)
  43. set_dec_cpu6(val);
  44. #else
  45. mtspr(SPRN_DEC, val);
  46. #endif
  47. }
  48. /* Accessor functions for the timebase (RTC on 601) registers. */
  49. /* If one day CONFIG_POWER is added just define __USE_RTC as 1 */
  50. #ifdef CONFIG_6xx
  51. extern __inline__ int __attribute_pure__ __USE_RTC(void) {
  52. return (mfspr(SPRN_PVR)>>16) == 1;
  53. }
  54. #else
  55. #define __USE_RTC() 0
  56. #endif
  57. extern __inline__ unsigned long get_tbl(void) {
  58. unsigned long tbl;
  59. #if defined(CONFIG_403GCX)
  60. asm volatile("mfspr %0, 0x3dd" : "=r" (tbl));
  61. #else
  62. asm volatile("mftb %0" : "=r" (tbl));
  63. #endif
  64. return tbl;
  65. }
  66. extern __inline__ unsigned long get_tbu(void) {
  67. unsigned long tbl;
  68. #if defined(CONFIG_403GCX)
  69. asm volatile("mfspr %0, 0x3dc" : "=r" (tbl));
  70. #else
  71. asm volatile("mftbu %0" : "=r" (tbl));
  72. #endif
  73. return tbl;
  74. }
  75. extern __inline__ void set_tb(unsigned int upper, unsigned int lower)
  76. {
  77. mtspr(SPRN_TBWL, 0);
  78. mtspr(SPRN_TBWU, upper);
  79. mtspr(SPRN_TBWL, lower);
  80. }
  81. extern __inline__ unsigned long get_rtcl(void) {
  82. unsigned long rtcl;
  83. asm volatile("mfrtcl %0" : "=r" (rtcl));
  84. return rtcl;
  85. }
  86. extern __inline__ unsigned long get_rtcu(void)
  87. {
  88. unsigned long rtcu;
  89. asm volatile("mfrtcu %0" : "=r" (rtcu));
  90. return rtcu;
  91. }
  92. extern __inline__ unsigned get_native_tbl(void) {
  93. if (__USE_RTC())
  94. return get_rtcl();
  95. else
  96. return get_tbl();
  97. }
  98. /* On machines with RTC, this function can only be used safely
  99. * after the timestamp and for 1 second. It is only used by gettimeofday
  100. * however so it should not matter.
  101. */
  102. extern __inline__ unsigned tb_ticks_since(unsigned tstamp) {
  103. if (__USE_RTC()) {
  104. int delta = get_rtcl() - tstamp;
  105. return delta<0 ? delta + 1000000000 : delta;
  106. } else {
  107. return get_tbl() - tstamp;
  108. }
  109. }
  110. #if 0
  111. extern __inline__ unsigned long get_bin_rtcl(void) {
  112. unsigned long rtcl, rtcu1, rtcu2;
  113. asm volatile("\
  114. 1: mfrtcu %0\n\
  115. mfrtcl %1\n\
  116. mfrtcu %2\n\
  117. cmpw %0,%2\n\
  118. bne- 1b\n"
  119. : "=r" (rtcu1), "=r" (rtcl), "=r" (rtcu2)
  120. : : "cr0");
  121. return rtcu2*1000000000+rtcl;
  122. }
  123. extern __inline__ unsigned binary_tbl(void) {
  124. if (__USE_RTC())
  125. return get_bin_rtcl();
  126. else
  127. return get_tbl();
  128. }
  129. #endif
  130. /* Use mulhwu to scale processor timebase to timeval */
  131. /* Specifically, this computes (x * y) / 2^32. -- paulus */
  132. #define mulhwu(x,y) \
  133. ({unsigned z; asm ("mulhwu %0,%1,%2" : "=r" (z) : "r" (x), "r" (y)); z;})
  134. unsigned mulhwu_scale_factor(unsigned, unsigned);
  135. #endif /* __ASM_TIME_H__ */
  136. #endif /* __KERNEL__ */