timer.c 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475
  1. #include <linux/init.h>
  2. #include <linux/kernel.h>
  3. #include <linux/string.h>
  4. #include <asm/timer.h>
  5. #ifdef CONFIG_HPET_TIMER
  6. /*
  7. * HPET memory read is slower than tsc reads, but is more dependable as it
  8. * always runs at constant frequency and reduces complexity due to
  9. * cpufreq. So, we prefer HPET timer to tsc based one. Also, we cannot use
  10. * timer_pit when HPET is active. So, we default to timer_tsc.
  11. */
  12. #endif
  13. /* list of timers, ordered by preference, NULL terminated */
  14. static struct init_timer_opts* __initdata timers[] = {
  15. #ifdef CONFIG_X86_CYCLONE_TIMER
  16. &timer_cyclone_init,
  17. #endif
  18. #ifdef CONFIG_HPET_TIMER
  19. &timer_hpet_init,
  20. #endif
  21. #ifdef CONFIG_X86_PM_TIMER
  22. &timer_pmtmr_init,
  23. #endif
  24. &timer_tsc_init,
  25. &timer_pit_init,
  26. NULL,
  27. };
  28. static char clock_override[10] __initdata;
  29. static int __init clock_setup(char* str)
  30. {
  31. if (str)
  32. strlcpy(clock_override, str, sizeof(clock_override));
  33. return 1;
  34. }
  35. __setup("clock=", clock_setup);
  36. /* The chosen timesource has been found to be bad.
  37. * Fall back to a known good timesource (the PIT)
  38. */
  39. void clock_fallback(void)
  40. {
  41. cur_timer = &timer_pit;
  42. }
  43. /* iterates through the list of timers, returning the first
  44. * one that initializes successfully.
  45. */
  46. struct timer_opts* __init select_timer(void)
  47. {
  48. int i = 0;
  49. /* find most preferred working timer */
  50. while (timers[i]) {
  51. if (timers[i]->init)
  52. if (timers[i]->init(clock_override) == 0)
  53. return timers[i]->opts;
  54. ++i;
  55. }
  56. panic("select_timer: Cannot find a suitable timer\n");
  57. return NULL;
  58. }
  59. int read_current_timer(unsigned long *timer_val)
  60. {
  61. if (cur_timer->read_timer) {
  62. *timer_val = cur_timer->read_timer();
  63. return 0;
  64. }
  65. return -1;
  66. }