time-ts.c 5.5 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223
  1. /*
  2. * linux/arch/kernel/time-ts.c
  3. *
  4. * Based on arm clockevents implementation and old bfin time tick.
  5. *
  6. * Copyright(C) 2008, GeoTechnologies, Vitja Makarov
  7. *
  8. * This code is licenced under the GPL version 2. For details see
  9. * kernel-base/COPYING.
  10. */
  11. #include <linux/module.h>
  12. #include <linux/profile.h>
  13. #include <linux/interrupt.h>
  14. #include <linux/time.h>
  15. #include <linux/timex.h>
  16. #include <linux/irq.h>
  17. #include <linux/clocksource.h>
  18. #include <linux/clockchips.h>
  19. #include <linux/cpufreq.h>
  20. #include <asm/blackfin.h>
  21. #include <asm/time.h>
  22. #ifdef CONFIG_CYCLES_CLOCKSOURCE
  23. /* Accelerators for sched_clock()
  24. * convert from cycles(64bits) => nanoseconds (64bits)
  25. * basic equation:
  26. * ns = cycles / (freq / ns_per_sec)
  27. * ns = cycles * (ns_per_sec / freq)
  28. * ns = cycles * (10^9 / (cpu_khz * 10^3))
  29. * ns = cycles * (10^6 / cpu_khz)
  30. *
  31. * Then we use scaling math (suggested by george@mvista.com) to get:
  32. * ns = cycles * (10^6 * SC / cpu_khz) / SC
  33. * ns = cycles * cyc2ns_scale / SC
  34. *
  35. * And since SC is a constant power of two, we can convert the div
  36. * into a shift.
  37. *
  38. * We can use khz divisor instead of mhz to keep a better precision, since
  39. * cyc2ns_scale is limited to 10^6 * 2^10, which fits in 32 bits.
  40. * (mathieu.desnoyers@polymtl.ca)
  41. *
  42. * -johnstul@us.ibm.com "math is hard, lets go shopping!"
  43. */
  44. static unsigned long cyc2ns_scale;
  45. #define CYC2NS_SCALE_FACTOR 10 /* 2^10, carefully chosen */
  46. static inline void set_cyc2ns_scale(unsigned long cpu_khz)
  47. {
  48. cyc2ns_scale = (1000000 << CYC2NS_SCALE_FACTOR) / cpu_khz;
  49. }
  50. static inline unsigned long long cycles_2_ns(cycle_t cyc)
  51. {
  52. return (cyc * cyc2ns_scale) >> CYC2NS_SCALE_FACTOR;
  53. }
  54. static cycle_t read_cycles(void)
  55. {
  56. return __bfin_cycles_off + (get_cycles() << __bfin_cycles_mod);
  57. }
  58. unsigned long long sched_clock(void)
  59. {
  60. return cycles_2_ns(read_cycles());
  61. }
  62. static struct clocksource clocksource_bfin = {
  63. .name = "bfin_cycles",
  64. .rating = 350,
  65. .read = read_cycles,
  66. .mask = CLOCKSOURCE_MASK(64),
  67. .shift = 22,
  68. .flags = CLOCK_SOURCE_IS_CONTINUOUS,
  69. };
  70. static int __init bfin_clocksource_init(void)
  71. {
  72. set_cyc2ns_scale(get_cclk() / 1000);
  73. clocksource_bfin.mult = clocksource_hz2mult(get_cclk(), clocksource_bfin.shift);
  74. if (clocksource_register(&clocksource_bfin))
  75. panic("failed to register clocksource");
  76. return 0;
  77. }
  78. #else
  79. # define bfin_clocksource_init()
  80. #endif
  81. static int bfin_timer_set_next_event(unsigned long cycles,
  82. struct clock_event_device *evt)
  83. {
  84. bfin_write_TCOUNT(cycles);
  85. CSYNC();
  86. return 0;
  87. }
  88. static void bfin_timer_set_mode(enum clock_event_mode mode,
  89. struct clock_event_device *evt)
  90. {
  91. switch (mode) {
  92. case CLOCK_EVT_MODE_PERIODIC: {
  93. unsigned long tcount = ((get_cclk() / (HZ * TIME_SCALE)) - 1);
  94. bfin_write_TCNTL(TMPWR);
  95. bfin_write_TSCALE(TIME_SCALE - 1);
  96. CSYNC();
  97. bfin_write_TPERIOD(tcount);
  98. bfin_write_TCOUNT(tcount);
  99. bfin_write_TCNTL(TMPWR | TMREN | TAUTORLD);
  100. CSYNC();
  101. break;
  102. }
  103. case CLOCK_EVT_MODE_ONESHOT:
  104. bfin_write_TSCALE(TIME_SCALE - 1);
  105. bfin_write_TCOUNT(0);
  106. bfin_write_TCNTL(TMPWR | TMREN);
  107. CSYNC();
  108. break;
  109. case CLOCK_EVT_MODE_UNUSED:
  110. case CLOCK_EVT_MODE_SHUTDOWN:
  111. bfin_write_TCNTL(0);
  112. CSYNC();
  113. break;
  114. case CLOCK_EVT_MODE_RESUME:
  115. break;
  116. }
  117. }
  118. static void __init bfin_timer_init(void)
  119. {
  120. /* power up the timer, but don't enable it just yet */
  121. bfin_write_TCNTL(TMPWR);
  122. CSYNC();
  123. /*
  124. * the TSCALE prescaler counter.
  125. */
  126. bfin_write_TSCALE(TIME_SCALE - 1);
  127. bfin_write_TPERIOD(0);
  128. bfin_write_TCOUNT(0);
  129. /* now enable the timer */
  130. CSYNC();
  131. }
  132. /*
  133. * timer_interrupt() needs to keep up the real-time clock,
  134. * as well as call the "do_timer()" routine every clocktick
  135. */
  136. #ifdef CONFIG_CORE_TIMER_IRQ_L1
  137. __attribute__((l1_text))
  138. #endif
  139. irqreturn_t timer_interrupt(int irq, void *dev_id);
  140. static struct clock_event_device clockevent_bfin = {
  141. .name = "bfin_core_timer",
  142. .features = CLOCK_EVT_FEAT_PERIODIC | CLOCK_EVT_FEAT_ONESHOT,
  143. .shift = 32,
  144. .cpumask = CPU_MASK_CPU0,
  145. .set_next_event = bfin_timer_set_next_event,
  146. .set_mode = bfin_timer_set_mode,
  147. };
  148. static struct irqaction bfin_timer_irq = {
  149. .name = "Blackfin Core Timer",
  150. .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
  151. .handler = timer_interrupt,
  152. .dev_id = &clockevent_bfin,
  153. };
  154. irqreturn_t timer_interrupt(int irq, void *dev_id)
  155. {
  156. struct clock_event_device *evt = dev_id;
  157. evt->event_handler(evt);
  158. return IRQ_HANDLED;
  159. }
  160. static int __init bfin_clockevent_init(void)
  161. {
  162. unsigned long timer_clk;
  163. timer_clk = get_cclk() / TIME_SCALE;
  164. setup_irq(IRQ_CORETMR, &bfin_timer_irq);
  165. bfin_timer_init();
  166. clockevent_bfin.mult = div_sc(timer_clk, NSEC_PER_SEC, clockevent_bfin.shift);
  167. clockevent_bfin.max_delta_ns = clockevent_delta2ns(-1, &clockevent_bfin);
  168. clockevent_bfin.min_delta_ns = clockevent_delta2ns(100, &clockevent_bfin);
  169. clockevents_register_device(&clockevent_bfin);
  170. return 0;
  171. }
  172. void __init time_init(void)
  173. {
  174. time_t secs_since_1970 = (365 * 37 + 9) * 24 * 60 * 60; /* 1 Jan 2007 */
  175. #ifdef CONFIG_RTC_DRV_BFIN
  176. /* [#2663] hack to filter junk RTC values that would cause
  177. * userspace to have to deal with time values greater than
  178. * 2^31 seconds (which uClibc cannot cope with yet)
  179. */
  180. if ((bfin_read_RTC_STAT() & 0xC0000000) == 0xC0000000) {
  181. printk(KERN_NOTICE "bfin-rtc: invalid date; resetting\n");
  182. bfin_write_RTC_STAT(0);
  183. }
  184. #endif
  185. /* Initialize xtime. From now on, xtime is updated with timer interrupts */
  186. xtime.tv_sec = secs_since_1970;
  187. xtime.tv_nsec = 0;
  188. set_normalized_timespec(&wall_to_monotonic, -xtime.tv_sec, -xtime.tv_nsec);
  189. bfin_clocksource_init();
  190. bfin_clockevent_init();
  191. }