From patchwork Mon Mar 11 11:11:50 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Nagarjuna Kristam X-Patchwork-Id: 10847325 Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork-2.web.codeaurora.org (Postfix) with ESMTP id 4683E13B5 for ; Mon, 11 Mar 2019 11:13:09 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 328C928F88 for ; Mon, 11 Mar 2019 11:13:09 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 26E2728F90; Mon, 11 Mar 2019 11:13:09 +0000 (UTC) X-Spam-Checker-Version: SpamAssassin 3.3.1 (2010-03-16) on pdx-wl-mail.web.codeaurora.org X-Spam-Level: X-Spam-Status: No, score=-8.0 required=2.0 tests=BAYES_00,DKIM_SIGNED, DKIM_VALID,DKIM_VALID_AU,MAILING_LIST_MULTI,RCVD_IN_DNSWL_HI autolearn=ham version=3.3.1 Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id A247928F88 for ; Mon, 11 Mar 2019 11:13:08 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727286AbfCKLNH (ORCPT ); Mon, 11 Mar 2019 07:13:07 -0400 Received: from hqemgate14.nvidia.com ([216.228.121.143]:12880 "EHLO hqemgate14.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726605AbfCKLNH (ORCPT ); Mon, 11 Mar 2019 07:13:07 -0400 Received: from hqpgpgate101.nvidia.com (Not Verified[216.228.121.13]) by hqemgate14.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Mon, 11 Mar 2019 04:13:06 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate101.nvidia.com (PGP Universal service); Mon, 11 Mar 2019 04:13:05 -0700 X-PGP-Universal: processed; by hqpgpgate101.nvidia.com on Mon, 11 Mar 2019 04:13:05 -0700 Received: from HQMAIL102.nvidia.com (172.18.146.10) by HQMAIL101.nvidia.com (172.20.187.10) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Mon, 11 Mar 2019 11:13:04 +0000 Received: from HQMAIL106.nvidia.com (172.18.146.12) by HQMAIL102.nvidia.com (172.18.146.10) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Mon, 11 Mar 2019 11:13:03 +0000 Received: from hqnvemgw02.nvidia.com (172.16.227.111) by HQMAIL106.nvidia.com (172.18.146.12) with Microsoft SMTP Server (TLS) id 15.0.1473.3 via Frontend Transport; Mon, 11 Mar 2019 11:13:03 +0000 Received: from nkristam-ubuntu.nvidia.com (Not Verified[10.19.65.118]) by hqnvemgw02.nvidia.com with Trustwave SEG (v7,5,8,10121) id ; Mon, 11 Mar 2019 04:13:03 -0700 From: Nagarjuna Kristam To: , , , CC: , , "Nagarjuna Kristam" Subject: [PATCH V2 2/8] phy: tegra: xusb: t210: add usb3 port fake support Date: Mon, 11 Mar 2019 16:41:50 +0530 Message-ID: <1552302716-18554-3-git-send-email-nkristam@nvidia.com> X-Mailer: git-send-email 2.7.4 In-Reply-To: <1552302716-18554-1-git-send-email-nkristam@nvidia.com> References: <1552302716-18554-1-git-send-email-nkristam@nvidia.com> X-NVConfidentiality: public MIME-Version: 1.0 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=nvidia.com; s=n1; t=1552302787; bh=iorPx1dDZX/cFbOY4WjSxrMWWaVwpeEuWSenn6oidKc=; h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:X-NVConfidentiality:MIME-Version: Content-Type; b=BkN5s/Svl3d4Yw+SBhF+DSqHq7KzpTTWeghhDpOW9d2nkmUxFve211X2USvWzzBdZ RPVA4AR4Wzo7ThCVPducWtquLYzRNRTcpykhG0egvurUPlVEYxk1eJhpfKEMtSgyWE KIAq0xKMRlAp8qJnE0GAf+glbXueWlPhfBUlrmbxtrqgm69PO168qiScPqxL+gVR1X 2bA4fQz85wwKJUjku03yDmphH4iZ6B4nCMkbgPiY/WOfnHfrgaV4Hyxf5wglewRWYj V95NvFw/EGKJzckGHzg/AlF7K00nNTK5IzWgPzsGJs9a9uvQyx6KFw3y4vW0eyQA73 jAhM6T+in9jmg== Sender: linux-usb-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-usb@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP On Tegra210, usb2 only otg/peripheral ports dont work in device mode. They need an assosciated usb3 port to work in device mode. Identify an unused usb3 port and assign it as a fake USB3 port to USB2 only port whose mode is otg/peripheral Based on work by BH Hsieh . Signed-off-by: Nagarjuna Kristam --- drivers/phy/tegra/xusb-tegra210.c | 40 +++++++++++++++++++++++++++++++++++++++ drivers/phy/tegra/xusb.c | 29 ++++++++++++++++++++++++++++ drivers/phy/tegra/xusb.h | 6 ++++++ 3 files changed, 75 insertions(+) diff --git a/drivers/phy/tegra/xusb-tegra210.c b/drivers/phy/tegra/xusb-tegra210.c index 4beebcc..48478bc4 100644 --- a/drivers/phy/tegra/xusb-tegra210.c +++ b/drivers/phy/tegra/xusb-tegra210.c @@ -58,6 +58,7 @@ #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_SHIFT(x) ((x) * 5) #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK(x) (0x7 << ((x) * 5)) #define XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(x, v) (((v) & 0x7) << ((x) * 5)) +#define XUSB_PADCTL_SS_PORT_MAP_PORT_DISABLED 0x7 #define XUSB_PADCTL_ELPG_PROGRAM1 0x024 #define XUSB_PADCTL_ELPG_PROGRAM1_AUX_MUX_LP0_VCORE_DOWN (1 << 31) @@ -952,6 +953,15 @@ static int tegra210_usb2_phy_power_on(struct phy *phy) priv = to_tegra210_xusb_padctl(padctl); + if (port->usb3_port_fake != -1) { + value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); + value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK( + port->usb3_port_fake); + value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP( + port->usb3_port_fake, index); + padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); + } + value = padctl_readl(padctl, XUSB_PADCTL_USB2_BIAS_PAD_CTL0); value &= ~((XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_MASK << XUSB_PADCTL_USB2_BIAS_PAD_CTL0_HS_SQUELCH_LEVEL_SHIFT) | @@ -1086,6 +1096,15 @@ static int tegra210_usb2_phy_power_off(struct phy *phy) mutex_lock(&padctl->lock); + if (port->usb3_port_fake != -1) { + value = padctl_readl(padctl, XUSB_PADCTL_SS_PORT_MAP); + value &= ~XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP_MASK( + port->usb3_port_fake); + value |= XUSB_PADCTL_SS_PORT_MAP_PORTX_MAP(port->usb3_port_fake, + XUSB_PADCTL_SS_PORT_MAP_PORT_DISABLED); + padctl_writel(padctl, value, XUSB_PADCTL_SS_PORT_MAP); + } + if (WARN_ON(pad->enable == 0)) goto out; @@ -1784,6 +1803,27 @@ static const struct tegra_xusb_pad_soc * const tegra210_pads[] = { static int tegra210_usb2_port_enable(struct tegra_xusb_port *port) { + struct tegra_xusb_usb2_port *usb2 = to_usb2_port(port); + struct tegra_xusb_padctl *padctl = port->padctl; + + /* Disable usb3_port_fake usage by default and assign if needed */ + usb2->usb3_port_fake = -1; + if (usb2 && (usb2->mode == USB_DR_MODE_OTG || + usb2->mode == USB_DR_MODE_PERIPHERAL)) { + if (!tegra_xusb_usb3_port_has_companion(padctl, port->index)) { + int fake = tegra_xusb_find_unused_usb3_port(padctl); + + if (fake >= 0) { + dev_dbg(&port->dev, "Found unused usb3 port: %d\n", + fake); + usb2->usb3_port_fake = fake; + } else { + dev_err(&port->dev, "usb2-%u has neither a companion nor an unused usb3 port to fake it\n", + port->index); + return -ENODEV; + } + } + } return 0; } diff --git a/drivers/phy/tegra/xusb.c b/drivers/phy/tegra/xusb.c index c6178a0..e89746d 100644 --- a/drivers/phy/tegra/xusb.c +++ b/drivers/phy/tegra/xusb.c @@ -799,6 +799,35 @@ static void __tegra_xusb_remove_ports(struct tegra_xusb_padctl *padctl) } } +bool tegra_xusb_usb3_port_has_companion(struct tegra_xusb_padctl *padctl, + unsigned int index) +{ + unsigned int i; + struct tegra_xusb_usb3_port *usb3; + + for (i = 0; i < padctl->soc->ports.usb3.count; i++) { + usb3 = tegra_xusb_find_usb3_port(padctl, i); + if (usb3 && usb3->port == index) + return true; + } + + return false; +} + +int tegra_xusb_find_unused_usb3_port(struct tegra_xusb_padctl *padctl) +{ + struct device_node *np; + unsigned int i; + + for (i = 0; i < padctl->soc->ports.usb3.count; i++) { + np = tegra_xusb_find_port_node(padctl, "usb3", i); + if (!np || !of_device_is_available(np)) + return i; + } + + return -ENODEV; +} + static int tegra_xusb_setup_ports(struct tegra_xusb_padctl *padctl) { struct tegra_xusb_port *port; diff --git a/drivers/phy/tegra/xusb.h b/drivers/phy/tegra/xusb.h index 17cc8dc..b263165 100644 --- a/drivers/phy/tegra/xusb.h +++ b/drivers/phy/tegra/xusb.h @@ -274,6 +274,7 @@ struct tegra_xusb_usb2_port { struct regulator *supply; bool internal; enum usb_dr_mode mode; + int usb3_port_fake; }; static inline struct tegra_xusb_usb2_port * @@ -413,6 +414,11 @@ struct tegra_xusb_lane *tegra_xusb_find_lane(struct tegra_xusb_padctl *padctl, const char *name, unsigned int index); +bool tegra_xusb_usb3_port_has_companion(struct tegra_xusb_padctl *padctl, + unsigned int index); + +int tegra_xusb_find_unused_usb3_port(struct tegra_xusb_padctl *padctl); + #if defined(CONFIG_ARCH_TEGRA_124_SOC) || defined(CONFIG_ARCH_TEGRA_132_SOC) extern const struct tegra_xusb_padctl_soc tegra124_xusb_padctl_soc; #endif