From patchwork Thu Aug 25 05:59:56 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: Ley Foon Tan X-Patchwork-Id: 9298731 X-Patchwork-Delegate: bhelgaas@google.com Return-Path: Received: from mail.wl.linuxfoundation.org (pdx-wl-mail.web.codeaurora.org [172.30.200.125]) by pdx-korg-patchwork.web.codeaurora.org (Postfix) with ESMTP id 8FDAD60757 for ; Thu, 25 Aug 2016 06:33:40 +0000 (UTC) Received: from mail.wl.linuxfoundation.org (localhost [127.0.0.1]) by mail.wl.linuxfoundation.org (Postfix) with ESMTP id 8082F291D4 for ; Thu, 25 Aug 2016 06:33:40 +0000 (UTC) Received: by mail.wl.linuxfoundation.org (Postfix, from userid 486) id 74CF5291D6; Thu, 25 Aug 2016 06:33:40 +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=-6.8 required=2.0 tests=BAYES_00,DKIM_SIGNED, RCVD_IN_DNSWL_HI,T_DKIM_INVALID autolearn=unavailable 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 4B11A291D4 for ; Thu, 25 Aug 2016 06:33:38 +0000 (UTC) Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1752517AbcHYGd1 (ORCPT ); Thu, 25 Aug 2016 02:33:27 -0400 Received: from mail-bn3nam01on0074.outbound.protection.outlook.com ([104.47.33.74]:26720 "EHLO NAM01-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1755878AbcHYGdY (ORCPT ); Thu, 25 Aug 2016 02:33:24 -0400 DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=altera.onmicrosoft.com; s=selector1-altera-com; h=From:Date:Subject:Message-ID:Content-Type:MIME-Version; bh=wlK5E/uySbM30d3KHOLMb8E+I6g4I9y3yWtd06LjNLA=; b=WnBo42V/vMOY7aIRoqxQ6aTDK62Z6m76avzbLRcAFPtLosNf12ungjFtWID8BOBmptJnuq+y+PX4P24BX6ZuD1znc7naXAux0FpQgU4/R019hMEgDlit8CpqXpDYg52spCZFCZMWQQr2JghU2PPs5GII+wxYygsfdt8FpteHkGs= Received: from BN6PR03CA0032.namprd03.prod.outlook.com (10.175.124.18) by CY1PR03MB1407.namprd03.prod.outlook.com (10.163.17.141) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.1.587.9; Thu, 25 Aug 2016 06:00:05 +0000 Received: from BY2FFO11OLC002.protection.gbl (2a01:111:f400:7c0c::161) by BN6PR03CA0032.outlook.office365.com (2603:10b6:404:10c::18) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.1.557.21 via Frontend Transport; Thu, 25 Aug 2016 06:00:04 +0000 Authentication-Results: spf=softfail (sender IP is 66.35.236.227) smtp.mailfrom=altera.com; vger.kernel.org; dkim=none (message not signed) header.d=none; vger.kernel.org; dmarc=none action=none header.from=altera.com; Received-SPF: SoftFail (protection.outlook.com: domain of transitioning altera.com discourages use of 66.35.236.227 as permitted sender) Received: from sj-itexedge03.altera.priv.altera.com (66.35.236.227) by BY2FFO11OLC002.mail.protection.outlook.com (10.1.15.178) with Microsoft SMTP Server (version=TLS1_0, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA_P384) id 15.1.587.6 via Frontend Transport; Thu, 25 Aug 2016 06:00:05 +0000 Received: from sj-mail01.altera.com (137.57.1.6) by webmail.altera.com (66.35.236.227) with Microsoft SMTP Server (TLS) id 14.3.174.1; Wed, 24 Aug 2016 22:59:52 -0700 Received: from ubuntu (pg-lftan-440b.altera.priv.altera.com [137.57.162.77]) by sj-mail01.altera.com (8.13.7+Sun/8.13.7) with SMTP id u7P5xv8Q023976; Wed, 24 Aug 2016 22:59:58 -0700 (PDT) Received: by ubuntu (sSMTP sendmail emulation); Thu, 25 Aug 2016 13:59:57 +0800 From: Ley Foon Tan To: Bjorn Helgaas CC: , , Ley Foon Tan , Ley Foon Tan Subject: [PATCH v3] PCI: altera: Retrain link in rootport mode only Date: Thu, 25 Aug 2016 13:59:56 +0800 Message-ID: <1472104796-20737-1-git-send-email-lftan@altera.com> X-Mailer: git-send-email 1.9.1 MIME-Version: 1.0 X-EOPAttributedMessage: 0 X-MS-Office365-Filtering-HT: Tenant X-Forefront-Antispam-Report: CIP:66.35.236.227; IPV:NLI; CTRY:US; EFV:NLI; SFV:NSPM; SFS:(10009020)(6009001)(7916002)(2980300002)(199003)(189002)(97736004)(4001430100002)(8676002)(81156014)(81166006)(36756003)(105596002)(189998001)(110136002)(107886002)(86362001)(305945005)(356003)(7846002)(626004)(87936001)(92566002)(19580405001)(19580395003)(5660300001)(4326007)(50466002)(2906002)(48376002)(50986999)(33646002)(229853001)(68736007)(586003)(106466001)(47776003)(5003940100001)(42186005)(8936002)(50226002)(7099028); DIR:OUT; SFP:1101; SCL:1; SRVR:CY1PR03MB1407; H:sj-itexedge03.altera.priv.altera.com; FPR:; SPF:SoftFail; PTR:InfoDomainNonexistent; A:1; MX:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11OLC002; 1:CDBeod7y39TjcY5988hQVoMfnlcGNROk97SQIpsHE0md5yOjjvVSTfX1AmXdUP21iq5qfzZJveVLGktZLTZSHg90D3wkHjPhWjCY6BUpi1d/YIRXYSW3IuT2pLhwRseZy4ZvpDaPDZL9WiORGBxapIflZ845kdPUiQItHjPQaNNpl3tQZduGiULuGLOEenNFUpx2n7PY0ukGqisDr6V3rSh4Yl4SL7CtUuVnysFP8q5RUr5PtUV5tR40CEETxNHHT6VFZQW+yjrkJLdrW4S9ac6iaJf8BEwpdwlZyP/RbXTbrJYZyVMINB4eBwyIO8Y5iXwUw/vY0e2wRYzGplfZRFiJkZgFgEKTuvvYl2C4AkRepPZWNQTCiZb5VlGwoBE1vsuzuOZfs3QqOR3yKZEjfzk2En0ylwj+WQvAXELHFIkW3OA/OVMaXpav/RCwO1hvyFUk0gBD/zbF+Xx4blQcY7NhlMKj74b2segxGPcD2K6Vco2shqNrKLRZS1OFzoBWMMhlp6nnA5yVWe90fRi0UNGbHWZOlASZFuz1pwxdSx73/5ZxqGh9PpX3QVSV8+cz X-MS-Office365-Filtering-Correlation-Id: a83882b9-0b5d-4de5-6cca-08d3ccad0fc9 X-Microsoft-Exchange-Diagnostics: 1; CY1PR03MB1407; 2:tPvLNR+ty2VmdpFYjaOqnTr2VRu9R0M/ODSV9iJbWAy91nU/ajuYpWd7K3XY+cr72oXvHkHdnGwRTuz65FfRtQmgww3VqJQUI/iyxip7NSng9LbNXaqpbLjQoClFxr23nDk8FSqkI20HmoLgILjgKM0KvCrL6UfLBuBLe5/DZN6hmW0pZICwqNwaNdlmuk4J; 3:bKcJVTe3DtYnWexvzr/mzOQTmiZbAw4ch0ucb5e/pTpaLoS3o1jkfeMNBOLQ9r3+l8tIe6VljPmFb0BZYWoku/iCB9/XRA9jpL/CNlbMM4UvODAOewTDJd5LUfQqmNvkX3k52E/T7UElOCA97LhDC9ZzK9CDN90ONIl3jufc6XoVajdWJ7Jo3Xmc1ModGnsYsJckL9svLFyS5N3wBNYTPiCHJeGncCmstkBdnes7syQ=; 25:K2t4oeYFo8Q9zE5D+9GdDoJ5vgqFFam+JyeNgqrQEf1aA8fQkOAobUBh5ozZi7qZ34pqCJ4JrjxsTNnC0RBoIaic35fiP6cWZpBuY+4FNIXvpLLBJb4YEvL+zVaA7WBMleAmtxA5aDKf9hIyzWZy7J0kPDwxoh6CqwaoMAKtWFhZNu4rxe/bueNblGLIZ2Uirmz+vLHmmn5+O7eVEDxd7FtoipYkkNhat97u9dIJNQ9orIqoqHASLUXbmhYk7eHhQr8As40M9UxMdb7hnUqFyjg9ok6ZPXDhrdEm+9o9IpvNYbHSTfvvNfowaPEOnkwH2RojCvJDYyJGpfhX5PFVxbrsm9KiM22z3hkNARE661qnzQ7ByLt6MCYkJxl4uNSzzVDHCrHZAucjcHxbGccdtsQh0lDR2AivH3gEIt1Z5a8= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:CY1PR03MB1407; X-Microsoft-Exchange-Diagnostics: 1; CY1PR03MB1407; 31:amciEh+Lusrq6PTXj8bGquuBef1tbAIu6LHoL3NuTm+pmtHrAuviROXL48E8ccoOi6hH+ES4ACuI+ox2y8SD5xqCqEDy9MhNRru9K2dhhv3o4kXHUXq8+0hjmMrV9hwmtzfVTA7iYYkNJIxjpk/ZNxZS+A7L/rI38Bq8qst8YHNYeWCcoFboaBj6HUb8263Nd8M/NayffiEJAwpG1A6leknwhPLDOHg+ynyMMT0lj6A=; 20:F+8Js2fC9PbDDSc5WE7tnBlfUEaKBXKfckERPhM17++6yjJwoeLND2Vjsa+zH2ET87wway/RKxiMxBRI2vHyK9xxmOnvp2tywliV/9VHe27efQjHIDFutyIJ+UYGrwvZFbpioA/GeyhipHH7LPwFsVb3VByG1QQEtHfGlKYyqB8=; 4:RymTS7f9zk13ApsieTwbEju8xVF+jJiUGmiCDpk8FTzBhG8OxBjl3aafs3JAkRzxnk0kJZA4z5mud993fJAHXBQqXpugbfvOnM9K3GaYpmflHXMmWZQTPSUP8imGdvg6Gfga8RReogqy0941IaZPEP5PPgdIiAwzJTefIRm2r30GPgDUz8VGb1TrSrAcbQ4DupUBXx54fRClud60DzKv3udxc3H0Ff60ZNbwNqxEAPTvwZFFGcWnnX1oEG+V4ICyINQ981hGftR5C+Lrmvx/nB+HH98CPsYa9R4vKT1Xhtr1GRdBRBT2D9cponziQeK+XYM5GBQRgE7P/qTqmld8BIuLqgX0OSmoW8S+61rO0FcVmhqztDYJQJwjeDHKFuaDfLPQcWcthwqBtZFSiQ+30ighgiqwuUjb2w2T3VcTR2pLQQDWgdlYKyoNPMqP2oUa0yWUc3fgc3QaVxyPy6JGUogrqtBpYYQLdMcu+NYwCeoqwFLXK81q1zden/LTHmh5Izb1gzdAn5 GAexKxtzZRoyS38pcjZu3vzEl+tVqwPNk= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(80048183373757); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(6040176)(601004)(2401047)(5005006)(8121501046)(13015025)(13017025)(13023025)(13024025)(13018025)(3002001)(10201501046)(6055026); SRVR:CY1PR03MB1407; BCL:0; PCL:0; RULEID:; SRVR:CY1PR03MB1407; X-Forefront-PRVS: 0045236D47 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; CY1PR03MB1407; 23:iqy0e++/XWcNzj/fSQT8IgX1aq1jVAo67u1Ot8llk?= =?us-ascii?Q?i+x8iknDPCuRzmDwtN8YnD0KZeGAADxJfCsix7tfy+N6VSEoduTghgziPoSD?= =?us-ascii?Q?+RcIuaztfGc8ExtQO8Srt0auV0zmV9XTmyTgQRrJplnd9bnalvwTvRRL915i?= =?us-ascii?Q?EadvxODVNsKMiQPotBFvL8TQqarSZL61Z81jKmDZ0cgoL4ygyQZUxvF9/gwj?= =?us-ascii?Q?kSPvn2cGqRmWGgM6sb5A4ptbhaCJ83O9wOWkikquTHYHhJaGmlxQDzYhejKo?= =?us-ascii?Q?cfq7npN+DSD4VNHnInX7v1Qwt+lBaKlegleRMIxvj4CM7rdZeiw4hwZtJgDJ?= =?us-ascii?Q?5zkKrTY++3Cr7qqozXjneGeBgVYBuBjaJzsajkA/mfsu4Wl4w4ClDNMzJUXs?= =?us-ascii?Q?mqjhLOS6VsL4pJmFJR/lFlPHLf5ZGyavNRFSDZ+aYRjxxjWix4CvCbHche0c?= =?us-ascii?Q?FT4Z5jNK9R085lJYWIXXDxuM/D4o3DK4woxyGwB0W9z17pB0a6iGcWmEnCTH?= =?us-ascii?Q?/Iv4qGfWRc71No7jrvsgt6uhoiaRtACeF3GdJL3vuoQS3lHrDeK6TJTeIuRM?= =?us-ascii?Q?2Yg212v9y8RAqR6pEnx8Lyoy41SXYmSq9/+yPol4ERkaJmC8crIHU1kvj4n+?= =?us-ascii?Q?ePC2W7gq/z3mCPT7Jo4wUk1PXhgaCSR53TGwZeD9OZJ+BEeetKBIRjsdP+vt?= =?us-ascii?Q?FxOagm2wzr25vEPqf/70O+MTuWjBK2HfF9/V8HfvwsvvvhIVmjGDkeYyeahc?= =?us-ascii?Q?hgy8V8sGiD6DtF69AfYGmYHHIUf+7kIG2Mzh0Hvr3t9Iass4chDO1a1KCesw?= =?us-ascii?Q?5n2bT/hruV3hSjrAnfl3y0bartawldxFwdETCdNyQtwoGx8X0coNFmJU+nhz?= =?us-ascii?Q?Vh1HOYrnqnzzyn7bc4x4qEueSFnp4GtkerU+srswxFs5epWZoeytD3Aa1z3P?= =?us-ascii?Q?WO5fbHf4xc4DR0ZGRFu6TjsrzxZgxElG4LWHFuhEarAOJykmzHdy9+mAkrAD?= =?us-ascii?Q?NfO54pY/P53MvDO6PsYHDS1?= X-Microsoft-Exchange-Diagnostics: 1; CY1PR03MB1407; 6:ABzVcwR62TEGyEs6n0m3qhomqOvfCTnJH+SLVLtyR4rIx+E6J02JUGihUWmlsaBSViDTDm219ClfIBo52tdhRwHxe999iONm16ZylK5HkwObf35cS6qXyg6yHvc2kPPREQr5yY3dXrH8VzFZbBMSwgVW55xN9VbFkwJYQ/44Lp6WeIM67YMH1MBZ8zoF8YBBmG6quW3LeWwUZx45Aj9HOvtK3MCKe6pLhoxIZNxa0CiL52x6vonfa9gW5eNWagbPSbj/XZ+b4kSWczq9p5vBplTu3Fwsuhe3Z8McIxyyc/Dr4IEjwwjh0lEOicpw5iTFQaYM3uUnwNldHFbwjsiQKA==; 5:o+Yf2A7F3zBjUNkhB01l9HhjdDjLfwoT/VR5oTMznlTJpYAzEF+n6b/hf2MX8qpIRyQa9zIOtBRtU6XOD9AH0LhNXWIKE0SROfRgNcfN+9P3q/BMVLKcyo/utxY5/VOnkJU+4/Iznj6gi0e0d16BNg==; 24:QVs/z0TgFyFqKhK6h4xH+5eJOr+SRTLjq+bCZGN2n49H7lwv7YZAnSxzt5zTDtRareHOnNC8967uN5yG0k4wkfXNI/NAJznsojzQ4/bPBlA=; 7:PCtMU4nfkgF2TqYnfTSmfFbTsRHxqpjsRw/bFS0glzehQnJykJ8J0TymAU0X2ZJKldXtgyrOHNUESUIZeGN+Psz1vPt6GIJC4ivlfbV5VkE9dGKcyYEDSbS1vtYPxTsNg9HUxgV/2n1rw+W0dElY2Z2FIcoCCqjpSCsWorZDaGofUtzBnKos8M7RWH6wRKVesKsY9fNB2cL3NY18LHQ3L4n9wRb9HwZJzNgW4li4RzC93GhYOTGvrjs4O+ZOxfMc SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-OriginatorOrg: altera.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 25 Aug 2016 06:00:05.3611 (UTC) X-MS-Exchange-CrossTenant-Id: fbd72e03-d4a5-4110-adce-614d51f2077a X-MS-Exchange-CrossTenant-OriginalAttributedTenantConnectingIp: TenantId=fbd72e03-d4a5-4110-adce-614d51f2077a; Ip=[66.35.236.227]; Helo=[sj-itexedge03.altera.priv.altera.com] X-MS-Exchange-CrossTenant-FromEntityHeader: HybridOnPrem X-MS-Exchange-Transport-CrossTenantHeadersStamped: CY1PR03MB1407 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 Altera PCIe IP can be configured as rootport or device and they might have same vendor ID. It will cause the system hang issue if Altera PCIe is in endpoint mode and work with other PCIe rootport that from other vendors. Moved retrain function to before pci_scan_root_bus and removed _FIXUP. Add _altera_pcie_cfg_read() and _altera_pcie_cfg_write() to use struct altera_pcie as argument instead of struct pci_bus. Signed-off-by: Ley Foon Tan --- v2: change to check PCIe type is PCI_EXP_TYPE_ROOT_PORT v3: Move retrain function to before pci_scan_root_bus and remove _FIXUP --- drivers/pci/host/pcie-altera.c | 217 +++++++++++++++++++++++++---------------- 1 file changed, 134 insertions(+), 83 deletions(-) diff --git a/drivers/pci/host/pcie-altera.c b/drivers/pci/host/pcie-altera.c index 58eef99..4ce6d86 100644 --- a/drivers/pci/host/pcie-altera.c +++ b/drivers/pci/host/pcie-altera.c @@ -43,6 +43,8 @@ #define RP_LTSSM_MASK 0x1f #define LTSSM_L0 0xf +#define PCIE_CAP_OFFSET 0x80 + /* TLP configuration type 0 and 1 */ #define TLP_FMTTYPE_CFGRD0 0x04 /* Configuration Read Type 0 */ #define TLP_FMTTYPE_CFGWR0 0x44 /* Configuration Write Type 0 */ @@ -100,66 +102,6 @@ static bool altera_pcie_link_is_up(struct altera_pcie *pcie) return !!((cra_readl(pcie, RP_LTSSM) & RP_LTSSM_MASK) == LTSSM_L0); } -static void altera_wait_link_retrain(struct pci_dev *dev) -{ - u16 reg16; - unsigned long start_jiffies; - struct altera_pcie *pcie = dev->bus->sysdata; - - /* Wait for link training end. */ - start_jiffies = jiffies; - for (;;) { - pcie_capability_read_word(dev, PCI_EXP_LNKSTA, ®16); - if (!(reg16 & PCI_EXP_LNKSTA_LT)) - break; - - if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) { - dev_err(&pcie->pdev->dev, "link retrain timeout\n"); - break; - } - udelay(100); - } - - /* Wait for link is up */ - start_jiffies = jiffies; - for (;;) { - if (altera_pcie_link_is_up(pcie)) - break; - - if (time_after(jiffies, start_jiffies + LINK_UP_TIMEOUT)) { - dev_err(&pcie->pdev->dev, "link up timeout\n"); - break; - } - udelay(100); - } -} - -static void altera_pcie_retrain(struct pci_dev *dev) -{ - u16 linkcap, linkstat; - struct altera_pcie *pcie = dev->bus->sysdata; - - if (!altera_pcie_link_is_up(pcie)) - return; - - /* - * Set the retrain bit if the PCIe rootport support > 2.5GB/s, but - * current speed is 2.5 GB/s. - */ - pcie_capability_read_word(dev, PCI_EXP_LNKCAP, &linkcap); - - if ((linkcap & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB) - return; - - pcie_capability_read_word(dev, PCI_EXP_LNKSTA, &linkstat); - if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) { - pcie_capability_set_word(dev, PCI_EXP_LNKCTL, - PCI_EXP_LNKCTL_RL); - altera_wait_link_retrain(dev); - } -} -DECLARE_PCI_FIXUP_EARLY(0x1172, PCI_ANY_ID, altera_pcie_retrain); - /* * Altera PCIe port uses BAR0 of RC's configuration space as the translation * from PCI bus to native BUS. Entire DDR region is mapped into PCIe space @@ -330,22 +272,14 @@ static int tlp_cfg_dword_write(struct altera_pcie *pcie, u8 bus, u32 devfn, return PCIBIOS_SUCCESSFUL; } -static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 *value) +static int _altera_pcie_cfg_read(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 *value) { - struct altera_pcie *pcie = bus->sysdata; int ret; u32 data; u8 byte_en; - if (altera_pcie_hide_rc_bar(bus, devfn, where)) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) { - *value = 0xffffffff; - return PCIBIOS_DEVICE_NOT_FOUND; - } - switch (size) { case 1: byte_en = 1 << (where & 3); @@ -358,7 +292,7 @@ static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, break; } - ret = tlp_cfg_dword_read(pcie, bus->number, devfn, + ret = tlp_cfg_dword_read(pcie, busno, devfn, (where & ~DWORD_MASK), byte_en, &data); if (ret != PCIBIOS_SUCCESSFUL) return ret; @@ -378,20 +312,14 @@ static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, return PCIBIOS_SUCCESSFUL; } -static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn, - int where, int size, u32 value) +static int _altera_pcie_cfg_write(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int where, int size, + u32 value) { - struct altera_pcie *pcie = bus->sysdata; u32 data32; u32 shift = 8 * (where & 3); u8 byte_en; - if (altera_pcie_hide_rc_bar(bus, devfn, where)) - return PCIBIOS_BAD_REGISTER_NUMBER; - - if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) - return PCIBIOS_DEVICE_NOT_FOUND; - switch (size) { case 1: data32 = (value & 0xff) << shift; @@ -407,8 +335,40 @@ static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn, break; } - return tlp_cfg_dword_write(pcie, bus->number, devfn, - (where & ~DWORD_MASK), byte_en, data32); + return tlp_cfg_dword_write(pcie, busno, devfn, (where & ~DWORD_MASK), + byte_en, data32); +} + +static int altera_pcie_cfg_read(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 *value) +{ + struct altera_pcie *pcie = bus->sysdata; + + if (altera_pcie_hide_rc_bar(bus, devfn, where)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) { + *value = 0xffffffff; + return PCIBIOS_DEVICE_NOT_FOUND; + } + + return _altera_pcie_cfg_read(pcie, bus->number, devfn, where, size, + value); +} + +static int altera_pcie_cfg_write(struct pci_bus *bus, unsigned int devfn, + int where, int size, u32 value) +{ + struct altera_pcie *pcie = bus->sysdata; + + if (altera_pcie_hide_rc_bar(bus, devfn, where)) + return PCIBIOS_BAD_REGISTER_NUMBER; + + if (!altera_pcie_valid_config(pcie, bus, PCI_SLOT(devfn))) + return PCIBIOS_DEVICE_NOT_FOUND; + + return _altera_pcie_cfg_write(pcie, bus->number, devfn, where, size, + value); } static struct pci_ops altera_pcie_ops = { @@ -416,6 +376,90 @@ static struct pci_ops altera_pcie_ops = { .write = altera_pcie_cfg_write, }; +static int altera_read_cap_word(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int offset, u16 *value) +{ + u32 data; + int ret; + + ret = _altera_pcie_cfg_read(pcie, busno, devfn, + PCIE_CAP_OFFSET + offset, sizeof(*value), + &data); + *value = data; + return ret; +} + +static int altera_write_cap_word(struct altera_pcie *pcie, u8 busno, + unsigned int devfn, int offset, u16 value) +{ + return _altera_pcie_cfg_write(pcie, busno, devfn, + PCIE_CAP_OFFSET + offset, sizeof(value), + value); +} + +static void altera_wait_link_retrain(struct altera_pcie *pcie) +{ + u16 reg16; + unsigned long start_jiffies; + + /* Wait for link training end. */ + start_jiffies = jiffies; + for (;;) { + altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, + PCI_EXP_LNKSTA, ®16); + if (!(reg16 & PCI_EXP_LNKSTA_LT)) + break; + + if (time_after(jiffies, start_jiffies + LINK_RETRAIN_TIMEOUT)) { + dev_err(&pcie->pdev->dev, "link retrain timeout\n"); + break; + } + udelay(100); + } + + /* Wait for link is up */ + start_jiffies = jiffies; + for (;;) { + if (altera_pcie_link_is_up(pcie)) + break; + + if (time_after(jiffies, start_jiffies + LINK_UP_TIMEOUT)) { + dev_err(&pcie->pdev->dev, "link up timeout\n"); + break; + } + udelay(100); + } +} + +static void altera_pcie_retrain(struct altera_pcie *pcie) +{ + u16 linkcap, linkstat, linkctl; + + if (!altera_pcie_link_is_up(pcie)) + return; + + /* + * Set the retrain bit if the PCIe rootport support > 2.5GB/s, but + * current speed is 2.5 GB/s. + */ + altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, PCI_EXP_LNKCAP, + &linkcap); + if ((linkcap & PCI_EXP_LNKCAP_SLS) <= PCI_EXP_LNKCAP_SLS_2_5GB) + return; + + altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, PCI_EXP_LNKSTA, + &linkstat); + if ((linkstat & PCI_EXP_LNKSTA_CLS) == PCI_EXP_LNKSTA_CLS_2_5GB) { + altera_read_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, + PCI_EXP_LNKCTL, &linkctl); + linkctl |= PCI_EXP_LNKCTL_RL; + altera_write_cap_word(pcie, pcie->root_bus_nr, RP_DEVFN, + PCI_EXP_LNKCTL, linkctl); + + altera_wait_link_retrain(pcie); + } +} + static int altera_pcie_intx_map(struct irq_domain *domain, unsigned int irq, irq_hw_number_t hwirq) { @@ -537,6 +581,11 @@ static int altera_pcie_parse_dt(struct altera_pcie *pcie) return 0; } +static void altera_pcie_host_init(struct altera_pcie *pcie) +{ + altera_pcie_retrain(pcie); +} + static int altera_pcie_probe(struct platform_device *pdev) { struct altera_pcie *pcie; @@ -575,6 +624,8 @@ static int altera_pcie_probe(struct platform_device *pdev) /* enable all interrupts */ cra_writel(pcie, P2A_INT_ENA_ALL, P2A_INT_ENABLE); + altera_pcie_host_init(pcie); + bus = pci_scan_root_bus(&pdev->dev, pcie->root_bus_nr, &altera_pcie_ops, pcie, &pcie->resources); if (!bus)