struct hpet __iomem *hp_hpet;
        unsigned long hp_hpet_phys;
        struct time_interpolator *hp_interpolator;
-       unsigned long hp_period;
+       unsigned long long hp_tick_freq;
        unsigned long hp_delta;
        unsigned int hp_ntimer;
        unsigned int hp_which;
        return 0;
 }
 
-static inline unsigned long hpet_time_div(unsigned long dis)
+/* converts Hz to number of timer ticks */
+static inline unsigned long hpet_time_div(struct hpets *hpets,
+                                         unsigned long dis)
 {
-       unsigned long long m = 1000000000000000ULL;
+       unsigned long long m;
 
+       m = hpets->hp_tick_freq + (dis >> 1);
        do_div(m, dis);
-
        return (unsigned long)m;
 }
 
                {
                        struct hpet_info info;
 
-                       info.hi_ireqfreq = hpet_time_div(hpetp->hp_period *
+                       info.hi_ireqfreq = hpet_time_div(hpetp,
                                                         devp->hd_ireqfreq);
                        info.hi_flags =
                            readq(&timer->hpet_config) & Tn_PER_INT_CAP_MASK;
                        break;
                }
 
-               devp->hd_ireqfreq = hpet_time_div(hpetp->hp_period * arg);
+               devp->hd_ireqfreq = hpet_time_div(hpetp, arg);
        }
 
        return err;
        ti->source = TIME_SOURCE_MMIO64;
        ti->shift = 10;
        ti->addr = &hpetp->hp_hpet->hpet_mc;
-       ti->frequency = hpet_time_div(hpets->hp_period);
+       ti->frequency = hpetp->hp_tick_freq;
        ti->drift = HPET_DRIFT;
        ti->mask = -1;
 
        t = read_counter(&timer->hpet_compare);
 
        i = 0;
-       count = hpet_time_div(hpetp->hp_period * TICK_CALIBRATE);
+       count = hpet_time_div(hpetp, TICK_CALIBRATE);
 
        local_irq_save(flags);
 
        size_t siz;
        struct hpet __iomem *hpet;
        static struct hpets *last = (struct hpets *)0;
-       unsigned long ns;
+       unsigned long ns, period;
+       unsigned long long temp;
 
        /*
         * hpet_alloc can be called by platform dependent code.
 
        last = hpetp;
 
-       hpetp->hp_period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
-           HPET_COUNTER_CLK_PERIOD_SHIFT;
+       period = (cap & HPET_COUNTER_CLK_PERIOD_MASK) >>
+               HPET_COUNTER_CLK_PERIOD_SHIFT; /* fs, 10^-15 */
+       temp = 1000000000000000uLL; /* 10^15 femtoseconds per second */
+       temp += period >> 1; /* round */
+       do_div(temp, period);
+       hpetp->hp_tick_freq = temp; /* ticks per second */
 
        printk(KERN_INFO "hpet%d: at MMIO 0x%lx, IRQ%s",
                hpetp->hp_which, hdp->hd_phys_address,
                printk("%s %d", i > 0 ? "," : "", hdp->hd_irq[i]);
        printk("\n");
 
-       ns = hpetp->hp_period;  /* femptoseconds, 10^-15 */
-       ns /= 1000000;          /* convert to nanoseconds, 10^-9 */
+       ns = period / 1000000;  /* convert to nanoseconds, 10^-9 */
        printk(KERN_INFO "hpet%d: %ldns tick, %d %d-bit timers\n",
                hpetp->hp_which, ns, hpetp->hp_ntimer,
                cap & HPET_COUNTER_SIZE_MASK ? 64 : 32);