提交 4936f63c 编写于 作者: G Geert Uytterhoeven

m68k/irq: Add genirq support

Disabled on all platforms for now
Signed-off-by: NGeert Uytterhoeven <geert@linux-m68k.org>
[v1] Acked-by: Thomas Gleixner <tglx@linutronix.de>
上级 5a239453
...@@ -84,6 +84,23 @@ config MMU_SUN3 ...@@ -84,6 +84,23 @@ config MMU_SUN3
bool bool
depends on MMU && !MMU_MOTOROLA depends on MMU && !MMU_MOTOROLA
config USE_GENERIC_HARDIRQS
bool "Use genirq"
depends on MMU
depends on !AMIGA
depends on !ATARI
depends on !MAC
depends on !APOLLO
depends on !MVME147
depends on !MVME16x
depends on !BVME6000
depends on !HP300
depends on !SUN3X
depends on !Q40
depends on !SUN3
select HAVE_GENERIC_HARDIRQS
select GENERIC_IRQ_SHOW
menu "Platform setup" menu "Platform setup"
source arch/m68k/Kconfig.cpu source arch/m68k/Kconfig.cpu
......
...@@ -18,6 +18,11 @@ ...@@ -18,6 +18,11 @@
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
static inline void ack_bad_irq(unsigned int irq)
{
pr_crit("unexpected IRQ trap at vector %02x\n", irq);
}
/* entry.S is sensitive to the offsets of these fields */ /* entry.S is sensitive to the offsets of these fields */
typedef struct { typedef struct {
unsigned int __softirq_pending; unsigned int __softirq_pending;
......
...@@ -27,11 +27,6 @@ ...@@ -27,11 +27,6 @@
#ifdef CONFIG_MMU #ifdef CONFIG_MMU
#include <linux/linkage.h>
#include <linux/hardirq.h>
#include <linux/irqreturn.h>
#include <linux/spinlock_types.h>
/* /*
* Interrupt source definitions * Interrupt source definitions
* General interrupt sources are the level 1-7. * General interrupt sources are the level 1-7.
...@@ -54,10 +49,6 @@ ...@@ -54,10 +49,6 @@
#define IRQ_USER 8 #define IRQ_USER 8
extern unsigned int irq_canonicalize(unsigned int irq);
struct pt_regs;
/* /*
* various flags for request_irq() - the Amiga now uses the standard * various flags for request_irq() - the Amiga now uses the standard
* mechanism like all other architectures - IRQF_DISABLED and * mechanism like all other architectures - IRQF_DISABLED and
...@@ -71,6 +62,15 @@ struct pt_regs; ...@@ -71,6 +62,15 @@ struct pt_regs;
#define IRQ_FLG_STD (0x8000) /* internally used */ #define IRQ_FLG_STD (0x8000) /* internally used */
#endif #endif
#ifndef CONFIG_GENERIC_HARDIRQS
#include <linux/linkage.h>
#include <linux/hardirq.h>
#include <linux/irqreturn.h>
#include <linux/spinlock_types.h>
struct pt_regs;
/* /*
* This structure is used to chain together the ISRs for a particular * This structure is used to chain together the ISRs for a particular
* interrupt source (if it supports chaining). * interrupt source (if it supports chaining).
...@@ -121,10 +121,33 @@ extern void m68k_setup_irq_chip(struct irq_chip *, unsigned int, unsigned int); ...@@ -121,10 +121,33 @@ extern void m68k_setup_irq_chip(struct irq_chip *, unsigned int, unsigned int);
extern void generic_handle_irq(unsigned int); extern void generic_handle_irq(unsigned int);
asmlinkage void do_IRQ(int irq, struct pt_regs *regs); asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
#else /* CONFIG_GENERIC_HARDIRQS */
struct irq_data;
struct irq_chip;
struct irq_desc;
extern unsigned int m68k_irq_startup(struct irq_data *data);
extern unsigned int m68k_irq_startup_irq(unsigned int irq);
extern void m68k_irq_shutdown(struct irq_data *data);
extern void m68k_setup_auto_interrupt(void (*handler)(unsigned int,
struct pt_regs *));
extern void m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
void (*handler)(unsigned int,
struct pt_regs *));
extern void m68k_setup_irq_controller(struct irq_chip *,
void (*handle)(unsigned int irq,
struct irq_desc *desc),
unsigned int irq, unsigned int cnt);
#endif /* CONFIG_GENERIC_HARDIRQS */
extern unsigned int irq_canonicalize(unsigned int irq);
#else #else
#define irq_canonicalize(irq) (irq) #define irq_canonicalize(irq) (irq)
#endif /* CONFIG_MMU */ #endif /* CONFIG_MMU */
asmlinkage void do_IRQ(int irq, struct pt_regs *regs); asmlinkage void do_IRQ(int irq, struct pt_regs *regs);
extern atomic_t irq_err_count;
#endif /* _M68K_IRQ_H_ */ #endif /* _M68K_IRQ_H_ */
...@@ -9,13 +9,18 @@ extra-y += vmlinux.lds ...@@ -9,13 +9,18 @@ extra-y += vmlinux.lds
obj-y := entry.o m68k_ksyms.o module.o process.o ptrace.o setup.o signal.o \ obj-y := entry.o m68k_ksyms.o module.o process.o ptrace.o setup.o signal.o \
sys_m68k.o syscalltable.o time.o traps.o sys_m68k.o syscalltable.o time.o traps.o
obj-$(CONFIG_MMU) += ints.o devres.o vectors.o obj-$(CONFIG_MMU) += ints.o vectors.o
devres-$(CONFIG_MMU) = ../../../kernel/irq/devres.o devres-$(CONFIG_MMU) = ../../../kernel/irq/devres.o
ifndef CONFIG_MMU_SUN3 ifndef CONFIG_MMU_SUN3
obj-y += dma.o obj-y += dma.o
endif endif
ifndef CONFIG_MMU ifndef CONFIG_MMU
obj-y += init_task.o irq.o obj-y += init_task.o
endif
ifdef CONFIG_GENERIC_HARDIRQS
obj-y += irq.o
else
obj-y += devres.o
endif endif
...@@ -31,6 +31,7 @@ extern u32 auto_irqhandler_fixup[]; ...@@ -31,6 +31,7 @@ extern u32 auto_irqhandler_fixup[];
extern u32 user_irqhandler_fixup[]; extern u32 user_irqhandler_fixup[];
extern u16 user_irqvec_fixup[]; extern u16 user_irqvec_fixup[];
#ifndef CONFIG_GENERIC_HARDIRQS
/* table for system interrupt handlers */ /* table for system interrupt handlers */
static struct irq_data *irq_list[NR_IRQS]; static struct irq_data *irq_list[NR_IRQS];
static struct irq_chip *irq_chip[NR_IRQS]; static struct irq_chip *irq_chip[NR_IRQS];
...@@ -41,6 +42,8 @@ static inline int irq_set_chip(unsigned int irq, struct irq_chip *chip) ...@@ -41,6 +42,8 @@ static inline int irq_set_chip(unsigned int irq, struct irq_chip *chip)
irq_chip[irq] = chip; irq_chip[irq] = chip;
return 0; return 0;
} }
#define irq_set_chip_and_handler(irq, chip, dummy) irq_set_chip(irq, chip)
#endif /* !CONFIG_GENERIC_HARDIRQS */
static int m68k_first_user_vec; static int m68k_first_user_vec;
...@@ -56,8 +59,10 @@ static struct irq_chip user_irq_chip = { ...@@ -56,8 +59,10 @@ static struct irq_chip user_irq_chip = {
.irq_shutdown = m68k_irq_shutdown, .irq_shutdown = m68k_irq_shutdown,
}; };
#ifndef CONFIG_GENERIC_HARDIRQS
#define NUM_IRQ_NODES 100 #define NUM_IRQ_NODES 100
static struct irq_data nodes[NUM_IRQ_NODES]; static struct irq_data nodes[NUM_IRQ_NODES];
#endif /* !CONFIG_GENERIC_HARDIRQS */
/* /*
* void init_IRQ(void) * void init_IRQ(void)
...@@ -81,7 +86,7 @@ void __init init_IRQ(void) ...@@ -81,7 +86,7 @@ void __init init_IRQ(void)
} }
for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++) for (i = IRQ_AUTO_1; i <= IRQ_AUTO_7; i++)
irq_set_chip(i, &auto_irq_chip); irq_set_chip_and_handler(i, &auto_irq_chip, handle_simple_irq);
mach_init_IRQ(); mach_init_IRQ();
} }
...@@ -128,6 +133,35 @@ void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt, ...@@ -128,6 +133,35 @@ void __init m68k_setup_user_interrupt(unsigned int vec, unsigned int cnt,
flush_icache(); flush_icache();
} }
#ifdef CONFIG_GENERIC_HARDIRQS
/**
* m68k_setup_irq_controller
* @chip: irq chip which controls specified irq
* @handle: flow handler which handles specified irq
* @irq: first irq to be managed by the controller
* @cnt: number of irqs to be managed by the controller
*
* Change the controller for the specified range of irq, which will be used to
* manage these irq. auto/user irq already have a default controller, which can
* be changed as well, but the controller probably should use m68k_irq_startup/
* m68k_irq_shutdown.
*/
void m68k_setup_irq_controller(struct irq_chip *chip,
irq_flow_handler_t handle, unsigned int irq,
unsigned int cnt)
{
int i;
for (i = 0; i < cnt; i++) {
irq_set_chip(irq + i, chip);
if (handle)
irq_set_handler(irq + i, handle);
}
}
#else /* !CONFIG_GENERIC_HARDIRQS */
/** /**
* m68k_setup_irq_chip * m68k_setup_irq_chip
* @contr: irq controller which controls specified irq * @contr: irq controller which controls specified irq
...@@ -316,6 +350,8 @@ void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq"))); ...@@ -316,6 +350,8 @@ void disable_irq_nosync(unsigned int irq) __attribute__((alias("disable_irq")));
EXPORT_SYMBOL(disable_irq_nosync); EXPORT_SYMBOL(disable_irq_nosync);
#endif /* !CONFIG_GENERIC_HARDIRQS */
unsigned int m68k_irq_startup_irq(unsigned int irq) unsigned int m68k_irq_startup_irq(unsigned int irq)
{ {
if (irq <= IRQ_AUTO_7) if (irq <= IRQ_AUTO_7)
...@@ -341,6 +377,8 @@ void m68k_irq_shutdown(struct irq_data *data) ...@@ -341,6 +377,8 @@ void m68k_irq_shutdown(struct irq_data *data)
} }
#ifndef CONFIG_GENERIC_HARDIRQS
/* /*
* Do we need these probe functions on the m68k? * Do we need these probe functions on the m68k?
* *
...@@ -367,6 +405,7 @@ int probe_irq_off (unsigned long irqs) ...@@ -367,6 +405,7 @@ int probe_irq_off (unsigned long irqs)
} }
EXPORT_SYMBOL(probe_irq_off); EXPORT_SYMBOL(probe_irq_off);
#endif /* CONFIG_GENERIC_HARDIRQS */
unsigned int irq_canonicalize(unsigned int irq) unsigned int irq_canonicalize(unsigned int irq)
{ {
...@@ -379,6 +418,7 @@ unsigned int irq_canonicalize(unsigned int irq) ...@@ -379,6 +418,7 @@ unsigned int irq_canonicalize(unsigned int irq)
EXPORT_SYMBOL(irq_canonicalize); EXPORT_SYMBOL(irq_canonicalize);
#ifndef CONFIG_GENERIC_HARDIRQS
void generic_handle_irq(unsigned int irq) void generic_handle_irq(unsigned int irq)
{ {
struct irq_data *node; struct irq_data *node;
...@@ -428,3 +468,13 @@ void init_irq_proc(void) ...@@ -428,3 +468,13 @@ void init_irq_proc(void)
/* Insert /proc/irq driver here */ /* Insert /proc/irq driver here */
} }
#endif #endif
#else /* CONFIG_GENERIC_HARDIRQS */
asmlinkage void handle_badint(struct pt_regs *regs)
{
atomic_inc(&irq_err_count);
pr_warn("unexpected interrupt from %u\n", regs->vector);
}
#endif /* CONFIG_GENERIC_HARDIRQS */
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册