summaryrefslogtreecommitdiff
path: root/arch/sparc/kernel/tick14.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/sparc/kernel/tick14.c')
-rw-r--r--arch/sparc/kernel/tick14.c85
1 files changed, 85 insertions, 0 deletions
diff --git a/arch/sparc/kernel/tick14.c b/arch/sparc/kernel/tick14.c
new file mode 100644
index 000000000000..fd8005a3e6bd
--- /dev/null
+++ b/arch/sparc/kernel/tick14.c
@@ -0,0 +1,85 @@
+/* tick14.c
+ * linux/arch/sparc/kernel/tick14.c
+ *
+ * Copyright (C) 1996 David Redman (djhr@tadpole.co.uk)
+ *
+ * This file handles the Sparc specific level14 ticker
+ * This is really useful for profiling OBP uses it for keyboard
+ * aborts and other stuff.
+ *
+ *
+ */
+#include <linux/errno.h>
+#include <linux/sched.h>
+#include <linux/kernel.h>
+#include <linux/param.h>
+#include <linux/string.h>
+#include <linux/mm.h>
+#include <linux/timex.h>
+#include <linux/interrupt.h>
+
+#include <asm/oplib.h>
+#include <asm/segment.h>
+#include <asm/timer.h>
+#include <asm/mostek.h>
+#include <asm/system.h>
+#include <asm/irq.h>
+#include <asm/io.h>
+
+extern unsigned long lvl14_save[5];
+static unsigned long *linux_lvl14 = NULL;
+static unsigned long obp_lvl14[4];
+
+/*
+ * Call with timer IRQ closed.
+ * First time we do it with disable_irq, later prom code uses spin_lock_irq().
+ */
+void install_linux_ticker(void)
+{
+
+ if (!linux_lvl14)
+ return;
+ linux_lvl14[0] = lvl14_save[0];
+ linux_lvl14[1] = lvl14_save[1];
+ linux_lvl14[2] = lvl14_save[2];
+ linux_lvl14[3] = lvl14_save[3];
+}
+
+void install_obp_ticker(void)
+{
+
+ if (!linux_lvl14)
+ return;
+ linux_lvl14[0] = obp_lvl14[0];
+ linux_lvl14[1] = obp_lvl14[1];
+ linux_lvl14[2] = obp_lvl14[2];
+ linux_lvl14[3] = obp_lvl14[3];
+}
+
+void claim_ticker14(irqreturn_t (*handler)(int, void *, struct pt_regs *),
+ int irq_nr, unsigned int timeout )
+{
+ int cpu = smp_processor_id();
+
+ /* first we copy the obp handler instructions
+ */
+ disable_irq(irq_nr);
+ if (!handler)
+ return;
+
+ linux_lvl14 = (unsigned long *)lvl14_save[4];
+ obp_lvl14[0] = linux_lvl14[0];
+ obp_lvl14[1] = linux_lvl14[1];
+ obp_lvl14[2] = linux_lvl14[2];
+ obp_lvl14[3] = linux_lvl14[3];
+
+ if (!request_irq(irq_nr,
+ handler,
+ (SA_INTERRUPT | SA_STATIC_ALLOC),
+ "counter14",
+ NULL)) {
+ install_linux_ticker();
+ load_profile_irq(cpu, timeout);
+ enable_irq(irq_nr);
+ }
+}