From mboxrd@z Thu Jan 1 00:00:00 1970 From: Martin Blumenstingl Subject: [PATCH usb-next v9 4/8] usb: core: hcd: integrate the PHY wrapper into the HCD core Date: Sun, 11 Feb 2018 22:06:47 +0100 Message-ID: <20180211210651.2046-5-martin.blumenstingl@googlemail.com> References: <20180211210651.2046-1-martin.blumenstingl@googlemail.com> Return-path: In-Reply-To: <20180211210651.2046-1-martin.blumenstingl-gM/Ye1E23mwN+BqQ9rBEUg@public.gmane.org> Sender: linux-usb-owner-u79uwXL29TY76Z2rM5mHXA@public.gmane.org To: linux-usb-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, mathias.nyman-ral2JQCrhuEAvxtiuMwx3w@public.gmane.org, arnd-r2nGTMty4D4@public.gmane.org, gregkh-hQyY1W1yCW8ekmWlsbkhG0B+6BGkLq7r@public.gmane.org, felipe.balbi-VuQAYsv1563Yd54FQh9/CA@public.gmane.org Cc: linux-omap-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-tegra-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, linux-mediatek-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org, linux-arm-kernel-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org, devicetree-u79uwXL29TY76Z2rM5mHXA@public.gmane.org, jonathanh-DDmLM1+adcrQT0dZR+AlfA@public.gmane.org, thierry.reding-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org, stern-nwvwT67g6+6dFdvTe/nMLpVzexx5G7lz@public.gmane.org, linux-ci5G2KO2hbZ+pU9mqzGVBQ@public.gmane.org, Peter.Chen-3arQi8VN3Tc@public.gmane.org, matthias.bgg-Re5JQEeQqe8AvxtiuMwx3w@public.gmane.org, mark.rutland-5wv7dgnIgG8@public.gmane.org, robh+dt-DgEjT+Ai2ygdnm+yROfE0A@public.gmane.org, narmstrong-rdvid1DuHRBWk0Htik3J/w@public.gmane.org, linux-amlogic-IAPFreCvJWM7uuMidbF8XUB+6BGkLq7r@public.gmane.org, yixun.lan-LpR1jeaWuhtBDgjK7y7TUQ@public.gmane.org, Martin Blumenstingl List-Id: linux-tegra@vger.kernel.org This integrates the PHY wrapper into the core hcd infrastructure. Multiple PHYs which are part of the HCD's device tree node are now managed (= powered on/off when needed), by the new usb_phy_roothub code. Suspend and resume is also supported, however not for runtime/auto-suspend (which is triggered for example when no devices are connected to the USB bus). This is needed on some SoCs (for example Amlogic Meson GXL) because if the PHYs are disabled during auto-suspend then devices which are plugged in afterwards are not seen by the host. One example where this is required is the Amlogic GXL and GXM SoCs: They are using a dwc3 USB controller with up to three ports enabled on the internal roothub. Each port has it's own PHY which must be enabled (if one of the PHYs is left disabled then none of the USB ports works at all). The new logic works on the Amlogic GXL and GXM SoCs because the dwc3 driver internally creates a xhci-hcd which then registers a HCD which then triggers our new PHY wrapper. USB controller drivers can opt out of this by setting "skip_phy_initialization" in struct usb_hcd to true. This is identical to how it works for a single USB PHY, so the "multiple PHY" handling is disabled for drivers that opted out of the management logic of a single PHY. Signed-off-by: Martin Blumenstingl Acked-by: Alan Stern Acked-by: Chunfeng Yun Tested-by: Yixun Lan --- drivers/usb/core/hcd.c | 31 +++++++++++++++++++++++++++++++ include/linux/usb/hcd.h | 1 + 2 files changed, 32 insertions(+) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index f2307470a31e..32797c25ac3b 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -37,6 +37,7 @@ #include #include "usb.h" +#include "phy.h" /*-------------------------------------------------------------------------*/ @@ -2260,6 +2261,9 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) usb_set_device_state(rhdev, USB_STATE_SUSPENDED); hcd->state = HC_STATE_SUSPENDED; + if (!PMSG_IS_AUTO(msg)) + usb_phy_roothub_power_off(hcd->phy_roothub); + /* Did we race with a root-hub wakeup event? */ if (rhdev->do_remote_wakeup) { char buffer[6]; @@ -2296,6 +2300,13 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume"); return 0; } + + if (!PMSG_IS_AUTO(msg)) { + status = usb_phy_roothub_power_on(hcd->phy_roothub); + if (status) + return status; + } + if (!hcd->driver->bus_resume) return -ENOENT; if (HCD_RH_RUNNING(hcd)) @@ -2333,6 +2344,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) } } else { hcd->state = old_state; + usb_phy_roothub_power_off(hcd->phy_roothub); dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", "resume", status); if (status != -ESHUTDOWN) @@ -2769,6 +2781,18 @@ int usb_add_hcd(struct usb_hcd *hcd, } } + if (!hcd->skip_phy_initialization) { + hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev); + if (IS_ERR(hcd->phy_roothub)) { + retval = PTR_ERR(hcd->phy_roothub); + goto err_phy_roothub_init; + } + + retval = usb_phy_roothub_power_on(hcd->phy_roothub); + if (retval) + goto err_usb_phy_roothub_power_on; + } + dev_info(hcd->self.controller, "%s\n", hcd->product_desc); /* Keep old behaviour if authorized_default is not in [0, 1]. */ @@ -2933,6 +2957,10 @@ int usb_add_hcd(struct usb_hcd *hcd, err_register_bus: hcd_buffer_destroy(hcd); err_create_buf: + usb_phy_roothub_power_off(hcd->phy_roothub); +err_usb_phy_roothub_power_on: + usb_phy_roothub_exit(hcd->phy_roothub); +err_phy_roothub_init: if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) { phy_power_off(hcd->phy); phy_exit(hcd->phy); @@ -3017,6 +3045,9 @@ void usb_remove_hcd(struct usb_hcd *hcd) usb_deregister_bus(&hcd->self); hcd_buffer_destroy(hcd); + usb_phy_roothub_power_off(hcd->phy_roothub); + usb_phy_roothub_exit(hcd->phy_roothub); + if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) { phy_power_off(hcd->phy); phy_exit(hcd->phy); diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index b46fb6dd43ab..b85e3d4fb0c5 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -110,6 +110,7 @@ struct usb_hcd { */ struct usb_phy *usb_phy; struct phy *phy; + struct usb_phy_roothub *phy_roothub; /* Flags that need to be manipulated atomically because they can * change while the host controller is running. Always use -- 2.16.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 From mboxrd@z Thu Jan 1 00:00:00 1970 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: base64 Subject: [usb-next,v9,4/8] usb: core: hcd: integrate the PHY wrapper into the HCD core From: Martin Blumenstingl Message-Id: <20180211210651.2046-5-martin.blumenstingl@googlemail.com> Date: Sun, 11 Feb 2018 22:06:47 +0100 To: linux-usb@vger.kernel.org, mathias.nyman@intel.com, arnd@arndb.de, gregkh@linuxfoundation.org, felipe.balbi@linux.intel.com Cc: linux-omap@vger.kernel.org, linux-tegra@vger.kernel.org, linux-mediatek@lists.infradead.org, linux-arm-kernel@lists.infradead.org, devicetree@vger.kernel.org, jonathanh@nvidia.com, thierry.reding@gmail.com, stern@rowland.harvard.edu, linux@prisktech.co.nz, Peter.Chen@nxp.com, matthias.bgg@gmail.com, mark.rutland@arm.com, robh+dt@kernel.org, narmstrong@baylibre.com, linux-amlogic@lists.infradead.org, yixun.lan@amlogic.com, Martin Blumenstingl List-ID: VGhpcyBpbnRlZ3JhdGVzIHRoZSBQSFkgd3JhcHBlciBpbnRvIHRoZSBjb3JlIGhjZCBpbmZyYXN0 cnVjdHVyZS4KTXVsdGlwbGUgUEhZcyB3aGljaCBhcmUgcGFydCBvZiB0aGUgSENEJ3MgZGV2aWNl IHRyZWUgbm9kZSBhcmUgbm93Cm1hbmFnZWQgKD0gcG93ZXJlZCBvbi9vZmYgd2hlbiBuZWVkZWQp LCBieSB0aGUgbmV3IHVzYl9waHlfcm9vdGh1YiBjb2RlLgoKU3VzcGVuZCBhbmQgcmVzdW1lIGlz IGFsc28gc3VwcG9ydGVkLCBob3dldmVyIG5vdCBmb3IKcnVudGltZS9hdXRvLXN1c3BlbmQgKHdo aWNoIGlzIHRyaWdnZXJlZCBmb3IgZXhhbXBsZSB3aGVuIG5vIGRldmljZXMgYXJlCmNvbm5lY3Rl ZCB0byB0aGUgVVNCIGJ1cykuIFRoaXMgaXMgbmVlZGVkIG9uIHNvbWUgU29DcyAoZm9yIGV4YW1w bGUKQW1sb2dpYyBNZXNvbiBHWEwpIGJlY2F1c2UgaWYgdGhlIFBIWXMgYXJlIGRpc2FibGVkIGR1 cmluZyBhdXRvLXN1c3BlbmQKdGhlbiBkZXZpY2VzIHdoaWNoIGFyZSBwbHVnZ2VkIGluIGFmdGVy d2FyZHMgYXJlIG5vdCBzZWVuIGJ5IHRoZSBob3N0LgoKT25lIGV4YW1wbGUgd2hlcmUgdGhpcyBp cyByZXF1aXJlZCBpcyB0aGUgQW1sb2dpYyBHWEwgYW5kIEdYTSBTb0NzOgpUaGV5IGFyZSB1c2lu ZyBhIGR3YzMgVVNCIGNvbnRyb2xsZXIgd2l0aCB1cCB0byB0aHJlZSBwb3J0cyBlbmFibGVkIG9u CnRoZSBpbnRlcm5hbCByb290aHViLiBFYWNoIHBvcnQgaGFzIGl0J3Mgb3duIFBIWSB3aGljaCBt dXN0IGJlIGVuYWJsZWQKKGlmIG9uZSBvZiB0aGUgUEhZcyBpcyBsZWZ0IGRpc2FibGVkIHRoZW4g bm9uZSBvZiB0aGUgVVNCIHBvcnRzIHdvcmtzIGF0CmFsbCkuClRoZSBuZXcgbG9naWMgd29ya3Mg b24gdGhlIEFtbG9naWMgR1hMIGFuZCBHWE0gU29DcyBiZWNhdXNlIHRoZSBkd2MzCmRyaXZlciBp bnRlcm5hbGx5IGNyZWF0ZXMgYSB4aGNpLWhjZCB3aGljaCB0aGVuIHJlZ2lzdGVycyBhIEhDRCB3 aGljaAp0aGVuIHRyaWdnZXJzIG91ciBuZXcgUEhZIHdyYXBwZXIuCgpVU0IgY29udHJvbGxlciBk cml2ZXJzIGNhbiBvcHQgb3V0IG9mIHRoaXMgYnkgc2V0dGluZwoic2tpcF9waHlfaW5pdGlhbGl6 YXRpb24iIGluIHN0cnVjdCB1c2JfaGNkIHRvIHRydWUuIFRoaXMgaXMgaWRlbnRpY2FsCnRvIGhv dyBpdCB3b3JrcyBmb3IgYSBzaW5nbGUgVVNCIFBIWSwgc28gdGhlICJtdWx0aXBsZSBQSFkiIGhh bmRsaW5nIGlzCmRpc2FibGVkIGZvciBkcml2ZXJzIHRoYXQgb3B0ZWQgb3V0IG9mIHRoZSBtYW5h Z2VtZW50IGxvZ2ljIG9mIGEgc2luZ2xlClBIWS4KClNpZ25lZC1vZmYtYnk6IE1hcnRpbiBCbHVt ZW5zdGluZ2wgPG1hcnRpbi5ibHVtZW5zdGluZ2xAZ29vZ2xlbWFpbC5jb20+CkFja2VkLWJ5OiBB bGFuIFN0ZXJuIDxzdGVybkByb3dsYW5kLmhhcnZhcmQuZWR1PgpBY2tlZC1ieTogQ2h1bmZlbmcg WXVuIDxjaHVuZmVuZy55dW5AbWVkaWF0ZWsuY29tPgpUZXN0ZWQtYnk6IFlpeHVuIExhbiA8eWl4 dW4ubGFuQGFtbG9naWMuY29tPgotLS0KIGRyaXZlcnMvdXNiL2NvcmUvaGNkLmMgIHwgMzEgKysr KysrKysrKysrKysrKysrKysrKysrKysrKysrKwogaW5jbHVkZS9saW51eC91c2IvaGNkLmggfCAg MSArCiAyIGZpbGVzIGNoYW5nZWQsIDMyIGluc2VydGlvbnMoKykKCmRpZmYgLS1naXQgYS9kcml2 ZXJzL3VzYi9jb3JlL2hjZC5jIGIvZHJpdmVycy91c2IvY29yZS9oY2QuYwppbmRleCBmMjMwNzQ3 MGEzMWUuLjMyNzk3YzI1YWMzYiAxMDA2NDQKLS0tIGEvZHJpdmVycy91c2IvY29yZS9oY2QuYwor KysgYi9kcml2ZXJzL3VzYi9jb3JlL2hjZC5jCkBAIC0zNyw2ICszNyw3IEBACiAjaW5jbHVkZSA8 bGludXgvdXNiL290Zy5oPgogCiAjaW5jbHVkZSAidXNiLmgiCisjaW5jbHVkZSAicGh5LmgiCiAK IAogLyotLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0tLS0t LS0tLS0tLS0tLS0tLS0tLS0tLS0tKi8KQEAgLTIyNjAsNiArMjI2MSw5IEBAIGludCBoY2RfYnVz X3N1c3BlbmQoc3RydWN0IHVzYl9kZXZpY2UgKnJoZGV2LCBwbV9tZXNzYWdlX3QgbXNnKQogCQl1 c2Jfc2V0X2RldmljZV9zdGF0ZShyaGRldiwgVVNCX1NUQVRFX1NVU1BFTkRFRCk7CiAJCWhjZC0+ c3RhdGUgPSBIQ19TVEFURV9TVVNQRU5ERUQ7CiAKKwkJaWYgKCFQTVNHX0lTX0FVVE8obXNnKSkK KwkJCXVzYl9waHlfcm9vdGh1Yl9wb3dlcl9vZmYoaGNkLT5waHlfcm9vdGh1Yik7CisKIAkJLyog RGlkIHdlIHJhY2Ugd2l0aCBhIHJvb3QtaHViIHdha2V1cCBldmVudD8gKi8KIAkJaWYgKHJoZGV2 LT5kb19yZW1vdGVfd2FrZXVwKSB7CiAJCQljaGFyCWJ1ZmZlcls2XTsKQEAgLTIyOTYsNiArMjMw MCwxMyBAQCBpbnQgaGNkX2J1c19yZXN1bWUoc3RydWN0IHVzYl9kZXZpY2UgKnJoZGV2LCBwbV9t ZXNzYWdlX3QgbXNnKQogCQlkZXZfZGJnKCZyaGRldi0+ZGV2LCAic2tpcHBlZCAlcyBvZiBkZWFk IGJ1c1xuIiwgInJlc3VtZSIpOwogCQlyZXR1cm4gMDsKIAl9CisKKwlpZiAoIVBNU0dfSVNfQVVU Tyhtc2cpKSB7CisJCXN0YXR1cyA9IHVzYl9waHlfcm9vdGh1Yl9wb3dlcl9vbihoY2QtPnBoeV9y b290aHViKTsKKwkJaWYgKHN0YXR1cykKKwkJCXJldHVybiBzdGF0dXM7CisJfQorCiAJaWYgKCFo Y2QtPmRyaXZlci0+YnVzX3Jlc3VtZSkKIAkJcmV0dXJuIC1FTk9FTlQ7CiAJaWYgKEhDRF9SSF9S VU5OSU5HKGhjZCkpCkBAIC0yMzMzLDYgKzIzNDQsNyBAQCBpbnQgaGNkX2J1c19yZXN1bWUoc3Ry dWN0IHVzYl9kZXZpY2UgKnJoZGV2LCBwbV9tZXNzYWdlX3QgbXNnKQogCQl9CiAJfSBlbHNlIHsK IAkJaGNkLT5zdGF0ZSA9IG9sZF9zdGF0ZTsKKwkJdXNiX3BoeV9yb290aHViX3Bvd2VyX29mZiho Y2QtPnBoeV9yb290aHViKTsKIAkJZGV2X2RiZygmcmhkZXYtPmRldiwgImJ1cyAlcyBmYWlsLCBl cnIgJWRcbiIsCiAJCQkJInJlc3VtZSIsIHN0YXR1cyk7CiAJCWlmIChzdGF0dXMgIT0gLUVTSFVU RE9XTikKQEAgLTI3NjksNiArMjc4MSwxOCBAQCBpbnQgdXNiX2FkZF9oY2Qoc3RydWN0IHVzYl9o Y2QgKmhjZCwKIAkJfQogCX0KIAorCWlmICghaGNkLT5za2lwX3BoeV9pbml0aWFsaXphdGlvbikg eworCQloY2QtPnBoeV9yb290aHViID0gdXNiX3BoeV9yb290aHViX2luaXQoaGNkLT5zZWxmLnN5 c2Rldik7CisJCWlmIChJU19FUlIoaGNkLT5waHlfcm9vdGh1YikpIHsKKwkJCXJldHZhbCA9IFBU Ul9FUlIoaGNkLT5waHlfcm9vdGh1Yik7CisJCQlnb3RvIGVycl9waHlfcm9vdGh1Yl9pbml0Owor CQl9CisKKwkJcmV0dmFsID0gdXNiX3BoeV9yb290aHViX3Bvd2VyX29uKGhjZC0+cGh5X3Jvb3Ro dWIpOworCQlpZiAocmV0dmFsKQorCQkJZ290byBlcnJfdXNiX3BoeV9yb290aHViX3Bvd2VyX29u OworCX0KKwogCWRldl9pbmZvKGhjZC0+c2VsZi5jb250cm9sbGVyLCAiJXNcbiIsIGhjZC0+cHJv ZHVjdF9kZXNjKTsKIAogCS8qIEtlZXAgb2xkIGJlaGF2aW91ciBpZiBhdXRob3JpemVkX2RlZmF1 bHQgaXMgbm90IGluIFswLCAxXS4gKi8KQEAgLTI5MzMsNiArMjk1NywxMCBAQCBpbnQgdXNiX2Fk ZF9oY2Qoc3RydWN0IHVzYl9oY2QgKmhjZCwKIGVycl9yZWdpc3Rlcl9idXM6CiAJaGNkX2J1ZmZl cl9kZXN0cm95KGhjZCk7CiBlcnJfY3JlYXRlX2J1ZjoKKwl1c2JfcGh5X3Jvb3RodWJfcG93ZXJf b2ZmKGhjZC0+cGh5X3Jvb3RodWIpOworZXJyX3VzYl9waHlfcm9vdGh1Yl9wb3dlcl9vbjoKKwl1 c2JfcGh5X3Jvb3RodWJfZXhpdChoY2QtPnBoeV9yb290aHViKTsKK2Vycl9waHlfcm9vdGh1Yl9p bml0OgogCWlmIChJU19FTkFCTEVEKENPTkZJR19HRU5FUklDX1BIWSkgJiYgaGNkLT5yZW1vdmVf cGh5ICYmIGhjZC0+cGh5KSB7CiAJCXBoeV9wb3dlcl9vZmYoaGNkLT5waHkpOwogCQlwaHlfZXhp dChoY2QtPnBoeSk7CkBAIC0zMDE3LDYgKzMwNDUsOSBAQCB2b2lkIHVzYl9yZW1vdmVfaGNkKHN0 cnVjdCB1c2JfaGNkICpoY2QpCiAJdXNiX2RlcmVnaXN0ZXJfYnVzKCZoY2QtPnNlbGYpOwogCWhj ZF9idWZmZXJfZGVzdHJveShoY2QpOwogCisJdXNiX3BoeV9yb290aHViX3Bvd2VyX29mZihoY2Qt PnBoeV9yb290aHViKTsKKwl1c2JfcGh5X3Jvb3RodWJfZXhpdChoY2QtPnBoeV9yb290aHViKTsK KwogCWlmIChJU19FTkFCTEVEKENPTkZJR19HRU5FUklDX1BIWSkgJiYgaGNkLT5yZW1vdmVfcGh5 ICYmIGhjZC0+cGh5KSB7CiAJCXBoeV9wb3dlcl9vZmYoaGNkLT5waHkpOwogCQlwaHlfZXhpdCho Y2QtPnBoeSk7CmRpZmYgLS1naXQgYS9pbmNsdWRlL2xpbnV4L3VzYi9oY2QuaCBiL2luY2x1ZGUv bGludXgvdXNiL2hjZC5oCmluZGV4IGI0NmZiNmRkNDNhYi4uYjg1ZTNkNGZiMGM1IDEwMDY0NAot LS0gYS9pbmNsdWRlL2xpbnV4L3VzYi9oY2QuaAorKysgYi9pbmNsdWRlL2xpbnV4L3VzYi9oY2Qu aApAQCAtMTEwLDYgKzExMCw3IEBAIHN0cnVjdCB1c2JfaGNkIHsKIAkgKi8KIAlzdHJ1Y3QgdXNi X3BoeQkJKnVzYl9waHk7CiAJc3RydWN0IHBoeQkJKnBoeTsKKwlzdHJ1Y3QgdXNiX3BoeV9yb290 aHViCSpwaHlfcm9vdGh1YjsKIAogCS8qIEZsYWdzIHRoYXQgbmVlZCB0byBiZSBtYW5pcHVsYXRl ZCBhdG9taWNhbGx5IGJlY2F1c2UgdGhleSBjYW4KIAkgKiBjaGFuZ2Ugd2hpbGUgdGhlIGhvc3Qg Y29udHJvbGxlciBpcyBydW5uaW5nLiAgQWx3YXlzIHVzZQo= From mboxrd@z Thu Jan 1 00:00:00 1970 From: martin.blumenstingl@googlemail.com (Martin Blumenstingl) Date: Sun, 11 Feb 2018 22:06:47 +0100 Subject: [PATCH usb-next v9 4/8] usb: core: hcd: integrate the PHY wrapper into the HCD core In-Reply-To: <20180211210651.2046-1-martin.blumenstingl@googlemail.com> References: <20180211210651.2046-1-martin.blumenstingl@googlemail.com> Message-ID: <20180211210651.2046-5-martin.blumenstingl@googlemail.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org This integrates the PHY wrapper into the core hcd infrastructure. Multiple PHYs which are part of the HCD's device tree node are now managed (= powered on/off when needed), by the new usb_phy_roothub code. Suspend and resume is also supported, however not for runtime/auto-suspend (which is triggered for example when no devices are connected to the USB bus). This is needed on some SoCs (for example Amlogic Meson GXL) because if the PHYs are disabled during auto-suspend then devices which are plugged in afterwards are not seen by the host. One example where this is required is the Amlogic GXL and GXM SoCs: They are using a dwc3 USB controller with up to three ports enabled on the internal roothub. Each port has it's own PHY which must be enabled (if one of the PHYs is left disabled then none of the USB ports works at all). The new logic works on the Amlogic GXL and GXM SoCs because the dwc3 driver internally creates a xhci-hcd which then registers a HCD which then triggers our new PHY wrapper. USB controller drivers can opt out of this by setting "skip_phy_initialization" in struct usb_hcd to true. This is identical to how it works for a single USB PHY, so the "multiple PHY" handling is disabled for drivers that opted out of the management logic of a single PHY. Signed-off-by: Martin Blumenstingl Acked-by: Alan Stern Acked-by: Chunfeng Yun Tested-by: Yixun Lan --- drivers/usb/core/hcd.c | 31 +++++++++++++++++++++++++++++++ include/linux/usb/hcd.h | 1 + 2 files changed, 32 insertions(+) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index f2307470a31e..32797c25ac3b 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -37,6 +37,7 @@ #include #include "usb.h" +#include "phy.h" /*-------------------------------------------------------------------------*/ @@ -2260,6 +2261,9 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) usb_set_device_state(rhdev, USB_STATE_SUSPENDED); hcd->state = HC_STATE_SUSPENDED; + if (!PMSG_IS_AUTO(msg)) + usb_phy_roothub_power_off(hcd->phy_roothub); + /* Did we race with a root-hub wakeup event? */ if (rhdev->do_remote_wakeup) { char buffer[6]; @@ -2296,6 +2300,13 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume"); return 0; } + + if (!PMSG_IS_AUTO(msg)) { + status = usb_phy_roothub_power_on(hcd->phy_roothub); + if (status) + return status; + } + if (!hcd->driver->bus_resume) return -ENOENT; if (HCD_RH_RUNNING(hcd)) @@ -2333,6 +2344,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) } } else { hcd->state = old_state; + usb_phy_roothub_power_off(hcd->phy_roothub); dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", "resume", status); if (status != -ESHUTDOWN) @@ -2769,6 +2781,18 @@ int usb_add_hcd(struct usb_hcd *hcd, } } + if (!hcd->skip_phy_initialization) { + hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev); + if (IS_ERR(hcd->phy_roothub)) { + retval = PTR_ERR(hcd->phy_roothub); + goto err_phy_roothub_init; + } + + retval = usb_phy_roothub_power_on(hcd->phy_roothub); + if (retval) + goto err_usb_phy_roothub_power_on; + } + dev_info(hcd->self.controller, "%s\n", hcd->product_desc); /* Keep old behaviour if authorized_default is not in [0, 1]. */ @@ -2933,6 +2957,10 @@ int usb_add_hcd(struct usb_hcd *hcd, err_register_bus: hcd_buffer_destroy(hcd); err_create_buf: + usb_phy_roothub_power_off(hcd->phy_roothub); +err_usb_phy_roothub_power_on: + usb_phy_roothub_exit(hcd->phy_roothub); +err_phy_roothub_init: if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) { phy_power_off(hcd->phy); phy_exit(hcd->phy); @@ -3017,6 +3045,9 @@ void usb_remove_hcd(struct usb_hcd *hcd) usb_deregister_bus(&hcd->self); hcd_buffer_destroy(hcd); + usb_phy_roothub_power_off(hcd->phy_roothub); + usb_phy_roothub_exit(hcd->phy_roothub); + if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) { phy_power_off(hcd->phy); phy_exit(hcd->phy); diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index b46fb6dd43ab..b85e3d4fb0c5 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -110,6 +110,7 @@ struct usb_hcd { */ struct usb_phy *usb_phy; struct phy *phy; + struct usb_phy_roothub *phy_roothub; /* Flags that need to be manipulated atomically because they can * change while the host controller is running. Always use -- 2.16.1 From mboxrd@z Thu Jan 1 00:00:00 1970 From: martin.blumenstingl@googlemail.com (Martin Blumenstingl) Date: Sun, 11 Feb 2018 22:06:47 +0100 Subject: [PATCH usb-next v9 4/8] usb: core: hcd: integrate the PHY wrapper into the HCD core In-Reply-To: <20180211210651.2046-1-martin.blumenstingl@googlemail.com> References: <20180211210651.2046-1-martin.blumenstingl@googlemail.com> Message-ID: <20180211210651.2046-5-martin.blumenstingl@googlemail.com> To: linus-amlogic@lists.infradead.org List-Id: linus-amlogic.lists.infradead.org This integrates the PHY wrapper into the core hcd infrastructure. Multiple PHYs which are part of the HCD's device tree node are now managed (= powered on/off when needed), by the new usb_phy_roothub code. Suspend and resume is also supported, however not for runtime/auto-suspend (which is triggered for example when no devices are connected to the USB bus). This is needed on some SoCs (for example Amlogic Meson GXL) because if the PHYs are disabled during auto-suspend then devices which are plugged in afterwards are not seen by the host. One example where this is required is the Amlogic GXL and GXM SoCs: They are using a dwc3 USB controller with up to three ports enabled on the internal roothub. Each port has it's own PHY which must be enabled (if one of the PHYs is left disabled then none of the USB ports works at all). The new logic works on the Amlogic GXL and GXM SoCs because the dwc3 driver internally creates a xhci-hcd which then registers a HCD which then triggers our new PHY wrapper. USB controller drivers can opt out of this by setting "skip_phy_initialization" in struct usb_hcd to true. This is identical to how it works for a single USB PHY, so the "multiple PHY" handling is disabled for drivers that opted out of the management logic of a single PHY. Signed-off-by: Martin Blumenstingl Acked-by: Alan Stern Acked-by: Chunfeng Yun Tested-by: Yixun Lan --- drivers/usb/core/hcd.c | 31 +++++++++++++++++++++++++++++++ include/linux/usb/hcd.h | 1 + 2 files changed, 32 insertions(+) diff --git a/drivers/usb/core/hcd.c b/drivers/usb/core/hcd.c index f2307470a31e..32797c25ac3b 100644 --- a/drivers/usb/core/hcd.c +++ b/drivers/usb/core/hcd.c @@ -37,6 +37,7 @@ #include #include "usb.h" +#include "phy.h" /*-------------------------------------------------------------------------*/ @@ -2260,6 +2261,9 @@ int hcd_bus_suspend(struct usb_device *rhdev, pm_message_t msg) usb_set_device_state(rhdev, USB_STATE_SUSPENDED); hcd->state = HC_STATE_SUSPENDED; + if (!PMSG_IS_AUTO(msg)) + usb_phy_roothub_power_off(hcd->phy_roothub); + /* Did we race with a root-hub wakeup event? */ if (rhdev->do_remote_wakeup) { char buffer[6]; @@ -2296,6 +2300,13 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) dev_dbg(&rhdev->dev, "skipped %s of dead bus\n", "resume"); return 0; } + + if (!PMSG_IS_AUTO(msg)) { + status = usb_phy_roothub_power_on(hcd->phy_roothub); + if (status) + return status; + } + if (!hcd->driver->bus_resume) return -ENOENT; if (HCD_RH_RUNNING(hcd)) @@ -2333,6 +2344,7 @@ int hcd_bus_resume(struct usb_device *rhdev, pm_message_t msg) } } else { hcd->state = old_state; + usb_phy_roothub_power_off(hcd->phy_roothub); dev_dbg(&rhdev->dev, "bus %s fail, err %d\n", "resume", status); if (status != -ESHUTDOWN) @@ -2769,6 +2781,18 @@ int usb_add_hcd(struct usb_hcd *hcd, } } + if (!hcd->skip_phy_initialization) { + hcd->phy_roothub = usb_phy_roothub_init(hcd->self.sysdev); + if (IS_ERR(hcd->phy_roothub)) { + retval = PTR_ERR(hcd->phy_roothub); + goto err_phy_roothub_init; + } + + retval = usb_phy_roothub_power_on(hcd->phy_roothub); + if (retval) + goto err_usb_phy_roothub_power_on; + } + dev_info(hcd->self.controller, "%s\n", hcd->product_desc); /* Keep old behaviour if authorized_default is not in [0, 1]. */ @@ -2933,6 +2957,10 @@ int usb_add_hcd(struct usb_hcd *hcd, err_register_bus: hcd_buffer_destroy(hcd); err_create_buf: + usb_phy_roothub_power_off(hcd->phy_roothub); +err_usb_phy_roothub_power_on: + usb_phy_roothub_exit(hcd->phy_roothub); +err_phy_roothub_init: if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) { phy_power_off(hcd->phy); phy_exit(hcd->phy); @@ -3017,6 +3045,9 @@ void usb_remove_hcd(struct usb_hcd *hcd) usb_deregister_bus(&hcd->self); hcd_buffer_destroy(hcd); + usb_phy_roothub_power_off(hcd->phy_roothub); + usb_phy_roothub_exit(hcd->phy_roothub); + if (IS_ENABLED(CONFIG_GENERIC_PHY) && hcd->remove_phy && hcd->phy) { phy_power_off(hcd->phy); phy_exit(hcd->phy); diff --git a/include/linux/usb/hcd.h b/include/linux/usb/hcd.h index b46fb6dd43ab..b85e3d4fb0c5 100644 --- a/include/linux/usb/hcd.h +++ b/include/linux/usb/hcd.h @@ -110,6 +110,7 @@ struct usb_hcd { */ struct usb_phy *usb_phy; struct phy *phy; + struct usb_phy_roothub *phy_roothub; /* Flags that need to be manipulated atomically because they can * change while the host controller is running. Always use -- 2.16.1