296 lines
6.9 KiB
Diff
Executable File
296 lines
6.9 KiB
Diff
Executable File
Index: linux-2.6.25-source/arch/x86/kernel/timer_cooperative.c
|
|
===================================================================
|
|
--- /dev/null
|
|
+++ linux-2.6.25-source/arch/x86/kernel/timer_cooperative.c
|
|
@@ -0,0 +1,153 @@
|
|
+/*
|
|
+ * Cooperative mode timer.
|
|
+ *
|
|
+ * Dan Aloni <da-x@colinux.org>, 2003-2004 (C).
|
|
+ */
|
|
+
|
|
+#include <linux/module.h>
|
|
+#include <linux/init.h>
|
|
+#include <linux/interrupt.h>
|
|
+
|
|
+#include <asm/timer.h>
|
|
+#include <asm/delay.h>
|
|
+
|
|
+#include <linux/clockchips.h>
|
|
+#include <linux/clocksource.h>
|
|
+#include <linux/cooperative.h>
|
|
+#include <linux/cooperative_internal.h>
|
|
+
|
|
+#define CO_CLOCK_SHIFT 20
|
|
+
|
|
+/* FSEC = 10^-15
|
|
+ NSEC = 10^-9 */
|
|
+#define FSEC_PER_NSEC 1000000
|
|
+
|
|
+/* 100Hz is fix from damons 10ms setup */
|
|
+#define CO_HOST_HZ 100
|
|
+
|
|
+unsigned int cpu_khz;
|
|
+EXPORT_SYMBOL(cpu_khz);
|
|
+
|
|
+/* unused here, but needed by linker */
|
|
+volatile unsigned long cmos_lock = 0;
|
|
+EXPORT_SYMBOL(cmos_lock);
|
|
+
|
|
+/*
|
|
+ * Functions copied from time.c
|
|
+ */
|
|
+unsigned long profile_pc(struct pt_regs *regs)
|
|
+{
|
|
+ unsigned long pc = instruction_pointer(regs);
|
|
+
|
|
+ return pc;
|
|
+}
|
|
+EXPORT_SYMBOL(profile_pc);
|
|
+
|
|
+/* Read system date and clock at startup */
|
|
+unsigned long read_persistent_clock(void)
|
|
+{
|
|
+ return co_get_host_time();
|
|
+}
|
|
+
|
|
+/* need by ntp.c */
|
|
+int update_persistent_clock(struct timespec now)
|
|
+{
|
|
+ return 0;
|
|
+}
|
|
+
|
|
+
|
|
+/*
|
|
+ * Clock source related code, based on arch/arm/mach-omap1/time.c
|
|
+ */
|
|
+
|
|
+static cycle_t query_host_highprec_time(void)
|
|
+{
|
|
+ unsigned long flags;
|
|
+ unsigned long long this_time;
|
|
+
|
|
+ co_passage_page_assert_valid();
|
|
+
|
|
+ co_passage_page_acquire(&flags);
|
|
+ co_passage_page->operation = CO_OPERATION_GET_HIGH_PREC_TIME;
|
|
+ co_switch_wrapper();
|
|
+ this_time = *(unsigned long long *)(&co_passage_page->params[0]);
|
|
+ co_passage_page_release(flags);
|
|
+
|
|
+ return this_time;
|
|
+}
|
|
+
|
|
+static struct clocksource co_clocksource = {
|
|
+ .name = "cooperative",
|
|
+ .rating = 450,
|
|
+ .read = query_host_highprec_time,
|
|
+ .mask = CLOCKSOURCE_MASK(64),
|
|
+ .shift = CO_CLOCK_SHIFT,
|
|
+ .flags = CLOCK_SOURCE_IS_CONTINUOUS,
|
|
+};
|
|
+
|
|
+
|
|
+static void co_timer_setup(enum clock_event_mode mode,
|
|
+ struct clock_event_device *evt)
|
|
+{
|
|
+}
|
|
+
|
|
+struct clock_event_device co_clockevent = {
|
|
+ .name = "clock",
|
|
+ .features = CLOCK_EVT_FEAT_PERIODIC,
|
|
+ .set_mode = co_timer_setup,
|
|
+ .shift = CO_CLOCK_SHIFT,
|
|
+};
|
|
+
|
|
+static irqreturn_t co_timer_interrupt(int irq, void *dev_id)
|
|
+{
|
|
+ struct clock_event_device *evt = &co_clockevent;
|
|
+
|
|
+ evt->event_handler(evt);
|
|
+
|
|
+ return IRQ_HANDLED;
|
|
+}
|
|
+
|
|
+static struct irqaction co_timer_irq = {
|
|
+ .name = "timer",
|
|
+ .flags = IRQF_DISABLED | IRQF_TIMER | IRQF_IRQPOLL,
|
|
+ .handler = co_timer_interrupt,
|
|
+};
|
|
+
|
|
+static void co_delay_loop(unsigned long loops)
|
|
+{
|
|
+ /*
|
|
+ * A bogos delay loop for creating BogoMIPS...
|
|
+ */
|
|
+
|
|
+ loops = loops / 0x10000;
|
|
+ while (loops) {
|
|
+ query_host_highprec_time();
|
|
+ loops -= 1;
|
|
+ }
|
|
+}
|
|
+
|
|
+extern void (*late_time_init)(void);
|
|
+static void co_register_timer(void)
|
|
+{
|
|
+ setup_irq(TIMER_IRQ, &co_timer_irq);
|
|
+}
|
|
+
|
|
+void __init time_init(void)
|
|
+{
|
|
+ u64 tmp;
|
|
+
|
|
+ tmp = (u64)CO_HOST_HZ << CO_CLOCK_SHIFT;
|
|
+ do_div(tmp, FSEC_PER_NSEC);
|
|
+ co_clockevent.mult = (u32)tmp;
|
|
+
|
|
+ co_clocksource.mult = clocksource_hz2mult(CO_HOST_HZ, CO_CLOCK_SHIFT);
|
|
+ co_clockevent.cpumask = cpumask_of_cpu(0);
|
|
+
|
|
+ clockevents_register_device(&co_clockevent);
|
|
+ late_time_init = co_register_timer;
|
|
+
|
|
+ setup_delay_function(co_delay_loop);
|
|
+
|
|
+ cpu_khz = co_boot_params.co_cpu_khz;
|
|
+}
|
|
+
|
|
Index: linux-2.6.25-source/arch/x86/lib/delay_32.c
|
|
===================================================================
|
|
--- linux-2.6.25-source.orig/arch/x86/lib/delay_32.c
|
|
+++ linux-2.6.25-source/arch/x86/lib/delay_32.c
|
|
@@ -40,6 +40,7 @@
|
|
:"0" (loops));
|
|
}
|
|
|
|
+#ifndef CONFIG_COOPERATIVE
|
|
/* TSC based delay: */
|
|
static void delay_tsc(unsigned long loops)
|
|
{
|
|
@@ -53,6 +54,7 @@
|
|
} while ((now-bclock) < loops);
|
|
preempt_enable();
|
|
}
|
|
+#endif
|
|
|
|
/*
|
|
* Since we calibrate only once at boot, this
|
|
@@ -60,6 +62,12 @@
|
|
*/
|
|
static void (*delay_fn)(unsigned long) = delay_loop;
|
|
|
|
+#ifdef CONFIG_COOPERATIVE
|
|
+void setup_delay_function(void (*fn)(unsigned long))
|
|
+{
|
|
+ delay_fn = fn;
|
|
+}
|
|
+#else
|
|
void use_tsc_delay(void)
|
|
{
|
|
delay_fn = delay_tsc;
|
|
@@ -73,6 +81,7 @@
|
|
}
|
|
return -1;
|
|
}
|
|
+#endif
|
|
|
|
void __delay(unsigned long loops)
|
|
{
|
|
Index: linux-2.6.25-source/arch/x86/mach-default/setup.c
|
|
===================================================================
|
|
--- linux-2.6.25-source.orig/arch/x86/mach-default/setup.c
|
|
+++ linux-2.6.25-source/arch/x86/mach-default/setup.c
|
|
@@ -83,6 +83,7 @@
|
|
{
|
|
}
|
|
|
|
+#ifndef CONFIG_COOPERATIVE
|
|
static struct irqaction irq0 = {
|
|
.handler = timer_interrupt,
|
|
.flags = IRQF_DISABLED | IRQF_NOBALANCING | IRQF_IRQPOLL,
|
|
@@ -102,6 +103,7 @@
|
|
irq0.mask = cpumask_of_cpu(0);
|
|
setup_irq(0, &irq0);
|
|
}
|
|
+#endif /* !CONFIG_COOPERATIVE */
|
|
|
|
#ifdef CONFIG_MCA
|
|
/**
|
|
Index: linux-2.6.25-source/include/asm-x86/delay.h
|
|
===================================================================
|
|
--- linux-2.6.25-source.orig/include/asm-x86/delay.h
|
|
+++ linux-2.6.25-source/include/asm-x86/delay.h
|
|
@@ -26,6 +26,10 @@
|
|
((n) > 20000 ? __bad_ndelay() : __const_udelay((n) * 5ul)) : \
|
|
__ndelay(n))
|
|
|
|
+#ifdef CONFIG_COOPERATIVE
|
|
+void setup_delay_function(void (*fn)(unsigned long));
|
|
+#else
|
|
void use_tsc_delay(void);
|
|
+#endif
|
|
|
|
#endif /* _ASM_X86_DELAY_H */
|
|
Index: linux-2.6.25-source/include/asm-x86/mach-default/do_timer.h
|
|
===================================================================
|
|
--- linux-2.6.25-source.orig/include/asm-x86/mach-default/do_timer.h
|
|
+++ linux-2.6.25-source/include/asm-x86/mach-default/do_timer.h
|
|
@@ -4,6 +4,7 @@
|
|
#include <asm/i8259.h>
|
|
#include <asm/i8253.h>
|
|
|
|
+#ifndef CONFIG_COOPERATIVE
|
|
/**
|
|
* do_timer_interrupt_hook - hook into timer tick
|
|
*
|
|
@@ -14,3 +15,4 @@
|
|
{
|
|
global_clock_event->event_handler(global_clock_event);
|
|
}
|
|
+#endif
|
|
Index: linux-2.6.25-source/include/asm-x86/timex.h
|
|
===================================================================
|
|
--- linux-2.6.25-source.orig/include/asm-x86/timex.h
|
|
+++ linux-2.6.25-source/include/asm-x86/timex.h
|
|
@@ -14,6 +14,8 @@
|
|
#endif
|
|
#define CLOCK_TICK_RATE PIT_TICK_RATE
|
|
|
|
+#ifndef CONFIG_COOPERATIVE
|
|
#define ARCH_HAS_READ_CURRENT_TIMER
|
|
+#endif /* !CONFIG_COOPERATIVE */
|
|
|
|
#endif
|
|
Index: linux-2.6.25-source/include/linux/timex.h
|
|
===================================================================
|
|
--- linux-2.6.25-source.orig/include/linux/timex.h
|
|
+++ linux-2.6.25-source/include/linux/timex.h
|
|
@@ -244,7 +244,9 @@
|
|
/* Don't use! Compatibility define for existing users. */
|
|
#define tickadj (500/HZ ? : 1)
|
|
|
|
+#ifndef CONFIG_COOPERATIVE
|
|
int read_current_timer(unsigned long *timer_val);
|
|
+#endif /* !CONFIG_COOPERATIVE */
|
|
|
|
#endif /* KERNEL */
|
|
|
|
Index: linux-2.6.25-source/include/asm-x86/msr.h
|
|
===================================================================
|
|
--- linux-2.6.25-source.orig/include/asm-x86/msr.h
|
|
+++ linux-2.6.25-source/include/asm-x86/msr.h
|
|
@@ -85,7 +85,12 @@
|
|
return err;
|
|
}
|
|
|
|
+#ifdef CONFIG_COOPERATIVE
|
|
+/* FIXME: */
|
|
+#define native_read_tsc() 0
|
|
+#else
|
|
extern unsigned long long native_read_tsc(void);
|
|
+#endif
|
|
|
|
static __always_inline unsigned long long __native_read_tsc(void)
|
|
{
|