hpet.c 1.6 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172
  1. #include <linux/clocksource.h>
  2. #include <linux/errno.h>
  3. #include <linux/hpet.h>
  4. #include <linux/init.h>
  5. #include <asm/hpet.h>
  6. #include <asm/io.h>
  7. #define HPET_MASK CLOCKSOURCE_MASK(32)
  8. #define HPET_SHIFT 22
  9. /* FSEC = 10^-15 NSEC = 10^-9 */
  10. #define FSEC_PER_NSEC 1000000
  11. static void *hpet_ptr;
  12. static cycle_t read_hpet(void)
  13. {
  14. return (cycle_t)readl(hpet_ptr);
  15. }
  16. static struct clocksource clocksource_hpet = {
  17. .name = "hpet",
  18. .rating = 250,
  19. .read = read_hpet,
  20. .mask = HPET_MASK,
  21. .mult = 0, /* set below */
  22. .shift = HPET_SHIFT,
  23. .is_continuous = 1,
  24. };
  25. static int __init init_hpet_clocksource(void)
  26. {
  27. unsigned long hpet_period;
  28. void __iomem* hpet_base;
  29. u64 tmp;
  30. int err;
  31. if (!is_hpet_enabled())
  32. return -ENODEV;
  33. /* calculate the hpet address: */
  34. hpet_base =
  35. (void __iomem*)ioremap_nocache(hpet_address, HPET_MMAP_SIZE);
  36. hpet_ptr = hpet_base + HPET_COUNTER;
  37. /* calculate the frequency: */
  38. hpet_period = readl(hpet_base + HPET_PERIOD);
  39. /*
  40. * hpet period is in femto seconds per cycle
  41. * so we need to convert this to ns/cyc units
  42. * aproximated by mult/2^shift
  43. *
  44. * fsec/cyc * 1nsec/1000000fsec = nsec/cyc = mult/2^shift
  45. * fsec/cyc * 1ns/1000000fsec * 2^shift = mult
  46. * fsec/cyc * 2^shift * 1nsec/1000000fsec = mult
  47. * (fsec/cyc << shift)/1000000 = mult
  48. * (hpet_period << shift)/FSEC_PER_NSEC = mult
  49. */
  50. tmp = (u64)hpet_period << HPET_SHIFT;
  51. do_div(tmp, FSEC_PER_NSEC);
  52. clocksource_hpet.mult = (u32)tmp;
  53. err = clocksource_register(&clocksource_hpet);
  54. if (err)
  55. iounmap(hpet_base);
  56. return err;
  57. }
  58. module_init(init_hpet_clocksource);