You can not select more than 25 topics
Topics must start with a letter or number, can include dashes ('-') and can be up to 35 characters long.
107 lines
3.1 KiB
107 lines
3.1 KiB
![]()
7 years ago
|
From 4f04c210d031667e503d6538a72345a36f3b5d71 Mon Sep 17 00:00:00 2001
|
||
|
From: =?UTF-8?q?Rafa=C5=82=20Mi=C5=82ecki?= <rafal@milecki.pl>
|
||
|
Date: Thu, 8 Jun 2017 18:08:32 +0200
|
||
|
Subject: [PATCH] usb: core: read USB ports from DT in the usbport LED trigger
|
||
|
driver
|
||
|
MIME-Version: 1.0
|
||
|
Content-Type: text/plain; charset=UTF-8
|
||
|
Content-Transfer-Encoding: 8bit
|
||
|
|
||
|
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: Rafał Miłecki <rafal@milecki.pl>
|
||
|
Signed-off-by: Greg Kroah-Hartman <gregkh@linuxfoundation.org>
|
||
|
---
|
||
|
drivers/usb/core/ledtrig-usbport.c | 56 ++++++++++++++++++++++++++++++++++++++
|
||
|
1 file changed, 56 insertions(+)
|
||
|
|
||
|
--- a/drivers/usb/core/ledtrig-usbport.c
|
||
|
+++ b/drivers/usb/core/ledtrig-usbport.c
|
||
|
@@ -11,8 +11,10 @@
|
||
|
#include <linux/device.h>
|
||
|
#include <linux/leds.h>
|
||
|
#include <linux/module.h>
|
||
|
+#include <linux/of.h>
|
||
|
#include <linux/slab.h>
|
||
|
#include <linux/usb.h>
|
||
|
+#include <linux/usb/of.h>
|
||
|
|
||
|
struct usbport_trig_data {
|
||
|
struct led_classdev *led_cdev;
|
||
|
@@ -123,6 +125,57 @@ static const struct attribute_group port
|
||
|
* 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,
|
||
|
struct usb_device *usb_dev,
|
||
|
const char *hub_name, int portnum)
|
||
|
@@ -141,6 +194,8 @@ static int usbport_trig_add_port(struct
|
||
|
port->data = usbport_data;
|
||
|
port->hub = usb_dev;
|
||
|
port->portnum = portnum;
|
||
|
+ port->observed = usbport_trig_port_observed(usbport_data, usb_dev,
|
||
|
+ portnum);
|
||
|
|
||
|
len = strlen(hub_name) + 8;
|
||
|
port->port_name = kzalloc(len, GFP_KERNEL);
|
||
|
@@ -255,6 +310,7 @@ static void usbport_trig_activate(struct
|
||
|
if (err)
|
||
|
goto err_free;
|
||
|
usb_for_each_dev(usbport_data, usbport_trig_add_usb_dev_ports);
|
||
|
+ usbport_trig_update_count(usbport_data);
|
||
|
|
||
|
/* Notifications */
|
||
|
usbport_data->nb.notifier_call = usbport_trig_notify,
|