timer_cyclone.c 6.9 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259
  1. /* Cyclone-timer:
  2. * This code implements timer_ops for the cyclone counter found
  3. * on IBM x440, x360, and other Summit based systems.
  4. *
  5. * Copyright (C) 2002 IBM, John Stultz (johnstul@us.ibm.com)
  6. */
  7. #include <linux/spinlock.h>
  8. #include <linux/init.h>
  9. #include <linux/timex.h>
  10. #include <linux/errno.h>
  11. #include <linux/string.h>
  12. #include <linux/jiffies.h>
  13. #include <asm/timer.h>
  14. #include <asm/io.h>
  15. #include <asm/pgtable.h>
  16. #include <asm/fixmap.h>
  17. #include <asm/i8253.h>
  18. #include "io_ports.h"
  19. /* Number of usecs that the last interrupt was delayed */
  20. static int delay_at_last_interrupt;
  21. #define CYCLONE_CBAR_ADDR 0xFEB00CD0
  22. #define CYCLONE_PMCC_OFFSET 0x51A0
  23. #define CYCLONE_MPMC_OFFSET 0x51D0
  24. #define CYCLONE_MPCS_OFFSET 0x51A8
  25. #define CYCLONE_TIMER_FREQ 100000000
  26. #define CYCLONE_TIMER_MASK (((u64)1<<40)-1) /* 40 bit mask */
  27. int use_cyclone = 0;
  28. static u32* volatile cyclone_timer; /* Cyclone MPMC0 register */
  29. static u32 last_cyclone_low;
  30. static u32 last_cyclone_high;
  31. static unsigned long long monotonic_base;
  32. static seqlock_t monotonic_lock = SEQLOCK_UNLOCKED;
  33. /* helper macro to atomically read both cyclone counter registers */
  34. #define read_cyclone_counter(low,high) \
  35. do{ \
  36. high = cyclone_timer[1]; low = cyclone_timer[0]; \
  37. } while (high != cyclone_timer[1]);
  38. static void mark_offset_cyclone(void)
  39. {
  40. unsigned long lost, delay;
  41. unsigned long delta = last_cyclone_low;
  42. int count;
  43. unsigned long long this_offset, last_offset;
  44. write_seqlock(&monotonic_lock);
  45. last_offset = ((unsigned long long)last_cyclone_high<<32)|last_cyclone_low;
  46. spin_lock(&i8253_lock);
  47. read_cyclone_counter(last_cyclone_low,last_cyclone_high);
  48. /* read values for delay_at_last_interrupt */
  49. outb_p(0x00, 0x43); /* latch the count ASAP */
  50. count = inb_p(0x40); /* read the latched count */
  51. count |= inb(0x40) << 8;
  52. /*
  53. * VIA686a test code... reset the latch if count > max + 1
  54. * from timer_pit.c - cjb
  55. */
  56. if (count > LATCH) {
  57. outb_p(0x34, PIT_MODE);
  58. outb_p(LATCH & 0xff, PIT_CH0);
  59. outb(LATCH >> 8, PIT_CH0);
  60. count = LATCH - 1;
  61. }
  62. spin_unlock(&i8253_lock);
  63. /* lost tick compensation */
  64. delta = last_cyclone_low - delta;
  65. delta /= (CYCLONE_TIMER_FREQ/1000000);
  66. delta += delay_at_last_interrupt;
  67. lost = delta/(1000000/HZ);
  68. delay = delta%(1000000/HZ);
  69. if (lost >= 2)
  70. jiffies_64 += lost-1;
  71. /* update the monotonic base value */
  72. this_offset = ((unsigned long long)last_cyclone_high<<32)|last_cyclone_low;
  73. monotonic_base += (this_offset - last_offset) & CYCLONE_TIMER_MASK;
  74. write_sequnlock(&monotonic_lock);
  75. /* calculate delay_at_last_interrupt */
  76. count = ((LATCH-1) - count) * TICK_SIZE;
  77. delay_at_last_interrupt = (count + LATCH/2) / LATCH;
  78. /* catch corner case where tick rollover occured
  79. * between cyclone and pit reads (as noted when
  80. * usec delta is > 90% # of usecs/tick)
  81. */
  82. if (lost && abs(delay - delay_at_last_interrupt) > (900000/HZ))
  83. jiffies_64++;
  84. }
  85. static unsigned long get_offset_cyclone(void)
  86. {
  87. u32 offset;
  88. if(!cyclone_timer)
  89. return delay_at_last_interrupt;
  90. /* Read the cyclone timer */
  91. offset = cyclone_timer[0];
  92. /* .. relative to previous jiffy */
  93. offset = offset - last_cyclone_low;
  94. /* convert cyclone ticks to microseconds */
  95. /* XXX slow, can we speed this up? */
  96. offset = offset/(CYCLONE_TIMER_FREQ/1000000);
  97. /* our adjusted time offset in microseconds */
  98. return delay_at_last_interrupt + offset;
  99. }
  100. static unsigned long long monotonic_clock_cyclone(void)
  101. {
  102. u32 now_low, now_high;
  103. unsigned long long last_offset, this_offset, base;
  104. unsigned long long ret;
  105. unsigned seq;
  106. /* atomically read monotonic base & last_offset */
  107. do {
  108. seq = read_seqbegin(&monotonic_lock);
  109. last_offset = ((unsigned long long)last_cyclone_high<<32)|last_cyclone_low;
  110. base = monotonic_base;
  111. } while (read_seqretry(&monotonic_lock, seq));
  112. /* Read the cyclone counter */
  113. read_cyclone_counter(now_low,now_high);
  114. this_offset = ((unsigned long long)now_high<<32)|now_low;
  115. /* convert to nanoseconds */
  116. ret = base + ((this_offset - last_offset)&CYCLONE_TIMER_MASK);
  117. return ret * (1000000000 / CYCLONE_TIMER_FREQ);
  118. }
  119. static int __init init_cyclone(char* override)
  120. {
  121. u32* reg;
  122. u32 base; /* saved cyclone base address */
  123. u32 pageaddr; /* page that contains cyclone_timer register */
  124. u32 offset; /* offset from pageaddr to cyclone_timer register */
  125. int i;
  126. /* check clock override */
  127. if (override[0] && strncmp(override,"cyclone",7))
  128. return -ENODEV;
  129. /*make sure we're on a summit box*/
  130. if(!use_cyclone) return -ENODEV;
  131. printk(KERN_INFO "Summit chipset: Starting Cyclone Counter.\n");
  132. /* find base address */
  133. pageaddr = (CYCLONE_CBAR_ADDR)&PAGE_MASK;
  134. offset = (CYCLONE_CBAR_ADDR)&(~PAGE_MASK);
  135. set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
  136. reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
  137. if(!reg){
  138. printk(KERN_ERR "Summit chipset: Could not find valid CBAR register.\n");
  139. return -ENODEV;
  140. }
  141. base = *reg;
  142. if(!base){
  143. printk(KERN_ERR "Summit chipset: Could not find valid CBAR value.\n");
  144. return -ENODEV;
  145. }
  146. /* setup PMCC */
  147. pageaddr = (base + CYCLONE_PMCC_OFFSET)&PAGE_MASK;
  148. offset = (base + CYCLONE_PMCC_OFFSET)&(~PAGE_MASK);
  149. set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
  150. reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
  151. if(!reg){
  152. printk(KERN_ERR "Summit chipset: Could not find valid PMCC register.\n");
  153. return -ENODEV;
  154. }
  155. reg[0] = 0x00000001;
  156. /* setup MPCS */
  157. pageaddr = (base + CYCLONE_MPCS_OFFSET)&PAGE_MASK;
  158. offset = (base + CYCLONE_MPCS_OFFSET)&(~PAGE_MASK);
  159. set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
  160. reg = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
  161. if(!reg){
  162. printk(KERN_ERR "Summit chipset: Could not find valid MPCS register.\n");
  163. return -ENODEV;
  164. }
  165. reg[0] = 0x00000001;
  166. /* map in cyclone_timer */
  167. pageaddr = (base + CYCLONE_MPMC_OFFSET)&PAGE_MASK;
  168. offset = (base + CYCLONE_MPMC_OFFSET)&(~PAGE_MASK);
  169. set_fixmap_nocache(FIX_CYCLONE_TIMER, pageaddr);
  170. cyclone_timer = (u32*)(fix_to_virt(FIX_CYCLONE_TIMER) + offset);
  171. if(!cyclone_timer){
  172. printk(KERN_ERR "Summit chipset: Could not find valid MPMC register.\n");
  173. return -ENODEV;
  174. }
  175. /*quick test to make sure its ticking*/
  176. for(i=0; i<3; i++){
  177. u32 old = cyclone_timer[0];
  178. int stall = 100;
  179. while(stall--) barrier();
  180. if(cyclone_timer[0] == old){
  181. printk(KERN_ERR "Summit chipset: Counter not counting! DISABLED\n");
  182. cyclone_timer = 0;
  183. return -ENODEV;
  184. }
  185. }
  186. init_cpu_khz();
  187. /* Everything looks good! */
  188. return 0;
  189. }
  190. static void delay_cyclone(unsigned long loops)
  191. {
  192. unsigned long bclock, now;
  193. if(!cyclone_timer)
  194. return;
  195. bclock = cyclone_timer[0];
  196. do {
  197. rep_nop();
  198. now = cyclone_timer[0];
  199. } while ((now-bclock) < loops);
  200. }
  201. /************************************************************/
  202. /* cyclone timer_opts struct */
  203. static struct timer_opts timer_cyclone = {
  204. .name = "cyclone",
  205. .mark_offset = mark_offset_cyclone,
  206. .get_offset = get_offset_cyclone,
  207. .monotonic_clock = monotonic_clock_cyclone,
  208. .delay = delay_cyclone,
  209. };
  210. struct init_timer_opts __initdata timer_cyclone_init = {
  211. .init = init_cyclone,
  212. .opts = &timer_cyclone,
  213. };