diff options
Diffstat (limited to 'drivers/of')
-rw-r--r-- | drivers/of/irq.c | 59 |
1 files changed, 59 insertions, 0 deletions
diff --git a/drivers/of/irq.c b/drivers/of/irq.c index c90bd4ec3183..62cfdc2c86ac 100644 --- a/drivers/of/irq.c +++ b/drivers/of/irq.c @@ -682,3 +682,62 @@ u32 of_msi_map_rid(struct device *dev, struct device_node *msi_np, u32 rid_in) return rid_out; } + +static struct irq_domain *__of_get_msi_domain(struct device_node *np, + enum irq_domain_bus_token token) +{ + struct irq_domain *d; + + d = irq_find_matching_host(np, token); + if (!d) + d = irq_find_host(np); + + return d; +} + +/** + * of_msi_get_domain - Use msi-parent to find the relevant MSI domain + * @dev: device for which the domain is requested + * @np: device node for @dev + * @token: bus type for this domain + * + * Parse the msi-parent property (both the simple and the complex + * versions), and returns the corresponding MSI domain. + * + * Returns: the MSI domain for this device (or NULL on failure). + */ +struct irq_domain *of_msi_get_domain(struct device *dev, + struct device_node *np, + enum irq_domain_bus_token token) +{ + struct device_node *msi_np; + struct irq_domain *d; + + /* Check for a single msi-parent property */ + msi_np = of_parse_phandle(np, "msi-parent", 0); + if (msi_np && !of_property_read_bool(msi_np, "#msi-cells")) { + d = __of_get_msi_domain(msi_np, token); + if (!d) + of_node_put(msi_np); + return d; + } + + if (token == DOMAIN_BUS_PLATFORM_MSI) { + /* Check for the complex msi-parent version */ + struct of_phandle_args args; + int index = 0; + + while (!of_parse_phandle_with_args(np, "msi-parent", + "#msi-cells", + index, &args)) { + d = __of_get_msi_domain(args.np, token); + if (d) + return d; + + of_node_put(args.np); + index++; + } + } + + return NULL; +} |