From patchwork Fri Jul 8 03:23:30 2016 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 7bit X-Patchwork-Submitter: thloh@altera.com X-Patchwork-Id: 646301 Return-Path: X-Original-To: incoming-dt@patchwork.ozlabs.org Delivered-To: patchwork-incoming-dt@bilbo.ozlabs.org Received: from vger.kernel.org (vger.kernel.org [209.132.180.67]) by ozlabs.org (Postfix) with ESMTP id 3rm40Y6TX5z9snk for ; Fri, 8 Jul 2016 16:12:44 +1000 (AEST) Authentication-Results: ozlabs.org; dkim=fail reason="signature verification failed" (1024-bit key; unprotected) header.d=altera.onmicrosoft.com header.i=@altera.onmicrosoft.com header.b=e75ADnSz; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751299AbcGHGMm (ORCPT ); Fri, 8 Jul 2016 02:12:42 -0400 Received: from mail-bn3nam01on0088.outbound.protection.outlook.com ([104.47.33.88]:18112 "EHLO NAM01-BN3-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1751220AbcGHGMk (ORCPT ); Fri, 8 Jul 2016 02:12:40 -0400 X-Greylist: delayed 9296 seconds by postgrey-1.27 at vger.kernel.org; Fri, 08 Jul 2016 02:12:39 EDT 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=/dkPx4RwOgGHLRGRyp3rGO/UkqNZBR/ipktxZJTMuMA=; b=e75ADnSzC+LLf/BEQTFWahp0y1g+NVH7HULSV4GvfOYqFBr9BC11+MZ7mnn1XHWeE3gojoSf7LQ+ozSnwfuZdY1Skb550QqpDzd3ts+qjJcbdy3mpS8y659l7TqvgT0X11Jlrb8RThX7G9ojSUnfRZ26uu+OVz6BiiUgbLniydM= Received: from BY2PR03CA076.namprd03.prod.outlook.com (10.141.249.49) by BY2PR03MB141.namprd03.prod.outlook.com (10.242.35.143) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.534.8; Fri, 8 Jul 2016 03:37:40 +0000 Received: from BY2FFO11FD041.protection.gbl (2a01:111:f400:7c0c::172) by BY2PR03CA076.outlook.office365.com (2a01:111:e400:2c5d::49) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.523.12 via Frontend Transport; Fri, 8 Jul 2016 03:37:40 +0000 Authentication-Results: spf=softfail (sender IP is 66.35.236.227) smtp.mailfrom=altera.com; st.com; dkim=none (message not signed) header.d=none; st.com; 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 BY2FFO11FD041.mail.protection.outlook.com (10.1.14.226) with Microsoft SMTP Server (TLS) id 15.1.534.7 via Frontend Transport; Fri, 8 Jul 2016 03:37:40 +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; Thu, 7 Jul 2016 20:36:51 -0700 Received: from ubuntu (ubuntu.altera.com [10.142.36.113]) by sj-mail01.altera.com (8.13.7+Sun/8.13.7) with SMTP id u683bW8F014004; Thu, 7 Jul 2016 20:37:33 -0700 (PDT) Received: by ubuntu (sSMTP sendmail emulation); Thu, 07 Jul 2016 20:37:35 -0700 From: To: , , , , , , , , , , , CC: Tien Hock Loh Subject: [PATCH v7 1/1] net: ethernet: Add TSE PCS support to dwmac-socfpga Date: Thu, 7 Jul 2016 20:23:30 -0700 Message-ID: <1467948210-21325-1-git-send-email-thloh@altera.com> X-Mailer: git-send-email 1.7.9.5 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)(189002)(199003)(575784001)(86362001)(86152002)(97736004)(81166006)(50986999)(2201001)(47776003)(81156014)(2876002)(48376002)(15975445007)(106466001)(5001770100001)(87936001)(305945005)(229853001)(50226002)(7846002)(19580395003)(8936002)(2906002)(105596002)(6806005)(356003)(42186005)(19580405001)(4326007)(8676002)(33646002)(11100500001)(586003)(5003940100001)(36756003)(107886002)(68736007)(92566002)(4001430100002)(189998001)(50466002)(7099028)(921003)(2004002)(1121003)(217873001)(4720700001); DIR:OUT; SFP:1101; SCL:1; SRVR:BY2PR03MB141; H:sj-itexedge03.altera.priv.altera.com; FPR:; SPF:SoftFail; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11FD041; 1:ydx0J4Cb8f8gXkn3moVkCtzWbKOCw2tr3dsJs8jlARThBWciXMNrca5MyDGeOo+eYTmh3TAYudBRVWleoLQQTAsZAucr9w6olCpx67kFhYeBqVPGz40Pv2EgPPPtx4blHqxzZxh5uuITWVShyavIEwwyP7URAAbdQYJ6JxCgo0jk0EcyMWcUu0pY6+RCX6pEEkOlRyilEZDIvqtzTyumv1TM+xZDzh9rlAGat9b4oODLJNahbjpcqOmfrggvvx7F5MPEjpjZ9Dq5wNYaoIZ4bFah2rCVOT/r9Ss/XGAT7RCPr2skn3KGRNggWULfAEri53AZjvT8XWc86UnxNKMUD8mdbHvFUt1XUIR+pTPc7PMxIE3mj6TU+6z8UF9jDHCvxxYOthzjF6RmUnB8VaypXdU2+CyjnKhGl6op2kEJXjhiZ/lf0qwZMZ8KZYVrqIHEjij1yv6ndrSoO8P8ImEjj4vSVjH6hC52Kg58RHyGRJ20HZmsDefMH+cPuS2m6hU7cz/tF28t1OZr3dZ5IeheHfSEr9q6UdgqKCJOyPnf+/q/QGT22UJ+Ua6E151Dwyk55gynJxr73ko9HMOZrDAPsBMNKGSioGjDh9fLKrazg2g= X-MS-Office365-Filtering-Correlation-Id: 78e8200c-3bdf-4aa5-d62f-08d3a6e1369e X-Microsoft-Exchange-Diagnostics: 1; BY2PR03MB141; 2:BY+chrWXvv231dG03WrzXVnTkMhhpA0JGx0ZJSVvPXWv31as+erqSGWis55xzlvGF/LLImtZ2rpL9NiMv79iNTlIThrydjIYG4PsKQ/tSOnMq0pDUCW9hIk1VXD0vS45MjYEkVRkJNo/GHluwvCdDY9NtdpM0JCwvIuFRy3MCs7rK0KV43XuI4/EhFHlMHlG; 3:I/UJ412GkPY6RqjZIO2mJjFmpsA2wUyAE8iw9DLCqxrAQl1U+q9zRSr/19n95qt3jh+tJt9cgL+U7yBYMejazoy9uGaxj3XVvsZmeelF1DkzaX+xVOmqOOI2021+NocC6qR8gfaZpJqzI4OcplIbi6ld/IMAW3cniXqNAEGC8zr1IYeIXDf7RehFGC5dWfqaogy+BVFiQ492YnPdI9Za5Lo2XdGbGTiDjiyHftqsXd4= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BY2PR03MB141; X-Microsoft-Exchange-Diagnostics: 1; BY2PR03MB141; 25:cimdL2RTK/Wk9H72CTlDaQQIXeW9JepmP6GgXN2QnH57azaXg7rBlVNoufhKqOmOEiMJ7XEhnb3RmY5V9MqbXDt7nIcMUxrgyuXC21Sxw0T3rkoGCyoClJh17pJ8dk7ACzZSZ+PocAdfCjOv+R4muuBZUSDE05WH9dxg56KW+94QZS1CDUSz/odwaNH0wuWSkReVvFuIsUGgRWpbMfpfY+WZxInXXBkrJUy06+XMWvDAT33jibf/VsKP1gNwFPAh7RqTHfZq7498/e4u/23AJk5kaK8oJBQefLVRl4lWOWaYmPTiqU30wKmskxrkzdPTSR+KC6kjft/L0m2a6hXUDoS1+PRs+jyPDlCImNQsmuSXsaOZE3ofG45FviXK+1qKvozhQFOL0rssZvXYBTP2T+mY6T5gjRXVquY0kKAONkVNFyMvN/JoaFtUqH4uLx29C4amGRqFcj3kyOXcFvErLgVSwMm0U1rnrsyWWYb8uvEmkUIMy/HL79K5mG32GpN57YECQawyvT6Xr/HFfUbfxA1qauVHx7wPKTjRH0q5DF3s2NkQ4a0OMLWk7hdHcgyxPjK9cn/LGg44qqUqqOK/y4QRKDB9pBLnK6EEQ658JJRxXpR51Ssyy26PDfGypB0OL0t4C7ZGnjpmaMZnO4kOI4J+ws8mfAfiPvXTZWoO/Shr0QUbMt7hygTpTAgCwvWCEvAriSwHZbLd1NeFs5Gre8I1GFOVPFY3pKM+AKjaUcWQLWSbb3hNrUb+GByy3/JomZxFc9PzIhwDR2rsYLgx+a+dlXSS92IizKMztj9KjlQsVq3ibR7AVf8fgix07i6vNXVm2MWO1SrW7TQK0Hy2ig== X-Microsoft-Exchange-Diagnostics: 1; BY2PR03MB141; 31:58SK0uB0LYFGmSMVvi1bFnrcHSp0GP1/EM4xkyRFrrRmXRUfpUwEbnsy7TOZNTxF7hiHBuZ3bnQHt3SOpm1EfVCnzCIIJC8cizLO1O4dl0NIGlVWYiOlDDPZkWz7z27vBhn0oGe2y9mBelQVcQVVDOnBWs5a3pQSQ57rFpk9bgHg800IBXJDCNBmV1svNxTbtOEoBCcS7Tq6rEpBw7RuZw==; 20:L//LcQmd2G3taqj/pYxrxGYyJso7B13tyrWwNJAzE7Xs7QJFm5Z4s/XRadmxWCt0J76YsdTtzqQ9qNzHE4qyUBcIjCtMIW+P9jhwC2KzbBPiwQ8ZLUHb4zqjMfSay01Iz48AhffvsUbhVOgsB/HEOT1VPOT35NEQX1GaS+9eRCM= X-Microsoft-Antispam-PRVS: X-Exchange-Antispam-Report-Test: UriScan:(250305191791016)(22074186197030)(80048183373757); X-Exchange-Antispam-Report-CFA-Test: BCL:0; PCL:0; RULEID:(601004)(2401047)(13015025)(13024025)(13023025)(13018025)(8121501046)(5005006)(13017025)(3002001)(10201501046)(6055026); SRVR:BY2PR03MB141; BCL:0; PCL:0; RULEID:; SRVR:BY2PR03MB141; X-Microsoft-Exchange-Diagnostics: 1; BY2PR03MB141; 4:DoGMDjwBB9OpXaJ7jZqqDs8xigTzMXHkPIoZCw/ubzAEcsfZYWwqTl99yE6rtAQjyVjj0dGqBK7ooWoM2sWrCa7r07U0cGFYDm1JK88Mva5pb+NPL4shaNHY1LM2ySteCuG0VIp0NlBXjTPJFXx+1hG5VqLM3Fh/GefdcmtEHQWU13Pbf9f3KpeDz4Wg16H9vstHzv1AGVfllkmO32ci4QjvSJeqx3I4lE1rF36WV1scqB3MwjqZcY/0bZ11eSCjZFEQaF7gPd2E8+uEAeSkWyTRIhnyuyAQFlfc6zimrMJpxQ8Ez9KeHiINlad03QsNgcb9oWPKr3a8bM0PRqHXOre5rcx2qzAEjtVM5ZrpUm5YXiizT+oFEigIeGoAsRqfOV7g8YYsUy0LMRU3RCEDtAU387tPztEk5sPifSFQt+QHe5QUhCiQBuWIDr6stLWSkXVWKfefQvqw6DlB+C+FBqIbXxh/azqfOn5IE84fwV5IZsL0L6FSNHtD+QMahW0Oqyekt8jbYfCeEDUAA5FCQtLEDekC9uZLyKBxO2CVdfenonD4vxX8EeisHF7CTioPlIN+qmY4vIEj2wU7EPZR9A== X-Forefront-PRVS: 0997523C40 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BY2PR03MB141; 23:/vzQmiJVhxL0gwMTHImKxIj9s/s6HGHvR7J8ppXbZ2?= =?us-ascii?Q?Pe5QQDKX8qf8RmfVQtnLd4f+qYynFJ47EoIKeU93aYy4GQ7RKUqTvipTS/aj?= =?us-ascii?Q?BKWy8jMb8OieMka8vYs1Cq8k41effD+lA48I/izlNoWEnz6I0YGfMwQMEWPw?= =?us-ascii?Q?TeU4ecUrMRbPcTQTCTgzH38Ne3DSTb/9IO+zVmy3PvU3qnSJqDvNn/B+nH3U?= =?us-ascii?Q?+BDIe1gi9L0LIwuiv/ZcsOjmLMMHFkG7SCLo3EK6LPD5vUAmptu/5gXis5MB?= =?us-ascii?Q?P9uO38+99FcRpaOurkVfToxoks555x2SJasWEEORhgOHCm5Tw9JxgXxjUEO4?= =?us-ascii?Q?6RBf6eA+MkzRlKaHmm3xu44LxxErQFY78hywm5uN17v/FvnBkANvhb1IjXGF?= =?us-ascii?Q?EFOtqdAUfDigsWkUD/bxmpKU2nK0WYxKX6seBN3RMV+enCT+1QG3ggRXpkW2?= =?us-ascii?Q?9LdpYsL1HWzdnk1MpiSyANVP+LwdacWDNk3zq9yVt0AIxLQjnCUUc5VhHAir?= =?us-ascii?Q?mUb33AzRTmsJY4CghHcfyLR48fEPROcmKUrEQlN+fk8igF/CgnrchFUtlGYu?= =?us-ascii?Q?PWfvYAmQmMm8QRdDc/klwkf1lmqj24JqNXcEuBrUmBZS9gogUFFv79IVLSR8?= =?us-ascii?Q?sKk3WGt42tNTyB9Z6s7yPTatRTUjbsGSZb7bTWcoaa5MOhJhbVn3zw3Qenie?= =?us-ascii?Q?7njuUZaPRdBqGsUBmO9bDvbKmkVNCIInzzDFjuGUhr7fiWr39t66C3GIyavs?= =?us-ascii?Q?iJ2umGJyKUw+ESIPSibClHnqsXoBqL1j/QjIfB5Fy/FnBNagcGvFZOXvKN9b?= =?us-ascii?Q?p4JUYJZy6CVh3mhLuvwPUZCPQc+nDzAJUXvU3FwXRQ1JIL8OyG75DgZ5v734?= =?us-ascii?Q?BgFgw7QCri0eBSr5bAuxjNTPcyAMNdXGtp8kgw+MXCnQtyKTPV5LghasTXdb?= =?us-ascii?Q?lZGfqaX959JAhdBXK99YY/4h3a6yhUHTxPbUijUZAeBV4UVkm8FLOqRr8CZq?= =?us-ascii?Q?5ag95++Q0bCWJ1cDNFUzlJzdKzd6TB3H8KENOF90B0wfG4HChg23DLaBvYwo?= =?us-ascii?Q?9c3evGxANKpXt4TVoyWegOzy15xP9tZ6TILaTczXOl+ea9hEmW6Oe8yqLRgs?= =?us-ascii?Q?m+sqfXBcs2jidLd2xC8D96LFPBrp/VONko+qM8AJ1/mVK3kiNAlyk0D4RHMB?= =?us-ascii?Q?Y2X9Wc3wvPmPaDj0n+rM9wrq1R/kWP5pdyUdbBUxVb2mfuRouqGoXOUlD0El?= =?us-ascii?Q?eUSQ4j8JN9H1A7Y40=3D?= X-Microsoft-Exchange-Diagnostics: 1; BY2PR03MB141; 6:nQTv/Qjeg5VV3lp4yKJL8OInYd/P4FF8Qg62D7dmCgTh6IDtUOnoiL1zmD4/su7y9M0bhkCtI6oDJMkC1AQUucUC3pfeI/irkhMVSu39Ogo5oFzWtaN/4afl4VZk/Th8jWFTwjhZczBtHFlOJRdXTQr8uw/fFmuz292uyFRfP0kSX5WPMARjJmmtfKU92JZm+HnAdwWyZJx0MLNknwZkdgwql+QUpZTnN5rYx5I0CDfqsvixRTmBUZxnVjJalVudLHta3uExQ8Av0ArjP1nYgxS6vSxm+tApy672nv0e9PVsMj+Evg0G1Sjf1dyj0Hj04HP36CAlGRzzOThEQL0hTg==; 5:tbWxR5VXxIVSCAM10vVlfResTYtC4E7m9jkiWUB/ZTIeC0TXA18O/U7Jb504bixrGN4NeJ2uJWIigU+hdkp/P1qYj1D5VRZ9FqrbBAqxjUTiVYJ1f+D0njYHcrHHPHuI4hgBGSvH28xm90b/yoTNqA==; 24:FigLs9gv5Ko8F+qX0PIp9O3d8AfdYYfbrZZbmgUcR/fz5DkwVT6m4BaJ8ZigXdreyl+zzOd0SWSoCHzAWZnNFe+SiMZhc3LTfZI5IMf86DM=; 7:ph/BeeHY36RG8iorwuTxh67oFEIjIV255AIQV4S+59e5oBmdCeFceWBIOFLf2gK5CZ4iqWmIBjeIrXkyZaHeY+r8Y1kBSmxQ0igeZUs0MKOufPo0fWXhAJ664L6+64gsDxxYAbQCiM0qhaT+ZuiErX5t86Wz0UzcZAlWfUafBuvmrgUHVGQFgizBUVmY/eUnzkp+KHjw/6HbcIoBiSBpACV3/LNzJpwPJo26PV+pIK5s674nvcYaLKgfQpbg0FP8 SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; BY2PR03MB141; 20:y594k7ftH1epJABU1bKnrMpQiF04EUPcNz+WU5d3Z+gq/43BDlLPvsvFUOfd4c5TVR5NPioCdo9Ji+HTa2dsOsroM5IPib/3MiN+yWn5TD0MXONMfKs3yaFJjiCKIA5Sgt72aHTZ0wIXNeqydJocOmLhozZKLGBPQHQ5CFjMPjc= X-OriginatorOrg: altera.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 08 Jul 2016 03:37:40.1419 (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: BY2PR03MB141 Sender: devicetree-owner@vger.kernel.org Precedence: bulk List-ID: X-Mailing-List: devicetree@vger.kernel.org From: Tien Hock Loh This adds support for TSE PCS that uses SGMII adapter when the phy-mode of the dwmac is set to sgmii. Signed-off-by: Tien Hock Loh Acked-by: Rob Herring --- v2: - Refactored the TSE PCS out from the dwmac-socfpga.c file - Added binding documentation for TSE PCS sgmii adapter v3: - Added missing license header for new source files - Updated tse_pcs.h include headers - Standardize if statements v4: - Reset SGMII adapter on speed change - Do not enable SGMII adapter if speed is not supported - On init, if PCS reset fails, do not enable adapter v5: - Fixed devicetree binding property name using _ instead of - v6: - Fixed a problem where driver build broken if driver is set as module v7: - Fixed code style (don't break variable declaration with empty lines) - Removed unnecessary parenthesis --- .../devicetree/bindings/net/socfpga-dwmac.txt | 19 ++ drivers/net/ethernet/stmicro/stmmac/Makefile | 3 +- drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c | 274 +++++++++++++++++++++ drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h | 36 +++ .../net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 140 +++++++++-- 5 files changed, 450 insertions(+), 22 deletions(-) create mode 100644 drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c create mode 100644 drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h diff --git a/Documentation/devicetree/bindings/net/socfpga-dwmac.txt b/Documentation/devicetree/bindings/net/socfpga-dwmac.txt index 72d82d6..2e68a3c 100644 --- a/Documentation/devicetree/bindings/net/socfpga-dwmac.txt +++ b/Documentation/devicetree/bindings/net/socfpga-dwmac.txt @@ -17,9 +17,26 @@ Required properties: Optional properties: altr,emac-splitter: Should be the phandle to the emac splitter soft IP node if DWMAC controller is connected emac splitter. +phy-mode: The phy mode the ethernet operates in +altr,sgmii-to-sgmii-converter: phandle to the TSE SGMII converter + +This device node has additional phandle dependency, the sgmii converter: + +Required properties: + - compatible : Should be altr,gmii-to-sgmii-2.0 + - reg-names : Should be "eth_tse_control_port" Example: +gmii_to_sgmii_converter: phy@0x100000240 { + compatible = "altr,gmii-to-sgmii-2.0"; + reg = <0x00000001 0x00000240 0x00000008>, + <0x00000001 0x00000200 0x00000040>; + reg-names = "eth_tse_control_port"; + clocks = <&sgmii_1_clk_0 &emac1 1 &sgmii_clk_125 &sgmii_clk_125>; + clock-names = "tse_pcs_ref_clk_clock_connection", "tse_rx_cdr_refclk"; +}; + gmac0: ethernet@ff700000 { compatible = "altr,socfpga-stmmac", "snps,dwmac-3.70a", "snps,dwmac"; altr,sysmgr-syscon = <&sysmgr 0x60 0>; @@ -30,4 +47,6 @@ gmac0: ethernet@ff700000 { mac-address = [00 00 00 00 00 00];/* Filled in by U-Boot */ clocks = <&emac_0_clk>; clock-names = "stmmaceth"; + phy-mode = "sgmii"; + altr,gmii-to-sgmii-converter = <&gmii_to_sgmii_converter>; }; diff --git a/drivers/net/ethernet/stmicro/stmmac/Makefile b/drivers/net/ethernet/stmicro/stmmac/Makefile index 0fb362d..44b630c 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -11,11 +11,12 @@ obj-$(CONFIG_DWMAC_IPQ806X) += dwmac-ipq806x.o obj-$(CONFIG_DWMAC_LPC18XX) += dwmac-lpc18xx.o obj-$(CONFIG_DWMAC_MESON) += dwmac-meson.o obj-$(CONFIG_DWMAC_ROCKCHIP) += dwmac-rk.o -obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-socfpga.o +obj-$(CONFIG_DWMAC_SOCFPGA) += dwmac-altr-socfpga.o obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o obj-$(CONFIG_DWMAC_GENERIC) += dwmac-generic.o stmmac-platform-objs:= stmmac_platform.o +dwmac-altr-socfpga-objs := altr_tse_pcs.o dwmac-socfpga.o obj-$(CONFIG_STMMAC_PCI) += stmmac-pci.o stmmac-pci-objs:= stmmac_pci.o diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c new file mode 100644 index 0000000..2920e2e --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c @@ -0,0 +1,274 @@ +/* Copyright Altera Corporation (C) 2016. All rights reserved. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Author: Tien Hock Loh + */ + +#include +#include +#include +#include +#include +#include +#include +#include + +#include "stmmac.h" +#include "stmmac_platform.h" +#include "altr_tse_pcs.h" + +#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0 +#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII BIT(1) +#define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII BIT(2) +#define SYSMGR_EMACGRP_CTRL_PHYSEL_WIDTH 2 +#define SYSMGR_EMACGRP_CTRL_PHYSEL_MASK GENMASK(1, 0) + +#define TSE_PCS_CONTROL_AN_EN_MASK BIT(12) +#define TSE_PCS_CONTROL_REG 0x00 +#define TSE_PCS_CONTROL_RESTART_AN_MASK BIT(9) +#define TSE_PCS_IF_MODE_REG 0x28 +#define TSE_PCS_LINK_TIMER_0_REG 0x24 +#define TSE_PCS_LINK_TIMER_1_REG 0x26 +#define TSE_PCS_SIZE 0x40 +#define TSE_PCS_STATUS_AN_COMPLETED_MASK BIT(5) +#define TSE_PCS_STATUS_LINK_MASK 0x0004 +#define TSE_PCS_STATUS_REG 0x02 +#define TSE_PCS_SGMII_SPEED_1000 BIT(3) +#define TSE_PCS_SGMII_SPEED_100 BIT(2) +#define TSE_PCS_SGMII_SPEED_10 0x0 +#define TSE_PCS_SW_RST_MASK 0x8000 +#define TSE_PCS_PARTNER_ABILITY_REG 0x0A +#define TSE_PCS_PARTNER_DUPLEX_FULL 0x1000 +#define TSE_PCS_PARTNER_DUPLEX_HALF 0x0000 +#define TSE_PCS_PARTNER_DUPLEX_MASK 0x1000 +#define TSE_PCS_PARTNER_SPEED_MASK GENMASK(11, 10) +#define TSE_PCS_PARTNER_SPEED_1000 BIT(11) +#define TSE_PCS_PARTNER_SPEED_100 BIT(10) +#define TSE_PCS_PARTNER_SPEED_10 0x0000 +#define TSE_PCS_PARTNER_SPEED_1000 BIT(11) +#define TSE_PCS_PARTNER_SPEED_100 BIT(10) +#define TSE_PCS_PARTNER_SPEED_10 0x0000 +#define TSE_PCS_SGMII_SPEED_MASK GENMASK(3, 2) +#define TSE_PCS_SGMII_LINK_TIMER_0 0x0D40 +#define TSE_PCS_SGMII_LINK_TIMER_1 0x0003 +#define TSE_PCS_SW_RESET_TIMEOUT 100 +#define TSE_PCS_USE_SGMII_AN_MASK BIT(2) +#define TSE_PCS_USE_SGMII_ENA BIT(1) + +#define SGMII_ADAPTER_CTRL_REG 0x00 +#define SGMII_ADAPTER_DISABLE 0x0001 +#define SGMII_ADAPTER_ENABLE 0x0000 + +#define AUTONEGO_LINK_TIMER 20 + +static int tse_pcs_reset(void __iomem *base, struct tse_pcs *pcs) +{ + int counter = 0; + u16 val; + + val = readw(base + TSE_PCS_CONTROL_REG); + val |= TSE_PCS_SW_RST_MASK; + writew(val, base + TSE_PCS_CONTROL_REG); + + while (counter < TSE_PCS_SW_RESET_TIMEOUT) { + val = readw(base + TSE_PCS_CONTROL_REG); + val &= TSE_PCS_SW_RST_MASK; + if (val == 0) + break; + counter++; + udelay(1); + } + if (counter >= TSE_PCS_SW_RESET_TIMEOUT) { + dev_err(pcs->dev, "PCS could not get out of sw reset\n"); + return -ETIMEDOUT; + } + + return 0; +} + +int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs) +{ + int ret = 0; + + writew(TSE_PCS_USE_SGMII_ENA, base + TSE_PCS_IF_MODE_REG); + + writew(TSE_PCS_SGMII_LINK_TIMER_0, base + TSE_PCS_LINK_TIMER_0_REG); + writew(TSE_PCS_SGMII_LINK_TIMER_1, base + TSE_PCS_LINK_TIMER_1_REG); + + ret = tse_pcs_reset(base, pcs); + if (ret == 0) + writew(SGMII_ADAPTER_ENABLE, + pcs->sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); + + return ret; +} + +static void pcs_link_timer_callback(unsigned long data) +{ + u16 val = 0; + struct tse_pcs *pcs = (struct tse_pcs *)data; + void __iomem *tse_pcs_base = pcs->tse_pcs_base; + void __iomem *sgmii_adapter_base = pcs->sgmii_adapter_base; + + val = readw(tse_pcs_base + TSE_PCS_STATUS_REG); + val &= TSE_PCS_STATUS_LINK_MASK; + + if (val != 0) { + dev_dbg(pcs->dev, "Adapter: Link is established\n"); + writew(SGMII_ADAPTER_ENABLE, + sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); + } else { + mod_timer(&pcs->aneg_link_timer, jiffies + + msecs_to_jiffies(AUTONEGO_LINK_TIMER)); + } +} + +static void auto_nego_timer_callback(unsigned long data) +{ + u16 val = 0; + u16 speed = 0; + u16 duplex = 0; + struct tse_pcs *pcs = (struct tse_pcs *)data; + void __iomem *tse_pcs_base = pcs->tse_pcs_base; + void __iomem *sgmii_adapter_base = pcs->sgmii_adapter_base; + + val = readw(tse_pcs_base + TSE_PCS_STATUS_REG); + val &= TSE_PCS_STATUS_AN_COMPLETED_MASK; + + if (val != 0) { + dev_dbg(pcs->dev, "Adapter: Auto Negotiation is completed\n"); + val = readw(tse_pcs_base + TSE_PCS_PARTNER_ABILITY_REG); + speed = val & TSE_PCS_PARTNER_SPEED_MASK; + duplex = val & TSE_PCS_PARTNER_DUPLEX_MASK; + + if (speed == TSE_PCS_PARTNER_SPEED_10 && + duplex == TSE_PCS_PARTNER_DUPLEX_FULL) + dev_dbg(pcs->dev, + "Adapter: Link Partner is Up - 10/Full\n"); + else if (speed == TSE_PCS_PARTNER_SPEED_100 && + duplex == TSE_PCS_PARTNER_DUPLEX_FULL) + dev_dbg(pcs->dev, + "Adapter: Link Partner is Up - 100/Full\n"); + else if (speed == TSE_PCS_PARTNER_SPEED_1000 && + duplex == TSE_PCS_PARTNER_DUPLEX_FULL) + dev_dbg(pcs->dev, + "Adapter: Link Partner is Up - 1000/Full\n"); + else if (speed == TSE_PCS_PARTNER_SPEED_10 && + duplex == TSE_PCS_PARTNER_DUPLEX_HALF) + dev_err(pcs->dev, + "Adapter does not support Half Duplex\n"); + else if (speed == TSE_PCS_PARTNER_SPEED_100 && + duplex == TSE_PCS_PARTNER_DUPLEX_HALF) + dev_err(pcs->dev, + "Adapter does not support Half Duplex\n"); + else if (speed == TSE_PCS_PARTNER_SPEED_1000 && + duplex == TSE_PCS_PARTNER_DUPLEX_HALF) + dev_err(pcs->dev, + "Adapter does not support Half Duplex\n"); + else + dev_err(pcs->dev, + "Adapter: Invalid Partner Speed and Duplex\n"); + + if (duplex == TSE_PCS_PARTNER_DUPLEX_FULL && + (speed == TSE_PCS_PARTNER_SPEED_10 || + speed == TSE_PCS_PARTNER_SPEED_100 || + speed == TSE_PCS_PARTNER_SPEED_1000)) + writew(SGMII_ADAPTER_ENABLE, + sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); + } else { + val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG); + val |= TSE_PCS_CONTROL_RESTART_AN_MASK; + writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG); + + tse_pcs_reset(tse_pcs_base, pcs); + mod_timer(&pcs->aneg_link_timer, jiffies + + msecs_to_jiffies(AUTONEGO_LINK_TIMER)); + } +} + +static void aneg_link_timer_callback(unsigned long data) +{ + struct tse_pcs *pcs = (struct tse_pcs *)data; + + if (pcs->autoneg == AUTONEG_ENABLE) + auto_nego_timer_callback(data); + else if (pcs->autoneg == AUTONEG_DISABLE) + pcs_link_timer_callback(data); +} + +void tse_pcs_fix_mac_speed(struct tse_pcs *pcs, struct phy_device *phy_dev, + unsigned int speed) +{ + void __iomem *tse_pcs_base = pcs->tse_pcs_base; + void __iomem *sgmii_adapter_base = pcs->sgmii_adapter_base; + u32 val; + + writew(SGMII_ADAPTER_ENABLE, + sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); + + pcs->autoneg = phy_dev->autoneg; + + if (phy_dev->autoneg == AUTONEG_ENABLE) { + val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG); + val |= TSE_PCS_CONTROL_AN_EN_MASK; + writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG); + + val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG); + val |= TSE_PCS_USE_SGMII_AN_MASK; + writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG); + + val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG); + val |= TSE_PCS_CONTROL_RESTART_AN_MASK; + + tse_pcs_reset(tse_pcs_base, pcs); + + setup_timer(&pcs->aneg_link_timer, + aneg_link_timer_callback, (unsigned long)pcs); + mod_timer(&pcs->aneg_link_timer, jiffies + + msecs_to_jiffies(AUTONEGO_LINK_TIMER)); + } else if (phy_dev->autoneg == AUTONEG_DISABLE) { + val = readw(tse_pcs_base + TSE_PCS_CONTROL_REG); + val &= ~TSE_PCS_CONTROL_AN_EN_MASK; + writew(val, tse_pcs_base + TSE_PCS_CONTROL_REG); + + val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG); + val &= ~TSE_PCS_USE_SGMII_AN_MASK; + writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG); + + val = readw(tse_pcs_base + TSE_PCS_IF_MODE_REG); + val &= ~TSE_PCS_SGMII_SPEED_MASK; + + switch (speed) { + case 1000: + val |= TSE_PCS_SGMII_SPEED_1000; + break; + case 100: + val |= TSE_PCS_SGMII_SPEED_100; + break; + case 10: + val |= TSE_PCS_SGMII_SPEED_10; + break; + default: + return; + } + writew(val, tse_pcs_base + TSE_PCS_IF_MODE_REG); + + tse_pcs_reset(tse_pcs_base, pcs); + + setup_timer(&pcs->aneg_link_timer, + aneg_link_timer_callback, (unsigned long)pcs); + mod_timer(&pcs->aneg_link_timer, jiffies + + msecs_to_jiffies(AUTONEGO_LINK_TIMER)); + } +} diff --git a/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h new file mode 100644 index 0000000..2f58824 --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h @@ -0,0 +1,36 @@ +/* Copyright Altera Corporation (C) 2016. All rights reserved. + * + * 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. + * + * This program is distributed in the hope that it will be useful, + * but WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the + * GNU General Public License for more details. + * + * You should have received a copy of the GNU General Public License + * along with this program. If not, see . + * + * Author: Tien Hock Loh + */ + +#ifndef __TSE_PCS_H__ +#define __TSE_PCS_H__ + +#include +#include + +struct tse_pcs { + struct device *dev; + void __iomem *tse_pcs_base; + void __iomem *sgmii_adapter_base; + struct timer_list aneg_link_timer; + int autoneg; +}; + +int tse_pcs_init(void __iomem *base, struct tse_pcs *pcs); +void tse_pcs_fix_mac_speed(struct tse_pcs *pcs, struct phy_device *phy_dev, + unsigned int speed); + +#endif /* __TSE_PCS_H__ */ diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c index f13499f..4bee2f9 100644 --- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c +++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c @@ -27,6 +27,11 @@ #include "stmmac.h" #include "stmmac_platform.h" +#include "altr_tse_pcs.h" + +#define SGMII_ADAPTER_CTRL_REG 0x00 +#define SGMII_ADAPTER_DISABLE 0x0001 + #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII 0x0 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RGMII 0x1 #define SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_RMII 0x2 @@ -52,35 +57,46 @@ struct socfpga_dwmac { struct reset_control *stmmac_rst; void __iomem *splitter_base; bool f2h_ptp_ref_clk; + struct tse_pcs pcs; }; static void socfpga_dwmac_fix_mac_speed(void *priv, unsigned int speed) { struct socfpga_dwmac *dwmac = (struct socfpga_dwmac *)priv; void __iomem *splitter_base = dwmac->splitter_base; + void __iomem *tse_pcs_base = dwmac->pcs.tse_pcs_base; + void __iomem *sgmii_adapter_base = dwmac->pcs.sgmii_adapter_base; + struct device *dev = dwmac->dev; + struct net_device *ndev = dev_get_drvdata(dev); + struct phy_device *phy_dev = ndev->phydev; u32 val; - if (!splitter_base) - return; - - val = readl(splitter_base + EMAC_SPLITTER_CTRL_REG); - val &= ~EMAC_SPLITTER_CTRL_SPEED_MASK; - - switch (speed) { - case 1000: - val |= EMAC_SPLITTER_CTRL_SPEED_1000; - break; - case 100: - val |= EMAC_SPLITTER_CTRL_SPEED_100; - break; - case 10: - val |= EMAC_SPLITTER_CTRL_SPEED_10; - break; - default: - return; + if ((tse_pcs_base) && (sgmii_adapter_base)) + writew(SGMII_ADAPTER_DISABLE, + sgmii_adapter_base + SGMII_ADAPTER_CTRL_REG); + + if (splitter_base) { + val = readl(splitter_base + EMAC_SPLITTER_CTRL_REG); + val &= ~EMAC_SPLITTER_CTRL_SPEED_MASK; + + switch (speed) { + case 1000: + val |= EMAC_SPLITTER_CTRL_SPEED_1000; + break; + case 100: + val |= EMAC_SPLITTER_CTRL_SPEED_100; + break; + case 10: + val |= EMAC_SPLITTER_CTRL_SPEED_10; + break; + default: + return; + } + writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG); } - writel(val, splitter_base + EMAC_SPLITTER_CTRL_REG); + if (tse_pcs_base && sgmii_adapter_base) + tse_pcs_fix_mac_speed(&dwmac->pcs, phy_dev, speed); } static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *dev) @@ -88,9 +104,12 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device * struct device_node *np = dev->of_node; struct regmap *sys_mgr_base_addr; u32 reg_offset, reg_shift; - int ret; - struct device_node *np_splitter; + int ret, index; + struct device_node *np_splitter = NULL; + struct device_node *np_sgmii_adapter = NULL; struct resource res_splitter; + struct resource res_tse_pcs; + struct resource res_sgmii_adapter; dwmac->interface = of_get_phy_mode(np); @@ -128,6 +147,77 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device * } } + np_sgmii_adapter = of_parse_phandle(np, + "altr,gmii-to-sgmii-converter", 0); + if (np_sgmii_adapter) { + index = of_property_match_string(np_sgmii_adapter, "reg-names", + "hps_emac_interface_splitter_avalon_slave"); + + if (index >= 0) { + if (of_address_to_resource(np_sgmii_adapter, index, + &res_splitter)) { + dev_err(dev, + "%s: ERROR: missing emac splitter address\n", + __func__); + return -EINVAL; + } + + dwmac->splitter_base = + devm_ioremap_resource(dev, &res_splitter); + + if (IS_ERR(dwmac->splitter_base)) { + dev_err(dev, + "%s: ERROR: failed mapping emac splitter\n", + __func__); + return PTR_ERR(dwmac->splitter_base); + } + } + + index = of_property_match_string(np_sgmii_adapter, "reg-names", + "gmii_to_sgmii_adapter_avalon_slave"); + + if (index >= 0) { + if (of_address_to_resource(np_sgmii_adapter, index, + &res_sgmii_adapter)) { + dev_err(dev, + "%s: ERROR: failed mapping adapter\n", + __func__); + return -EINVAL; + } + + dwmac->pcs.sgmii_adapter_base = + devm_ioremap_resource(dev, &res_sgmii_adapter); + + if (IS_ERR(dwmac->pcs.sgmii_adapter_base)) { + dev_err(dev, "%s: failed to mapping adapter\n", + __func__); + return PTR_ERR(dwmac->pcs.sgmii_adapter_base); + } + } + + index = of_property_match_string(np_sgmii_adapter, "reg-names", + "eth_tse_control_port"); + + if (index >= 0) { + if (of_address_to_resource(np_sgmii_adapter, index, + &res_tse_pcs)) { + dev_err(dev, + "%s: ERROR: failed mapping tse control port\n", + __func__); + return -EINVAL; + } + + dwmac->pcs.tse_pcs_base = + devm_ioremap_resource(dev, &res_tse_pcs); + + if (IS_ERR(dwmac->pcs.tse_pcs_base)) { + dev_err(dev, + "%s: ERROR: failed mapping tse control port\n", + __func__); + return PTR_ERR(dwmac->pcs.sgmii_adapter_base); + } + } + } dwmac->reg_offset = reg_offset; dwmac->reg_shift = reg_shift; dwmac->sys_mgr_base_addr = sys_mgr_base_addr; @@ -151,6 +241,7 @@ static int socfpga_dwmac_set_phy_mode(struct socfpga_dwmac *dwmac) break; case PHY_INTERFACE_MODE_MII: case PHY_INTERFACE_MODE_GMII: + case PHY_INTERFACE_MODE_SGMII: val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; break; default: @@ -191,6 +282,12 @@ static int socfpga_dwmac_set_phy_mode(struct socfpga_dwmac *dwmac) */ if (dwmac->stmmac_rst) reset_control_deassert(dwmac->stmmac_rst); + if (phymode == PHY_INTERFACE_MODE_SGMII) { + if (tse_pcs_init(dwmac->pcs.tse_pcs_base, &dwmac->pcs) != 0) { + dev_err(dwmac->dev, "Unable to initialize TSE PCS"); + return -EINVAL; + } + } return 0; } @@ -225,6 +322,7 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed; ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); + if (!ret) { struct net_device *ndev = platform_get_drvdata(pdev); struct stmmac_priv *stpriv = netdev_priv(ndev);