From patchwork Sat Oct 12 09:09:41 2013 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Peter Chen X-Patchwork-Id: 3031201 Return-Path: X-Original-To: patchwork-linux-arm@patchwork.kernel.org Delivered-To: patchwork-parsemail@patchwork1.web.kernel.org Received: from mail.kernel.org (mail.kernel.org [198.145.19.201]) by patchwork1.web.kernel.org (Postfix) with ESMTP id 57CAE9F2B7 for ; Sat, 12 Oct 2013 10:16:24 +0000 (UTC) Received: from mail.kernel.org (localhost [127.0.0.1]) by mail.kernel.org (Postfix) with ESMTP id 6D929200E6 for ; Sat, 12 Oct 2013 10:16:23 +0000 (UTC) Received: from casper.infradead.org (casper.infradead.org [85.118.1.10]) (using TLSv1 with cipher DHE-RSA-AES256-SHA (256/256 bits)) (No client certificate requested) by mail.kernel.org (Postfix) with ESMTPS id 4F3CF200DB for ; Sat, 12 Oct 2013 10:16:22 +0000 (UTC) Received: from merlin.infradead.org ([2001:4978:20e::2]) by casper.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VUvRH-0002Rs-4G; Sat, 12 Oct 2013 09:24:48 +0000 Received: from localhost ([::1] helo=merlin.infradead.org) by merlin.infradead.org with esmtp (Exim 4.80.1 #2 (Red Hat Linux)) id 1VUvQb-0001dh-Ff; Sat, 12 Oct 2013 09:24:05 +0000 Received: from va3ehsobe004.messaging.microsoft.com ([216.32.180.14] helo=va3outboundpool.messaging.microsoft.com) by merlin.infradead.org with esmtps (Exim 4.80.1 #2 (Red Hat Linux)) id 1VUvPo-0001Vb-U9 for linux-arm-kernel@lists.infradead.org; Sat, 12 Oct 2013 09:23:20 +0000 Received: from mail157-va3-R.bigfish.com (10.7.14.246) by VA3EHSOBE004.bigfish.com (10.7.40.24) with Microsoft SMTP Server id 14.1.225.22; Sat, 12 Oct 2013 09:22:54 +0000 Received: from mail157-va3 (localhost [127.0.0.1]) by mail157-va3-R.bigfish.com (Postfix) with ESMTP id C8B912A007F; Sat, 12 Oct 2013 09:22:54 +0000 (UTC) X-Forefront-Antispam-Report: CIP:70.37.183.190; KIP:(null); UIP:(null); IPV:NLI; H:mail.freescale.net; RD:none; EFVD:NLI X-SpamScore: 0 X-BigFish: VS0(zzzz1f42h208ch1ee6h1de0h1fdah2073h1202h1e76h1d1ah1d2ah1fc6hzz1de098h1de097h8275bhz2dh2a8h839hd24he5bhf0ah1288h12a5h12a9h12bdh12e5h137ah139eh13b6h1441h1504h1537h162dh1631h1758h1898h18e1h1946h19b5h1ad9h1b0ah1b2fh1fb3h1d0ch1d2eh1d3fh1dfeh1dffh1e23h1fe8h1ff5h1155h) Received: from mail157-va3 (localhost.localdomain [127.0.0.1]) by mail157-va3 (MessageSwitch) id 1381569773150037_22016; Sat, 12 Oct 2013 09:22:53 +0000 (UTC) Received: from VA3EHSMHS018.bigfish.com (unknown [10.7.14.239]) by mail157-va3.bigfish.com (Postfix) with ESMTP id 0DDA910004A; Sat, 12 Oct 2013 09:22:53 +0000 (UTC) Received: from mail.freescale.net (70.37.183.190) by VA3EHSMHS018.bigfish.com (10.7.99.28) with Microsoft SMTP Server (TLS) id 14.16.227.3; Sat, 12 Oct 2013 09:22:52 +0000 Received: from tx30smr01.am.freescale.net (10.81.153.31) by 039-SN1MMR1-003.039d.mgd.msft.net (10.84.1.16) with Microsoft SMTP Server (TLS) id 14.3.158.2; Sat, 12 Oct 2013 09:22:52 +0000 Received: from shlinux1.ap.freescale.net (shlinux1.ap.freescale.net [10.192.225.216]) by tx30smr01.am.freescale.net (8.14.3/8.14.0) with ESMTP id r9C9MKv9017154; Sat, 12 Oct 2013 02:22:48 -0700 From: Peter Chen To: , Subject: [PATCH 07/12] usb: phy-mxs: Add implementation of set_wakeup Date: Sat, 12 Oct 2013 17:09:41 +0800 Message-ID: <1381568986-19802-8-git-send-email-peter.chen@freescale.com> X-Mailer: git-send-email 1.7.1 In-Reply-To: <1381568986-19802-1-git-send-email-peter.chen@freescale.com> References: <1381568986-19802-1-git-send-email-peter.chen@freescale.com> MIME-Version: 1.0 X-OriginatorOrg: freescale.com X-FOPE-CONNECTOR: Id%0$Dn%*$RO%0$TLS%0$FQDN%$TlsDn% X-CRM114-Version: 20100106-BlameMichelson ( TRE 0.8.0 (BSD) ) MR-646709E3 X-CRM114-CacheID: sfid-20131012_052317_154314_90076AD3 X-CRM114-Status: GOOD ( 16.67 ) X-Spam-Score: -2.6 (--) Cc: marex@denx.de, m.grzeschik@pengutronix.de, frank.li@freescale.com, alexander.shishkin@linux.intel.com, gregkh@linuxfoundation.org, linux-usb@vger.kernel.org, peter.chen@freescale.com, kernel@pengutronix.de, festevam@gmail.com, linux-arm-kernel@lists.infradead.org X-BeenThere: linux-arm-kernel@lists.infradead.org X-Mailman-Version: 2.1.15 Precedence: list List-Id: List-Unsubscribe: , List-Archive: List-Post: List-Help: List-Subscribe: , Sender: "linux-arm-kernel" Errors-To: linux-arm-kernel-bounces+patchwork-linux-arm=patchwork.kernel.org@lists.infradead.org X-Spam-Status: No, score=-4.4 required=5.0 tests=BAYES_00,KHOP_BIG_TO_CC, RCVD_IN_DNSWL_MED, RP_MATCHES_RCVD, UNPARSEABLE_RELAY autolearn=unavailable version=3.3.1 X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on mail.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP When we need the PHY can be waken up by external signals, we can call this API. Besides, we call mxs_phy_disconnect_line at this API to close the connection between USB PHY and controller, after that, the line state from controller is SE0. Once the PHY is out of power, without calling mxs_phy_disconnect_line, there are unknown wakeups due to dp/dm floating at device mode. Signed-off-by: Peter Chen --- drivers/usb/phy/phy-mxs-usb.c | 82 ++++++++++++++++++++++++++++++++++++++++- 1 files changed, 81 insertions(+), 1 deletions(-) diff --git a/drivers/usb/phy/phy-mxs-usb.c b/drivers/usb/phy/phy-mxs-usb.c index 8661dae..693f9a4 100644 --- a/drivers/usb/phy/phy-mxs-usb.c +++ b/drivers/usb/phy/phy-mxs-usb.c @@ -31,6 +31,9 @@ #define HW_USBPHY_CTRL_SET 0x34 #define HW_USBPHY_CTRL_CLR 0x38 +#define HW_USBPHY_DEBUG_SET 0x54 +#define HW_USBPHY_DEBUG_CLR 0x58 + #define HW_USBPHY_IP 0x90 #define HW_USBPHY_IP_SET 0x94 #define HW_USBPHY_IP_CLR 0x98 @@ -39,6 +42,9 @@ #define BM_USBPHY_CTRL_CLKGATE BIT(30) #define BM_USBPHY_CTRL_ENAUTOSET_USBCLKS BIT(26) #define BM_USBPHY_CTRL_ENAUTOCLR_USBCLKGATE BIT(25) +#define BM_USBPHY_CTRL_ENVBUSCHG_WKUP BIT(23) +#define BM_USBPHY_CTRL_ENIDCHG_WKUP BIT(22) +#define BM_USBPHY_CTRL_ENDPDMCHG_WKUP BIT(21) #define BM_USBPHY_CTRL_ENAUTOCLR_PHY_PWD BIT(20) #define BM_USBPHY_CTRL_ENAUTOCLR_CLKGATE BIT(19) #define BM_USBPHY_CTRL_ENAUTO_PWRON_PLL BIT(18) @@ -46,7 +52,20 @@ #define BM_USBPHY_CTRL_ENUTMILEVEL2 BIT(14) #define BM_USBPHY_CTRL_ENHOSTDISCONDETECT BIT(1) -#define BM_USBPHY_IP_FIX (BIT(17) | BIT(18)) +#define BM_USBPHY_IP_FIX (BIT(17) | BIT(18)) + +#define BM_USBPHY_DEBUG_CLKGATE BIT(30) + +/* Anatop Registers */ +#define ANADIG_USB1_VBUS_DET_STAT 0x1c0 + +#define ANADIG_USB1_LOOPBACK_SET 0x1e4 +#define ANADIG_USB1_LOOPBACK_CLR 0x1e8 + +#define BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID BIT(3) + +#define BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1 BIT(2) +#define BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN BIT(5) #define to_mxs_phy(p) container_of((p), struct mxs_phy, phy) @@ -61,6 +80,7 @@ struct mxs_phy { struct clk *clk; enum imx_phy_type devtype; struct regmap *regmap_anatop; + bool disconnect_line_without_vbus_is_needed; }; static inline int is_mx6q_phy(struct mxs_phy *data) @@ -134,6 +154,44 @@ static int mxs_phy_hw_init(struct mxs_phy *mxs_phy) return 0; } +static void mxs_phy_disconnect_line(struct mxs_phy *mxs_phy, bool on) +{ + void __iomem *base = mxs_phy->phy.io_priv; + bool vbus_is_on = false; + static bool line_is_disconnected; + unsigned int vbus_value = 0; + + /* Only the SoCs have anatop need below operation */ + if (!mxs_phy->disconnect_line_without_vbus_is_needed) + return; + + regmap_read(mxs_phy->regmap_anatop, ANADIG_USB1_VBUS_DET_STAT, + &vbus_value); + if (vbus_value & BM_ANADIG_USB1_VBUS_DET_STAT_VBUS_VALID) + vbus_is_on = true; + + if (on && !vbus_is_on) { + writel_relaxed(BM_USBPHY_DEBUG_CLKGATE, + base + HW_USBPHY_DEBUG_CLR); + regmap_write(mxs_phy->regmap_anatop, ANADIG_USB1_LOOPBACK_SET, + BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1 | + BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN); + /* Delay some time, and let Linestate be SE0 for controller */ + usleep_range(500, 1000); + line_is_disconnected = true; + } else if (line_is_disconnected) { + regmap_write(mxs_phy->regmap_anatop, ANADIG_USB1_LOOPBACK_CLR, + BM_ANADIG_USB1_LOOPBACK_UTMI_DIG_TST1 | + BM_ANADIG_USB1_LOOPBACK_TSTI_TX_EN); + writel_relaxed(BM_USBPHY_DEBUG_CLKGATE, + base + HW_USBPHY_DEBUG_SET); + line_is_disconnected = false; + } + + dev_dbg(mxs_phy->phy.dev, "line is %s\n", line_is_disconnected + ? "disconnected" : "connected"); +} + static int mxs_phy_init(struct usb_phy *phy) { struct mxs_phy *mxs_phy = to_mxs_phy(phy); @@ -171,6 +229,23 @@ static int mxs_phy_suspend(struct usb_phy *x, int suspend) return 0; } +static int mxs_phy_set_wakeup(struct usb_phy *x, bool enabled) +{ + struct mxs_phy *mxs_phy = to_mxs_phy(x); + u32 value = BM_USBPHY_CTRL_ENVBUSCHG_WKUP | + BM_USBPHY_CTRL_ENDPDMCHG_WKUP | + BM_USBPHY_CTRL_ENIDCHG_WKUP; + if (enabled) { + mxs_phy_disconnect_line(mxs_phy, true); + writel_relaxed(value, x->io_priv + HW_USBPHY_CTRL_SET); + } else { + writel_relaxed(value, x->io_priv + HW_USBPHY_CTRL_CLR); + mxs_phy_disconnect_line(mxs_phy, false); + } + + return 0; +} + static int mxs_phy_on_connect(struct usb_phy *phy, enum usb_device_speed speed) { @@ -315,6 +390,10 @@ static int mxs_phy_probe(struct platform_device *pdev) } } + if (of_find_property(np, "disconnect_line_without_vbus", NULL) && + mxs_phy->regmap_anatop) + mxs_phy->disconnect_line_without_vbus_is_needed = true; + mxs_phy->phy.io_priv = base; mxs_phy->phy.dev = &pdev->dev; mxs_phy->phy.label = DRIVER_NAME; @@ -324,6 +403,7 @@ static int mxs_phy_probe(struct platform_device *pdev) mxs_phy->phy.notify_connect = mxs_phy_on_connect; mxs_phy->phy.notify_disconnect = mxs_phy_on_disconnect; mxs_phy->phy.type = USB_PHY_TYPE_USB2; + mxs_phy->phy.set_wakeup = mxs_phy_set_wakeup; ATOMIC_INIT_NOTIFIER_HEAD(&mxs_phy->phy.notifier);