diff options
| -rw-r--r-- | Documentation/devicetree/bindings/arm/omap/crossbar.txt | 12 | ||||
| -rw-r--r-- | drivers/irqchip/irq-crossbar.c | 20 |
2 files changed, 28 insertions, 4 deletions
diff --git a/Documentation/devicetree/bindings/arm/omap/crossbar.txt b/Documentation/devicetree/bindings/arm/omap/crossbar.txt index ce7d01d86705..4139db353d0a 100644 --- a/Documentation/devicetree/bindings/arm/omap/crossbar.txt +++ b/Documentation/devicetree/bindings/arm/omap/crossbar.txt | |||
| @@ -44,8 +44,10 @@ Documentation/devicetree/bindings/arm/gic.txt for further details. | |||
| 44 | 44 | ||
| 45 | An interrupt consumer on an SoC using crossbar will use: | 45 | An interrupt consumer on an SoC using crossbar will use: |
| 46 | interrupts = <GIC_SPI request_number interrupt_level> | 46 | interrupts = <GIC_SPI request_number interrupt_level> |
| 47 | request number shall be between 0 to that described by | 47 | When the request number is between 0 to that described by |
| 48 | "ti,max-crossbar-sources" | 48 | "ti,max-crossbar-sources", it is assumed to be a crossbar mapping. If the |
| 49 | request_number is greater than "ti,max-crossbar-sources", then it is mapped as a | ||
| 50 | quirky hardware mapping direct to GIC. | ||
| 49 | 51 | ||
| 50 | Example: | 52 | Example: |
| 51 | device_x@0x4a023000 { | 53 | device_x@0x4a023000 { |
| @@ -53,3 +55,9 @@ Example: | |||
| 53 | interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; | 55 | interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>; |
| 54 | ... | 56 | ... |
| 55 | }; | 57 | }; |
| 58 | |||
| 59 | device_y@0x4a033000 { | ||
| 60 | /* Direct mapped GIC SPI 1 used */ | ||
| 61 | interrupts = <GIC_SPI DIRECT_IRQ(1) IRQ_TYPE_LEVEL_HIGH>; | ||
| 62 | ... | ||
| 63 | }; | ||
diff --git a/drivers/irqchip/irq-crossbar.c b/drivers/irqchip/irq-crossbar.c index 83f803bfab76..85c2985d8bcb 100644 --- a/drivers/irqchip/irq-crossbar.c +++ b/drivers/irqchip/irq-crossbar.c | |||
| @@ -86,8 +86,13 @@ static inline int allocate_free_irq(int cb_no) | |||
| 86 | 86 | ||
| 87 | static inline bool needs_crossbar_write(irq_hw_number_t hw) | 87 | static inline bool needs_crossbar_write(irq_hw_number_t hw) |
| 88 | { | 88 | { |
| 89 | if (hw > GIC_IRQ_START) | 89 | int cb_no; |
| 90 | return true; | 90 | |
| 91 | if (hw > GIC_IRQ_START) { | ||
| 92 | cb_no = cb->irq_map[hw - GIC_IRQ_START]; | ||
| 93 | if (cb_no != IRQ_RESERVED && cb_no != IRQ_SKIP) | ||
| 94 | return true; | ||
| 95 | } | ||
| 91 | 96 | ||
| 92 | return false; | 97 | return false; |
| 93 | } | 98 | } |
| @@ -130,8 +135,19 @@ static int crossbar_domain_xlate(struct irq_domain *d, | |||
| 130 | { | 135 | { |
| 131 | int ret; | 136 | int ret; |
| 132 | int req_num = intspec[1]; | 137 | int req_num = intspec[1]; |
| 138 | int direct_map_num; | ||
| 133 | 139 | ||
| 134 | if (req_num >= cb->max_crossbar_sources) { | 140 | if (req_num >= cb->max_crossbar_sources) { |
| 141 | direct_map_num = req_num - cb->max_crossbar_sources; | ||
| 142 | if (direct_map_num < cb->int_max) { | ||
| 143 | ret = cb->irq_map[direct_map_num]; | ||
| 144 | if (ret == IRQ_RESERVED || ret == IRQ_SKIP) { | ||
| 145 | /* We use the interrupt num as h/w irq num */ | ||
| 146 | ret = direct_map_num; | ||
| 147 | goto found; | ||
| 148 | } | ||
| 149 | } | ||
| 150 | |||
| 135 | pr_err("%s: requested crossbar number %d > max %d\n", | 151 | pr_err("%s: requested crossbar number %d > max %d\n", |
| 136 | __func__, req_num, cb->max_crossbar_sources); | 152 | __func__, req_num, cb->max_crossbar_sources); |
| 137 | return -EINVAL; | 153 | return -EINVAL; |
