|
@@ -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;
|
|
|
+}
|