Rebased from upstream / out of band repository.
[librecmc/librecmc.git] / target / linux / generic / backport-4.9 / 082-0001-usb-core-read-USB-ports-from-DT-in-the-usbport-LED-t.patch
1 From 4f04c210d031667e503d6538a72345a36f3b5d71 Mon Sep 17 00:00:00 2001
2 From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
3 Date: Thu, 8 Jun 2017 18:08:32 +0200
4 Subject: [PATCH] usb: core: read USB ports from DT in the usbport LED trigger
5  driver
6 MIME-Version: 1.0
7 Content-Type: text/plain; charset=UTF-8
8 Content-Transfer-Encoding: 8bit
9
10 This uses DT info to read relation description of LEDs and USB ports. If
11 DT has properly described LEDs, trigger will know when to turn them on.
12
13 Signed-off-by: Rafał Miłecki <rafal@milecki.pl>
14 Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
15 ---
16  drivers/usb/core/ledtrig-usbport.c | 56 ++++++++++++++++++++++++++++++++++++++
17  1 file changed, 56 insertions(+)
18
19 --- a/drivers/usb/core/ledtrig-usbport.c
20 +++ b/drivers/usb/core/ledtrig-usbport.c
21 @@ -11,8 +11,10 @@
22  #include <linux/device.h>
23  #include <linux/leds.h>
24  #include <linux/module.h>
25 +#include <linux/of.h>
26  #include <linux/slab.h>
27  #include <linux/usb.h>
28 +#include <linux/usb/of.h>
29  
30  struct usbport_trig_data {
31         struct led_classdev *led_cdev;
32 @@ -123,6 +125,57 @@ static const struct attribute_group port
33   * Adding & removing ports
34   ***************************************/
35  
36 +/**
37 + * usbport_trig_port_observed - Check if port should be observed
38 + */
39 +static bool usbport_trig_port_observed(struct usbport_trig_data *usbport_data,
40 +                                      struct usb_device *usb_dev, int port1)
41 +{
42 +       struct device *dev = usbport_data->led_cdev->dev;
43 +       struct device_node *led_np = dev->of_node;
44 +       struct of_phandle_args args;
45 +       struct device_node *port_np;
46 +       int count, i;
47 +
48 +       if (!led_np)
49 +               return false;
50 +
51 +       /* Get node of port being added */
52 +       port_np = usb_of_get_child_node(usb_dev->dev.of_node, port1);
53 +       if (!port_np)
54 +               return false;
55 +
56 +       /* Amount of trigger sources for this LED */
57 +       count = of_count_phandle_with_args(led_np, "trigger-sources",
58 +                                          "#trigger-source-cells");
59 +       if (count < 0) {
60 +               dev_warn(dev, "Failed to get trigger sources for %s\n",
61 +                        led_np->full_name);
62 +               return false;
63 +       }
64 +
65 +       /* Check list of sources for this specific port */
66 +       for (i = 0; i < count; i++) {
67 +               int err;
68 +
69 +               err = of_parse_phandle_with_args(led_np, "trigger-sources",
70 +                                                "#trigger-source-cells", i,
71 +                                                &args);
72 +               if (err) {
73 +                       dev_err(dev, "Failed to get trigger source phandle at index %d: %d\n",
74 +                               i, err);
75 +                       continue;
76 +               }
77 +
78 +               of_node_put(args.np);
79 +
80 +               if (args.np == port_np)
81 +                       return true;
82 +       }
83 +
84 +       return false;
85 +}
86 +
87  static int usbport_trig_add_port(struct usbport_trig_data *usbport_data,
88                                  struct usb_device *usb_dev,
89                                  const char *hub_name, int portnum)
90 @@ -141,6 +194,8 @@ static int usbport_trig_add_port(struct
91         port->data = usbport_data;
92         port->hub = usb_dev;
93         port->portnum = portnum;
94 +       port->observed = usbport_trig_port_observed(usbport_data, usb_dev,
95 +                                                   portnum);
96  
97         len = strlen(hub_name) + 8;
98         port->port_name = kzalloc(len, GFP_KERNEL);
99 @@ -255,6 +310,7 @@ static void usbport_trig_activate(struct
100         if (err)
101                 goto err_free;
102         usb_for_each_dev(usbport_data, usbport_trig_add_usb_dev_ports);
103 +       usbport_trig_update_count(usbport_data);
104  
105         /* Notifications */
106         usbport_data->nb.notifier_call = usbport_trig_notify,