linux-kernel.vger.kernel.org archive mirror
 help / color / mirror / Atom feed
From: Peter Chen <peter.chen@nxp.com>
To: <gregkh@linuxfoundation.org>, <stern@rowland.harvard.edu>,
	<ulf.hansson@linaro.org>, <broonie@kernel.org>, <sre@kernel.org>,
	<robh+dt@kernel.org>, <shawnguo@kernel.org>,
	<dbaryshkov@gmail.com>, <dwmw3@infradead.org>
Cc: <k.kozlowski@samsung.com>, <linux-arm-kernel@lists.infradead.org>,
	<p.zabel@pengutronix.de>, <devicetree@vger.kernel.org>,
	<pawel.moll@arm.com>, <mark.rutland@arm.com>,
	<linux-usb@vger.kernel.org>, <arnd@arndb.de>,
	<s.hauer@pengutronix.de>, <mail@maciej.szmigiero.name>,
	<troy.kisky@boundarydevices.com>, <festevam@gmail.com>,
	<oscar@naiandei.net>, <stephen.boyd@linaro.org>,
	<linux-pm@vger.kernel.org>, <stillcompiling@gmail.com>,
	<linux-kernel@vger.kernel.org>, <mka@chromium.org>,
	<vaibhav.hiremath@linaro.org>, Peter Chen <peter.chen@nxp.com>
Subject: [PATCH v7 4/8] usb: core: add power sequence handling for USB devices
Date: Tue, 20 Sep 2016 11:36:43 +0800	[thread overview]
Message-ID: <1474342607-27512-5-git-send-email-peter.chen@nxp.com> (raw)
In-Reply-To: <1474342607-27512-1-git-send-email-peter.chen@nxp.com>

Some hard-wired USB devices need to do power sequence to let the
device work normally, the typical power sequence like: enable USB
PHY clock, toggle reset pin, etc. But current Linux USB driver
lacks of such code to do it, it may cause some hard-wired USB devices
works abnormal or can't be recognized by controller at all.

In this patch, it calls power sequence library APIs to finish
the power sequence events. It will do power on sequence at hub's
probe for all devices under this hub (includes root hub).
At hub_disconnect, it will do power off sequence which is at powered
on list.

Signed-off-by: Peter Chen <peter.chen@nxp.com>
Tested-by Joshua Clayton <stillcompiling@gmail.com>
---
 drivers/usb/core/hub.c | 41 ++++++++++++++++++++++++++++++++++++++---
 drivers/usb/core/hub.h |  1 +
 2 files changed, 39 insertions(+), 3 deletions(-)

diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index b48dc76..f3de1de 100644
--- a/drivers/usb/core/hub.c
+++ b/drivers/usb/core/hub.c
@@ -26,6 +26,7 @@
 #include <linux/mutex.h>
 #include <linux/random.h>
 #include <linux/pm_qos.h>
+#include <linux/power/pwrseq.h>
 
 #include <asm/uaccess.h>
 #include <asm/byteorder.h>
@@ -1695,6 +1696,7 @@ static void hub_disconnect(struct usb_interface *intf)
 	hub->error = 0;
 	hub_quiesce(hub, HUB_DISCONNECT);
 
+	of_pwrseq_off_list(&hub->pwrseq_on_list);
 	mutex_lock(&usb_port_peer_mutex);
 
 	/* Avoid races with recursively_mark_NOTATTACHED() */
@@ -1722,12 +1724,41 @@ static void hub_disconnect(struct usb_interface *intf)
 	kref_put(&hub->kref, hub_release);
 }
 
+#ifdef CONFIG_OF
+static int hub_of_pwrseq_on(struct usb_hub *hub)
+{
+	struct device *parent;
+	struct usb_device *hdev = hub->hdev;
+	struct device_node *np;
+	int ret;
+
+	if (hdev->parent)
+		parent = &hdev->dev;
+	else
+		parent = bus_to_hcd(hdev->bus)->self.controller;
+
+	for_each_child_of_node(parent->of_node, np) {
+		ret = of_pwrseq_on_list(np, &hub->pwrseq_on_list);
+		if (ret)
+			return ret;
+	}
+
+	return 0;
+}
+#else
+static int hub_of_pwrseq_on(struct usb_hub *hub)
+{
+	return 0;
+}
+#endif
+
 static int hub_probe(struct usb_interface *intf, const struct usb_device_id *id)
 {
 	struct usb_host_interface *desc;
 	struct usb_endpoint_descriptor *endpoint;
 	struct usb_device *hdev;
 	struct usb_hub *hub;
+	int ret = -ENODEV;
 
 	desc = intf->cur_altsetting;
 	hdev = interface_to_usbdev(intf);
@@ -1832,6 +1863,7 @@ descriptor_error:
 	INIT_DELAYED_WORK(&hub->leds, led_work);
 	INIT_DELAYED_WORK(&hub->init_work, NULL);
 	INIT_WORK(&hub->events, hub_event);
+	INIT_LIST_HEAD(&hub->pwrseq_on_list);
 	usb_get_intf(intf);
 	usb_get_dev(hdev);
 
@@ -1845,11 +1877,14 @@ descriptor_error:
 	if (id->driver_info & HUB_QUIRK_CHECK_PORT_AUTOSUSPEND)
 		hub->quirk_check_port_auto_suspend = 1;
 
-	if (hub_configure(hub, endpoint) >= 0)
-		return 0;
+	if (hub_configure(hub, endpoint) >= 0) {
+		ret = hub_of_pwrseq_on(hub);
+		if (!ret)
+			return 0;
+	}
 
 	hub_disconnect(intf);
-	return -ENODEV;
+	return ret;
 }
 
 static int
diff --git a/drivers/usb/core/hub.h b/drivers/usb/core/hub.h
index 34c1a7e..cd86f91 100644
--- a/drivers/usb/core/hub.h
+++ b/drivers/usb/core/hub.h
@@ -78,6 +78,7 @@ struct usb_hub {
 	struct delayed_work	init_work;
 	struct work_struct      events;
 	struct usb_port		**ports;
+	struct list_head	pwrseq_on_list; /* powered pwrseq node list */
 };
 
 /**
-- 
2.7.4

  parent reply	other threads:[~2016-09-20  3:37 UTC|newest]

Thread overview: 17+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2016-09-20  3:36 [PATCH v7 0/8] power: add power sequence library Peter Chen
2016-09-20  3:36 ` [PATCH v7 1/8] binding-doc: power: pwrseq-generic: add binding doc for generic " Peter Chen
2016-09-20  3:36 ` [PATCH v7 2/8] power: add " Peter Chen
2016-10-12 10:30   ` Heiko Stuebner
2016-10-13  1:22     ` Peter Chen
2016-10-13  7:04       ` Heiko Stuebner
2016-10-13  8:57         ` Peter Chen
2016-09-20  3:36 ` [PATCH v7 3/8] binding-doc: usb: usb-device: add optional properties for power sequence Peter Chen
2016-09-20  3:36 ` Peter Chen [this message]
2016-09-20  3:36 ` [PATCH v7 5/8] usb: chipidea: let chipidea core device of_node equal's glue layer device of_node Peter Chen
2016-09-20  3:36 ` [PATCH v7 6/8] ARM: dts: imx6qdl: Enable usb node children with <reg> Peter Chen
2016-09-20  3:36 ` [PATCH v7 7/8] ARM: dts: imx6qdl-udoo.dtsi: fix onboard USB HUB property Peter Chen
2016-09-20  3:36 ` [PATCH v7 8/8] ARM: dts: imx6q-evi: Fix onboard hub reset line Peter Chen
2016-09-26  6:26 ` [PATCH v7 0/8] power: add power sequence library Peter Chen
2016-10-08  8:56   ` Peter Chen
2016-09-27 23:30 ` Maciej S. Szmigiero
2016-09-27 23:53   ` Peter Chen

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=1474342607-27512-5-git-send-email-peter.chen@nxp.com \
    --to=peter.chen@nxp.com \
    --cc=arnd@arndb.de \
    --cc=broonie@kernel.org \
    --cc=dbaryshkov@gmail.com \
    --cc=devicetree@vger.kernel.org \
    --cc=dwmw3@infradead.org \
    --cc=festevam@gmail.com \
    --cc=gregkh@linuxfoundation.org \
    --cc=k.kozlowski@samsung.com \
    --cc=linux-arm-kernel@lists.infradead.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux-pm@vger.kernel.org \
    --cc=linux-usb@vger.kernel.org \
    --cc=mail@maciej.szmigiero.name \
    --cc=mark.rutland@arm.com \
    --cc=mka@chromium.org \
    --cc=oscar@naiandei.net \
    --cc=p.zabel@pengutronix.de \
    --cc=pawel.moll@arm.com \
    --cc=robh+dt@kernel.org \
    --cc=s.hauer@pengutronix.de \
    --cc=shawnguo@kernel.org \
    --cc=sre@kernel.org \
    --cc=stephen.boyd@linaro.org \
    --cc=stern@rowland.harvard.edu \
    --cc=stillcompiling@gmail.com \
    --cc=troy.kisky@boundarydevices.com \
    --cc=ulf.hansson@linaro.org \
    --cc=vaibhav.hiremath@linaro.org \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).