From patchwork Tue Apr 23 09:28:03 2019 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Manikanta Maddireddy X-Patchwork-Id: 10912521 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 7309B1575 for ; Tue, 23 Apr 2019 09:29:11 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 626BD1FFEB for ; Tue, 23 Apr 2019 09:29:11 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 56D2728715; Tue, 23 Apr 2019 09:29:11 +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 D3A051FFEB for ; Tue, 23 Apr 2019 09:29:10 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1727170AbfDWJ3J (ORCPT ); Tue, 23 Apr 2019 05:29:09 -0400 Received: from hqemgate14.nvidia.com ([216.228.121.143]:7884 "EHLO hqemgate14.nvidia.com" rhost-flags-OK-OK-OK-OK) by vger.kernel.org with ESMTP id S1726930AbfDWJ3I (ORCPT ); Tue, 23 Apr 2019 05:29:08 -0400 Received: from hqpgpgate102.nvidia.com (Not Verified[216.228.121.13]) by hqemgate14.nvidia.com (using TLS: TLSv1.2, DES-CBC3-SHA) id ; Tue, 23 Apr 2019 02:29:12 -0700 Received: from hqmail.nvidia.com ([172.20.161.6]) by hqpgpgate102.nvidia.com (PGP Universal service); Tue, 23 Apr 2019 02:29:06 -0700 X-PGP-Universal: processed; by hqpgpgate102.nvidia.com on Tue, 23 Apr 2019 02:29:06 -0700 Received: from HQMAIL102.nvidia.com (172.18.146.10) by HQMAIL106.nvidia.com (172.18.146.12) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 23 Apr 2019 09:29:01 +0000 Received: from HQMAIL103.nvidia.com (172.20.187.11) by HQMAIL102.nvidia.com (172.18.146.10) with Microsoft SMTP Server (TLS) id 15.0.1473.3; Tue, 23 Apr 2019 09:29:01 +0000 Received: from manikanta-bm2.nvidia.com (172.20.13.39) by HQMAIL.nvidia.com (172.20.187.11) with Microsoft SMTP Server id 15.0.1473.3 via Frontend Transport; Tue, 23 Apr 2019 09:28:58 +0000 From: Manikanta Maddireddy To: , , , , , , CC: , , , Manikanta Maddireddy Subject: [PATCH V2 06/28] PCI: tegra: Add PCIe Gen2 link speed support Date: Tue, 23 Apr 2019 14:58:03 +0530 Message-ID: <20190423092825.759-7-mmaddireddy@nvidia.com> X-Mailer: git-send-email 2.17.1 In-Reply-To: <20190423092825.759-1-mmaddireddy@nvidia.com> References: <20190423092825.759-1-mmaddireddy@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=1556011752; bh=GX0wb/MG8hEbiGmXz2Wd/Rwi79FPLBNJFQQVeJodHQY=; h=X-PGP-Universal:From:To:CC:Subject:Date:Message-ID:X-Mailer: In-Reply-To:References:X-NVConfidentiality:MIME-Version: Content-Type; b=AqSUJ6+WUBvuxuvNSR+X7YVMDHjBsl2Nj8sUNPlK7UJQQ8n5un7ohQQW0OEUg9VAr 8VRhludddkuhXdsxFlkW9IxqQ59GdGxJFhE1UI8RSWmxBMe2M8znSTSq/VXUjwLEVL h/2IdhdnsWbE8byA1WKe7bjHW5lg14W1Dur2D33JSyJbEI8P9BToYkjKejaKbnnnwi HwK1UyX7YlD9XFF07Q20tVPq+YIJgE4WVNu4eO03OuxSdOdvJqjG09un/3BIOWC7bx Yfz/D9QtpnCtupZeSjLwSLcYDozuhCx9JNWeQTOWlr0spHq+MWAFoYJKVc7HtLjIKR MgNuACrhInvPA== Sender: linux-pci-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: linux-pci@vger.kernel.org X-Virus-Scanned: ClamAV using ClamSMTP Tegra124, Tegra132, Tegra210 and Tegra186 support Gen2 link speed. After PCIe link is up in Gen1, set target link speed as Gen2 and retrain link. Link switches to Gen2 speed if Gen2 capable end point is connected, else link stays in Gen1. Per PCIe 4.0r0.9 sec 7.6.3.7 implementation note, driver need to wait for PCIe LTSSM to come back from recovery before retraining the link. Signed-off-by: Manikanta Maddireddy Acked-by: Thierry Reding --- V2: Changed "for loop" to "while", to make it compact and handled coding style comments. drivers/pci/controller/pci-tegra.c | 62 ++++++++++++++++++++++++++++++ 1 file changed, 62 insertions(+) diff --git a/drivers/pci/controller/pci-tegra.c b/drivers/pci/controller/pci-tegra.c index ed0cfd355b28..0ae8ebe92bb9 100644 --- a/drivers/pci/controller/pci-tegra.c +++ b/drivers/pci/controller/pci-tegra.c @@ -191,6 +191,8 @@ #define RP_LINK_CONTROL_STATUS_DL_LINK_ACTIVE 0x20000000 #define RP_LINK_CONTROL_STATUS_LINKSTAT_MASK 0x3fff0000 +#define RP_LINK_CONTROL_STATUS_2 0x000000b0 + #define PADS_CTL_SEL 0x0000009c #define PADS_CTL 0x000000a0 @@ -226,6 +228,7 @@ #define PADS_REFCLK_CFG_DRVI_SHIFT 12 /* 15:12 */ #define PME_ACK_TIMEOUT 10000 +#define LINK_RETRAIN_TIMEOUT 100000 /* in usec */ struct tegra_msi { struct msi_controller chip; @@ -2092,6 +2095,62 @@ static bool tegra_pcie_port_check_link(struct tegra_pcie_port *port) return false; } +static void tegra_pcie_change_link_speed(struct tegra_pcie *pcie) +{ + struct device *dev = pcie->dev; + struct tegra_pcie_port *port, *tmp; + ktime_t deadline; + u32 value; + + list_for_each_entry_safe(port, tmp, &pcie->ports, list) { + /* + * "Supported Link Speeds Vector" in "Link Capabilities 2" + * is not supported by Tegra. tegra_pcie_change_link_speed() + * is called only for Tegra chips which support Gen2. + * So there no harm if supported link speed is not verified. + */ + value = readl(port->base + RP_LINK_CONTROL_STATUS_2); + value &= ~PCI_EXP_LNKSTA_CLS; + value |= PCI_EXP_LNKSTA_CLS_5_0GB; + writel(value, port->base + RP_LINK_CONTROL_STATUS_2); + + /* + * Poll until link comes back from recovery to avoid race + * condition. + */ + deadline = ktime_add_us(ktime_get(), LINK_RETRAIN_TIMEOUT); + + while (ktime_before(ktime_get(), deadline)) { + value = readl(port->base + RP_LINK_CONTROL_STATUS); + if ((value & PCI_EXP_LNKSTA_LT) == 0) + break; + + usleep_range(2000, 3000); + } + if (value & PCI_EXP_LNKSTA_LT) + dev_warn(dev, "PCIe port %u link is in recovery\n", + port->index); + + /* Retrain the link */ + value = readl(port->base + RP_LINK_CONTROL_STATUS); + value |= PCI_EXP_LNKCTL_RL; + writel(value, port->base + RP_LINK_CONTROL_STATUS); + + deadline = ktime_add_us(ktime_get(), LINK_RETRAIN_TIMEOUT); + + while (ktime_before(ktime_get(), deadline)) { + value = readl(port->base + RP_LINK_CONTROL_STATUS); + if ((value & PCI_EXP_LNKSTA_LT) == 0) + break; + + usleep_range(2000, 3000); + } + if (value & PCI_EXP_LNKSTA_LT) + dev_err(dev, "failed to retrain link of port %u\n", + port->index); + } +} + static void tegra_pcie_enable_ports(struct tegra_pcie *pcie) { struct device *dev = pcie->dev; @@ -2116,6 +2175,9 @@ static void tegra_pcie_enable_ports(struct tegra_pcie *pcie) tegra_pcie_port_disable(port); tegra_pcie_port_free(port); } + + if (pcie->soc->has_gen2) + tegra_pcie_change_link_speed(pcie); } static void tegra_pcie_disable_ports(struct tegra_pcie *pcie)