[RFC PATCH 3/5] usb: hub: add device_path regulator control to generic hub

[Date Prev][Date Next][Thread Prev][Thread Next][Date Index][Thread Index]

 



This adds the config option to associate a regulator with each hub,
when the hub on a specific, interesting device path appears, then
the regular is powered while the logical hub exists.

Signed-off-by: Andy Green <andy.green@xxxxxxxxxx>
---
 drivers/usb/core/Kconfig |   10 ++++++++++
 drivers/usb/core/hub.c   |   26 +++++++++++++++++++++++++-
 2 files changed, 35 insertions(+), 1 deletion(-)

diff --git a/drivers/usb/core/Kconfig b/drivers/usb/core/Kconfig
index f70c1a1..4a91eb1 100644
--- a/drivers/usb/core/Kconfig
+++ b/drivers/usb/core/Kconfig
@@ -95,3 +95,13 @@ config USB_OTG_BLACKLIST_HUB
 	  and software costs by not supporting external hubs.  So
 	  are "Embedded Hosts" that don't offer OTG support.
 
+config USB_HUB_DEVICE_PATH_REGULATOR
+	bool "Support generic regulators at hubs"
+	select DEVICEPATH
+	depends on USB
+	default n
+	help
+	  Allows you to use the device_path APIs to associate kernel regulators
+	  with dynamically probed USB hubs, so the regulators are enabled
+	  as the appropriate hub instance gets created and disabled as it
+	  is destroyed.
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index a815fd2..49ebb5e 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -26,6 +26,7 @@
 #include <linux/mutex.h>
 #include <linux/freezer.h>
 #include <linux/random.h>
+#include <linux/regulator/consumer.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
@@ -54,7 +55,9 @@ struct usb_hub {
 	struct usb_device	*hdev;
 	struct kref		kref;
 	struct urb		*urb;		/* for interrupt polling pipe */
-
+#ifdef CONFIG_USB_HUB_DEVICE_PATH_REGULATOR
+	struct regulator	*regulator;	/* optional power control */
+#endif
 	/* buffer for urb ... with extra space in case of babble */
 	char			(*buffer)[8];
 	union {
@@ -1594,6 +1597,12 @@ static void hub_disconnect(struct usb_interface *intf)
 	if (hub->hdev->speed == USB_SPEED_HIGH)
 		highspeed_hubs--;
 
+#ifdef CONFIG_USB_HUB_DEVICE_PATH_REGULATOR
+	if (hub->regulator && !IS_ERR(hub->regulator)) {
+		regulator_disable(hub->regulator);
+		regulator_put(hub->regulator);
+	}
+#endif
 	usb_free_urb(hub->urb);
 	kfree(hub->ports);
 	kfree(hub->descriptor);
@@ -1609,6 +1618,9 @@ static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_device *hdev;
 	struct usb_hub *hub;
+#ifdef CONFIG_USB_HUB_DEVICE_PATH_REGULATOR
+	char *dev_path;
+#endif
 
 	desc = intf->cur_altsetting;
 	hdev = interface_to_usbdev(intf);
@@ -1692,6 +1704,18 @@ descriptor_error:
 		return -ENOMEM;
 	}
 
+#ifdef CONFIG_USB_HUB_DEVICE_PATH_REGULATOR
+	/* if a regulator is associated on our device_path, use it */
+	dev_path = kmalloc(MAX_DEV_PATH_SIZE, GFP_KERNEL);
+	if (!device_path_generate(&hdev->dev, dev_path, MAX_DEV_PATH_SIZE)) {
+		dev_info(&hdev->dev, "device_path: %s\n", dev_path);
+		hub->regulator = regulator_get(&hdev->dev, dev_path);
+		if (!IS_ERR(hub->regulator))
+			regulator_enable(hub->regulator);
+	}
+	kfree(dev_path);
+#endif
+
 	kref_init(&hub->kref);
 	INIT_LIST_HEAD(&hub->event_list);
 	hub->intfdev = &intf->dev;

--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo@xxxxxxxxxxxxxxx
More majordomo info at  http://vger.kernel.org/majordomo-info.html


[Index of Archives]     [Linux Media]     [Linux Input]     [Linux Audio Users]     [Yosemite News]     [Linux Kernel]     [Linux SCSI]     [Old Linux USB Devel Archive]

  Powered by Linux