return PVOP_CALL1(int, pv_time_ops.set_wallclock, nowtime);
}
-static inline void (*choose_time_init(void))(void)
-{
- return pv_time_ops.time_init;
-}
-
/* The paravirtualized CPUID instruction. */
static inline void __cpuid(unsigned int *eax, unsigned int *ebx,
unsigned int *ecx, unsigned int *edx)
};
struct pv_time_ops {
- void (*time_init)(void);
-
/* Set and set time of day */
unsigned long (*get_wallclock)(void);
int (*set_wallclock)(unsigned long);
#define COMMAND_LINE_SIZE 2048
-#ifndef __ASSEMBLY__
-
-#include <asm/x86_init.h>
-
-/*
- * Any setup quirks to be performed?
- */
-
-struct x86_quirks {
- int (*arch_pre_time_init)(void);
- int (*arch_time_init)(void);
-};
-
-extern void x86_quirk_pre_time_init(void);
-extern void x86_quirk_time_init(void);
-
-#endif /* __ASSEMBLY__ */
-
#ifdef __i386__
#include <linux/pfn.h>
#ifndef __ASSEMBLY__
#include <asm/bootparam.h>
+#include <asm/x86_init.h>
/* Interrupt control for vSMPowered x86_64 systems */
#ifdef CONFIG_X86_64
static inline int is_visws_box(void) { return 0; }
#endif
-extern struct x86_quirks *x86_quirks;
extern unsigned long saved_video_mode;
extern void reserve_standard_io_resources(void);
extern void i386_reserve_resources(void);
+extern void setup_default_timer_irq(void);
#ifndef _SETUP
#define get_wallclock() native_get_wallclock()
#define set_wallclock(x) native_set_wallclock(x)
-#define choose_time_init() hpet_time_init
#endif /* CONFIG_PARAVIRT */
#ifdef CONFIG_X86_32
extern int timer_ack;
-extern irqreturn_t timer_interrupt(int irq, void *dev_id);
-#endif /* CONFIG_X86_32 */
+#endif
extern int recalibrate_cpu_khz(void);
extern int no_timer_check;
* struct x86_init_timers - platform specific timer setup
* @setup_perpcu_clockev: set up the per cpu clock event device for the
* boot cpu
+ * @tsc_pre_init: platform function called before TSC init
+ * @timer_init: initialize the platform timer (default PIT/HPET)
*/
struct x86_init_timers {
void (*setup_percpu_clockev)(void);
+ void (*tsc_pre_init)(void);
+ void (*timer_init)(void);
};
/**
}
}
-static int __init numaq_pre_time_init(void)
+static void __init numaq_tsc_init(void)
{
numaq_tsc_disable();
- return 0;
}
static inline int generate_logical_apicid(int quad, int phys_apicid)
}
}
-static struct x86_quirks numaq_x86_quirks __initdata = {
- .arch_pre_time_init = numaq_pre_time_init,
- .arch_time_init = NULL,
-};
-
static __init void early_check_numaq(void)
{
/*
early_get_smp_config();
if (found_numaq) {
- x86_quirks = &numaq_x86_quirks;
x86_init.mpparse.mpc_record = numaq_mpc_record;
x86_init.mpparse.setup_ioapic_ids = x86_init_noop;
x86_init.mpparse.mpc_apic_id = mpc_apic_id;
x86_init.mpparse.smp_read_mpc_oem = smp_read_mpc_oem;
x86_init.mpparse.mpc_oem_pci_bus = mpc_oem_pci_bus;
x86_init.mpparse.mpc_oem_bus_info = mpc_oem_bus_info;
+ x86_init.timers.tsc_pre_init = numaq_tsc_init;
}
}
};
struct pv_time_ops pv_time_ops = {
- .time_init = hpet_time_init,
.get_wallclock = native_get_wallclock,
.set_wallclock = native_set_wallclock,
.sched_clock = native_sched_clock,
early_param("elfcorehdr", setup_elfcorehdr);
#endif
-static struct x86_quirks default_x86_quirks __initdata;
-
-struct x86_quirks *x86_quirks __initdata = &default_x86_quirks;
-
#ifdef CONFIG_X86_RESERVE_LOW_64K
static int __init dmi_low_memory_corruption(const struct dmi_system_id *d)
{
#ifdef CONFIG_X86_32
-static struct irqaction irq0 = {
- .handler = timer_interrupt,
- .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
- .name = "timer"
-};
-
-/**
- * x86_quirk_pre_time_init - do any specific initialisations before.
- *
- **/
-void __init x86_quirk_pre_time_init(void)
-{
- if (x86_quirks->arch_pre_time_init)
- x86_quirks->arch_pre_time_init();
-}
-
-/**
- * x86_quirk_time_init - do any specific initialisations for the system timer.
- *
- * Description:
- * Must plug the system timer interrupt source at HZ into the IRQ listed
- * in irq_vectors.h:TIMER_IRQ
- **/
-void __init x86_quirk_time_init(void)
-{
- if (x86_quirks->arch_time_init) {
- /*
- * A nonzero return code does not mean failure, it means
- * that the architecture quirk does not want any
- * generic (timer) setup to be performed after this:
- */
- if (x86_quirks->arch_time_init())
- return;
- }
-
- irq0.mask = cpumask_of_cpu(0);
- setup_irq(0, &irq0);
-}
-
static struct resource video_ram_resource = {
.name = "Video RAM area",
.start = 0xa0000,
* Time Stamp Counter value at the time of the timer interrupt, so that
* we later on can estimate the time of day more exactly.
*/
-irqreturn_t timer_interrupt(int irq, void *dev_id)
+static irqreturn_t timer_interrupt(int irq, void *dev_id)
{
/* Keep nmi watchdog up to date */
inc_irq_stat(irq0_irqs);
return IRQ_HANDLED;
}
-/* Duplicate of time_init() below, with hpet_enable part added */
+static struct irqaction irq0 = {
+ .handler = timer_interrupt,
+ .flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL | IRQF_TIMER,
+ .name = "timer"
+};
+
+void __init setup_default_timer_irq(void)
+{
+ irq0.mask = cpumask_of_cpu(0);
+ setup_irq(0, &irq0);
+}
+
+/* Default timer init function */
void __init hpet_time_init(void)
{
if (!hpet_enable())
setup_pit_timer();
- x86_quirk_time_init();
+ setup_default_timer_irq();
+}
+
+static void x86_late_time_init(void)
+{
+ x86_init.timers.timer_init();
}
/*
- * This is called directly from init code; we must delay timer setup in the
- * HPET case as we can't make the decision to turn on HPET this early in the
- * boot process.
- *
- * The chosen time_init function will usually be hpet_time_init, above, but
- * in the case of virtual hardware, an alternative function may be substituted.
+ * Initialize TSC and delay the periodic timer init to
+ * late x86_late_time_init() so ioremap works.
*/
void __init time_init(void)
{
- x86_quirk_pre_time_init();
tsc_init();
- late_time_init = choose_time_init();
+ late_time_init = x86_late_time_init;
}
#include <linux/mca.h>
#include <linux/nmi.h>
+#include <asm/x86_init.h>
#include <asm/i8253.h>
#include <asm/hpet.h>
#include <asm/vgtod.h>
setup_irq(0, &irq0);
}
+static void x86_late_time_init(void)
+{
+ x86_init.timers.timer_init();
+}
+
void __init time_init(void)
{
tsc_init();
-
- late_time_init = choose_time_init();
+ late_time_init = x86_late_time_init;
}
u64 lpj;
int cpu;
+ x86_init.timers.tsc_pre_init();
+
if (!cpu_has_tsc)
return;
#include <asm/setup.h>
#include <asm/apic.h>
#include <asm/e820.h>
+#include <asm/time.h>
#include <asm/io.h>
#include <linux/kernel_stat.h>
return visws_board_type >= 0;
}
-static int __init visws_time_init(void)
+static void __init visws_time_init(void)
{
printk(KERN_INFO "Starting Cobalt Timer system clock\n");
/* Enable (unmask) the timer interrupt */
co_cpu_write(CO_CPU_CTRL, co_cpu_read(CO_CPU_CTRL) & ~CO_CTRL_TIMEMASK);
- /*
- * Zero return means the generic timer setup code will set up
- * the standard vector:
- */
- return 0;
+ setup_default_timer_irq();
}
/* Replaces the default init_ISA_irqs in the generic setup */
static void visws_trap_init(void);
-static struct x86_quirks visws_x86_quirks __initdata = {
- .arch_time_init = visws_time_init,
-};
-
void __init visws_early_detect(void)
{
int raw;
return;
/*
- * Install special quirks for timer, interrupt and memory setup:
- * Fall back to generic behavior for traps:
- * Override generic MP-table parsing:
+ * Override the default platform setup functions
*/
- x86_quirks = &visws_x86_quirks;
-
x86_init.resources.memory_setup = visws_memory_setup;
x86_init.mpparse.get_smp_config = visws_get_smp_config;
x86_init.mpparse.find_smp_config = visws_find_smp_config;
x86_init.irqs.pre_vector_init = visws_pre_intr_init;
x86_init.irqs.trap_init = visws_trap_init;
+ x86_init.timers.timer_init = visws_time_init;
/*
* Install reboot quirks:
vmi_timer_ops.set_alarm = vmi_get_function(VMI_CALL_SetAlarm);
vmi_timer_ops.cancel_alarm =
vmi_get_function(VMI_CALL_CancelAlarm);
- pv_time_ops.time_init = vmi_time_init;
+ x86_init.timers.timer_init = vmi_time_init;
pv_time_ops.get_wallclock = vmi_get_wallclock;
pv_time_ops.set_wallclock = vmi_set_wallclock;
#ifdef CONFIG_X86_LOCAL_APIC
#include <asm/setup.h>
#include <asm/apic.h>
#include <asm/e820.h>
+#include <asm/time.h>
#include <asm/irq.h>
void __cpuinit x86_init_noop(void) { }
.timers = {
.setup_percpu_clockev = setup_boot_APIC_clock,
+ .tsc_pre_init = x86_init_noop,
+ .timer_init = hpet_time_init,
},
};
/* Time operations */
pv_time_ops.get_wallclock = lguest_get_wallclock;
- pv_time_ops.time_init = lguest_time_init;
pv_time_ops.get_tsc_khz = lguest_tsc_khz;
x86_init.resources.memory_setup = lguest_memory_setup;
x86_init.irqs.intr_init = lguest_init_IRQ;
+ x86_init.timers.timer_init = lguest_time_init;
/*
* Now is a good time to look at the implementations of these functions
};
static const struct pv_time_ops xen_time_ops __initdata = {
- .time_init = xen_time_init,
-
.set_wallclock = xen_set_wallclock,
.get_wallclock = xen_get_wallclock,
.get_tsc_khz = xen_tsc_khz,
x86_init.resources.memory_setup = xen_memory_setup;
x86_init.oem.arch_setup = xen_arch_setup;
x86_init.oem.banner = xen_banner;
+
+ x86_init.timers.timer_init = xen_time_init;
x86_init.timers.setup_percpu_clockev = x86_init_noop;
x86_cpuinit.setup_percpu_clockev = x86_init_noop;