#include <asm/hpet.h>
#include <linux/hpet.h>
-unsigned long hpet_period; /* fsecs / HPET clock */
-unsigned long hpet_tick; /* hpet clks count per tick */
-unsigned long hpet_address; /* hpet memory map physical address */
+static unsigned long hpet_period; /* fsecs / HPET clock */
+unsigned long hpet_tick; /* hpet clks count per tick */
+unsigned long hpet_address; /* hpet memory map physical address */
+int hpet_use_timer;
static int use_hpet; /* can be used for runtime check of hpet */
static int boot_hpet_disable; /* boottime override for HPET timer */
return readl(hpet_virt_address + a);
}
-void hpet_writel(unsigned long d, unsigned long a)
+static void hpet_writel(unsigned long d, unsigned long a)
{
writel(d, hpet_virt_address + a);
}
* comparator value and continue. Next tick can be caught by checking
* for a change in the comparator value. Used in apic.c.
*/
-void __init wait_hpet_tick(void)
+static void __init wait_hpet_tick(void)
{
unsigned int start_cmp_val, end_cmp_val;
hpet_writel(0, HPET_COUNTER);
hpet_writel(0, HPET_COUNTER + 4);
- /*
- * Set up timer 0, as periodic with first interrupt to happen at
- * hpet_tick, and period also hpet_tick.
- */
- cfg = hpet_readl(HPET_T0_CFG);
- cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
- HPET_TN_SETVAL | HPET_TN_32BIT;
- hpet_writel(cfg, HPET_T0_CFG);
- /*
- * Some systems seems to need two writes to HPET_T0_CMP,
- * to get interrupts working
- */
- hpet_writel(tick, HPET_T0_CMP);
- hpet_writel(tick, HPET_T0_CMP);
+ if (hpet_use_timer) {
+ /*
+ * Set up timer 0, as periodic with first interrupt to happen at
+ * hpet_tick, and period also hpet_tick.
+ */
+ cfg = hpet_readl(HPET_T0_CFG);
+ cfg |= HPET_TN_ENABLE | HPET_TN_PERIODIC |
+ HPET_TN_SETVAL | HPET_TN_32BIT;
+ hpet_writel(cfg, HPET_T0_CFG);
+ /*
+ * The first write after writing TN_SETVAL to the config register sets
+ * the counter value, the second write sets the threshold.
+ */
+ hpet_writel(tick, HPET_T0_CMP);
+ hpet_writel(tick, HPET_T0_CMP);
+ }
/*
* Go!
*/
cfg = hpet_readl(HPET_CFG);
- cfg |= HPET_CFG_ENABLE | HPET_CFG_LEGACY;
+ if (hpet_use_timer)
+ cfg |= HPET_CFG_LEGACY;
+ cfg |= HPET_CFG_ENABLE;
hpet_writel(cfg, HPET_CFG);
return 0;
id = hpet_readl(HPET_ID);
/*
- * We are checking for value '1' or more in number field.
- * So, we are OK with HPET_EMULATE_RTC part too, where we need
- * to have atleast 2 timers.
+ * We are checking for value '1' or more in number field if
+ * CONFIG_HPET_EMULATE_RTC is set because we will need an
+ * additional timer for RTC emulation.
+ * However, we can do with one timer otherwise using the
+ * the single HPET timer for system time.
*/
- if (!(id & HPET_ID_NUMBER) ||
- !(id & HPET_ID_LEGSUP))
+#ifdef CONFIG_HPET_EMULATE_RTC
+ if (!(id & HPET_ID_NUMBER))
return -1;
+#endif
+
hpet_period = hpet_readl(HPET_PERIOD);
if ((hpet_period < HPET_MIN_PERIOD) || (hpet_period > HPET_MAX_PERIOD))
if (hpet_tick_rem > (hpet_period >> 1))
hpet_tick++; /* rounding the result */
+ hpet_use_timer = id & HPET_ID_LEGSUP;
+
if (hpet_timer_stop_set_go(hpet_tick))
return -1;
#endif
#ifdef CONFIG_X86_LOCAL_APIC
- wait_timer_tick = wait_hpet_tick;
+ if (hpet_use_timer)
+ wait_timer_tick = wait_hpet_tick;
#endif
return 0;
}