From bf3a00f88c926635932c91afd90b4a0907dfbe78 Mon Sep 17 00:00:00 2001 From: Paul Mundt Date: Mon, 16 Jan 2006 22:14:14 -0800 Subject: [PATCH] sh: IRQ handler updates This moves the various IRQ controller drivers into a new subdirectory, and also extends the INTC2 IRQ handler to also deal with SH7760 and SH7780 interrupts, rather than just ST-40. The old CONFIG_SH_GENERIC has also been removed from the IRQ definitions, as new ports are expected to be based off of CONFIG_SH_UNKNOWN. Since there are plenty of incompatible machvecs, CONFIG_SH_GENERIC doesn't make sense anymore. Signed-off-by: Paul Mundt Signed-off-by: Andrew Morton Signed-off-by: Linus Torvalds --- arch/sh/kernel/cpu/irq/imask.c | 110 +++++++++++++++++++++++++++++++++++++++++ 1 file changed, 110 insertions(+) create mode 100644 arch/sh/kernel/cpu/irq/imask.c (limited to 'arch/sh/kernel/cpu/irq/imask.c') diff --git a/arch/sh/kernel/cpu/irq/imask.c b/arch/sh/kernel/cpu/irq/imask.c new file mode 100644 index 000000000000..baed9a550d39 --- /dev/null +++ b/arch/sh/kernel/cpu/irq/imask.c @@ -0,0 +1,110 @@ +/* + * arch/sh/kernel/cpu/irq/imask.c + * + * Copyright (C) 1999, 2000 Niibe Yutaka + * + * Simple interrupt handling using IMASK of SR register. + * + */ +/* NOTE: Will not work on level 15 */ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + +/* Bitmap of IRQ masked */ +static unsigned long imask_mask = 0x7fff; +static int interrupt_priority = 0; + +static void enable_imask_irq(unsigned int irq); +static void disable_imask_irq(unsigned int irq); +static void shutdown_imask_irq(unsigned int irq); +static void mask_and_ack_imask(unsigned int); +static void end_imask_irq(unsigned int irq); + +#define IMASK_PRIORITY 15 + +static unsigned int startup_imask_irq(unsigned int irq) +{ + /* Nothing to do */ + return 0; /* never anything pending */ +} + +static struct hw_interrupt_type imask_irq_type = { + .typename = "SR.IMASK", + .startup = startup_imask_irq, + .shutdown = shutdown_imask_irq, + .enable = enable_imask_irq, + .disable = disable_imask_irq, + .ack = mask_and_ack_imask, + .end = end_imask_irq +}; + +void static inline set_interrupt_registers(int ip) +{ + unsigned long __dummy; + + asm volatile("ldc %2, r6_bank\n\t" + "stc sr, %0\n\t" + "and #0xf0, %0\n\t" + "shlr2 %0\n\t" + "cmp/eq #0x3c, %0\n\t" + "bt/s 1f ! CLI-ed\n\t" + " stc sr, %0\n\t" + "and %1, %0\n\t" + "or %2, %0\n\t" + "ldc %0, sr\n" + "1:" + : "=&z" (__dummy) + : "r" (~0xf0), "r" (ip << 4) + : "t"); +} + +static void disable_imask_irq(unsigned int irq) +{ + clear_bit(irq, &imask_mask); + if (interrupt_priority < IMASK_PRIORITY - irq) + interrupt_priority = IMASK_PRIORITY - irq; + + set_interrupt_registers(interrupt_priority); +} + +static void enable_imask_irq(unsigned int irq) +{ + set_bit(irq, &imask_mask); + interrupt_priority = IMASK_PRIORITY - ffz(imask_mask); + + set_interrupt_registers(interrupt_priority); +} + +static void mask_and_ack_imask(unsigned int irq) +{ + disable_imask_irq(irq); +} + +static void end_imask_irq(unsigned int irq) +{ + if (!(irq_desc[irq].status & (IRQ_DISABLED|IRQ_INPROGRESS))) + enable_imask_irq(irq); +} + +static void shutdown_imask_irq(unsigned int irq) +{ + /* Nothing to do */ +} + +void make_imask_irq(unsigned int irq) +{ + disable_irq_nosync(irq); + irq_desc[irq].handler = &imask_irq_type; + enable_irq(irq); +} -- cgit v1.2.1