hpet.c 10 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453
  1. #include <linux/kernel.h>
  2. #include <linux/sched.h>
  3. #include <linux/init.h>
  4. #include <linux/mc146818rtc.h>
  5. #include <linux/time.h>
  6. #include <linux/clocksource.h>
  7. #include <linux/ioport.h>
  8. #include <linux/acpi.h>
  9. #include <linux/hpet.h>
  10. #include <asm/pgtable.h>
  11. #include <asm/vsyscall.h>
  12. #include <asm/timex.h>
  13. #include <asm/hpet.h>
  14. int nohpet __initdata;
  15. unsigned long hpet_address;
  16. unsigned long hpet_period; /* fsecs / HPET clock */
  17. unsigned long hpet_tick; /* HPET clocks / interrupt */
  18. int hpet_use_timer; /* Use counter of hpet for time keeping,
  19. * otherwise PIT
  20. */
  21. unsigned int do_gettimeoffset_hpet(void)
  22. {
  23. /* cap counter read to one tick to avoid inconsistencies */
  24. unsigned long counter = hpet_readl(HPET_COUNTER) - vxtime.last;
  25. return (min(counter,hpet_tick) * vxtime.quot) >> US_SCALE;
  26. }
  27. #ifdef CONFIG_HPET
  28. static __init int late_hpet_init(void)
  29. {
  30. struct hpet_data hd;
  31. unsigned int ntimer;
  32. if (!hpet_address)
  33. return 0;
  34. memset(&hd, 0, sizeof(hd));
  35. ntimer = hpet_readl(HPET_ID);
  36. ntimer = (ntimer & HPET_ID_NUMBER) >> HPET_ID_NUMBER_SHIFT;
  37. ntimer++;
  38. /*
  39. * Register with driver.
  40. * Timer0 and Timer1 is used by platform.
  41. */
  42. hd.hd_phys_address = hpet_address;
  43. hd.hd_address = (void __iomem *)fix_to_virt(FIX_HPET_BASE);
  44. hd.hd_nirqs = ntimer;
  45. hd.hd_flags = HPET_DATA_PLATFORM;
  46. hpet_reserve_timer(&hd, 0);
  47. #ifdef CONFIG_HPET_EMULATE_RTC
  48. hpet_reserve_timer(&hd, 1);
  49. #endif
  50. hd.hd_irq[0] = HPET_LEGACY_8254;
  51. hd.hd_irq[1] = HPET_LEGACY_RTC;
  52. if (ntimer > 2) {
  53. struct hpet *hpet;
  54. struct hpet_timer *timer;
  55. int i;
  56. hpet = (struct hpet *) fix_to_virt(FIX_HPET_BASE);
  57. timer = &hpet->hpet_timers[2];
  58. for (i = 2; i < ntimer; timer++, i++)
  59. hd.hd_irq[i] = (timer->hpet_config &
  60. Tn_INT_ROUTE_CNF_MASK) >>
  61. Tn_INT_ROUTE_CNF_SHIFT;
  62. }
  63. hpet_alloc(&hd);
  64. return 0;
  65. }
  66. fs_initcall(late_hpet_init);
  67. #endif
  68. int hpet_timer_stop_set_go(unsigned long tick)
  69. {
  70. unsigned int cfg;
  71. /*
  72. * Stop the timers and reset the main counter.
  73. */
  74. cfg = hpet_readl(HPET_CFG);
  75. cfg &= ~(HPET_CFG_ENABLE | HPET_CFG_LEGACY);
  76. hpet_writel(cfg, HPET_CFG);
  77. hpet_writel(0, HPET_COUNTER);
  78. hpet_writel(0, HPET_COUNTER + 4);
  79. /*
  80. * Set up timer 0, as periodic with first interrupt to happen at hpet_tick,
  81. * and period also hpet_tick.
  82. */
  83. if (hpet_use_timer) {
  84. hpet_writel(HPET_TN_ENABLE | HPET_TN_PERIODIC | HPET_TN_SETVAL |
  85. HPET_TN_32BIT, HPET_T0_CFG);
  86. hpet_writel(hpet_tick, HPET_T0_CMP); /* next interrupt */
  87. hpet_writel(hpet_tick, HPET_T0_CMP); /* period */
  88. cfg |= HPET_CFG_LEGACY;
  89. }
  90. /*
  91. * Go!
  92. */
  93. cfg |= HPET_CFG_ENABLE;
  94. hpet_writel(cfg, HPET_CFG);
  95. return 0;
  96. }
  97. int hpet_arch_init(void)
  98. {
  99. unsigned int id;
  100. if (!hpet_address)
  101. return -1;
  102. set_fixmap_nocache(FIX_HPET_BASE, hpet_address);
  103. __set_fixmap(VSYSCALL_HPET, hpet_address, PAGE_KERNEL_VSYSCALL_NOCACHE);
  104. /*
  105. * Read the period, compute tick and quotient.
  106. */
  107. id = hpet_readl(HPET_ID);
  108. if (!(id & HPET_ID_VENDOR) || !(id & HPET_ID_NUMBER))
  109. return -1;
  110. hpet_period = hpet_readl(HPET_PERIOD);
  111. if (hpet_period < 100000 || hpet_period > 100000000)
  112. return -1;
  113. hpet_tick = (FSEC_PER_TICK + hpet_period / 2) / hpet_period;
  114. hpet_use_timer = (id & HPET_ID_LEGSUP);
  115. return hpet_timer_stop_set_go(hpet_tick);
  116. }
  117. int hpet_reenable(void)
  118. {
  119. return hpet_timer_stop_set_go(hpet_tick);
  120. }
  121. /*
  122. * calibrate_tsc() calibrates the processor TSC in a very simple way, comparing
  123. * it to the HPET timer of known frequency.
  124. */
  125. #define TICK_COUNT 100000000
  126. #define TICK_MIN 5000
  127. /*
  128. * Some platforms take periodic SMI interrupts with 5ms duration. Make sure none
  129. * occurs between the reads of the hpet & TSC.
  130. */
  131. static void __init read_hpet_tsc(int *hpet, int *tsc)
  132. {
  133. int tsc1, tsc2, hpet1;
  134. do {
  135. tsc1 = get_cycles_sync();
  136. hpet1 = hpet_readl(HPET_COUNTER);
  137. tsc2 = get_cycles_sync();
  138. } while (tsc2 - tsc1 > TICK_MIN);
  139. *hpet = hpet1;
  140. *tsc = tsc2;
  141. }
  142. unsigned int __init hpet_calibrate_tsc(void)
  143. {
  144. int tsc_start, hpet_start;
  145. int tsc_now, hpet_now;
  146. unsigned long flags;
  147. local_irq_save(flags);
  148. read_hpet_tsc(&hpet_start, &tsc_start);
  149. do {
  150. local_irq_disable();
  151. read_hpet_tsc(&hpet_now, &tsc_now);
  152. local_irq_restore(flags);
  153. } while ((tsc_now - tsc_start) < TICK_COUNT &&
  154. (hpet_now - hpet_start) < TICK_COUNT);
  155. return (tsc_now - tsc_start) * 1000000000L
  156. / ((hpet_now - hpet_start) * hpet_period / 1000);
  157. }
  158. #ifdef CONFIG_HPET_EMULATE_RTC
  159. /* HPET in LegacyReplacement Mode eats up RTC interrupt line. When, HPET
  160. * is enabled, we support RTC interrupt functionality in software.
  161. * RTC has 3 kinds of interrupts:
  162. * 1) Update Interrupt - generate an interrupt, every sec, when RTC clock
  163. * is updated
  164. * 2) Alarm Interrupt - generate an interrupt at a specific time of day
  165. * 3) Periodic Interrupt - generate periodic interrupt, with frequencies
  166. * 2Hz-8192Hz (2Hz-64Hz for non-root user) (all freqs in powers of 2)
  167. * (1) and (2) above are implemented using polling at a frequency of
  168. * 64 Hz. The exact frequency is a tradeoff between accuracy and interrupt
  169. * overhead. (DEFAULT_RTC_INT_FREQ)
  170. * For (3), we use interrupts at 64Hz or user specified periodic
  171. * frequency, whichever is higher.
  172. */
  173. #include <linux/rtc.h>
  174. #define DEFAULT_RTC_INT_FREQ 64
  175. #define RTC_NUM_INTS 1
  176. static unsigned long UIE_on;
  177. static unsigned long prev_update_sec;
  178. static unsigned long AIE_on;
  179. static struct rtc_time alarm_time;
  180. static unsigned long PIE_on;
  181. static unsigned long PIE_freq = DEFAULT_RTC_INT_FREQ;
  182. static unsigned long PIE_count;
  183. static unsigned long hpet_rtc_int_freq; /* RTC interrupt frequency */
  184. static unsigned int hpet_t1_cmp; /* cached comparator register */
  185. int is_hpet_enabled(void)
  186. {
  187. return hpet_address != 0;
  188. }
  189. /*
  190. * Timer 1 for RTC, we do not use periodic interrupt feature,
  191. * even if HPET supports periodic interrupts on Timer 1.
  192. * The reason being, to set up a periodic interrupt in HPET, we need to
  193. * stop the main counter. And if we do that everytime someone diables/enables
  194. * RTC, we will have adverse effect on main kernel timer running on Timer 0.
  195. * So, for the time being, simulate the periodic interrupt in software.
  196. *
  197. * hpet_rtc_timer_init() is called for the first time and during subsequent
  198. * interuppts reinit happens through hpet_rtc_timer_reinit().
  199. */
  200. int hpet_rtc_timer_init(void)
  201. {
  202. unsigned int cfg, cnt;
  203. unsigned long flags;
  204. if (!is_hpet_enabled())
  205. return 0;
  206. /*
  207. * Set the counter 1 and enable the interrupts.
  208. */
  209. if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
  210. hpet_rtc_int_freq = PIE_freq;
  211. else
  212. hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
  213. local_irq_save(flags);
  214. cnt = hpet_readl(HPET_COUNTER);
  215. cnt += ((hpet_tick*HZ)/hpet_rtc_int_freq);
  216. hpet_writel(cnt, HPET_T1_CMP);
  217. hpet_t1_cmp = cnt;
  218. cfg = hpet_readl(HPET_T1_CFG);
  219. cfg &= ~HPET_TN_PERIODIC;
  220. cfg |= HPET_TN_ENABLE | HPET_TN_32BIT;
  221. hpet_writel(cfg, HPET_T1_CFG);
  222. local_irq_restore(flags);
  223. return 1;
  224. }
  225. static void hpet_rtc_timer_reinit(void)
  226. {
  227. unsigned int cfg, cnt, ticks_per_int, lost_ints;
  228. if (unlikely(!(PIE_on | AIE_on | UIE_on))) {
  229. cfg = hpet_readl(HPET_T1_CFG);
  230. cfg &= ~HPET_TN_ENABLE;
  231. hpet_writel(cfg, HPET_T1_CFG);
  232. return;
  233. }
  234. if (PIE_on && (PIE_freq > DEFAULT_RTC_INT_FREQ))
  235. hpet_rtc_int_freq = PIE_freq;
  236. else
  237. hpet_rtc_int_freq = DEFAULT_RTC_INT_FREQ;
  238. /* It is more accurate to use the comparator value than current count.*/
  239. ticks_per_int = hpet_tick * HZ / hpet_rtc_int_freq;
  240. hpet_t1_cmp += ticks_per_int;
  241. hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
  242. /*
  243. * If the interrupt handler was delayed too long, the write above tries
  244. * to schedule the next interrupt in the past and the hardware would
  245. * not interrupt until the counter had wrapped around.
  246. * So we have to check that the comparator wasn't set to a past time.
  247. */
  248. cnt = hpet_readl(HPET_COUNTER);
  249. if (unlikely((int)(cnt - hpet_t1_cmp) > 0)) {
  250. lost_ints = (cnt - hpet_t1_cmp) / ticks_per_int + 1;
  251. /* Make sure that, even with the time needed to execute
  252. * this code, the next scheduled interrupt has been moved
  253. * back to the future: */
  254. lost_ints++;
  255. hpet_t1_cmp += lost_ints * ticks_per_int;
  256. hpet_writel(hpet_t1_cmp, HPET_T1_CMP);
  257. if (PIE_on)
  258. PIE_count += lost_ints;
  259. if (printk_ratelimit())
  260. printk(KERN_WARNING "rtc: lost some interrupts at %ldHz.\n",
  261. hpet_rtc_int_freq);
  262. }
  263. }
  264. /*
  265. * The functions below are called from rtc driver.
  266. * Return 0 if HPET is not being used.
  267. * Otherwise do the necessary changes and return 1.
  268. */
  269. int hpet_mask_rtc_irq_bit(unsigned long bit_mask)
  270. {
  271. if (!is_hpet_enabled())
  272. return 0;
  273. if (bit_mask & RTC_UIE)
  274. UIE_on = 0;
  275. if (bit_mask & RTC_PIE)
  276. PIE_on = 0;
  277. if (bit_mask & RTC_AIE)
  278. AIE_on = 0;
  279. return 1;
  280. }
  281. int hpet_set_rtc_irq_bit(unsigned long bit_mask)
  282. {
  283. int timer_init_reqd = 0;
  284. if (!is_hpet_enabled())
  285. return 0;
  286. if (!(PIE_on | AIE_on | UIE_on))
  287. timer_init_reqd = 1;
  288. if (bit_mask & RTC_UIE) {
  289. UIE_on = 1;
  290. }
  291. if (bit_mask & RTC_PIE) {
  292. PIE_on = 1;
  293. PIE_count = 0;
  294. }
  295. if (bit_mask & RTC_AIE) {
  296. AIE_on = 1;
  297. }
  298. if (timer_init_reqd)
  299. hpet_rtc_timer_init();
  300. return 1;
  301. }
  302. int hpet_set_alarm_time(unsigned char hrs, unsigned char min, unsigned char sec)
  303. {
  304. if (!is_hpet_enabled())
  305. return 0;
  306. alarm_time.tm_hour = hrs;
  307. alarm_time.tm_min = min;
  308. alarm_time.tm_sec = sec;
  309. return 1;
  310. }
  311. int hpet_set_periodic_freq(unsigned long freq)
  312. {
  313. if (!is_hpet_enabled())
  314. return 0;
  315. PIE_freq = freq;
  316. PIE_count = 0;
  317. return 1;
  318. }
  319. int hpet_rtc_dropped_irq(void)
  320. {
  321. if (!is_hpet_enabled())
  322. return 0;
  323. return 1;
  324. }
  325. irqreturn_t hpet_rtc_interrupt(int irq, void *dev_id, struct pt_regs *regs)
  326. {
  327. struct rtc_time curr_time;
  328. unsigned long rtc_int_flag = 0;
  329. int call_rtc_interrupt = 0;
  330. hpet_rtc_timer_reinit();
  331. if (UIE_on | AIE_on) {
  332. rtc_get_rtc_time(&curr_time);
  333. }
  334. if (UIE_on) {
  335. if (curr_time.tm_sec != prev_update_sec) {
  336. /* Set update int info, call real rtc int routine */
  337. call_rtc_interrupt = 1;
  338. rtc_int_flag = RTC_UF;
  339. prev_update_sec = curr_time.tm_sec;
  340. }
  341. }
  342. if (PIE_on) {
  343. PIE_count++;
  344. if (PIE_count >= hpet_rtc_int_freq/PIE_freq) {
  345. /* Set periodic int info, call real rtc int routine */
  346. call_rtc_interrupt = 1;
  347. rtc_int_flag |= RTC_PF;
  348. PIE_count = 0;
  349. }
  350. }
  351. if (AIE_on) {
  352. if ((curr_time.tm_sec == alarm_time.tm_sec) &&
  353. (curr_time.tm_min == alarm_time.tm_min) &&
  354. (curr_time.tm_hour == alarm_time.tm_hour)) {
  355. /* Set alarm int info, call real rtc int routine */
  356. call_rtc_interrupt = 1;
  357. rtc_int_flag |= RTC_AF;
  358. }
  359. }
  360. if (call_rtc_interrupt) {
  361. rtc_int_flag |= (RTC_IRQF | (RTC_NUM_INTS << 8));
  362. rtc_interrupt(rtc_int_flag, dev_id);
  363. }
  364. return IRQ_HANDLED;
  365. }
  366. #endif
  367. static int __init nohpet_setup(char *s)
  368. {
  369. nohpet = 1;
  370. return 1;
  371. }
  372. __setup("nohpet", nohpet_setup);