Loading Documentation/devicetree/bindings/arm/omap/crossbar.txt +36 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ Required properties: - compatible : Should be "ti,irq-crossbar" - reg: Base address and the size of the crossbar registers. - ti,max-irqs: Total number of irqs available at the interrupt controller. - ti,max-crossbar-sources: Maximum number of crossbar sources that can be routed. - ti,reg-size: Size of a individual register in bytes. Every individual register is assumed to be of same size. Valid sizes are 1, 2, 4. - ti,irqs-reserved: List of the reserved irq lines that are not muxed using Loading @@ -17,11 +18,46 @@ Required properties: so crossbar bar driver should not consider them as free lines. Optional properties: - ti,irqs-skip: This is similar to "ti,irqs-reserved", but these are for SOC-specific hard-wiring of those irqs which unexpectedly bypasses the crossbar. These irqs have a crossbar register, but still cannot be used. - ti,irqs-safe-map: integer which maps to a safe configuration to use when the interrupt controller irq is unused (when not provided, default is 0) Examples: crossbar_mpu: @4a020000 { compatible = "ti,irq-crossbar"; reg = <0x4a002a48 0x130>; ti,max-irqs = <160>; ti,max-crossbar-sources = <400>; ti,reg-size = <2>; ti,irqs-reserved = <0 1 2 3 5 6 131 132 139 140>; ti,irqs-skip = <10 133 139 140>; }; Consumer: ======== See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt and Documentation/devicetree/bindings/arm/gic.txt for further details. An interrupt consumer on an SoC using crossbar will use: interrupts = <GIC_SPI request_number interrupt_level> When the request number is between 0 to that described by "ti,max-crossbar-sources", it is assumed to be a crossbar mapping. If the request_number is greater than "ti,max-crossbar-sources", then it is mapped as a quirky hardware mapping direct to GIC. Example: device_x@0x4a023000 { /* Crossbar 8 used */ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; ... }; device_y@0x4a033000 { /* Direct mapped GIC SPI 1 used */ interrupts = <GIC_SPI DIRECT_IRQ(1) IRQ_TYPE_LEVEL_HIGH>; ... }; Documentation/devicetree/bindings/interrupt-controller/opencores,or1k-pic.txt 0 → 100644 +23 −0 Original line number Diff line number Diff line OpenRISC 1000 Programmable Interrupt Controller Required properties: - compatible : should be "opencores,or1k-pic-level" for variants with level triggered interrupt lines, "opencores,or1k-pic-edge" for variants with edge triggered interrupt lines or "opencores,or1200-pic" for machines with the non-spec compliant or1200 type implementation. "opencores,or1k-pic" is also provided as an alias to "opencores,or1200-pic", but this is only for backwards compatibility. - interrupt-controller : Identifies the node as an interrupt controller - #interrupt-cells : Specifies the number of cells needed to encode an interrupt source. The value shall be 1. Example: intc: interrupt-controller { compatible = "opencores,or1k-pic-level"; interrupt-controller; #interrupt-cells = <1>; }; arch/openrisc/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading arch/openrisc/include/asm/irq.h +3 −0 Original line number Diff line number Diff line Loading @@ -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__ */ arch/openrisc/kernel/irq.c +13 −133 Original line number Diff line number Diff line Loading @@ -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 */ Loading @@ -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) void __init init_IRQ(void) { 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); irqchip_init(); } static void (*handle_arch_irq)(struct pt_regs *); static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) void __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) { irq_set_chip_and_handler_name(irq, &or1k_dev, handle_level_irq, "level"); irq_set_status_flags(irq, IRQ_LEVEL | IRQ_NOPROBE); return 0; handle_arch_irq = handle_irq; } 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) void handle_IRQ(unsigned int irq, struct pt_regs *regs) { 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); } void __init init_IRQ(void) { or1k_irq_init(); } void __irq_entry do_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); irq_exit(); set_irq_regs(old_regs); } void __irq_entry do_IRQ(struct pt_regs *regs) { handle_arch_irq(regs); } Loading
Documentation/devicetree/bindings/arm/omap/crossbar.txt +36 −0 Original line number Diff line number Diff line Loading @@ -10,6 +10,7 @@ Required properties: - compatible : Should be "ti,irq-crossbar" - reg: Base address and the size of the crossbar registers. - ti,max-irqs: Total number of irqs available at the interrupt controller. - ti,max-crossbar-sources: Maximum number of crossbar sources that can be routed. - ti,reg-size: Size of a individual register in bytes. Every individual register is assumed to be of same size. Valid sizes are 1, 2, 4. - ti,irqs-reserved: List of the reserved irq lines that are not muxed using Loading @@ -17,11 +18,46 @@ Required properties: so crossbar bar driver should not consider them as free lines. Optional properties: - ti,irqs-skip: This is similar to "ti,irqs-reserved", but these are for SOC-specific hard-wiring of those irqs which unexpectedly bypasses the crossbar. These irqs have a crossbar register, but still cannot be used. - ti,irqs-safe-map: integer which maps to a safe configuration to use when the interrupt controller irq is unused (when not provided, default is 0) Examples: crossbar_mpu: @4a020000 { compatible = "ti,irq-crossbar"; reg = <0x4a002a48 0x130>; ti,max-irqs = <160>; ti,max-crossbar-sources = <400>; ti,reg-size = <2>; ti,irqs-reserved = <0 1 2 3 5 6 131 132 139 140>; ti,irqs-skip = <10 133 139 140>; }; Consumer: ======== See Documentation/devicetree/bindings/interrupt-controller/interrupts.txt and Documentation/devicetree/bindings/arm/gic.txt for further details. An interrupt consumer on an SoC using crossbar will use: interrupts = <GIC_SPI request_number interrupt_level> When the request number is between 0 to that described by "ti,max-crossbar-sources", it is assumed to be a crossbar mapping. If the request_number is greater than "ti,max-crossbar-sources", then it is mapped as a quirky hardware mapping direct to GIC. Example: device_x@0x4a023000 { /* Crossbar 8 used */ interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; ... }; device_y@0x4a033000 { /* Direct mapped GIC SPI 1 used */ interrupts = <GIC_SPI DIRECT_IRQ(1) IRQ_TYPE_LEVEL_HIGH>; ... };
Documentation/devicetree/bindings/interrupt-controller/opencores,or1k-pic.txt 0 → 100644 +23 −0 Original line number Diff line number Diff line OpenRISC 1000 Programmable Interrupt Controller Required properties: - compatible : should be "opencores,or1k-pic-level" for variants with level triggered interrupt lines, "opencores,or1k-pic-edge" for variants with edge triggered interrupt lines or "opencores,or1200-pic" for machines with the non-spec compliant or1200 type implementation. "opencores,or1k-pic" is also provided as an alias to "opencores,or1200-pic", but this is only for backwards compatibility. - interrupt-controller : Identifies the node as an interrupt controller - #interrupt-cells : Specifies the number of cells needed to encode an interrupt source. The value shall be 1. Example: intc: interrupt-controller { compatible = "opencores,or1k-pic-level"; interrupt-controller; #interrupt-cells = <1>; };
arch/openrisc/Kconfig +1 −0 Original line number Diff line number Diff line Loading @@ -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 Loading
arch/openrisc/include/asm/irq.h +3 −0 Original line number Diff line number Diff line Loading @@ -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__ */
arch/openrisc/kernel/irq.c +13 −133 Original line number Diff line number Diff line Loading @@ -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 */ Loading @@ -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) void __init init_IRQ(void) { 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); irqchip_init(); } static void (*handle_arch_irq)(struct pt_regs *); static int or1k_map(struct irq_domain *d, unsigned int irq, irq_hw_number_t hw) void __init set_handle_irq(void (*handle_irq)(struct pt_regs *)) { irq_set_chip_and_handler_name(irq, &or1k_dev, handle_level_irq, "level"); irq_set_status_flags(irq, IRQ_LEVEL | IRQ_NOPROBE); return 0; handle_arch_irq = handle_irq; } 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) void handle_IRQ(unsigned int irq, struct pt_regs *regs) { 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); } void __init init_IRQ(void) { or1k_irq_init(); } void __irq_entry do_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); irq_exit(); set_irq_regs(old_regs); } void __irq_entry do_IRQ(struct pt_regs *regs) { handle_arch_irq(regs); }