From patchwork Fri Jan 20 18:50:53 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 92109 Delivered-To: patch@linaro.org Received: by 10.182.3.34 with SMTP id 2csp199443obz; Fri, 20 Jan 2017 10:52:26 -0800 (PST) X-Received: by 10.98.84.193 with SMTP id i184mr18289114pfb.27.1484938346602; Fri, 20 Jan 2017 10:52:26 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id z74si7563976pff.228.2017.01.20.10.52.26; Fri, 20 Jan 2017 10:52:26 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753329AbdATSwT (ORCPT + 25 others); Fri, 20 Jan 2017 13:52:19 -0500 Received: from mail-pf0-f180.google.com ([209.85.192.180]:35098 "EHLO mail-pf0-f180.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752741AbdATSvB (ORCPT ); Fri, 20 Jan 2017 13:51:01 -0500 Received: by mail-pf0-f180.google.com with SMTP id f144so24348229pfa.2 for ; Fri, 20 Jan 2017 10:51:01 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=L7oTDZQz+Ccz0Xv8iAY1SiJBteUFq0kkXxglmVeLLW0=; b=Hc/LiwtBY3wgpAlakfyODYdJkvrutpuTLgac4VYbLYdgjPIRf8bDXN2msg6S8g3tVm 7kCvx8Z8PCFoq79Z7RiimTBAmpOHm/sMkwYm/uIcW5AjhO8/CUX19Ii9stQcNCTCahXr 8dqi3spJAgULDjUUK1fCr/U+G02XhGn6h8cEg= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=L7oTDZQz+Ccz0Xv8iAY1SiJBteUFq0kkXxglmVeLLW0=; b=jlK4AWbqsH3o38eo4fAhxXDGTy6o7TInPUWsnZzwFvDeNbevZSn71KdOJDpwtB40gJ Ea6tnXj1+yjRN66pydvL1BBRav6a3Od0UTR/19kZK8s53F3sRMm+qjydJWNO7x6cpwHy YLRpweB+2jMK7w747Ja6qO1ssEIy/AOeRbdem3BfmKRZcRbmbsd7BkFwAbcALlwuIi3f kb9OjkNuh/5NcPmHhgzukziZ5k5HEYN+wM3jjFUSKqN+Vth3LjPIaiiFs5XmoOzPxW1c 4tXKkjyA8PGpjRz9rqq3onJZCF8h03NEvXFXup0gr5nusxvR2FJ6GnpA6MiRT6Q70qas KPAw== X-Gm-Message-State: AIkVDXJV3EcH8v94eQODQ2bI59d+NKaGo80Y3wsbiHdNGs5KfiHMjVRlXpAwOoggdVgpzkxe X-Received: by 10.84.209.204 with SMTP id y70mr23596643plh.180.1484938260653; Fri, 20 Jan 2017 10:51:00 -0800 (PST) Received: from localhost.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id j78sm18574274pfk.39.2017.01.20.10.50.59 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 20 Jan 2017 10:51:00 -0800 (PST) From: Stephen Boyd To: Peter Chen , Kishon Vijay Abraham I Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Andy Gross , Bjorn Andersson , Neil Armstrong , Arnd Bergmann , Felipe Balbi , linux-usb@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v7 1/5] phy: Add support for Qualcomm's USB HSIC phy Date: Fri, 20 Jan 2017 10:50:53 -0800 Message-Id: <20170120185057.16206-2-stephen.boyd@linaro.org> X-Mailer: git-send-email 2.10.0.297.gf6727b0 In-Reply-To: <20170120185057.16206-1-stephen.boyd@linaro.org> References: <20170120185057.16206-1-stephen.boyd@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The HSIC USB controller on qcom SoCs has an integrated all digital phy controlled via the ULPI viewport. Acked-by: Rob Herring Cc: Signed-off-by: Stephen Boyd --- No changes. .../devicetree/bindings/phy/qcom,usb-hsic-phy.txt | 65 +++++++++ drivers/phy/Kconfig | 7 + drivers/phy/Makefile | 1 + drivers/phy/phy-qcom-usb-hsic.c | 160 +++++++++++++++++++++ 4 files changed, 233 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/qcom,usb-hsic-phy.txt create mode 100644 drivers/phy/phy-qcom-usb-hsic.c -- 2.10.0.297.gf6727b0 diff --git a/Documentation/devicetree/bindings/phy/qcom,usb-hsic-phy.txt b/Documentation/devicetree/bindings/phy/qcom,usb-hsic-phy.txt new file mode 100644 index 000000000000..3c7cb2be4b12 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/qcom,usb-hsic-phy.txt @@ -0,0 +1,65 @@ +Qualcomm's USB HSIC PHY + +PROPERTIES + +- compatible: + Usage: required + Value type: + Definition: Should contain "qcom,usb-hsic-phy" and more specifically one of the + following: + + "qcom,usb-hsic-phy-mdm9615" + "qcom,usb-hsic-phy-msm8974" + +- #phy-cells: + Usage: required + Value type: + Definition: Should contain 0 + +- clocks: + Usage: required + Value type: + Definition: Should contain clock specifier for phy, calibration and + a calibration sleep clock + +- clock-names: + Usage: required + Value type: + Definition: Should contain "phy, "cal" and "cal_sleep" + +- pinctrl-names: + Usage: required + Value type: + Definition: Should contain "init" and "default" in that order + +- pinctrl-0: + Usage: required + Value type: + Definition: List of pinctrl settings to apply to keep HSIC pins in a glitch + free state + +- pinctrl-1: + Usage: required + Value type: + Definition: List of pinctrl settings to apply to mux out the HSIC pins + +EXAMPLE + +usb-controller { + ulpi { + phy { + compatible = "qcom,usb-hsic-phy-msm8974", + "qcom,usb-hsic-phy"; + #phy-cells = <0>; + pinctrl-names = "init", "default"; + pinctrl-0 = <&hsic_sleep>; + pinctrl-1 = <&hsic_default>; + clocks = <&gcc GCC_USB_HSIC_CLK>, + <&gcc GCC_USB_HSIC_IO_CAL_CLK>, + <&gcc GCC_USB_HSIC_IO_CAL_SLEEP_CLK>; + clock-names = "phy", "cal", "cal_sleep"; + assigned-clocks = <&gcc GCC_USB_HSIC_IO_CAL_CLK>; + assigned-clock-rates = <960000>; + }; + }; +}; diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index e8eb7f225a88..a430a64981d5 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -437,6 +437,13 @@ config PHY_QCOM_UFS help Support for UFS PHY on QCOM chipsets. +config PHY_QCOM_USB_HSIC + tristate "Qualcomm USB HSIC ULPI PHY module" + depends on USB_ULPI_BUS + select GENERIC_PHY + help + Support for the USB HSIC ULPI compliant PHY on QCOM chipsets. + config PHY_TUSB1210 tristate "TI TUSB1210 ULPI PHY module" depends on USB_ULPI_BUS diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index 65eb2f436a41..c43c9df5d301 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o +obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o obj-$(CONFIG_PHY_PISTACHIO_USB) += phy-pistachio-usb.o diff --git a/drivers/phy/phy-qcom-usb-hsic.c b/drivers/phy/phy-qcom-usb-hsic.c new file mode 100644 index 000000000000..47690f9945b9 --- /dev/null +++ b/drivers/phy/phy-qcom-usb-hsic.c @@ -0,0 +1,160 @@ +/** + * Copyright (C) 2016 Linaro Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include + +#include "ulpi_phy.h" + +#define ULPI_HSIC_CFG 0x30 +#define ULPI_HSIC_IO_CAL 0x33 + +struct qcom_usb_hsic_phy { + struct ulpi *ulpi; + struct phy *phy; + struct pinctrl *pctl; + struct clk *phy_clk; + struct clk *cal_clk; + struct clk *cal_sleep_clk; +}; + +static int qcom_usb_hsic_phy_power_on(struct phy *phy) +{ + struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy); + struct ulpi *ulpi = uphy->ulpi; + struct pinctrl_state *pins_default; + int ret; + + ret = clk_prepare_enable(uphy->phy_clk); + if (ret) + return ret; + + ret = clk_prepare_enable(uphy->cal_clk); + if (ret) + goto err_cal; + + ret = clk_prepare_enable(uphy->cal_sleep_clk); + if (ret) + goto err_sleep; + + /* Set periodic calibration interval to ~2.048sec in HSIC_IO_CAL_REG */ + ret = ulpi_write(ulpi, ULPI_HSIC_IO_CAL, 0xff); + if (ret) + goto err_ulpi; + + /* Enable periodic IO calibration in HSIC_CFG register */ + ret = ulpi_write(ulpi, ULPI_HSIC_CFG, 0xa8); + if (ret) + goto err_ulpi; + + /* Configure pins for HSIC functionality */ + pins_default = pinctrl_lookup_state(uphy->pctl, PINCTRL_STATE_DEFAULT); + if (IS_ERR(pins_default)) + return PTR_ERR(pins_default); + + ret = pinctrl_select_state(uphy->pctl, pins_default); + if (ret) + goto err_ulpi; + + /* Enable HSIC mode in HSIC_CFG register */ + ret = ulpi_write(ulpi, ULPI_SET(ULPI_HSIC_CFG), 0x01); + if (ret) + goto err_ulpi; + + /* Disable auto-resume */ + ret = ulpi_write(ulpi, ULPI_CLR(ULPI_IFC_CTRL), + ULPI_IFC_CTRL_AUTORESUME); + if (ret) + goto err_ulpi; + + return ret; +err_ulpi: + clk_disable_unprepare(uphy->cal_sleep_clk); +err_sleep: + clk_disable_unprepare(uphy->cal_clk); +err_cal: + clk_disable_unprepare(uphy->phy_clk); + return ret; +} + +static int qcom_usb_hsic_phy_power_off(struct phy *phy) +{ + struct qcom_usb_hsic_phy *uphy = phy_get_drvdata(phy); + + clk_disable_unprepare(uphy->cal_sleep_clk); + clk_disable_unprepare(uphy->cal_clk); + clk_disable_unprepare(uphy->phy_clk); + + return 0; +} + +static const struct phy_ops qcom_usb_hsic_phy_ops = { + .power_on = qcom_usb_hsic_phy_power_on, + .power_off = qcom_usb_hsic_phy_power_off, + .owner = THIS_MODULE, +}; + +static int qcom_usb_hsic_phy_probe(struct ulpi *ulpi) +{ + struct qcom_usb_hsic_phy *uphy; + struct phy_provider *p; + struct clk *clk; + + uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL); + if (!uphy) + return -ENOMEM; + ulpi_set_drvdata(ulpi, uphy); + + uphy->ulpi = ulpi; + uphy->pctl = devm_pinctrl_get(&ulpi->dev); + if (IS_ERR(uphy->pctl)) + return PTR_ERR(uphy->pctl); + + uphy->phy_clk = clk = devm_clk_get(&ulpi->dev, "phy"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + uphy->cal_clk = clk = devm_clk_get(&ulpi->dev, "cal"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + uphy->cal_sleep_clk = clk = devm_clk_get(&ulpi->dev, "cal_sleep"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node, + &qcom_usb_hsic_phy_ops); + if (IS_ERR(uphy->phy)) + return PTR_ERR(uphy->phy); + phy_set_drvdata(uphy->phy, uphy); + + p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate); + return PTR_ERR_OR_ZERO(p); +} + +static const struct of_device_id qcom_usb_hsic_phy_match[] = { + { .compatible = "qcom,usb-hsic-phy", }, + { } +}; +MODULE_DEVICE_TABLE(of, qcom_usb_hsic_phy_match); + +static struct ulpi_driver qcom_usb_hsic_phy_driver = { + .probe = qcom_usb_hsic_phy_probe, + .driver = { + .name = "qcom_usb_hsic_phy", + .of_match_table = qcom_usb_hsic_phy_match, + }, +}; +module_ulpi_driver(qcom_usb_hsic_phy_driver); + +MODULE_DESCRIPTION("Qualcomm USB HSIC phy"); +MODULE_LICENSE("GPL v2"); From patchwork Fri Jan 20 18:50:54 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 92108 Delivered-To: patch@linaro.org Received: by 10.182.3.34 with SMTP id 2csp199272obz; Fri, 20 Jan 2017 10:51:57 -0800 (PST) X-Received: by 10.99.232.5 with SMTP id s5mr17766684pgh.66.1484938317896; Fri, 20 Jan 2017 10:51:57 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id b88si7569320pli.222.2017.01.20.10.51.57; Fri, 20 Jan 2017 10:51:57 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753292AbdATSv4 (ORCPT + 25 others); Fri, 20 Jan 2017 13:51:56 -0500 Received: from mail-pg0-f42.google.com ([74.125.83.42]:33041 "EHLO mail-pg0-f42.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1752630AbdATSvC (ORCPT ); Fri, 20 Jan 2017 13:51:02 -0500 Received: by mail-pg0-f42.google.com with SMTP id 204so25654737pge.0 for ; Fri, 20 Jan 2017 10:51:02 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=LSF8wmYZeZ1EtDEzeK0K+D7OAW9TSjZGln9gDKva/TY=; b=Eom+w7RQgzkoNNqrHansobhnDAaVP27Z685+ZiHYGEl6W7lLOqyUpUi804CIeNbnZV hceMkFaxRd1iq1FenvnBZiXrg+dJQ2jA9xjljIScZ07IKLHWh56dKVaf11pCofb8PEkx k+n4NSodbIUmbR8Db4WGs3usFRpdDQ4BGXmlY= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=LSF8wmYZeZ1EtDEzeK0K+D7OAW9TSjZGln9gDKva/TY=; b=QQ9CZHLx9C9g5xF2vH3CWQlUZGfU13SRlseajugAJOf0NrVcy5FezQ1lx6eYlUB2ZG F9r5fS+PP0DmhVJdO3ALXzTuJUUNAyKTNGgflgkF+dEQk0QH+7ttLO3O4oOpVoIzj1Ze 8HJoiv9tW0dEwCl8wNdKxy0igrdYALHS4LnNzAhCj2K2zqjKaHHtQpo3DCmr2QqiY7JW FDYzmp1sDTZhOa+PobRyZQjkqg+yhKTBWhy3d/fbO916UKP3F//Yg0XN7BJQ3tDa5RSZ Dnd6JsX6OC4mJXnLtO0goaDzC63Ern712micD4bIQAUamLwkoB0Pu5CyzvyxTv/Y2T4E l4Fw== X-Gm-Message-State: AIkVDXLmpllrpthODikuyyUUHNVW+Z2xLtGHmA8R8X+WVHKdNbzT/TCK3OZ9EzIkCNJP21Gu X-Received: by 10.99.170.70 with SMTP id x6mr18423389pgo.14.1484938261867; Fri, 20 Jan 2017 10:51:01 -0800 (PST) Received: from localhost.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id j78sm18574274pfk.39.2017.01.20.10.51.00 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 20 Jan 2017 10:51:01 -0800 (PST) From: Stephen Boyd To: Peter Chen , Kishon Vijay Abraham I Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Andy Gross , Bjorn Andersson , Neil Armstrong , Arnd Bergmann , Felipe Balbi , linux-usb@vger.kernel.org, Greg Kroah-Hartman Subject: [PATCH v7 2/5] usb: chipidea: msm: Configure phy for appropriate mode Date: Fri, 20 Jan 2017 10:50:54 -0800 Message-Id: <20170120185057.16206-3-stephen.boyd@linaro.org> X-Mailer: git-send-email 2.10.0.297.gf6727b0 In-Reply-To: <20170120185057.16206-1-stephen.boyd@linaro.org> References: <20170120185057.16206-1-stephen.boyd@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org When the qcom chipidea controller is used with an extcon, we need to signal device mode or host mode to the phy so it can configure itself for the correct mode. This should be done after the phy is powered up, so that the register writes work correctly. Add in the appropriate phy_set_mode() call here. To signal the correct state to the qcom glue driver we need to change the ci->role before we do the role switch. Make sure to undo the change if the role switch fails, but otherwise update the state before calling the role start function so that the glue driver knows what state to configure for. Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd --- Made this msm specific because of how msm handles phy powerup. drivers/usb/chipidea/ci.h | 7 +++++-- drivers/usb/chipidea/ci_hdrc_msm.c | 4 ++++ 2 files changed, 9 insertions(+), 2 deletions(-) -- 2.10.0.297.gf6727b0 diff --git a/drivers/usb/chipidea/ci.h b/drivers/usb/chipidea/ci.h index 59e22389c10b..18348b0529af 100644 --- a/drivers/usb/chipidea/ci.h +++ b/drivers/usb/chipidea/ci.h @@ -268,6 +268,7 @@ static inline struct ci_role_driver *ci_role(struct ci_hdrc *ci) static inline int ci_role_start(struct ci_hdrc *ci, enum ci_role role) { int ret; + enum ci_role prev_role; if (role >= CI_ROLE_END) return -EINVAL; @@ -275,9 +276,11 @@ static inline int ci_role_start(struct ci_hdrc *ci, enum ci_role role) if (!ci->roles[role]) return -ENXIO; + prev_role = ci->role; + ci->role = role; ret = ci->roles[role]->start(ci); - if (!ret) - ci->role = role; + if (ret) + ci->role = prev_role; return ret; } diff --git a/drivers/usb/chipidea/ci_hdrc_msm.c b/drivers/usb/chipidea/ci_hdrc_msm.c index f1ede7909f54..9c58d13970ca 100644 --- a/drivers/usb/chipidea/ci_hdrc_msm.c +++ b/drivers/usb/chipidea/ci_hdrc_msm.c @@ -125,6 +125,10 @@ static int ci_hdrc_msm_notify_event(struct ci_hdrc *ci, unsigned event) hw_write(ci, OP_USBCMD, HSPHY_SESS_VLD_CTRL, HSPHY_SESS_VLD_CTRL); + if (ci->role == CI_ROLE_GADGET) + phy_set_mode(ci->phy, PHY_MODE_USB_DEVICE); + else if (ci->role == CI_ROLE_HOST) + phy_set_mode(ci->phy, PHY_MODE_USB_HOST); } break; case CI_HDRC_CONTROLLER_STOPPED_EVENT: From patchwork Fri Jan 20 18:50:55 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 92105 Delivered-To: patch@linaro.org Received: by 10.182.3.34 with SMTP id 2csp199091obz; Fri, 20 Jan 2017 10:51:23 -0800 (PST) X-Received: by 10.99.132.200 with SMTP id k191mr18584986pgd.10.1484938283501; Fri, 20 Jan 2017 10:51:23 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 1si7191612pgs.278.2017.01.20.10.51.23; Fri, 20 Jan 2017 10:51:23 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-arm-msm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=neutral (body hash did not verify) header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-arm-msm-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-arm-msm-owner@vger.kernel.org; dmarc=fail (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753115AbdATSvG (ORCPT + 9 others); Fri, 20 Jan 2017 13:51:06 -0500 Received: from mail-pg0-f46.google.com ([74.125.83.46]:33909 "EHLO mail-pg0-f46.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753041AbdATSvD (ORCPT ); Fri, 20 Jan 2017 13:51:03 -0500 Received: by mail-pg0-f46.google.com with SMTP id 14so25596738pgg.1 for ; Fri, 20 Jan 2017 10:51:03 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=1IpWcgUTmLVlQ2BjgLx73U6iz+Or+DLLkJ487QgzWOc=; b=GNlpKimaZkP6P1VxUruCFQ0GnhDSVPxmtCCiJQMNTf34+onpuO1r+SEDlUZl6WwmCP OLyE2qnq4e/n4gs/UewGHJ4BDxydu3/goemDa+X3Xi0FAQYNJWYiRkJ6/dRgL/I0jtv+ A+FNFumJowdAu8vcr3A+nRRkDcpNWQgywn/P4= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=1IpWcgUTmLVlQ2BjgLx73U6iz+Or+DLLkJ487QgzWOc=; b=LF7lM4nfyJs81EeLenA6VxEtUeqHmr5tgwF/mbRRnQsrv7VRCTAtQflReS9VPej4dj wLB9tfWzTB5pyVwCMCq0DhfcMQe4g6ya4d+uYP94j924g4RbTS+n0cGN3u81HLJ64vSq JE73sbOkLEOJXG/kAoMmtC/AEJ0E+ee/28BNpxbn220/K1KbPLjhlhq4tI4TZHoLnfI+ 2pF5BMJaZDcN+QZ4suqpXObp6D3TtV/LUyQ8IZS6YurNrppNKwYPdGlHP/tPhPnBoX3E JGhtKh9MqFWjQHQ5iu4bXgRQkFdA3HlJCWwMUq3FToaQXVr+nus+yQZi4ot220SYwlJM 3s7Q== X-Gm-Message-State: AIkVDXJQfknnOymBMyq0QaqDGS36l+ChuKZjn9Vh6FOnACDgXatoA5S5BKp56tq/zS9EdOiC X-Received: by 10.84.254.74 with SMTP id a10mr23482645pln.57.1484938262858; Fri, 20 Jan 2017 10:51:02 -0800 (PST) Received: from localhost.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id j78sm18574274pfk.39.2017.01.20.10.51.01 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 20 Jan 2017 10:51:02 -0800 (PST) From: Stephen Boyd To: Peter Chen , Kishon Vijay Abraham I Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Andy Gross , Bjorn Andersson , Neil Armstrong , Arnd Bergmann , Felipe Balbi , linux-usb@vger.kernel.org Subject: [PATCH v7 3/5] phy: Add set_vbus callback Date: Fri, 20 Jan 2017 10:50:55 -0800 Message-Id: <20170120185057.16206-4-stephen.boyd@linaro.org> X-Mailer: git-send-email 2.10.0.297.gf6727b0 In-Reply-To: <20170120185057.16206-1-stephen.boyd@linaro.org> References: <20170120185057.16206-1-stephen.boyd@linaro.org> Sender: linux-arm-msm-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-arm-msm@vger.kernel.org Some USB PHYs need to be told about vbus changing state explicitly. For example the qcom USB HS PHY needs to toggle a bit when vbus goes from low to high (VBUSVLDEXT) to cause the "session valid" signal to toggle. This signal will pull up D+ when the phy starts running. If the vbus signal isn't routed to the PHY this "session valid" signal won't ever toggle, so we have to toggle it explicitly. This callback is used to do that. Cc: Peter Chen Signed-off-by: Stephen Boyd --- New patch drivers/phy/phy-core.c | 15 +++++++++++++++ include/linux/phy/phy.h | 10 ++++++++++ 2 files changed, 25 insertions(+) -- 2.10.0.297.gf6727b0 -- To unsubscribe from this list: send the line "unsubscribe linux-arm-msm" in the body of a message to majordomo@vger.kernel.org More majordomo info at http://vger.kernel.org/majordomo-info.html diff --git a/drivers/phy/phy-core.c b/drivers/phy/phy-core.c index a268f4d6f3e9..8b1a6bfa5133 100644 --- a/drivers/phy/phy-core.c +++ b/drivers/phy/phy-core.c @@ -357,6 +357,21 @@ int phy_set_mode(struct phy *phy, enum phy_mode mode) } EXPORT_SYMBOL_GPL(phy_set_mode); +int phy_set_vbus(struct phy *phy, int on) +{ + int ret; + + if (!phy || !phy->ops->set_vbus) + return 0; + + mutex_lock(&phy->mutex); + ret = phy->ops->set_vbus(phy, on); + mutex_unlock(&phy->mutex); + + return ret; +} +EXPORT_SYMBOL_GPL(phy_set_vbus); + int phy_reset(struct phy *phy) { int ret; diff --git a/include/linux/phy/phy.h b/include/linux/phy/phy.h index 78bb0d7f6b11..4d1ebde7fb14 100644 --- a/include/linux/phy/phy.h +++ b/include/linux/phy/phy.h @@ -36,6 +36,7 @@ enum phy_mode { * @power_on: powering on the phy * @power_off: powering off the phy * @set_mode: set the mode of the phy + * @set_vbus: enable/disable vbus in the phy (USB) * @reset: resetting the phy * @owner: the module owner containing the ops */ @@ -45,6 +46,7 @@ struct phy_ops { int (*power_on)(struct phy *phy); int (*power_off)(struct phy *phy); int (*set_mode)(struct phy *phy, enum phy_mode mode); + int (*set_vbus)(struct phy *phy, int on); int (*reset)(struct phy *phy); struct module *owner; }; @@ -138,6 +140,7 @@ int phy_exit(struct phy *phy); int phy_power_on(struct phy *phy); int phy_power_off(struct phy *phy); int phy_set_mode(struct phy *phy, enum phy_mode mode); +int phy_set_vbus(struct phy *phy, int on); int phy_reset(struct phy *phy); static inline int phy_get_bus_width(struct phy *phy) { @@ -253,6 +256,13 @@ static inline int phy_set_mode(struct phy *phy, enum phy_mode mode) return -ENOSYS; } +static inline int phy_set_vbus(struct phy *phy, int on) +{ + if (!phy) + return 0; + return -ENOSYS; +} + static inline int phy_reset(struct phy *phy) { if (!phy) From patchwork Fri Jan 20 18:50:56 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 92107 Delivered-To: patch@linaro.org Received: by 10.182.3.34 with SMTP id 2csp199239obz; Fri, 20 Jan 2017 10:51:50 -0800 (PST) X-Received: by 10.98.13.203 with SMTP id 72mr18119751pfn.64.1484938310270; Fri, 20 Jan 2017 10:51:50 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id d137si3832635pfd.198.2017.01.20.10.51.49; Fri, 20 Jan 2017 10:51:50 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753254AbdATSvi (ORCPT + 25 others); Fri, 20 Jan 2017 13:51:38 -0500 Received: from mail-pf0-f179.google.com ([209.85.192.179]:34310 "EHLO mail-pf0-f179.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753063AbdATSvE (ORCPT ); Fri, 20 Jan 2017 13:51:04 -0500 Received: by mail-pf0-f179.google.com with SMTP id e4so24307712pfg.1 for ; Fri, 20 Jan 2017 10:51:04 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=GYsYXqztIk+Y2jiL4EIDnC3RFFOTx/R/cAAyKisUa4I=; b=VKW+hFfi7JM+bUBnEs2uMeBrp/rCCYPhaO5WuDnajsaIs8TIjI/TlQUoSd63b1Ro0z IgK7GGCabYAH4g2x70Di6zyahQuXgtw4Cu9gkG1MLCuvH+p4OpAfCzWseNTG1IOik0Us ZhCFptLx/f8f/P5BK9A3kkywiGWurbzCipej0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=GYsYXqztIk+Y2jiL4EIDnC3RFFOTx/R/cAAyKisUa4I=; b=KP8xRPtGd+Jg5imjHvMAwjmLYiTKfjS7z4dMFz9rGh4dFMH+DfG8B2g3lE0Ow2pXcI 2eeEvc6FC/UCp7nllRXS6Czg1G2ElGq9pNE3MtJgQRPr8hcM1YT8lYrk6wMyIr+ut1Bo gt4NmZuFNbJ5dOE2IxHt7lD3CZc20LvecTyNa2XiviQ39wX8s2Xg8ngr50Gy6N5tEd/8 OGJ3fqctd0cwqUHC0BrJdiIhELUtsaqAXu6qfN9JQxOY+tc2mue1vv4qL7Z9LKuCAbbZ HrmHYAzNDQhpBcFEomzDyB0v+gsNWeWGQAJMG8tuZpqwbEp5PBWWT5XBVhvJpLAlGrmG faEw== X-Gm-Message-State: AIkVDXLLZjYcl/JaOfe933m7naEVoVQ8lFVd3aNerNIh4lgWMvRtQEhWoAUW2NjUVv+01/vb X-Received: by 10.98.87.142 with SMTP id i14mr17951011pfj.85.1484938263983; Fri, 20 Jan 2017 10:51:03 -0800 (PST) Received: from localhost.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id j78sm18574274pfk.39.2017.01.20.10.51.02 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 20 Jan 2017 10:51:03 -0800 (PST) From: Stephen Boyd To: Peter Chen , Kishon Vijay Abraham I Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Andy Gross , Bjorn Andersson , Neil Armstrong , Arnd Bergmann , Felipe Balbi , linux-usb@vger.kernel.org, Greg Kroah-Hartman Subject: [PATCH v7 4/5] usb: chipidea: Signal vbus state to phy Date: Fri, 20 Jan 2017 10:50:56 -0800 Message-Id: <20170120185057.16206-5-stephen.boyd@linaro.org> X-Mailer: git-send-email 2.10.0.297.gf6727b0 In-Reply-To: <20170120185057.16206-1-stephen.boyd@linaro.org> References: <20170120185057.16206-1-stephen.boyd@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org Some USB PHYs need to be told about vbus changing state explicitly. For example the qcom USB HS PHY needs to toggle a bit when vbus goes from low to high (VBUSVLDEXT) to cause the "session valid" signal to toggle. This signal will pull up D+ when the phy starts running. Add the appropriate phy_set_vbus() call here to signal vbus state changes to the phy. Cc: Greg Kroah-Hartman Signed-off-by: Stephen Boyd --- New patch drivers/usb/chipidea/otg.c | 7 +++++-- 1 file changed, 5 insertions(+), 2 deletions(-) -- 2.10.0.297.gf6727b0 diff --git a/drivers/usb/chipidea/otg.c b/drivers/usb/chipidea/otg.c index 10236fe71522..6ea702beed48 100644 --- a/drivers/usb/chipidea/otg.c +++ b/drivers/usb/chipidea/otg.c @@ -134,10 +134,13 @@ void ci_handle_vbus_change(struct ci_hdrc *ci) if (!ci->is_otg) return; - if (hw_read_otgsc(ci, OTGSC_BSV) && !ci->vbus_active) + if (hw_read_otgsc(ci, OTGSC_BSV) && !ci->vbus_active) { usb_gadget_vbus_connect(&ci->gadget); - else if (!hw_read_otgsc(ci, OTGSC_BSV) && ci->vbus_active) + phy_set_vbus(ci->phy, 1); + } else if (!hw_read_otgsc(ci, OTGSC_BSV) && ci->vbus_active) { + phy_set_vbus(ci->phy, 0); usb_gadget_vbus_disconnect(&ci->gadget); + } } /** From patchwork Fri Jan 20 18:50:57 2017 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Stephen Boyd X-Patchwork-Id: 92106 Delivered-To: patch@linaro.org Received: by 10.182.3.34 with SMTP id 2csp199098obz; Fri, 20 Jan 2017 10:51:24 -0800 (PST) X-Received: by 10.84.143.165 with SMTP id 34mr2889219plz.2.1484938284552; Fri, 20 Jan 2017 10:51:24 -0800 (PST) Return-Path: Received: from vger.kernel.org (vger.kernel.org. [209.132.180.67]) by mx.google.com with ESMTP id 1si7191612pgs.278.2017.01.20.10.51.24; Fri, 20 Jan 2017 10:51:24 -0800 (PST) Received-SPF: pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) client-ip=209.132.180.67; Authentication-Results: mx.google.com; dkim=pass header.i=@linaro.org; spf=pass (google.com: best guess record for domain of linux-kernel-owner@vger.kernel.org designates 209.132.180.67 as permitted sender) smtp.mailfrom=linux-kernel-owner@vger.kernel.org; dmarc=pass (p=NONE sp=NONE dis=NONE) header.from=linaro.org Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1753207AbdATSvO (ORCPT + 25 others); Fri, 20 Jan 2017 13:51:14 -0500 Received: from mail-pf0-f175.google.com ([209.85.192.175]:33655 "EHLO mail-pf0-f175.google.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1753074AbdATSvG (ORCPT ); Fri, 20 Jan 2017 13:51:06 -0500 Received: by mail-pf0-f175.google.com with SMTP id y143so24372813pfb.0 for ; Fri, 20 Jan 2017 10:51:05 -0800 (PST) DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=linaro.org; s=google; h=from:to:cc:subject:date:message-id:in-reply-to:references; bh=BLSsjseEhbJZ/vKMLzldWrn3i56v4+sIDBaoJf7Clg8=; b=Ur6+dsPngXfCjXfxmsTSsKS1kQRdOij362MgxJ0VWIgo9qMu/yiZkVW1Ml1d4d8QH/ Ay4JKyXGibYxQVmH6/rbf+h8weFynwbaLnoPmAdAuADRHIzwUf+qNn2oW1FDW8Tc8qfi 4quPR+tkDzgKgVIGvKo5mvcB5QUdwkxX2dGB0= X-Google-DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=1e100.net; s=20161025; h=x-gm-message-state:from:to:cc:subject:date:message-id:in-reply-to :references; bh=BLSsjseEhbJZ/vKMLzldWrn3i56v4+sIDBaoJf7Clg8=; b=rmOi6BXbHMjwASZtLbdjfTigT8RY3A/DlJVMjLaAMtyZFrET/WkFEskATo45Kigo1i eGKgSdYgfUhlkS7IJr0nPlFG4DMqlJyQm6EfhOx9KpU91ZX0S2G4rk1Jc69dEPsttuIG EbiX4PNWr9JljUSdC/0WKivoStT1K3n9gJxvOnmEvA0XwNo5qWFyBuGeKT9jf+QGt2sk 5A3IyQOYuLuhL7VOMnnGKM9W1flf15NZv4RfKxLNZeDbS0TZUOvQGP/aEYkCJN31eW+L QmNUsniaZD23NEb6D8JRKvmxAWX0wb1iyTzUzpg6wzRAu+94VMQVsFMCk08UEEUrYdXe pNlw== X-Gm-Message-State: AIkVDXKkpmLSZdIr5oelw637ogFk230rwg48DKr5YpfN/7cvf4eRAT29qtzEUaNcOGskRtpa X-Received: by 10.99.123.68 with SMTP id k4mr18716186pgn.101.1484938265300; Fri, 20 Jan 2017 10:51:05 -0800 (PST) Received: from localhost.localdomain (i-global254.qualcomm.com. [199.106.103.254]) by smtp.gmail.com with ESMTPSA id j78sm18574274pfk.39.2017.01.20.10.51.04 (version=TLS1_2 cipher=ECDHE-RSA-AES128-SHA bits=128/128); Fri, 20 Jan 2017 10:51:04 -0800 (PST) From: Stephen Boyd To: Peter Chen , Kishon Vijay Abraham I Cc: linux-arm-kernel@lists.infradead.org, linux-kernel@vger.kernel.org, linux-arm-msm@vger.kernel.org, Andy Gross , Bjorn Andersson , Neil Armstrong , Arnd Bergmann , Felipe Balbi , linux-usb@vger.kernel.org, devicetree@vger.kernel.org Subject: [PATCH v7 5/5] phy: Add support for Qualcomm's USB HS phy Date: Fri, 20 Jan 2017 10:50:57 -0800 Message-Id: <20170120185057.16206-6-stephen.boyd@linaro.org> X-Mailer: git-send-email 2.10.0.297.gf6727b0 In-Reply-To: <20170120185057.16206-1-stephen.boyd@linaro.org> References: <20170120185057.16206-1-stephen.boyd@linaro.org> Sender: linux-kernel-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-kernel@vger.kernel.org The high-speed phy on qcom SoCs is controlled via the ULPI viewport. Cc: Acked-by: Rob Herring Signed-off-by: Stephen Boyd --- phy_set_mode() hook split up to toggle two bits independently with new set_vbus() hook. .../devicetree/bindings/phy/qcom,usb-hs-phy.txt | 78 +++++++ drivers/phy/Kconfig | 8 + drivers/phy/Makefile | 1 + drivers/phy/phy-qcom-usb-hs.c | 256 +++++++++++++++++++++ 4 files changed, 343 insertions(+) create mode 100644 Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt create mode 100644 drivers/phy/phy-qcom-usb-hs.c -- 2.10.0.297.gf6727b0 diff --git a/Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt b/Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt new file mode 100644 index 000000000000..bec77a74bd39 --- /dev/null +++ b/Documentation/devicetree/bindings/phy/qcom,usb-hs-phy.txt @@ -0,0 +1,78 @@ +Qualcomm's USB HS PHY + +PROPERTIES + +- compatible: + Usage: required + Value type: + Definition: Should contain "qcom,usb-hs-phy" and more specifically one of the + following: + + "qcom,usb-hs-phy-apq8064" + "qcom,usb-hs-phy-msm8916" + "qcom,usb-hs-phy-msm8974" + +- #phy-cells: + Usage: required + Value type: + Definition: Should contain 0 + +- clocks: + Usage: required + Value type: + Definition: Should contain clock specifier for the reference and sleep + clocks + +- clock-names: + Usage: required + Value type: + Definition: Should contain "ref" and "sleep" for the reference and sleep + clocks respectively + +- resets: + Usage: required + Value type: + Definition: Should contain the phy and POR resets + +- reset-names: + Usage: required + Value type: + Definition: Should contain "phy" and "por" for the phy and POR resets + respectively + +- v3p3-supply: + Usage: required + Value type: + Definition: Should contain a reference to the 3.3V supply + +- v1p8-supply: + Usage: required + Value type: + Definition: Should contain a reference to the 1.8V supply + +- qcom,init-seq: + Usage: optional + Value type: + Definition: Should contain a sequence of ULPI address and value pairs to + program into the ULPI_EXT_VENDOR_SPECIFIC area. This is related + to Device Mode Eye Diagram test. The addresses are offsets + from the ULPI_EXT_VENDOR_SPECIFIC address, for example, + <0x1 0x53> would mean "write the value 0x53 to address 0x81". + +EXAMPLE + +otg: usb-controller { + ulpi { + phy { + compatible = "qcom,usb-hs-phy-msm8974", "qcom,usb-hs-phy"; + #phy-cells = <0>; + clocks = <&xo_board>, <&gcc GCC_USB2A_PHY_SLEEP_CLK>; + clock-names = "ref", "sleep"; + resets = <&gcc GCC_USB2A_PHY_BCR>, <&otg 0>; + reset-names = "phy", "por"; + v3p3-supply = <&pm8941_l24>; + v1p8-supply = <&pm8941_l6>; + qcom,init-seq = /bits/ 8 <0x1 0x63>; + }; + }; +}; diff --git a/drivers/phy/Kconfig b/drivers/phy/Kconfig index a430a64981d5..61a22e985831 100644 --- a/drivers/phy/Kconfig +++ b/drivers/phy/Kconfig @@ -437,6 +437,14 @@ config PHY_QCOM_UFS help Support for UFS PHY on QCOM chipsets. +config PHY_QCOM_USB_HS + tristate "Qualcomm USB HS PHY module" + depends on USB_ULPI_BUS + select GENERIC_PHY + help + Support for the USB high-speed ULPI compliant phy on Qualcomm + chipsets. + config PHY_QCOM_USB_HSIC tristate "Qualcomm USB HSIC ULPI PHY module" depends on USB_ULPI_BUS diff --git a/drivers/phy/Makefile b/drivers/phy/Makefile index c43c9df5d301..0e4259473d28 100644 --- a/drivers/phy/Makefile +++ b/drivers/phy/Makefile @@ -52,6 +52,7 @@ obj-$(CONFIG_PHY_STIH407_USB) += phy-stih407-usb.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-20nm.o obj-$(CONFIG_PHY_QCOM_UFS) += phy-qcom-ufs-qmp-14nm.o +obj-$(CONFIG_PHY_QCOM_USB_HS) += phy-qcom-usb-hs.o obj-$(CONFIG_PHY_QCOM_USB_HSIC) += phy-qcom-usb-hsic.o obj-$(CONFIG_PHY_TUSB1210) += phy-tusb1210.o obj-$(CONFIG_PHY_BRCM_SATA) += phy-brcm-sata.o diff --git a/drivers/phy/phy-qcom-usb-hs.c b/drivers/phy/phy-qcom-usb-hs.c new file mode 100644 index 000000000000..50cb40977737 --- /dev/null +++ b/drivers/phy/phy-qcom-usb-hs.c @@ -0,0 +1,256 @@ +/** + * Copyright (C) 2016 Linaro Ltd + * + * This program is free software; you can redistribute it and/or modify + * it under the terms of the GNU General Public License version 2 as + * published by the Free Software Foundation. + */ +#include +#include +#include +#include +#include +#include +#include +#include + +#include "ulpi_phy.h" + +#define ULPI_PWR_CLK_MNG_REG 0x88 +# define ULPI_PWR_OTG_COMP_DISABLE BIT(0) + +#define ULPI_MISC_A 0x96 +# define ULPI_MISC_A_VBUSVLDEXTSEL BIT(1) +# define ULPI_MISC_A_VBUSVLDEXT BIT(0) + + +struct ulpi_seq { + u8 addr; + u8 val; +}; + +struct qcom_usb_hs_phy { + struct ulpi *ulpi; + struct phy *phy; + struct clk *ref_clk; + struct clk *sleep_clk; + struct regulator *v1p8; + struct regulator *v3p3; + struct reset_control *reset; + struct ulpi_seq *init_seq; + enum usb_dr_mode dr_mode; +}; + +static int qcom_usb_hs_phy_set_mode(struct phy *phy, enum phy_mode mode) +{ + struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy); + u8 addr, val = 0; + int ret; + + switch (mode) { + case PHY_MODE_USB_OTG: + switch (uphy->dr_mode) { + case USB_DR_MODE_OTG: + val |= ULPI_INT_IDGRD; + case USB_DR_MODE_PERIPHERAL: + val |= ULPI_INT_SESS_VALID; + default: + break; + } + + ret = ulpi_write(uphy->ulpi, ULPI_USB_INT_EN_RISE, val); + if (ret) + return ret; + return ulpi_write(uphy->ulpi, ULPI_USB_INT_EN_FALL, val); + case PHY_MODE_USB_DEVICE: + addr = ULPI_SET(ULPI_MISC_A); + break; + case PHY_MODE_USB_HOST: + addr = ULPI_CLR(ULPI_MISC_A); + break; + default: + return -EINVAL; + } + + ulpi_write(uphy->ulpi, ULPI_SET(ULPI_PWR_CLK_MNG_REG), + ULPI_PWR_OTG_COMP_DISABLE); + return ulpi_write(uphy->ulpi, addr, ULPI_MISC_A_VBUSVLDEXTSEL); +} + +static int qcom_usb_hs_phy_set_vbus(struct phy *phy, int on) +{ + struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy); + u8 addr, val; + int ret; + + if (on) + addr = ULPI_SET(ULPI_MISC_A); + else + addr = ULPI_CLR(ULPI_MISC_A); + + return ulpi_write(uphy->ulpi, addr, ULPI_MISC_A_VBUSVLDEXT); +} + +static int qcom_usb_hs_phy_power_on(struct phy *phy) +{ + struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy); + struct ulpi *ulpi = uphy->ulpi; + const struct ulpi_seq *seq; + int ret; + + ret = clk_prepare_enable(uphy->ref_clk); + if (ret) + return ret; + + ret = clk_prepare_enable(uphy->sleep_clk); + if (ret) + goto err_sleep; + + ret = regulator_set_load(uphy->v1p8, 50000); + if (ret < 0) + goto err_1p8; + + ret = regulator_enable(uphy->v1p8); + if (ret) + goto err_1p8; + + ret = regulator_set_voltage_triplet(uphy->v3p3, 3050000, 3300000, + 3300000); + if (ret) + goto err_3p3; + + ret = regulator_set_load(uphy->v3p3, 50000); + if (ret < 0) + goto err_3p3; + + ret = regulator_enable(uphy->v3p3); + if (ret) + goto err_3p3; + + for (seq = uphy->init_seq; seq->addr; seq++) { + ret = ulpi_write(ulpi, ULPI_EXT_VENDOR_SPECIFIC + seq->addr, + seq->val); + if (ret) + goto err_ulpi; + } + + if (uphy->reset) { + ret = reset_control_reset(uphy->reset); + if (ret) + goto err_ulpi; + } + + return 0; +err_ulpi: + regulator_disable(uphy->v3p3); +err_3p3: + regulator_disable(uphy->v1p8); +err_1p8: + clk_disable_unprepare(uphy->sleep_clk); +err_sleep: + clk_disable_unprepare(uphy->ref_clk); + return ret; +} + +static int qcom_usb_hs_phy_power_off(struct phy *phy) +{ + struct qcom_usb_hs_phy *uphy = phy_get_drvdata(phy); + + regulator_disable(uphy->v3p3); + regulator_disable(uphy->v1p8); + clk_disable_unprepare(uphy->sleep_clk); + clk_disable_unprepare(uphy->ref_clk); + + return 0; +} + +static const struct phy_ops qcom_usb_hs_phy_ops = { + .power_on = qcom_usb_hs_phy_power_on, + .power_off = qcom_usb_hs_phy_power_off, + .set_mode = qcom_usb_hs_phy_set_mode, + .set_vbus = qcom_usb_hs_phy_set_vbus, + .owner = THIS_MODULE, +}; + +static int qcom_usb_hs_phy_probe(struct ulpi *ulpi) +{ + struct qcom_usb_hs_phy *uphy; + struct phy_provider *p; + struct clk *clk; + struct regulator *reg; + struct reset_control *reset; + int size; + int ret; + + uphy = devm_kzalloc(&ulpi->dev, sizeof(*uphy), GFP_KERNEL); + if (!uphy) + return -ENOMEM; + ulpi_set_drvdata(ulpi, uphy); + uphy->ulpi = ulpi; + uphy->dr_mode = of_usb_get_dr_mode_by_phy(ulpi->dev.of_node, -1); + + size = of_property_count_u8_elems(ulpi->dev.of_node, "qcom,init-seq"); + if (size < 0) + size = 0; + uphy->init_seq = devm_kmalloc_array(&ulpi->dev, (size / 2) + 1, + sizeof(*uphy->init_seq), GFP_KERNEL); + if (!uphy->init_seq) + return -ENOMEM; + ret = of_property_read_u8_array(ulpi->dev.of_node, "qcom,init-seq", + (u8 *)uphy->init_seq, size); + if (ret && size) + return ret; + /* NUL terminate */ + uphy->init_seq[size / 2].addr = uphy->init_seq[size / 2].val = 0; + + uphy->ref_clk = clk = devm_clk_get(&ulpi->dev, "ref"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + uphy->sleep_clk = clk = devm_clk_get(&ulpi->dev, "sleep"); + if (IS_ERR(clk)) + return PTR_ERR(clk); + + uphy->v1p8 = reg = devm_regulator_get(&ulpi->dev, "v1p8"); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + uphy->v3p3 = reg = devm_regulator_get(&ulpi->dev, "v3p3"); + if (IS_ERR(reg)) + return PTR_ERR(reg); + + uphy->reset = reset = devm_reset_control_get(&ulpi->dev, "por"); + if (IS_ERR(reset)) { + if (PTR_ERR(reset) == -EPROBE_DEFER) + return PTR_ERR(reset); + uphy->reset = NULL; + } + + uphy->phy = devm_phy_create(&ulpi->dev, ulpi->dev.of_node, + &qcom_usb_hs_phy_ops); + if (IS_ERR(uphy->phy)) + return PTR_ERR(uphy->phy); + + phy_set_drvdata(uphy->phy, uphy); + + p = devm_of_phy_provider_register(&ulpi->dev, of_phy_simple_xlate); + return PTR_ERR_OR_ZERO(p); +} + +static const struct of_device_id qcom_usb_hs_phy_match[] = { + { .compatible = "qcom,usb-hs-phy", }, + { } +}; +MODULE_DEVICE_TABLE(of, qcom_usb_hs_phy_match); + +static struct ulpi_driver qcom_usb_hs_phy_driver = { + .probe = qcom_usb_hs_phy_probe, + .driver = { + .name = "qcom_usb_hs_phy", + .of_match_table = qcom_usb_hs_phy_match, + }, +}; +module_ulpi_driver(qcom_usb_hs_phy_driver); + +MODULE_DESCRIPTION("Qualcomm USB HS phy"); +MODULE_LICENSE("GPL v2");