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; |