diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-06 02:38:45 +0200 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-08-06 02:38:45 +0200 |
commit | 08d69a25714429850cf9ef71f22d8cdc9189d93f (patch) | |
tree | c03f4e91834b5280a4695f0c805b58c599e895cc /arch/openrisc | |
parent | x86: MCE: Add raw_lock conversion again (diff) | |
parent | Revert "irq: Warn when shared interrupts do not match on NO_SUSPEND" (diff) | |
download | linux-08d69a25714429850cf9ef71f22d8cdc9189d93f.tar.xz linux-08d69a25714429850cf9ef71f22d8cdc9189d93f.zip |
Merge branch 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip
Pull irq updates from Thomas Gleixner:
"Nothing spectacular from the irq department this time:
- overhaul of the crossbar chip driver
- overhaul of the spear shirq chip driver
- support for the atmel-aic chip
- code move from arch to drivers
- the usual tiny fixlets
- two reverts worth to mention which undo the too simple attempt of
supporting wakeup interrupts on shared interrupt lines"
* 'irq-core-for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/tip/tip: (41 commits)
Revert "irq: Warn when shared interrupts do not match on NO_SUSPEND"
Revert "PM / sleep / irq: Do not suspend wakeup interrupts"
irq: Warn when shared interrupts do not match on NO_SUSPEND
irqchip: atmel-aic: Define irq fixups for atmel SoCs
irqchip: atmel-aic: Implement RTC irq fixup
irqchip: atmel-aic: Add irq fixup infrastructure
irqchip: atmel-aic: Add atmel AIC/AIC5 drivers
irqchip: atmel-aic: Move binding doc to interrupt-controller directory
genirq: generic chip: Export irq_map_generic_chip function
PM / sleep / irq: Do not suspend wakeup interrupts
irqchip: or1k-pic: Migrate from arch/openrisc/
irqchip: crossbar: Allow for quirky hardware with direct hardwiring of GIC
documentation: dt: omap: crossbar: Add description for interrupt consumer
irqchip: crossbar: Introduce centralized check for crossbar write
irqchip: crossbar: Introduce ti, max-crossbar-sources to identify valid crossbar mapping
irqchip: crossbar: Add kerneldoc for crossbar_domain_unmap callback
irqchip: crossbar: Set cb pointer to null in case of error
irqchip: crossbar: Change the goto naming
irqchip: crossbar: Return proper error value
irqchip: crossbar: Fix kerneldoc warning
...
Diffstat (limited to 'arch/openrisc')
-rw-r--r-- | arch/openrisc/Kconfig | 1 | ||||
-rw-r--r-- | arch/openrisc/include/asm/irq.h | 3 | ||||
-rw-r--r-- | arch/openrisc/kernel/irq.c | 146 |
3 files changed, 17 insertions, 133 deletions
diff --git a/arch/openrisc/Kconfig b/arch/openrisc/Kconfig index e71d712afb79..88e83368bbf5 100644 --- a/arch/openrisc/Kconfig +++ b/arch/openrisc/Kconfig @@ -22,6 +22,7 @@ config OPENRISC select GENERIC_STRNLEN_USER select MODULES_USE_ELF_RELA select HAVE_DEBUG_STACKOVERFLOW + select OR1K_PIC config MMU def_bool y diff --git a/arch/openrisc/include/asm/irq.h b/arch/openrisc/include/asm/irq.h index eb612b1865d2..b84634cc95eb 100644 --- a/arch/openrisc/include/asm/irq.h +++ b/arch/openrisc/include/asm/irq.h @@ -24,4 +24,7 @@ #define NO_IRQ (-1) +void handle_IRQ(unsigned int, struct pt_regs *); +extern void set_handle_irq(void (*handle_irq)(struct pt_regs *)); + #endif /* __ASM_OPENRISC_IRQ_H__ */ diff --git a/arch/openrisc/kernel/irq.c b/arch/openrisc/kernel/irq.c index 8ec77bc9f1e7..967eb1430203 100644 --- a/arch/openrisc/kernel/irq.c +++ b/arch/openrisc/kernel/irq.c @@ -16,11 +16,10 @@ #include <linux/interrupt.h> #include <linux/init.h> -#include <linux/of.h> #include <linux/ftrace.h> #include <linux/irq.h> +#include <linux/irqchip.h> #include <linux/export.h> -#include <linux/irqdomain.h> #include <linux/irqflags.h> /* read interrupt enabled status */ @@ -37,150 +36,31 @@ void arch_local_irq_restore(unsigned long flags) } EXPORT_SYMBOL(arch_local_irq_restore); - -/* OR1K PIC implementation */ - -/* We're a couple of cycles faster than the generic implementations with - * these 'fast' versions. - */ - -static void or1k_pic_mask(struct irq_data *data) -{ - mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq)); -} - -static void or1k_pic_unmask(struct irq_data *data) -{ - mtspr(SPR_PICMR, mfspr(SPR_PICMR) | (1UL << data->hwirq)); -} - -static void or1k_pic_ack(struct irq_data *data) -{ - /* EDGE-triggered interrupts need to be ack'ed in order to clear - * the latch. - * LEVEL-triggered interrupts do not need to be ack'ed; however, - * ack'ing the interrupt has no ill-effect and is quicker than - * trying to figure out what type it is... - */ - - /* The OpenRISC 1000 spec says to write a 1 to the bit to ack the - * interrupt, but the OR1200 does this backwards and requires a 0 - * to be written... - */ - -#ifdef CONFIG_OR1K_1200 - /* There are two oddities with the OR1200 PIC implementation: - * i) LEVEL-triggered interrupts are latched and need to be cleared - * ii) the interrupt latch is cleared by writing a 0 to the bit, - * as opposed to a 1 as mandated by the spec - */ - - mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq)); -#else - WARN(1, "Interrupt handling possibly broken\n"); - mtspr(SPR_PICSR, (1UL << data->hwirq)); -#endif -} - -static void or1k_pic_mask_ack(struct irq_data *data) -{ - /* Comments for pic_ack apply here, too */ - -#ifdef CONFIG_OR1K_1200 - mtspr(SPR_PICMR, mfspr(SPR_PICMR) & ~(1UL << data->hwirq)); - mtspr(SPR_PICSR, mfspr(SPR_PICSR) & ~(1UL << data->hwirq)); -#else - WARN(1, "Interrupt handling possibly broken\n"); - mtspr(SPR_PICMR, (1UL << data->hwirq)); - mtspr(SPR_PICSR, (1UL << data->hwirq)); -#endif -} - -#if 0 -static int or1k_pic_set_type(struct irq_data *data, unsigned int flow_type) -{ - /* There's nothing to do in the PIC configuration when changing - * flow type. Level and edge-triggered interrupts are both - * supported, but it's PIC-implementation specific which type - * is handled. */ - - return irq_setup_alt_chip(data, flow_type); -} -#endif - -static struct irq_chip or1k_dev = { - .name = "or1k-PIC", - .irq_unmask = or1k_pic_unmask, - .irq_mask = or1k_pic_mask, - .irq_ack = or1k_pic_ack, - .irq_mask_ack = or1k_pic_mask_ack, -}; - -static struct irq_domain *root_domain; - -static inline int pic_get_irq(int first) -{ - int hwirq; - - hwirq = ffs(mfspr(SPR_PICSR) >> first); - if (!hwirq) - return NO_IRQ; - else - hwirq = hwirq + first -1; - - return irq_find_mapping(root_domain, hwirq); -} - - -static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) +void __init init_IRQ(void) { - irq_set_chip_and_handler_name(irq, &or1k_dev, - handle_level_irq, "level"); - irq_set_status_flags(irq, IRQ_LEVEL | IRQ_NOPROBE); - - return 0; + irqchip_init(); } -static const struct irq_domain_ops or1k_irq_domain_ops = { - .xlate = irq_domain_xlate_onecell, - .map = or1k_map, -}; - -/* - * This sets up the IRQ domain for the PIC built in to the OpenRISC - * 1000 CPU. This is the "root" domain as these are the interrupts - * that directly trigger an exception in the CPU. - */ -static void __init or1k_irq_init(void) -{ - struct device_node *intc = NULL; - - /* The interrupt controller device node is mandatory */ - intc = of_find_compatible_node(NULL, NULL, "opencores,or1k-pic"); - BUG_ON(!intc); - - /* Disable all interrupts until explicitly requested */ - mtspr(SPR_PICMR, (0UL)); - - root_domain = irq_domain_add_linear(intc, 32, - &or1k_irq_domain_ops, NULL); -} +static void (*handle_arch_irq)(struct pt_regs *); -void __init init_IRQ(void) +void __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) { - or1k_irq_init(); + handle_arch_irq = handle_irq; } -void __irq_entry do_IRQ(struct pt_regs *regs) +void handle_IRQ(unsigned int irq, struct pt_regs *regs) { - int irq = -1; struct pt_regs *old_regs = set_irq_regs(regs); irq_enter(); - while ((irq = pic_get_irq(irq + 1)) != NO_IRQ) - generic_handle_irq(irq); + generic_handle_irq(irq); irq_exit(); set_irq_regs(old_regs); } + +void __irq_entry do_IRQ(struct pt_regs *regs) +{ + handle_arch_irq(regs); +} |