Commit 4f04c210 authored by Rafał Miłecki's avatar Rafał Miłecki Committed by Greg Kroah-Hartman

usb: core: read USB ports from DT in the usbport LED trigger driver

This uses DT info to read relation description of LEDs and USB ports. If
DT has properly described LEDs, trigger will know when to turn them on.
Signed-off-by: default avatarRafał Miłecki <rafal@milecki.pl>
Signed-off-by: default avatarGreg Kroah-Hartman <gregkh@linuxfoundation.org>
parent 80dc6e1c
...@@ -11,8 +11,10 @@ ...@@ -11,8 +11,10 @@
#include <linux/device.h> #include <linux/device.h>
#include <linux/leds.h> #include <linux/leds.h>
#include <linux/module.h> #include <linux/module.h>
#include <linux/of.h>
#include <linux/slab.h> #include <linux/slab.h>
#include <linux/usb.h> #include <linux/usb.h>
#include <linux/usb/of.h>
struct usbport_trig_data { struct usbport_trig_data {
struct led_classdev *led_cdev; struct led_classdev *led_cdev;
...@@ -123,6 +125,57 @@ static const struct attribute_group ports_group = { ...@@ -123,6 +125,57 @@ static const struct attribute_group ports_group = {
* Adding & removing ports * Adding & removing ports
***************************************/ ***************************************/
/**
* usbport_trig_port_observed - Check if port should be observed
*/
static bool usbport_trig_port_observed(struct usbport_trig_data *usbport_data,
struct usb_device *usb_dev, int port1)
{
struct device *dev = usbport_data->led_cdev->dev;
struct device_node *led_np = dev->of_node;
struct of_phandle_args args;
struct device_node *port_np;
int count, i;
if (!led_np)
return false;
/* Get node of port being added */
port_np = usb_of_get_child_node(usb_dev->dev.of_node, port1);
if (!port_np)
return false;
/* Amount of trigger sources for this LED */
count = of_count_phandle_with_args(led_np, "trigger-sources",
"#trigger-source-cells");
if (count < 0) {
dev_warn(dev, "Failed to get trigger sources for %s\n",
led_np->full_name);
return false;
}
/* Check list of sources for this specific port */
for (i = 0; i < count; i++) {
int err;
err = of_parse_phandle_with_args(led_np, "trigger-sources",
"#trigger-source-cells", i,
&args);
if (err) {
dev_err(dev, "Failed to get trigger source phandle at index %d: %d\n",
i, err);
continue;
}
of_node_put(args.np);
if (args.np == port_np)
return true;
}
return false;
}
static int usbport_trig_add_port(struct usbport_trig_data *usbport_data, static int usbport_trig_add_port(struct usbport_trig_data *usbport_data,
struct usb_device *usb_dev, struct usb_device *usb_dev,
const char *hub_name, int portnum) const char *hub_name, int portnum)
...@@ -141,6 +194,8 @@ static int usbport_trig_add_port(struct usbport_trig_data *usbport_data, ...@@ -141,6 +194,8 @@ static int usbport_trig_add_port(struct usbport_trig_data *usbport_data,
port->data = usbport_data; port->data = usbport_data;
port->hub = usb_dev; port->hub = usb_dev;
port->portnum = portnum; port->portnum = portnum;
port->observed = usbport_trig_port_observed(usbport_data, usb_dev,
portnum);
len = strlen(hub_name) + 8; len = strlen(hub_name) + 8;
port->port_name = kzalloc(len, GFP_KERNEL); port->port_name = kzalloc(len, GFP_KERNEL);
...@@ -255,6 +310,7 @@ static void usbport_trig_activate(struct led_classdev *led_cdev) ...@@ -255,6 +310,7 @@ static void usbport_trig_activate(struct led_classdev *led_cdev)
if (err) if (err)
goto err_free; goto err_free;
usb_for_each_dev(usbport_data, usbport_trig_add_usb_dev_ports); usb_for_each_dev(usbport_data, usbport_trig_add_usb_dev_ports);
usbport_trig_update_count(usbport_data);
/* Notifications */ /* Notifications */
usbport_data->nb.notifier_call = usbport_trig_notify, usbport_data->nb.notifier_call = usbport_trig_notify,
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment