From mboxrd@z Thu Jan 1 00:00:00 1970 Return-Path: X-Cyrus-Session-Id: sloti22d1t05-3019937-1519393671-2-16510768190427513895 X-Sieve: CMU Sieve 3.0 X-Spam-known-sender: no X-Spam-score: 0.0 X-Spam-hits: BAYES_00 -1.9, HEADER_FROM_DIFFERENT_DOMAINS 0.001, ME_NOAUTH 0.01, RCVD_IN_DNSWL_HI -5, T_RP_MATCHES_RCVD -0.01, LANGUAGES en, BAYES_USED global, SA_VERSION 3.4.0 X-Spam-source: IP='209.132.180.67', Host='vger.kernel.org', Country='CN', FromHeader='com', MailFrom='org', XOriginatingCountry='UNK' X-Spam-charsets: X-Resolved-to: greg@kroah.com X-Delivered-to: greg@kroah.com X-Mail-from: linux-usb-owner@vger.kernel.org ARC-Seal: i=1; a=rsa-sha256; cv=none; d=messagingengine.com; s=arctest; t=1519393671; b=H4B6riP7lJ+EDqevZKAxDE5apLoLjDacxxzgUbRT0eHVrSh cob5KTXYHSunmpmhMTD03PiwrhUeewYffvgU7Gxp4XnL4j5Ukm48voPUA3PozIKw nGbqnkBzV+JiHPJ7XMpezEuZfiZs9Gfcb8g83trgIKgFJfvpBhehCFVSs6ld1ItM gRDHuzhUrckN58zgSQIMSao+pLH3zXc12ep2uUnt8lpQYYqvVJWBuaRl9d3l3sZp HDy7XsY7MYEPm029ulAQnseGJk7JDW6UnA4vX2HdBjhV+bqAtjNHQWDBODQrrBbS wLY/kesRPD8tnFhGaMWPY7ydyvlqjZb7ZTX0w3Q== ARC-Message-Signature: i=1; a=rsa-sha256; c=relaxed/relaxed; d= messagingengine.com; h=from:to:cc:subject:date:message-id :mime-version:content-type:sender:list-id; s=arctest; t= 1519393671; bh=jH9fNTCS0skX9CMVHPq9ppvttE7Xr1ktk3Vf+sbwo8E=; b=F J38arBRPTGnMy8YNQ7KNmXzh5QFwTFpVDZoCh6RmkDrlUaAwV8LT2x/RUvJVAiZw 3mId+H35BHrnJdzAccNs8SQZ+2HiP0mdw6UyorpFR7dkv6utyXOPJUYh8yLM/8pv baTBBC9DkTvsVjm+sPBRbLdPYWTQ0eJ6hIR5QaAV/ptRUep9kqe5EVVpl6xmkNzF TgBmI9Fdzpopi10ujfbpDcwk4XzAs2Ya+bBwv549gvG9L8KcdJRnlQyn5xXK5qIj RDrAhRST8CdfUeCjrdbE0bM+gInxKWIJDNMED15oZfRqdoBtTfdQkqA3Xu/YB75I 9DXYOCMq2mdc2lQs1GJXw== ARC-Authentication-Results: i=1; mx1.messagingengine.com; arc=none (no signatures found); dkim=none (no signatures found); dmarc=none (p=none,has-list-id=yes,d=none) header.from=st.com; iprev=pass policy.iprev=209.132.180.67 (vger.kernel.org); spf=none smtp.mailfrom=linux-usb-owner@vger.kernel.org smtp.helo=vger.kernel.org; x-aligned-from=fail; x-ptr=pass x-ptr-helo=vger.kernel.org x-ptr-lookup=vger.kernel.org; x-return-mx=pass smtp.domain=vger.kernel.org smtp.result=pass smtp_org.domain=kernel.org smtp_org.result=pass smtp_is_org_domain=no header.domain=st.com header.result=pass header_is_org_domain=yes Authentication-Results: mx1.messagingengine.com; arc=none (no signatures found); dkim=none (no signatures found); dmarc=none (p=none,has-list-id=yes,d=none) header.from=st.com; iprev=pass policy.iprev=209.132.180.67 (vger.kernel.org); spf=none smtp.mailfrom=linux-usb-owner@vger.kernel.org smtp.helo=vger.kernel.org; x-aligned-from=fail; x-ptr=pass x-ptr-helo=vger.kernel.org x-ptr-lookup=vger.kernel.org; x-return-mx=pass smtp.domain=vger.kernel.org smtp.result=pass smtp_org.domain=kernel.org smtp_org.result=pass smtp_is_org_domain=no header.domain=st.com header.result=pass header_is_org_domain=yes Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751560AbeBWNrh (ORCPT ); Fri, 23 Feb 2018 08:47:37 -0500 Received: from mx07-00178001.pphosted.com ([62.209.51.94]:50200 "EHLO mx07-00178001.pphosted.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1751437AbeBWNrf (ORCPT ); Fri, 23 Feb 2018 08:47:35 -0500 From: Amelie Delaunay To: Greg Kroah-Hartman , Rob Herring , Mark Rutland , Tony Prisk , Alan Stern , "Roger Quadros" , Felipe Balbi CC: , , , , Amelie Delaunay Subject: [PATCH v3] usb: host: ehci-platform: add support for optional external vbus supply Date: Fri, 23 Feb 2018 14:46:51 +0100 Message-ID: <1519393611-31367-1-git-send-email-amelie.delaunay@st.com> X-Mailer: git-send-email 2.7.4 MIME-Version: 1.0 Content-Type: text/plain X-Originating-IP: [10.201.20.5] X-Proofpoint-Virus-Version: vendor=fsecure engine=2.50.10432:,, definitions=2018-02-23_04:,, signatures=0 Sender: linux-usb-owner@vger.kernel.org X-Mailing-List: linux-usb@vger.kernel.org X-getmail-retrieved-from-mailbox: INBOX X-Mailing-List: linux-kernel@vger.kernel.org List-ID: On some boards, especially when vbus supply requires large current, and the charge pump on the PHY isn't enough, an external vbus power switch may be used. Add support for optional external vbus supply per port in ehci-platform. Signed-off-by: Amelie Delaunay --- Changes in v3: * Address Felipe Balbi comments: reduce indentation in ehci_platform_port_power. * Address Roger Quadros and Alan Stern comments: platforms can have one external vbus supply per port, so add support to get as many optional regulator as implemented ports on the host controller. Changes in v2: * Address Roger Quadros comments: move regulator_enable/disable from ehci_platform_power_on/off to ehci_platform_port_power. --- Documentation/devicetree/bindings/usb/usb-ehci.txt | 1 + drivers/usb/host/ehci-platform.c | 52 +++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt index 3efde12..cd576db 100644 --- a/Documentation/devicetree/bindings/usb/usb-ehci.txt +++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt @@ -19,6 +19,7 @@ Optional properties: - phys : phandle + phy specifier pair - phy-names : "usb" - resets : phandle + reset specifier pair + - portN_vbus-supply : phandle of regulator supplying vbus for port N Example (Sequoia 440EPx): ehci@e0000300 { diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index b065a96..8e9f201 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,7 @@ struct ehci_platform_priv { struct reset_control *rsts; struct phy **phys; int num_phys; + struct regulator **vbus_supplies; bool reset_on_resume; }; @@ -56,7 +58,8 @@ static int ehci_platform_reset(struct usb_hcd *hcd) struct platform_device *pdev = to_platform_device(hcd->self.controller); struct usb_ehci_pdata *pdata = dev_get_platdata(&pdev->dev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); + int portnum, n_ports, retval; ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug; @@ -71,11 +74,57 @@ static int ehci_platform_reset(struct usb_hcd *hcd) if (retval) return retval; + n_ports = HCS_N_PORTS(ehci->hcs_params); + priv->vbus_supplies = devm_kcalloc(&pdev->dev, n_ports, + sizeof(struct regulator *), + GFP_KERNEL); + if (!priv->vbus_supplies) + return -ENOMEM; + + for (portnum = 0; portnum < n_ports; portnum++) { + struct regulator *vbus_supply; + char id[20]; + + sprintf(id, "port%d_vbus", portnum); + + vbus_supply = devm_regulator_get_optional(&pdev->dev, id); + if (IS_ERR(vbus_supply)) { + retval = PTR_ERR(vbus_supply); + if (retval == -ENODEV) + priv->vbus_supplies[portnum] = NULL; + else + return retval; + } else { + priv->vbus_supplies[portnum] = vbus_supply; + } + } + if (pdata->no_io_watchdog) ehci->need_io_watchdog = 0; return 0; } +static int ehci_platform_port_power(struct usb_hcd *hcd, int portnum, + bool enable) +{ + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); + int ret; + + if (!priv->vbus_supplies[portnum]) + return 0; + + if (enable) + ret = regulator_enable(priv->vbus_supplies[portnum]); + else + ret = regulator_disable(priv->vbus_supplies[portnum]); + if (ret) + dev_err(hcd->self.controller, + "failed to %s vbus supply for port %d: %d\n", + enable ? "enable" : "disable", portnum, ret); + + return ret; +} + static int ehci_platform_power_on(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); @@ -134,6 +183,7 @@ static struct hc_driver __read_mostly ehci_platform_hc_driver; static const struct ehci_driver_overrides platform_overrides __initconst = { .reset = ehci_platform_reset, .extra_priv_size = sizeof(struct ehci_platform_priv), + .port_power = ehci_platform_port_power, }; static struct usb_ehci_pdata ehci_platform_defaults = { -- 2.7.4 From mboxrd@z Thu Jan 1 00:00:00 1970 From: Amelie Delaunay Subject: [PATCH v3] usb: host: ehci-platform: add support for optional external vbus supply Date: Fri, 23 Feb 2018 14:46:51 +0100 Message-ID: <1519393611-31367-1-git-send-email-amelie.delaunay@st.com> Mime-Version: 1.0 Content-Type: text/plain; charset="us-ascii" Content-Transfer-Encoding: 7bit Return-path: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+linux-arm-kernel=m.gmane.org@lists.infradead.org To: Greg Kroah-Hartman , Rob Herring , Mark Rutland , Tony Prisk , Alan Stern , Roger Quadros , Felipe Balbi Cc: devicetree@vger.kernel.org, Amelie Delaunay , linux-usb@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org List-Id: devicetree@vger.kernel.org On some boards, especially when vbus supply requires large current, and the charge pump on the PHY isn't enough, an external vbus power switch may be used. Add support for optional external vbus supply per port in ehci-platform. Signed-off-by: Amelie Delaunay --- Changes in v3: * Address Felipe Balbi comments: reduce indentation in ehci_platform_port_power. * Address Roger Quadros and Alan Stern comments: platforms can have one external vbus supply per port, so add support to get as many optional regulator as implemented ports on the host controller. Changes in v2: * Address Roger Quadros comments: move regulator_enable/disable from ehci_platform_power_on/off to ehci_platform_port_power. --- Documentation/devicetree/bindings/usb/usb-ehci.txt | 1 + drivers/usb/host/ehci-platform.c | 52 +++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt index 3efde12..cd576db 100644 --- a/Documentation/devicetree/bindings/usb/usb-ehci.txt +++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt @@ -19,6 +19,7 @@ Optional properties: - phys : phandle + phy specifier pair - phy-names : "usb" - resets : phandle + reset specifier pair + - portN_vbus-supply : phandle of regulator supplying vbus for port N Example (Sequoia 440EPx): ehci@e0000300 { diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index b065a96..8e9f201 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,7 @@ struct ehci_platform_priv { struct reset_control *rsts; struct phy **phys; int num_phys; + struct regulator **vbus_supplies; bool reset_on_resume; }; @@ -56,7 +58,8 @@ static int ehci_platform_reset(struct usb_hcd *hcd) struct platform_device *pdev = to_platform_device(hcd->self.controller); struct usb_ehci_pdata *pdata = dev_get_platdata(&pdev->dev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); + int portnum, n_ports, retval; ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug; @@ -71,11 +74,57 @@ static int ehci_platform_reset(struct usb_hcd *hcd) if (retval) return retval; + n_ports = HCS_N_PORTS(ehci->hcs_params); + priv->vbus_supplies = devm_kcalloc(&pdev->dev, n_ports, + sizeof(struct regulator *), + GFP_KERNEL); + if (!priv->vbus_supplies) + return -ENOMEM; + + for (portnum = 0; portnum < n_ports; portnum++) { + struct regulator *vbus_supply; + char id[20]; + + sprintf(id, "port%d_vbus", portnum); + + vbus_supply = devm_regulator_get_optional(&pdev->dev, id); + if (IS_ERR(vbus_supply)) { + retval = PTR_ERR(vbus_supply); + if (retval == -ENODEV) + priv->vbus_supplies[portnum] = NULL; + else + return retval; + } else { + priv->vbus_supplies[portnum] = vbus_supply; + } + } + if (pdata->no_io_watchdog) ehci->need_io_watchdog = 0; return 0; } +static int ehci_platform_port_power(struct usb_hcd *hcd, int portnum, + bool enable) +{ + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); + int ret; + + if (!priv->vbus_supplies[portnum]) + return 0; + + if (enable) + ret = regulator_enable(priv->vbus_supplies[portnum]); + else + ret = regulator_disable(priv->vbus_supplies[portnum]); + if (ret) + dev_err(hcd->self.controller, + "failed to %s vbus supply for port %d: %d\n", + enable ? "enable" : "disable", portnum, ret); + + return ret; +} + static int ehci_platform_power_on(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); @@ -134,6 +183,7 @@ static struct hc_driver __read_mostly ehci_platform_hc_driver; static const struct ehci_driver_overrides platform_overrides __initconst = { .reset = ehci_platform_reset, .extra_priv_size = sizeof(struct ehci_platform_priv), + .port_power = ehci_platform_port_power, }; static struct usb_ehci_pdata ehci_platform_defaults = { -- 2.7.4 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: [v3] usb: host: ehci-platform: add support for optional external vbus supply From: Amelie Delaunay Message-Id: <1519393611-31367-1-git-send-email-amelie.delaunay@st.com> Date: Fri, 23 Feb 2018 14:46:51 +0100 To: Greg Kroah-Hartman , Rob Herring , Mark Rutland , Tony Prisk , Alan Stern , Roger Quadros , Felipe Balbi Cc: linux-usb@vger.kernel.org, devicetree@vger.kernel.org, linux-kernel@vger.kernel.org, linux-arm-kernel@lists.infradead.org, Amelie Delaunay List-ID: T24gc29tZSBib2FyZHMsIGVzcGVjaWFsbHkgd2hlbiB2YnVzIHN1cHBseSByZXF1aXJlcyBsYXJn ZSBjdXJyZW50LAphbmQgdGhlIGNoYXJnZSBwdW1wIG9uIHRoZSBQSFkgaXNuJ3QgZW5vdWdoLCBh biBleHRlcm5hbCB2YnVzIHBvd2VyIHN3aXRjaAptYXkgYmUgdXNlZC4KQWRkIHN1cHBvcnQgZm9y IG9wdGlvbmFsIGV4dGVybmFsIHZidXMgc3VwcGx5IHBlciBwb3J0IGluIGVoY2ktcGxhdGZvcm0u CgpTaWduZWQtb2ZmLWJ5OiBBbWVsaWUgRGVsYXVuYXkgPGFtZWxpZS5kZWxhdW5heUBzdC5jb20+ Ci0tLQpDaGFuZ2VzIGluIHYzOgogKiBBZGRyZXNzIEZlbGlwZSBCYWxiaSBjb21tZW50czogcmVk dWNlIGluZGVudGF0aW9uIGluCiAgIGVoY2lfcGxhdGZvcm1fcG9ydF9wb3dlci4KICogQWRkcmVz cyBSb2dlciBRdWFkcm9zIGFuZCBBbGFuIFN0ZXJuIGNvbW1lbnRzOiBwbGF0Zm9ybXMgY2FuIGhh dmUgb25lCiAgIGV4dGVybmFsIHZidXMgc3VwcGx5IHBlciBwb3J0LCBzbyBhZGQgc3VwcG9ydCB0 byBnZXQgYXMgbWFueSBvcHRpb25hbAogICByZWd1bGF0b3IgYXMgaW1wbGVtZW50ZWQgcG9ydHMg b24gdGhlIGhvc3QgY29udHJvbGxlci4KCkNoYW5nZXMgaW4gdjI6CiAqIEFkZHJlc3MgUm9nZXIg UXVhZHJvcyBjb21tZW50czogbW92ZSByZWd1bGF0b3JfZW5hYmxlL2Rpc2FibGUgZnJvbQogICBl aGNpX3BsYXRmb3JtX3Bvd2VyX29uL29mZiB0byBlaGNpX3BsYXRmb3JtX3BvcnRfcG93ZXIuCi0t LQogRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL3VzYi91c2ItZWhjaS50eHQgfCAg MSArCiBkcml2ZXJzL3VzYi9ob3N0L2VoY2ktcGxhdGZvcm0uYyAgICAgICAgICAgICAgICAgICB8 IDUyICsrKysrKysrKysrKysrKysrKysrKy0KIDIgZmlsZXMgY2hhbmdlZCwgNTIgaW5zZXJ0aW9u cygrKSwgMSBkZWxldGlvbigtKQoKZGlmZiAtLWdpdCBhL0RvY3VtZW50YXRpb24vZGV2aWNldHJl ZS9iaW5kaW5ncy91c2IvdXNiLWVoY2kudHh0IGIvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2Jp bmRpbmdzL3VzYi91c2ItZWhjaS50eHQKaW5kZXggM2VmZGUxMi4uY2Q1NzZkYiAxMDA2NDQKLS0t IGEvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL3VzYi91c2ItZWhjaS50eHQKKysr IGIvRG9jdW1lbnRhdGlvbi9kZXZpY2V0cmVlL2JpbmRpbmdzL3VzYi91c2ItZWhjaS50eHQKQEAg LTE5LDYgKzE5LDcgQEAgT3B0aW9uYWwgcHJvcGVydGllczoKICAtIHBoeXMgOiBwaGFuZGxlICsg cGh5IHNwZWNpZmllciBwYWlyCiAgLSBwaHktbmFtZXMgOiAidXNiIgogIC0gcmVzZXRzIDogcGhh bmRsZSArIHJlc2V0IHNwZWNpZmllciBwYWlyCisgLSBwb3J0Tl92YnVzLXN1cHBseSA6IHBoYW5k bGUgb2YgcmVndWxhdG9yIHN1cHBseWluZyB2YnVzIGZvciBwb3J0IE4KIAogRXhhbXBsZSAoU2Vx dW9pYSA0NDBFUHgpOgogICAgIGVoY2lAZTAwMDAzMDAgewpkaWZmIC0tZ2l0IGEvZHJpdmVycy91 c2IvaG9zdC9laGNpLXBsYXRmb3JtLmMgYi9kcml2ZXJzL3VzYi9ob3N0L2VoY2ktcGxhdGZvcm0u YwppbmRleCBiMDY1YTk2Li44ZTlmMjAxIDEwMDY0NAotLS0gYS9kcml2ZXJzL3VzYi9ob3N0L2Vo Y2ktcGxhdGZvcm0uYworKysgYi9kcml2ZXJzL3VzYi9ob3N0L2VoY2ktcGxhdGZvcm0uYwpAQCAt MjksNiArMjksNyBAQAogI2luY2x1ZGUgPGxpbnV4L29mLmg+CiAjaW5jbHVkZSA8bGludXgvcGh5 L3BoeS5oPgogI2luY2x1ZGUgPGxpbnV4L3BsYXRmb3JtX2RldmljZS5oPgorI2luY2x1ZGUgPGxp bnV4L3JlZ3VsYXRvci9jb25zdW1lci5oPgogI2luY2x1ZGUgPGxpbnV4L3Jlc2V0Lmg+CiAjaW5j bHVkZSA8bGludXgvdXNiLmg+CiAjaW5jbHVkZSA8bGludXgvdXNiL2hjZC5oPgpAQCAtNDYsNiAr NDcsNyBAQCBzdHJ1Y3QgZWhjaV9wbGF0Zm9ybV9wcml2IHsKIAlzdHJ1Y3QgcmVzZXRfY29udHJv bCAqcnN0czsKIAlzdHJ1Y3QgcGh5ICoqcGh5czsKIAlpbnQgbnVtX3BoeXM7CisJc3RydWN0IHJl Z3VsYXRvciAqKnZidXNfc3VwcGxpZXM7CiAJYm9vbCByZXNldF9vbl9yZXN1bWU7CiB9OwogCkBA IC01Niw3ICs1OCw4IEBAIHN0YXRpYyBpbnQgZWhjaV9wbGF0Zm9ybV9yZXNldChzdHJ1Y3QgdXNi X2hjZCAqaGNkKQogCXN0cnVjdCBwbGF0Zm9ybV9kZXZpY2UgKnBkZXYgPSB0b19wbGF0Zm9ybV9k ZXZpY2UoaGNkLT5zZWxmLmNvbnRyb2xsZXIpOwogCXN0cnVjdCB1c2JfZWhjaV9wZGF0YSAqcGRh dGEgPSBkZXZfZ2V0X3BsYXRkYXRhKCZwZGV2LT5kZXYpOwogCXN0cnVjdCBlaGNpX2hjZCAqZWhj aSA9IGhjZF90b19laGNpKGhjZCk7Ci0JaW50IHJldHZhbDsKKwlzdHJ1Y3QgZWhjaV9wbGF0Zm9y bV9wcml2ICpwcml2ID0gaGNkX3RvX2VoY2lfcHJpdihoY2QpOworCWludCBwb3J0bnVtLCBuX3Bv cnRzLCByZXR2YWw7CiAKIAllaGNpLT5oYXNfc3lub3BzeXNfaGNfYnVnID0gcGRhdGEtPmhhc19z eW5vcHN5c19oY19idWc7CiAKQEAgLTcxLDExICs3NCw1NyBAQCBzdGF0aWMgaW50IGVoY2lfcGxh dGZvcm1fcmVzZXQoc3RydWN0IHVzYl9oY2QgKmhjZCkKIAlpZiAocmV0dmFsKQogCQlyZXR1cm4g cmV0dmFsOwogCisJbl9wb3J0cyA9IEhDU19OX1BPUlRTKGVoY2ktPmhjc19wYXJhbXMpOworCXBy aXYtPnZidXNfc3VwcGxpZXMgPSBkZXZtX2tjYWxsb2MoJnBkZXYtPmRldiwgbl9wb3J0cywKKwkJ CQkJICAgc2l6ZW9mKHN0cnVjdCByZWd1bGF0b3IgKiksCisJCQkJCSAgIEdGUF9LRVJORUwpOwor CWlmICghcHJpdi0+dmJ1c19zdXBwbGllcykKKwkJcmV0dXJuIC1FTk9NRU07CisKKwlmb3IgKHBv cnRudW0gPSAwOyBwb3J0bnVtIDwgbl9wb3J0czsgcG9ydG51bSsrKSB7CisJCXN0cnVjdCByZWd1 bGF0b3IgKnZidXNfc3VwcGx5OworCQljaGFyIGlkWzIwXTsKKworCQlzcHJpbnRmKGlkLCAicG9y dCVkX3ZidXMiLCBwb3J0bnVtKTsKKworCQl2YnVzX3N1cHBseSA9IGRldm1fcmVndWxhdG9yX2dl dF9vcHRpb25hbCgmcGRldi0+ZGV2LCBpZCk7CisJCWlmIChJU19FUlIodmJ1c19zdXBwbHkpKSB7 CisJCQlyZXR2YWwgPSBQVFJfRVJSKHZidXNfc3VwcGx5KTsKKwkJCWlmIChyZXR2YWwgPT0gLUVO T0RFVikKKwkJCQlwcml2LT52YnVzX3N1cHBsaWVzW3BvcnRudW1dID0gTlVMTDsKKwkJCWVsc2UK KwkJCQlyZXR1cm4gcmV0dmFsOworCQl9IGVsc2UgeworCQkJcHJpdi0+dmJ1c19zdXBwbGllc1tw b3J0bnVtXSA9IHZidXNfc3VwcGx5OworCQl9CisJfQorCiAJaWYgKHBkYXRhLT5ub19pb193YXRj aGRvZykKIAkJZWhjaS0+bmVlZF9pb193YXRjaGRvZyA9IDA7CiAJcmV0dXJuIDA7CiB9CiAKK3N0 YXRpYyBpbnQgZWhjaV9wbGF0Zm9ybV9wb3J0X3Bvd2VyKHN0cnVjdCB1c2JfaGNkICpoY2QsIGlu dCBwb3J0bnVtLAorCQkJCSAgICBib29sIGVuYWJsZSkKK3sKKwlzdHJ1Y3QgZWhjaV9wbGF0Zm9y bV9wcml2ICpwcml2ID0gaGNkX3RvX2VoY2lfcHJpdihoY2QpOworCWludCByZXQ7CisKKwlpZiAo IXByaXYtPnZidXNfc3VwcGxpZXNbcG9ydG51bV0pCisJCXJldHVybiAwOworCisJaWYgKGVuYWJs ZSkKKwkJcmV0ID0gcmVndWxhdG9yX2VuYWJsZShwcml2LT52YnVzX3N1cHBsaWVzW3BvcnRudW1d KTsKKwllbHNlCisJCXJldCA9IHJlZ3VsYXRvcl9kaXNhYmxlKHByaXYtPnZidXNfc3VwcGxpZXNb cG9ydG51bV0pOworCWlmIChyZXQpCisJCWRldl9lcnIoaGNkLT5zZWxmLmNvbnRyb2xsZXIsCisJ CQkiZmFpbGVkIHRvICVzIHZidXMgc3VwcGx5IGZvciBwb3J0ICVkOiAlZFxuIiwKKwkJCWVuYWJs ZSA/ICJlbmFibGUiIDogImRpc2FibGUiLCBwb3J0bnVtLCByZXQpOworCisJcmV0dXJuIHJldDsK K30KKwogc3RhdGljIGludCBlaGNpX3BsYXRmb3JtX3Bvd2VyX29uKHN0cnVjdCBwbGF0Zm9ybV9k ZXZpY2UgKmRldikKIHsKIAlzdHJ1Y3QgdXNiX2hjZCAqaGNkID0gcGxhdGZvcm1fZ2V0X2RydmRh dGEoZGV2KTsKQEAgLTEzNCw2ICsxODMsNyBAQCBzdGF0aWMgc3RydWN0IGhjX2RyaXZlciBfX3Jl YWRfbW9zdGx5IGVoY2lfcGxhdGZvcm1faGNfZHJpdmVyOwogc3RhdGljIGNvbnN0IHN0cnVjdCBl aGNpX2RyaXZlcl9vdmVycmlkZXMgcGxhdGZvcm1fb3ZlcnJpZGVzIF9faW5pdGNvbnN0ID0gewog CS5yZXNldCA9CQllaGNpX3BsYXRmb3JtX3Jlc2V0LAogCS5leHRyYV9wcml2X3NpemUgPQlzaXpl b2Yoc3RydWN0IGVoY2lfcGxhdGZvcm1fcHJpdiksCisJLnBvcnRfcG93ZXIgPQkJZWhjaV9wbGF0 Zm9ybV9wb3J0X3Bvd2VyLAogfTsKIAogc3RhdGljIHN0cnVjdCB1c2JfZWhjaV9wZGF0YSBlaGNp X3BsYXRmb3JtX2RlZmF1bHRzID0gewo= From mboxrd@z Thu Jan 1 00:00:00 1970 From: amelie.delaunay@st.com (Amelie Delaunay) Date: Fri, 23 Feb 2018 14:46:51 +0100 Subject: [PATCH v3] usb: host: ehci-platform: add support for optional external vbus supply Message-ID: <1519393611-31367-1-git-send-email-amelie.delaunay@st.com> To: linux-arm-kernel@lists.infradead.org List-Id: linux-arm-kernel.lists.infradead.org On some boards, especially when vbus supply requires large current, and the charge pump on the PHY isn't enough, an external vbus power switch may be used. Add support for optional external vbus supply per port in ehci-platform. Signed-off-by: Amelie Delaunay --- Changes in v3: * Address Felipe Balbi comments: reduce indentation in ehci_platform_port_power. * Address Roger Quadros and Alan Stern comments: platforms can have one external vbus supply per port, so add support to get as many optional regulator as implemented ports on the host controller. Changes in v2: * Address Roger Quadros comments: move regulator_enable/disable from ehci_platform_power_on/off to ehci_platform_port_power. --- Documentation/devicetree/bindings/usb/usb-ehci.txt | 1 + drivers/usb/host/ehci-platform.c | 52 +++++++++++++++++++++- 2 files changed, 52 insertions(+), 1 deletion(-) diff --git a/Documentation/devicetree/bindings/usb/usb-ehci.txt b/Documentation/devicetree/bindings/usb/usb-ehci.txt index 3efde12..cd576db 100644 --- a/Documentation/devicetree/bindings/usb/usb-ehci.txt +++ b/Documentation/devicetree/bindings/usb/usb-ehci.txt @@ -19,6 +19,7 @@ Optional properties: - phys : phandle + phy specifier pair - phy-names : "usb" - resets : phandle + reset specifier pair + - portN_vbus-supply : phandle of regulator supplying vbus for port N Example (Sequoia 440EPx): ehci at e0000300 { diff --git a/drivers/usb/host/ehci-platform.c b/drivers/usb/host/ehci-platform.c index b065a96..8e9f201 100644 --- a/drivers/usb/host/ehci-platform.c +++ b/drivers/usb/host/ehci-platform.c @@ -29,6 +29,7 @@ #include #include #include +#include #include #include #include @@ -46,6 +47,7 @@ struct ehci_platform_priv { struct reset_control *rsts; struct phy **phys; int num_phys; + struct regulator **vbus_supplies; bool reset_on_resume; }; @@ -56,7 +58,8 @@ static int ehci_platform_reset(struct usb_hcd *hcd) struct platform_device *pdev = to_platform_device(hcd->self.controller); struct usb_ehci_pdata *pdata = dev_get_platdata(&pdev->dev); struct ehci_hcd *ehci = hcd_to_ehci(hcd); - int retval; + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); + int portnum, n_ports, retval; ehci->has_synopsys_hc_bug = pdata->has_synopsys_hc_bug; @@ -71,11 +74,57 @@ static int ehci_platform_reset(struct usb_hcd *hcd) if (retval) return retval; + n_ports = HCS_N_PORTS(ehci->hcs_params); + priv->vbus_supplies = devm_kcalloc(&pdev->dev, n_ports, + sizeof(struct regulator *), + GFP_KERNEL); + if (!priv->vbus_supplies) + return -ENOMEM; + + for (portnum = 0; portnum < n_ports; portnum++) { + struct regulator *vbus_supply; + char id[20]; + + sprintf(id, "port%d_vbus", portnum); + + vbus_supply = devm_regulator_get_optional(&pdev->dev, id); + if (IS_ERR(vbus_supply)) { + retval = PTR_ERR(vbus_supply); + if (retval == -ENODEV) + priv->vbus_supplies[portnum] = NULL; + else + return retval; + } else { + priv->vbus_supplies[portnum] = vbus_supply; + } + } + if (pdata->no_io_watchdog) ehci->need_io_watchdog = 0; return 0; } +static int ehci_platform_port_power(struct usb_hcd *hcd, int portnum, + bool enable) +{ + struct ehci_platform_priv *priv = hcd_to_ehci_priv(hcd); + int ret; + + if (!priv->vbus_supplies[portnum]) + return 0; + + if (enable) + ret = regulator_enable(priv->vbus_supplies[portnum]); + else + ret = regulator_disable(priv->vbus_supplies[portnum]); + if (ret) + dev_err(hcd->self.controller, + "failed to %s vbus supply for port %d: %d\n", + enable ? "enable" : "disable", portnum, ret); + + return ret; +} + static int ehci_platform_power_on(struct platform_device *dev) { struct usb_hcd *hcd = platform_get_drvdata(dev); @@ -134,6 +183,7 @@ static struct hc_driver __read_mostly ehci_platform_hc_driver; static const struct ehci_driver_overrides platform_overrides __initconst = { .reset = ehci_platform_reset, .extra_priv_size = sizeof(struct ehci_platform_priv), + .port_power = ehci_platform_port_power, }; static struct usb_ehci_pdata ehci_platform_defaults = { -- 2.7.4