From 80e04837a40f6f1c8e93437be3f772c967a41d2f Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 13 Feb 2019 10:45:56 +0300 Subject: device connection: Prepare support for firmware described connections When the connections are defined in firmware, struct device_connection will have the fwnode member pointing to the device node (struct fwnode_handle) of the requested device. The endpoint member for the device names will not be used at all in that case. Acked-by: Hans de Goede Reviewed-by: Andy Shevchenko Reviewed-by: Jun Li Tested-by: Jun Li Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/base/devcon.c | 24 ++++++++++++++++++++++++ 1 file changed, 24 insertions(+) (limited to 'drivers/base') diff --git a/drivers/base/devcon.c b/drivers/base/devcon.c index d427e806cd73..858b8d2f6ef8 100644 --- a/drivers/base/devcon.c +++ b/drivers/base/devcon.c @@ -75,12 +75,36 @@ static struct bus_type *generic_match_buses[] = { NULL, }; +static int device_fwnode_match(struct device *dev, void *fwnode) +{ + return dev_fwnode(dev) == fwnode; +} + +static void *device_connection_fwnode_match(struct device_connection *con) +{ + struct bus_type *bus; + struct device *dev; + + for (bus = generic_match_buses[0]; bus; bus++) { + dev = bus_find_device(bus, NULL, (void *)con->fwnode, + device_fwnode_match); + if (dev && !strncmp(dev_name(dev), con->id, strlen(con->id))) + return dev; + + put_device(dev); + } + return NULL; +} + /* This tries to find the device from the most common bus types by name. */ static void *generic_match(struct device_connection *con, int ep, void *data) { struct bus_type *bus; struct device *dev; + if (con->fwnode) + return device_connection_fwnode_match(con); + for (bus = generic_match_buses[0]; bus; bus++) { dev = bus_find_device_by_name(bus, NULL, con->endpoint[ep]); if (dev) -- cgit From 637e9e52b185e5b10372366bd6db97f27cf3f202 Mon Sep 17 00:00:00 2001 From: Heikki Krogerus Date: Wed, 13 Feb 2019 10:45:57 +0300 Subject: device connection: Find device connections also from device graphs If connections between devices are described in OF graph or ACPI device graph, we can find them by using the fwnode_graph_*() functions. Acked-by: Hans de Goede Reviewed-by: Andy Shevchenko Reviewed-by: Jun Li Tested-by: Jun Li Signed-off-by: Heikki Krogerus Signed-off-by: Greg Kroah-Hartman --- drivers/base/devcon.c | 38 +++++++++++++++++++++++++++++++++++--- 1 file changed, 35 insertions(+), 3 deletions(-) (limited to 'drivers/base') diff --git a/drivers/base/devcon.c b/drivers/base/devcon.c index 858b8d2f6ef8..04db9ae235e4 100644 --- a/drivers/base/devcon.c +++ b/drivers/base/devcon.c @@ -7,10 +7,37 @@ */ #include +#include static DEFINE_MUTEX(devcon_lock); static LIST_HEAD(devcon_list); +typedef void *(*devcon_match_fn_t)(struct device_connection *con, int ep, + void *data); + +static void * +fwnode_graph_devcon_match(struct fwnode_handle *fwnode, const char *con_id, + void *data, devcon_match_fn_t match) +{ + struct device_connection con = { .id = con_id }; + struct fwnode_handle *ep; + void *ret; + + fwnode_graph_for_each_endpoint(fwnode, ep) { + con.fwnode = fwnode_graph_get_remote_port_parent(ep); + if (!fwnode_device_is_available(con.fwnode)) + continue; + + ret = match(&con, -1, data); + fwnode_handle_put(con.fwnode); + if (ret) { + fwnode_handle_put(ep); + return ret; + } + } + return NULL; +} + /** * device_connection_find_match - Find physical connection to a device * @dev: Device with the connection @@ -23,10 +50,9 @@ static LIST_HEAD(devcon_list); * caller is expecting to be returned. */ void *device_connection_find_match(struct device *dev, const char *con_id, - void *data, - void *(*match)(struct device_connection *con, - int ep, void *data)) + void *data, devcon_match_fn_t match) { + struct fwnode_handle *fwnode = dev_fwnode(dev); const char *devname = dev_name(dev); struct device_connection *con; void *ret = NULL; @@ -35,6 +61,12 @@ void *device_connection_find_match(struct device *dev, const char *con_id, if (!match) return NULL; + if (fwnode) { + ret = fwnode_graph_devcon_match(fwnode, con_id, data, match); + if (ret) + return ret; + } + mutex_lock(&devcon_lock); list_for_each_entry(con, &devcon_list, list) { -- cgit