|
@@ -27,6 +27,9 @@
|
|
#define HPET_DEV_FSB_CAP 0x1000
|
|
#define HPET_DEV_FSB_CAP 0x1000
|
|
#define HPET_DEV_PERI_CAP 0x2000
|
|
#define HPET_DEV_PERI_CAP 0x2000
|
|
|
|
|
|
|
|
+#define HPET_MIN_CYCLES 128
|
|
|
|
+#define HPET_MIN_PROG_DELTA (HPET_MIN_CYCLES + (HPET_MIN_CYCLES >> 1))
|
|
|
|
+
|
|
#define EVT_TO_HPET_DEV(evt) container_of(evt, struct hpet_dev, evt)
|
|
#define EVT_TO_HPET_DEV(evt) container_of(evt, struct hpet_dev, evt)
|
|
|
|
|
|
/*
|
|
/*
|
|
@@ -299,8 +302,9 @@ static void hpet_legacy_clockevent_register(void)
|
|
/* Calculate the min / max delta */
|
|
/* Calculate the min / max delta */
|
|
hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
|
|
hpet_clockevent.max_delta_ns = clockevent_delta2ns(0x7FFFFFFF,
|
|
&hpet_clockevent);
|
|
&hpet_clockevent);
|
|
- /* 5 usec minimum reprogramming delta. */
|
|
|
|
- hpet_clockevent.min_delta_ns = 5000;
|
|
|
|
|
|
+ /* Setup minimum reprogramming delta. */
|
|
|
|
+ hpet_clockevent.min_delta_ns = clockevent_delta2ns(HPET_MIN_PROG_DELTA,
|
|
|
|
+ &hpet_clockevent);
|
|
|
|
|
|
/*
|
|
/*
|
|
* Start hpet with the boot cpu mask and make it
|
|
* Start hpet with the boot cpu mask and make it
|
|
@@ -393,22 +397,24 @@ static int hpet_next_event(unsigned long delta,
|
|
* the wraparound into account) nor a simple count down event
|
|
* the wraparound into account) nor a simple count down event
|
|
* mode. Further the write to the comparator register is
|
|
* mode. Further the write to the comparator register is
|
|
* delayed internally up to two HPET clock cycles in certain
|
|
* delayed internally up to two HPET clock cycles in certain
|
|
- * chipsets (ATI, ICH9,10). We worked around that by reading
|
|
|
|
- * back the compare register, but that required another
|
|
|
|
- * workaround for ICH9,10 chips where the first readout after
|
|
|
|
- * write can return the old stale value. We already have a
|
|
|
|
- * minimum delta of 5us enforced, but a NMI or SMI hitting
|
|
|
|
|
|
+ * chipsets (ATI, ICH9,10). Some newer AMD chipsets have even
|
|
|
|
+ * longer delays. We worked around that by reading back the
|
|
|
|
+ * compare register, but that required another workaround for
|
|
|
|
+ * ICH9,10 chips where the first readout after write can
|
|
|
|
+ * return the old stale value. We already had a minimum
|
|
|
|
+ * programming delta of 5us enforced, but a NMI or SMI hitting
|
|
* between the counter readout and the comparator write can
|
|
* between the counter readout and the comparator write can
|
|
* move us behind that point easily. Now instead of reading
|
|
* move us behind that point easily. Now instead of reading
|
|
* the compare register back several times, we make the ETIME
|
|
* the compare register back several times, we make the ETIME
|
|
* decision based on the following: Return ETIME if the
|
|
* decision based on the following: Return ETIME if the
|
|
- * counter value after the write is less than 8 HPET cycles
|
|
|
|
|
|
+ * counter value after the write is less than HPET_MIN_CYCLES
|
|
* away from the event or if the counter is already ahead of
|
|
* away from the event or if the counter is already ahead of
|
|
- * the event.
|
|
|
|
|
|
+ * the event. The minimum programming delta for the generic
|
|
|
|
+ * clockevents code is set to 1.5 * HPET_MIN_CYCLES.
|
|
*/
|
|
*/
|
|
res = (s32)(cnt - hpet_readl(HPET_COUNTER));
|
|
res = (s32)(cnt - hpet_readl(HPET_COUNTER));
|
|
|
|
|
|
- return res < 8 ? -ETIME : 0;
|
|
|
|
|
|
+ return res < HPET_MIN_CYCLES ? -ETIME : 0;
|
|
}
|
|
}
|
|
|
|
|
|
static void hpet_legacy_set_mode(enum clock_event_mode mode,
|
|
static void hpet_legacy_set_mode(enum clock_event_mode mode,
|