@@ -26,6 +26,8 @@
#include <linux/mutex.h>
#include <linux/freezer.h>
#include <linux/random.h>
+#include <linux/power_controller.h>
+#include <linux/usb/port.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
@@ -848,8 +850,15 @@ static unsigned hub_power_on(struct usb_hub *hub, bool do_delay)
else
dev_dbg(hub->intfdev, "trying to enable port power on "
"non-switchable hub\n");
- for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++)
+ for (port1 = 1; port1 <= hub->descriptor->bNbrPorts; port1++) {
+ struct usb_port *port = hub->ports[port1 - 1];
+ struct pc_dev_data *pc_data = dev_pc_get_data(&port->dev);
+
+ /* The power supply for this port isn't managed by bus only */
+ if (pc_data)
+ dev_pc_power_on(&port->dev);
set_port_feature(hub->hdev, port1, USB_PORT_FEAT_POWER);
+ }
/* Wait at least 100 msec for power to become stable */
delay = max(pgood_delay, (unsigned) 100);
@@ -1541,10 +1550,20 @@ static int hub_configure(struct usb_hub *hub,
if (hub->has_indicators && blinkenlights)
hub->indicator [0] = INDICATOR_CYCLE;
- for (i = 0; i < hdev->maxchild; i++)
+ for (i = 0; i < hdev->maxchild; i++) {
if (usb_hub_create_port_device(hub, i + 1) < 0)
dev_err(hub->intfdev,
"couldn't create port%d device.\n", i + 1);
+ else {
+ struct usb_port *port = hub->ports[i];
+ struct pc_dev_data *pc_data = dev_pc_get_data(&port->dev);
+ if (pc_data && pc_data->dev_data) {
+ struct usb_port_power_switch_data *up =
+ pc_data->dev_data;
+ usb_set_hub_port_connect_type(hdev, i + 1, up->type);
+ }
+ }
+ }
hub_activate(hub, HUB_INIT);
return 0;
@@ -1587,8 +1606,14 @@ static void hub_disconnect(struct usb_interface *intf)
usb_set_intfdata (intf, NULL);
- for (i = 0; i < hdev->maxchild; i++)
+ for (i = 0; i < hdev->maxchild; i++) {
+ struct usb_port *port = hub->ports[i];
+ struct pc_dev_data *pc_data = dev_pc_get_data(&port->dev);
+ if (pc_data)
+ dev_pc_power_off(&port->dev);
+
usb_hub_remove_port_device(hub, i + 1);
+ }
hub->hdev->maxchild = 0;
if (hub->hdev->speed == USB_SPEED_HIGH)
new file mode 100644
@@ -0,0 +1,16 @@
+#ifndef __USB_CORE_PORT_H
+#define __USB_CORE_PORT_H
+
+#include <linux/usb.h>
+
+/*
+ * Only used for describing power switch which provide power to
+ * hardwired self-powered device which attached to the port
+ */
+struct usb_port_power_switch_data {
+ int hub_tier; /* root hub is zero, next tier is 1, ... */
+ int port_number;
+ enum usb_port_connect_type type;
+};
+
+#endif
This patch applies the power controller on usb port, so that hub driver can power on one port which isn't provided power by bus. Cc: Andy Green <andy.green@linaro.org> Cc: Roger Quadros <rogerq@ti.com> Cc: Alan Stern <stern@rowland.harvard.edu> Cc: Felipe Balbi <balbi@ti.com> Signed-off-by: Ming Lei <tom.leiming@gmail.com> --- drivers/usb/core/hub.c | 31 ++++++++++++++++++++++++++++--- include/linux/usb/port.h | 16 ++++++++++++++++ 2 files changed, 44 insertions(+), 3 deletions(-) create mode 100644 include/linux/usb/port.h