aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--Documentation/devicetree/bindings/arm/omap/crossbar.txt12
-rw-r--r--drivers/irqchip/irq-crossbar.c20
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
45An interrupt consumer on an SoC using crossbar will use: 45An 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>
47request number shall be between 0 to that described by 47When 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
49request_number is greater than "ti,max-crossbar-sources", then it is mapped as a
50quirky hardware mapping direct to GIC.
49 51
50Example: 52Example:
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
87static inline bool needs_crossbar_write(irq_hw_number_t hw) 87static 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;