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. An interrupt consumer on an SoC using crossbar will use: interrupts = <GIC_SPI request_number interrupt_level> -request number shall be between 0 to that described by -"ti,max-crossbar-sources" +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 { @@ -53,3 +55,9 @@ Example: 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>; + ... + }; 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) static inline bool needs_crossbar_write(irq_hw_number_t hw) { - if (hw > GIC_IRQ_START) - return true; + int cb_no; + + if (hw > GIC_IRQ_START) { + cb_no = cb->irq_map[hw - GIC_IRQ_START]; + if (cb_no != IRQ_RESERVED && cb_no != IRQ_SKIP) + return true; + } return false; } @@ -130,8 +135,19 @@ static int crossbar_domain_xlate(struct irq_domain *d, { int ret; int req_num = intspec[1]; + int direct_map_num; if (req_num >= cb->max_crossbar_sources) { + direct_map_num = req_num - cb->max_crossbar_sources; + if (direct_map_num < cb->int_max) { + ret = cb->irq_map[direct_map_num]; + if (ret == IRQ_RESERVED || ret == IRQ_SKIP) { + /* We use the interrupt num as h/w irq num */ + ret = direct_map_num; + goto found; + } + } + pr_err("%s: requested crossbar number %d > max %d\n", __func__, req_num, cb->max_crossbar_sources); return -EINVAL; |