@@ -35,8 +35,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 {
@@ -44,3 +46,9 @@ Example:
interrupts = <GIC_SPI 8 IRQ_TYPE_LEVEL_HIGH>;
...
};
+
+ device_y@0x4a033000 {
+ /* Direct mapped GIC SPI 1 used */
+ interrupts = <GIC_SPI 401 IRQ_TYPE_LEVEL_HIGH>;
+ ...
+ };
@@ -98,8 +98,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;
}
@@ -139,8 +144,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;