This patch adds device connection parsing in of_platform_populate(). TODO: - How to free the devcon memories? - How to remove the devcon instances? Signed-off-by: Yoshihiro Shimoda <yoshihiro.shimoda.uh@xxxxxxxxxxx> --- drivers/of/platform.c | 66 +++++++++++++++++++++++++++++++++++++++++++++++++++ include/linux/of.h | 1 + 2 files changed, 67 insertions(+) diff --git a/drivers/of/platform.c b/drivers/of/platform.c index c00d81d..41c018d 100644 --- a/drivers/of/platform.c +++ b/drivers/of/platform.c @@ -17,6 +17,7 @@ #include <linux/slab.h> #include <linux/of_address.h> #include <linux/of_device.h> +#include <linux/of_graph.h> #include <linux/of_iommu.h> #include <linux/of_irq.h> #include <linux/of_platform.h> @@ -326,6 +327,63 @@ static const struct of_dev_auxdata *of_dev_lookup(const struct of_dev_auxdata *l return NULL; } +static int of_parse_device_connection(struct device_node *np) +{ + struct device_node *child_ep, *parent, *remote_parent; + struct platform_device *pdev, *remote_pdev; + struct device_connection *devcon = NULL; + const char *id; + + if (of_node_check_flag(np, OF_DEVICE_CONNECTED)) { + pr_debug("%s() - skipping %pOF, already device connected\n", + __func__, np); + return 0; + } + + of_node_set_flag(np, OF_DEVICE_CONNECTED); + + for_each_endpoint_of_node(np, child_ep) { + if (of_property_read_string(child_ep, "device-connection-id", + &id) < 0) + continue; + + remote_parent = of_graph_get_remote_port_parent(child_ep); + if (!remote_parent) + return 0; + + parent = of_graph_get_port_parent(child_ep); + if (!parent) + return 0; + + pdev = of_find_device_by_node(parent); + if (!pdev) + return 0; + + /* + * WARN_ON in really_probe() may happen if devm_kzalloc is + * used. TODO: How to free this? + */ + devcon = kzalloc(sizeof(*devcon), GFP_KERNEL); + if (!devcon) + return -ENOMEM; + + devcon->id = id; + remote_pdev = of_find_device_by_node(remote_parent); + if (!remote_pdev) { + kfree(devcon); + return 0; + } + + devcon->endpoint[0] = dev_name(&pdev->dev); + devcon->endpoint[1] = dev_name(&remote_pdev->dev); + + /* TODO: How to remove the connection? */ + device_connection_add(devcon); + } + + return 0; +} + /** * of_platform_bus_create() - Create a device for a node and its children. * @bus: device node of the bus to instantiate @@ -477,6 +535,14 @@ int of_platform_populate(struct device_node *root, } of_node_set_flag(root, OF_POPULATED_BUS); + for_each_child_of_node(root, child) { + rc = of_parse_device_connection(child); + if (rc) { + of_node_put(child); + break; + } + } + of_node_put(root); return rc; } diff --git a/include/linux/of.h b/include/linux/of.h index 4d25e4f..30aa103 100644 --- a/include/linux/of.h +++ b/include/linux/of.h @@ -143,6 +143,7 @@ static inline void of_node_put(struct device_node *node) { } #define OF_DETACHED 2 /* node has been detached from the device tree */ #define OF_POPULATED 3 /* device already created for the node */ #define OF_POPULATED_BUS 4 /* of_platform_populate recursed to children of this node */ +#define OF_DEVICE_CONNECTED 5 /* checked devcon on of_platform_populate */ #define OF_BAD_ADDR ((u64)-1) -- 1.9.1 -- To unsubscribe from this list: send the line "unsubscribe devicetree" in the body of a message to majordomo@xxxxxxxxxxxxxxx More majordomo info at http://vger.kernel.org/majordomo-info.html