From: Peter Chen <peter.chen-3arQi8VN3Tc@public.gmane.org>
To: gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org,
stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz@public.gmane.org,
ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
sre-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org,
robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org
Cc: k.kozlowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org,
linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org,
p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org,
devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org,
pawel.moll-5wv7dgnIgG8@public.gmane.org,
mark.rutland-5wv7dgnIgG8@public.gmane.org,
linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
arnd-r2nGTMty4D4@public.gmane.org,
s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org,
mail-APzI5cXaD1zVlRWJc41N0YvC60bnQu0Y@public.gmane.org,
troy.kisky-Q5RJGjKts06CY9SHAMCTRUEOCMrvLtNR@public.gmane.org,
festevam-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org,
oscar-Bdbr4918Nnnk1uMJSBkQmQ@public.gmane.org,
stephen.boyd-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org,
linux-pm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
linux-mmc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org,
Peter Chen <peter.chen-3arQi8VN3Tc@public.gmane.org>
Subject: [PATCH 10/12] usb: core: add power sequence handling for USB devices
Date: Fri, 17 Jun 2016 18:09:23 +0800 [thread overview]
Message-ID: <1466158165-9380-11-git-send-email-peter.chen@nxp.com> (raw)
In-Reply-To: <1466158165-9380-1-git-send-email-peter.chen-3arQi8VN3Tc@public.gmane.org>
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 will do power on sequence at hub's probe for all
devices under this hub (includes root hub) if this device is described
at dts and there is a phandle "usb-pwrseq" for it.
At hub_disconnect, it will do power off sequence which is at powered on
list.
Signed-off-by: Peter Chen <peter.chen-3arQi8VN3Tc@public.gmane.org>
---
drivers/usb/core/hub.c | 73 +++++++++++++++++++++++++++++++++++++++++++++++---
drivers/usb/core/hub.h | 1 +
include/linux/pwrseq.h | 6 +++++
3 files changed, 77 insertions(+), 3 deletions(-)
diff --git a/drivers/usb/core/hub.c b/drivers/usb/core/hub.c
index bee1351..cc0f942 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/pwrseq.h>
#include <asm/uaccess.h>
#include <asm/byteorder.h>
@@ -1684,6 +1685,66 @@ static void hub_release(struct kref *kref)
static unsigned highspeed_hubs;
+static void hub_of_pwrseq_off(struct usb_interface *intf)
+{
+ struct usb_hub *hub = usb_get_intfdata(intf);
+ struct pwrseq *hdev_pwrseq;
+ struct pwrseq_node_powered_on *pwrseq_node, *tmp_node;
+
+ list_for_each_entry_safe(pwrseq_node, tmp_node,
+ &hub->pwrseq_list, list) {
+ hdev_pwrseq = pwrseq_node->pwrseq_on;
+ pwrseq_power_off(hdev_pwrseq);
+ list_del(&pwrseq_node->list);
+ pwrseq_free(hdev_pwrseq);
+ kfree(pwrseq_node);
+ }
+}
+
+static int hub_of_pwrseq_on(struct usb_interface *intf)
+{
+ struct device *parent;
+ struct device_node *node;
+ struct pwrseq *hdev_pwrseq;
+ struct usb_device *hdev = interface_to_usbdev(intf);
+ struct usb_hub *hub = usb_get_intfdata(intf);
+ struct pwrseq_node_powered_on *pwrseq_node;
+ int ret = 0;
+
+ if (hdev->parent)
+ parent = &hdev->dev;
+ else
+ parent = bus_to_hcd(hdev->bus)->self.controller;
+
+ for_each_child_of_node(parent->of_node, node) {
+ hdev_pwrseq = pwrseq_alloc(node, "usb-pwrseq");
+ if (!IS_ERR_OR_NULL(hdev_pwrseq)) {
+ pwrseq_node = kzalloc(sizeof(pwrseq_node), GFP_KERNEL);
+ if (!pwrseq_node) {
+ ret = -ENOMEM;
+ goto err1;
+ }
+ /* power on sequence */
+ ret = pwrseq_pre_power_on(hdev_pwrseq);
+ if (ret)
+ goto err2;
+
+ pwrseq_node->pwrseq_on = hdev_pwrseq;
+ list_add(&pwrseq_node->list, &hub->pwrseq_list);
+ } else if (IS_ERR(hdev_pwrseq)) {
+ return PTR_ERR(hdev_pwrseq);
+ }
+ }
+
+ return ret;
+
+err2:
+ kfree(pwrseq_node);
+err1:
+ pwrseq_free(hdev_pwrseq);
+ return ret;
+}
+
static void hub_disconnect(struct usb_interface *intf)
{
struct usb_hub *hub = usb_get_intfdata(intf);
@@ -1700,6 +1761,7 @@ static void hub_disconnect(struct usb_interface *intf)
hub->error = 0;
hub_quiesce(hub, HUB_DISCONNECT);
+ hub_of_pwrseq_off(intf);
mutex_lock(&usb_port_peer_mutex);
/* Avoid races with recursively_mark_NOTATTACHED() */
@@ -1733,6 +1795,7 @@ 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;
+ int ret = -ENODEV;
desc = intf->cur_altsetting;
hdev = interface_to_usbdev(intf);
@@ -1839,6 +1902,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_list);
usb_get_intf(intf);
usb_get_dev(hdev);
@@ -1852,11 +1916,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(intf);
+ 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..f52169c 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_list; /* powered on pwrseq node list */
};
/**
diff --git a/include/linux/pwrseq.h b/include/linux/pwrseq.h
index f726e7e..36dde42 100644
--- a/include/linux/pwrseq.h
+++ b/include/linux/pwrseq.h
@@ -15,6 +15,12 @@ struct pwrseq {
struct module *owner;
};
+/* This structure is used for recording powered on pwrseq node */
+struct pwrseq_node_powered_on {
+ struct pwrseq *pwrseq_on;
+ struct list_head list;
+};
+
struct pwrseq_ops {
int (*pre_power_on)(struct pwrseq *pwrseq);
void (*post_power_on)(struct pwrseq *pwrseq);
--
1.9.1
--
To unsubscribe from this list: send the line "unsubscribe linux-usb" in
the body of a message to majordomo-u79uwXL29TY76Z2rM5mHXA@public.gmane.org
More majordomo info at http://vger.kernel.org/majordomo-info.html
next prev parent reply other threads:[~2016-06-17 10:09 UTC|newest]
Thread overview: 29+ messages / expand[flat|nested] mbox.gz Atom feed top
2016-06-17 10:09 [PATCH 00/12] power: add generic power sequence framework Peter Chen
2016-06-17 10:09 ` [PATCH 01/12] power/mmc: Move pwrseq drivers to power/pwrseq Peter Chen
2016-06-17 10:09 ` [PATCH 02/12] MAINTAINERS: Retain Ulf Hansson as the same maintainer of pwrseq Peter Chen
2016-06-17 10:09 ` [PATCH 03/12] power: pwrseq: Enable COMPILE_TEST for drivers Peter Chen
2016-06-17 10:09 ` [PATCH 05/12] power: pwrseq: Generalize mmc_pwrseq operations by removing mmc prefix Peter Chen
2016-06-17 10:09 ` [PATCH 06/12] power: pwrseq: change common helpers as generic Peter Chen
2016-06-17 10:09 ` [PATCH 07/12] power: pwrseq: rename file name for generic driver Peter Chen
2016-06-20 12:48 ` Krzysztof Kozlowski
2016-06-21 2:19 ` Peter Chen
2016-06-17 10:09 ` [PATCH 09/12] power: pwrseq: pwrseq_usb_generic: add generic power sequence support for USB deivces Peter Chen
2016-06-17 10:09 ` [PATCH 11/12] usb: chipidea: host: let the hcd know's parent device node Peter Chen
[not found] ` <1466158165-9380-1-git-send-email-peter.chen-3arQi8VN3Tc@public.gmane.org>
2016-06-17 10:09 ` [PATCH 04/12] power: pwrseq: Remove mmc prefix from mmc_pwrseq Peter Chen
2016-06-17 10:09 ` [PATCH 08/12] doc: binding: pwrseq-usb-generic: add binding doc for generic usb power sequence driver Peter Chen
2016-06-17 17:16 ` Rob Herring
2016-06-20 11:26 ` Peter Chen
2016-06-20 12:29 ` Chen-Yu Tsai
2016-06-21 2:14 ` Peter Chen
2016-06-20 16:16 ` Rob Herring
2016-06-20 17:06 ` Mark Brown
2016-06-21 2:11 ` Peter Chen
2016-06-21 21:26 ` Rob Herring
2016-06-22 1:14 ` Peter Chen
2016-06-22 9:09 ` Ulf Hansson
2016-06-24 15:25 ` Rob Herring
2016-06-17 10:09 ` Peter Chen [this message]
[not found] ` <1466158165-9380-11-git-send-email-peter.chen-3arQi8VN3Tc@public.gmane.org>
2016-06-17 16:12 ` [PATCH 10/12] usb: core: add power sequence handling for USB devices Alan Stern
2016-06-17 10:09 ` [PATCH 12/12] ARM: dts: imx6qdl-udoo.dtsi: fix onboard USB HUB property Peter Chen
2016-06-17 23:29 ` [PATCH 00/12] power: add generic power sequence framework Maciej S. Szmigiero
2016-06-20 11:27 ` 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=1466158165-9380-11-git-send-email-peter.chen@nxp.com \
--to=peter.chen-3arqi8vn3tc@public.gmane.org \
--cc=arnd-r2nGTMty4D4@public.gmane.org \
--cc=broonie-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=festevam-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org \
--cc=gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org \
--cc=javier-JPH+aEBZ4P+UEJcrhfAQsw@public.gmane.org \
--cc=k.kozlowski-Sze3O3UU22JBDgjK7y7TUQ@public.gmane.org \
--cc=linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org \
--cc=linux-mmc-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-pm-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org \
--cc=mail-APzI5cXaD1zVlRWJc41N0YvC60bnQu0Y@public.gmane.org \
--cc=mark.rutland-5wv7dgnIgG8@public.gmane.org \
--cc=oscar-Bdbr4918Nnnk1uMJSBkQmQ@public.gmane.org \
--cc=p.zabel-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org \
--cc=pawel.moll-5wv7dgnIgG8@public.gmane.org \
--cc=robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=s.hauer-bIcnvbaLZ9MEGnE8C9+IrQ@public.gmane.org \
--cc=sre-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org \
--cc=stephen.boyd-QSEj5FYQhm4dnm+yROfE0A@public.gmane.org \
--cc=stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz@public.gmane.org \
--cc=troy.kisky-Q5RJGjKts06CY9SHAMCTRUEOCMrvLtNR@public.gmane.org \
--cc=ulf.hansson-QSEj5FYQhm4dnm+yROfE0A@public.gmane.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).