diff options
-rw-r--r-- | drivers/char/hpet.c | 32 |
1 files changed, 19 insertions, 13 deletions
diff --git a/drivers/char/hpet.c b/drivers/char/hpet.c index b619ca5eaf8c..a1eb14e6d9f7 100644 --- a/drivers/char/hpet.c +++ b/drivers/char/hpet.c | |||
@@ -78,7 +78,7 @@ struct hpets { | |||
78 | struct hpet __iomem *hp_hpet; | 78 | struct hpet __iomem *hp_hpet; |
79 | unsigned long hp_hpet_phys; | 79 | unsigned long hp_hpet_phys; |
80 | struct time_interpolator *hp_interpolator; | 80 | struct time_interpolator *hp_interpolator; |
81 | unsigned long hp_period; | 81 | unsigned long long hp_tick_freq; |
82 | unsigned long hp_delta; | 82 | unsigned long hp_delta; |
83 | unsigned int hp_ntimer; | 83 | unsigned int hp_ntimer; |
84 | unsigned int hp_which; | 84 | unsigned int hp_which; |
@@ -427,12 +427,14 @@ static int hpet_ioctl_ieon(struct hpet_dev *devp) | |||
427 | return 0; | 427 | return 0; |
428 | } | 428 | } |
429 | 429 | ||
430 | static inline unsigned long hpet_time_div(unsigned long dis) | 430 | /* converts Hz to number of timer ticks */ |
431 | static inline unsigned long hpet_time_div(struct hpets *hpets, | ||
432 | unsigned long dis) | ||
431 | { | 433 | { |
432 | unsigned long long m = 1000000000000000ULL; | 434 | unsigned long long m; |
433 | 435 | ||
436 | m = hpets->hp_tick_freq + (dis >> 1); | ||
434 | do_div(m, dis); | 437 | do_div(m, dis); |
435 | |||
436 | return (unsigned long)m; | 438 | return (unsigned long)m; |
437 | } | 439 | } |
438 | 440 | ||
@@ -480,7 +482,7 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) | |||
480 | { | 482 | { |
481 | struct hpet_info info; | 483 | struct hpet_info info; |
482 | 484 | ||
483 | info.hi_ireqfreq = hpet_time_div(hpetp->hp_period * | 485 | info.hi_ireqfreq = hpet_time_div(hpetp, |
484 | devp->hd_ireqfreq); | 486 | devp->hd_ireqfreq); |
485 | info.hi_flags = | 487 | info.hi_flags = |
486 | readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; | 488 | readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK; |
@@ -524,7 +526,7 @@ hpet_ioctl_common(struct hpet_dev *devp, int cmd, unsigned long arg, int kernel) | |||
524 | break; | 526 | break; |
525 | } | 527 | } |
526 | 528 | ||
527 | devp->hd_ireqfreq = hpet_time_div(hpetp->hp_period * arg); | 529 | devp->hd_ireqfreq = hpet_time_div(hpetp, arg); |
528 | } | 530 | } |
529 | 531 | ||
530 | return err; | 532 | return err; |
@@ -713,7 +715,7 @@ static void hpet_register_interpolator(struct hpets *hpetp) | |||
713 | ti->source = TIME_SOURCE_MMIO64; | 715 | ti->source = TIME_SOURCE_MMIO64; |
714 | ti->shift = 10; | 716 | ti->shift = 10; |
715 | ti->addr = &hpetp->hp_hpet->hpet_mc; | 717 | ti->addr = &hpetp->hp_hpet->hpet_mc; |
716 | ti->frequency = hpet_time_div(hpets->hp_period); | 718 | ti->frequency = hpetp->hp_tick_freq; |
717 | ti->drift = HPET_DRIFT; | 719 | ti->drift = HPET_DRIFT; |
718 | ti->mask = -1; | 720 | ti->mask = -1; |
719 | 721 | ||
@@ -750,7 +752,7 @@ static unsigned long hpet_calibrate(struct hpets *hpetp) | |||
750 | t = read_counter(&timer->hpet_compare); | 752 | t = read_counter(&timer->hpet_compare); |
751 | 753 | ||
752 | i = 0; | 754 | i = 0; |
753 | count = hpet_time_div(hpetp->hp_period * TICK_CALIBRATE); | 755 | count = hpet_time_div(hpetp, TICK_CALIBRATE); |
754 | 756 | ||
755 | local_irq_save(flags); | 757 | local_irq_save(flags); |
756 | 758 | ||
@@ -775,7 +777,8 @@ int hpet_alloc(struct hpet_data *hdp) | |||
775 | size_t siz; | 777 | size_t siz; |
776 | struct hpet __iomem *hpet; | 778 | struct hpet __iomem *hpet; |
777 | static struct hpets *last = (struct hpets *)0; | 779 | static struct hpets *last = (struct hpets *)0; |
778 | unsigned long ns; | 780 | unsigned long ns, period; |
781 | unsigned long long temp; | ||
779 | 782 | ||
780 | /* | 783 | /* |
781 | * hpet_alloc can be called by platform dependent code. | 784 | * hpet_alloc can be called by platform dependent code. |
@@ -825,8 +828,12 @@ int hpet_alloc(struct hpet_data *hdp) | |||
825 | 828 | ||
826 | last = hpetp; | 829 | last = hpetp; |
827 | 830 | ||
828 | hpetp->hp_period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >> | 831 | period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >> |
829 | HPET_COUNTER_CLK_PERIOD_SHIFT; | 832 | HPET_COUNTER_CLK_PERIOD_SHIFT; /* fs, 10^-15 */ |
833 | temp = 1000000000000000uLL; /* 10^15 femtoseconds per second */ | ||
834 | temp += period >> 1; /* round */ | ||
835 | do_div(temp, period); | ||
836 | hpetp->hp_tick_freq = temp; /* ticks per second */ | ||
830 | 837 | ||
831 | printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s", | 838 | printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s", |
832 | hpetp->hp_which, hdp->hd_phys_address, | 839 | hpetp->hp_which, hdp->hd_phys_address, |
@@ -835,8 +842,7 @@ int hpet_alloc(struct hpet_data *hdp) | |||
835 | printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); | 842 | printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]); |
836 | printk("\n"); | 843 | printk("\n"); |
837 | 844 | ||
838 | ns = hpetp->hp_period; /* femptoseconds, 10^-15 */ | 845 | ns = period / 1000000; /* convert to nanoseconds, 10^-9 */ |
839 | ns /= 1000000; /* convert to nanoseconds, 10^-9 */ | ||
840 | printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n", | 846 | printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n", |
841 | hpetp->hp_which, ns, hpetp->hp_ntimer, | 847 | hpetp->hp_which, ns, hpetp->hp_ntimer, |
842 | cap & HPET_COUNTER_SIZE_MASK ? 64 : 32); | 848 | cap & HPET_COUNTER_SIZE_MASK ? 64 : 32); |