From patchwork Sun Dec 2 15:01:05 2012 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ming Lei X-Patchwork-Id: 1830911 Return-Path: X-Original-To: patchwork-linux-pm@patchwork.kernel.org Delivered-To: patchwork-process-083081@patchwork1.kernel.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by patchwork1.kernel.org (Postfix) with ESMTP id 54B823FCA5 for ; Sun, 2 Dec 2012 15:02:23 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753156Ab2LBPCW (ORCPT ); Sun, 2 Dec 2012 10:02:22 -0500 Received: from mail-pb0-f46.google.com ([209.85.160.46]:56131 "EHLO mail-pb0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752017Ab2LBPCV (ORCPT ); Sun, 2 Dec 2012 10:02:21 -0500 Received: by mail-pb0-f46.google.com with SMTP id wy7so1445313pbc.19 for ; Sun, 02 Dec 2012 07:02:21 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=gmail.com; s=20120113; h=from:to:cc:subject:date:message-id:x-mailer:in-reply-to:references; bh=gim0NDEWTEE3D+rsFJbc0RGdztj8RViJNXmEju8mkjY=; b=I6NaCGtH7fZBSbC6g6uEXHEA/kYKnW7S/6Yj3UQuCv+d8rpJOqkT4/TOcNjgzT/Xe8 8as7XbyStJ1Hb3YmeQ+jT31upQHXHK0geH2JjWG5LknqO2C9YqWlkDCe0z4VimtMnP+7 fCxhRTzRhhRmclfV75gGKatop0VR//dhLi+RqSb7p0ku43GWSrWMH/EYhK3IXJOS4maC tc3IXXw3YIDENt4MA2kxAvOogAWtVM4K8R3pbetIS+6BCNmlZdUAZuNsjRO1OXV8cP3z ZacU3km9Eg314fsuY+JX0X8GgRzUdX/9bY2FXuwoMG9J0RnaWg6Stngz4Uo++9H8PtPA 7oKw== Received: by 10.68.143.201 with SMTP id sg9mr22049955pbb.32.1354460541573; Sun, 02 Dec 2012 07:02:21 -0800 (PST) Received: from localhost ([183.37.207.193]) by mx.google.com with ESMTPS id s7sm6409560paz.7.2012.12.02.07.02.12 (version=TLSv1/SSLv3 cipher=OTHER); Sun, 02 Dec 2012 07:02:20 -0800 (PST) From: Ming Lei To: Alan Stern , Greg Kroah-Hartman Cc: Lan Tianyu , Sarah Sharp , "Rafael J. Wysocki" , linux-pm@vger.kernel.org, Oliver Neukum , linux-omap@vger.kernel.org, linux-usb@vger.kernel.org, Ming Lei , Andy Green , Roger Quadros , Felipe Balbi Subject: [RFC PATCH 3/5] USB: hub: apply power controller on usb port Date: Sun, 2 Dec 2012 23:01:05 +0800 Message-Id: <1354460467-28006-4-git-send-email-tom.leiming@gmail.com> X-Mailer: git-send-email 1.7.9.5 In-Reply-To: <1354460467-28006-1-git-send-email-tom.leiming@gmail.com> References: <1354460467-28006-1-git-send-email-tom.leiming@gmail.com> Sender: linux-pm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pm@vger.kernel.org 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 Cc: Roger Quadros Cc: Alan Stern Cc: Felipe Balbi Signed-off-by: Ming Lei --- 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 diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c index a815fd2..f8075d7 100644 --- a/drivers/usb/core/hub.c +++ b/drivers/usb/core/hub.c @@ -26,6 +26,8 @@ #include #include #include +#include +#include #include #include @@ -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) diff --git a/include/linux/usb/port.h b/include/linux/usb/port.h new file mode 100644 index 0000000..a853d5e --- /dev/null +++ b/include/linux/usb/port.h @@ -0,0 +1,16 @@ +#ifndef __USB_CORE_PORT_H +#define __USB_CORE_PORT_H + +#include + +/* + * 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