From patchwork Fri Jun 24 09:13:23 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: 640109 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 3rbYTJ30BZz9s8d for ; Fri, 24 Jun 2016 19:49:40 +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=GcuLYH+P; dkim-atps=neutral Received: (majordomo@vger.kernel.org) by vger.kernel.org via listexpand id S1751081AbcFXJt3 (ORCPT ); Fri, 24 Jun 2016 05:49:29 -0400 Received: from mail-bn1bon0089.outbound.protection.outlook.com ([157.56.111.89]:45952 "EHLO na01-bn1-obe.outbound.protection.outlook.com" rhost-flags-OK-OK-OK-FAIL) by vger.kernel.org with ESMTP id S1750960AbcFXJsY (ORCPT ); Fri, 24 Jun 2016 05:48: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=BXAYAVKS69xZ2R95DtYBXvZjDxnZheL2+5HEdTlqoNg=; b=GcuLYH+P9i5Mifd4M9xf8l2G7DcRDYhp9RT36YTzNKIzxWoQJ8G4CZfSOPiRFB8HGAXAa+tAx0/phM19CPeDHxeaGEC31ZtA8K1fJHNo+2nJBkpv/sSXn5EVMwxP0eYypd105GpjqN+2xV6YodkKh6UTa8OGidXdHewhRPu07Yk= Received: from BY2PR03CA010.namprd03.prod.outlook.com (10.255.93.27) by BL2PR03MB513.namprd03.prod.outlook.com (10.141.94.18) with Microsoft SMTP Server (version=TLS1_2, cipher=TLS_ECDHE_RSA_WITH_AES_256_CBC_SHA384_P384) id 15.1.523.12; Fri, 24 Jun 2016 09:14:13 +0000 Received: from BY2FFO11FD007.protection.gbl (10.255.93.4) by BY2PR03CA010.outlook.office365.com (10.255.93.27) with Microsoft SMTP Server (TLS) id 15.1.492.11 via Frontend Transport; Fri, 24 Jun 2016 09:14:12 +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 BY2FFO11FD007.mail.protection.outlook.com (10.1.14.128) with Microsoft SMTP Server (TLS) id 15.1.517.7 via Frontend Transport; Fri, 24 Jun 2016 09:14:12 +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; Fri, 24 Jun 2016 02:13:48 -0700 Received: from ubuntu (pg-thloh-l.altera.com [10.142.36.106]) by sj-mail01.altera.com (8.13.7+Sun/8.13.7) with SMTP id u5O9DwAR001975; Fri, 24 Jun 2016 02:13:59 -0700 (PDT) Received: by ubuntu (sSMTP sendmail emulation); Fri, 24 Jun 2016 02:14:14 -0700 From: To: , , , , , , , , , , , , Subject: [PATCH V5 1/1] net: ethernet: Add TSE PCS support to dwmac-socfpga Date: Fri, 24 Jun 2016 02:13:23 -0700 Message-ID: <1466759603-30769-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)(97736004)(305945005)(6806005)(107886002)(15975445007)(4001450100002)(229853001)(5001770100001)(81166006)(2876002)(586003)(2906002)(189998001)(68736007)(81156014)(8676002)(33646002)(11100500001)(92566002)(5003940100001)(7049001)(19580395003)(19580405001)(50466002)(48376002)(50986999)(36756003)(50226002)(87936001)(7846002)(86362001)(2201001)(575784001)(106466001)(86152002)(105596002)(42186005)(8936002)(356003)(47776003)(7099028)(2004002)(921003)(217873001)(1121003)(4720700001); DIR:OUT; SFP:1101; SCL:1; SRVR:BL2PR03MB513; H:sj-itexedge03.altera.priv.altera.com; FPR:; SPF:SoftFail; PTR:InfoDomainNonexistent; MX:1; A:1; LANG:en; X-Microsoft-Exchange-Diagnostics: 1; BY2FFO11FD007; 1:TOmecYB7hT5yGqjpWzFlKeq8kYfLYNOQtVq2y0jssU0htvtR6lbBWZALq0hKY3nRYdD8aKa+j95+5IVu6OABXzWFe0fJAgDcZ1cfEoSwxYYcBuRGctub+z6px/jmneZy+wk995tTmbdnfykM8rR51Uk25IrpC9gM9ReM8W1nmncNRkwBLJs2Hx3OSc0wX0KlH2132tq+i648C4AFqgMQNZXu1Iz0txCHw2C7ZsFaThyEo4xzRwMf/nFsih136g5ww69LsuqmlMeKAbcd2463qGiUpRMbBaACiKk+OJNv+U4W2PtQTPMbaTlSK6mQSDTU677kRZYiUYR4pm3grmBTGYrQMH576ys1Rlr9CcEg6dtTB+OEy/t6ZsBH9F4wVZmKp4wbu+d8rIQLKM8ykzXQrNhUXB6t7dPQou7nKulCn57YlJFf1hIIau+p+aLrIBDBRREInIDPyT9sIV2tTCgZ4m/B9rfv9jS0IKxsqk8eiUiFgRGbbZO+9TgyV/CNBjGUUnQrSUzaeR8kX9zDmTeN7ru1ulwvzu+uxRzRdJAFPbHOEGwpFWJ/Byj5luu+E/VARvCV8asrrRDScdx2e6rVnQ== X-MS-Office365-Filtering-Correlation-Id: 6e5206ce-cdf5-417b-171a-08d39c0fe83c X-Microsoft-Exchange-Diagnostics: 1; BL2PR03MB513; 2:MFfMVuJV57BNvYmGtg3Lc1tRIwfZvnQTqQGsZXswgojb6BR4kEyxPKjTVu09zwru6iu2r+Almh3CRSjKhq8YbU+9I9wHxaf7QR00LyBA+ZY8nPB4RmT93mO9logoshkJ4s0gzE+NJhaAcNFqfrX9wC1R+EiXR4JNzRUcwelRA4FQQgrZyw8rDbFbtdt6/HC7; 3:veTHqjDXq+eruE9fSX2XT2ooK/ptP/HKB3+pHf5oz92Tm6AjgMmpvduXmVl3Xdc8GVOfwVAjz5IcFCtbFLF5q7y1UIKTKVl1krjXErGx83JozrD+JOwKgU/yRZ/gXx1gb9fNsjL1d5yrS2xmjovMg7dOFOUa2R1+R2I8/9AmSDh3NRreMHZkWl7xZhPckzGtLC2p0ex9b6SW2sabfMcV1tkPUDoOPjTPidRdet3PseM= X-Microsoft-Antispam: UriScan:;BCL:0;PCL:0;RULEID:;SRVR:BL2PR03MB513; X-Microsoft-Exchange-Diagnostics: 1; BL2PR03MB513; 25:fpBLEPwq3k+/E2HqQYdZLpPHG4WVoBPYoN+WBhbYCbG1DeVm+AZgTJEtrPIHHJC+L8vrFXsu5cfu0fYwSd65gjKUo0TCB0cRgtAFYPa6PfheVgXcAgse99qtJ8jRtJqNP2nKN0NUANUSSeYhIkjRFjYLdn5QFnezd9U48XMBLL0tJrSmDL3bxNbge0tuFFCZXQe+Krk3YkprnVVUrP1//FqmCByFpMTnnzGkNOGj0uGk4PGrNzPPwTR1xfBw+AfLhRnKui1mRQXaqAd4YRCt1HtpQgQKjukTb7ntTEFjqX+avwc5CkchIAU12cfT5lKC5oXoUMN/oELljMhdIcM1934U9qEOFKzFStlx6Mt/clZXZrD6ALbkbGB4Vao5S3PJdPrCYlM0hm5k5MBIuK8d5l+DveTbYexFWWodgUEcT4Z1tp6ZMebEqodB4RKyanWy9Bx6m5CUVUOSP1+eyP05N8vCumLv02NwxNaRRhpfc/W+a16GwDssu+59xy8uPc36z5kr6fj826RroDH4D3E9GZYNIgH1h+Se9idYXwXijmc3RG8SbvkWeeoaOXVgSnatfsjxYC25VC0i/UBTkRdYMSKi1fhoY7a1RiOwzCKV+BgD4uPFM1poB/Qu2BNzgEsjDu1nRguqrhSZ2EevQEOvFoJA+CJk1Vj0ibMry2Ntzqil6TOEq8H0Na8SWgKamnBcbWdSMgwOztF41fKx0HdVkhVO+TE93NMmSpOA5MJ00gIc7D1mZctgYddp3xE2Twte7xCMai2nkuKb98SxhgA9gwSZyCLyEWpmlTHfEN8yutTpuqcmo48oVffKAoJJOi4ehWmMjf4aeGSRpd3+gZiuug== X-Microsoft-Exchange-Diagnostics: 1; BL2PR03MB513; 20:hpvUK0fShOZjUWsHjZBfqQhhAP2wXgJaX9X6f1Shh6NAWunYFr8xY7FHg28GU2uU44vPuB9CXigI2q9QjCyGbGXoXAgOQ5SohlMYYBKEKBZyTgWZGDnuCTVwr301b7jpqgE1Zauntr5U4yQAmJRBzXQVj8SBhoXaAGca/91gWdU=; 4:uc/yz3PCfw0rrOS9swZlfiN+RbCCiQEo1rnYJ+WPu+9ddgjAxA4V3ZJUNrl8QXh1UwShiCC7dCqXlx7Q7xBawYSVSMbBIpgwD4jKlhpVpDzruqR+R5Jd7ymKpN26qumNEFZa7RSovKZ1bM4TGCRiydCSYRUrcBid6fI2Wtdw6dDI+M/GteDZNW+8V8/RG24aI15d/xTiECLUH+CDG4SfoVN6hnB8dHnfCGfuklRrIycJiMWKlZNfzOSRkk7eGPJP3HnRbP8ofVb69Li6Z9HajHfRH2+RRTZROiVqEZb/6/C7TunrW93vIcAbKIR8vfcH7LvjVZf6XK9mAF7DqamimUq3DsnJV2L0HT6ly0+15eFOQfz9/yql39xArHaTUmRYOu6m/SzYVd9TBzNCN2LKg8xEJYln4jxUiRmkKH3rIcTB9QAmuqfqgCP9jDCADXrXRKv3wuDHH1EmcZazQCZQaP8dAt+RiUAF050SHED5vQo4/nqF64q0AN9oVP/Oe+MH1nJIZfy6aIJ2+TSwlyqHrjOGfWoIXKU70AUMFoZMQFYCV5bxh3/c8FicBu0arQ/ZDbTSOyW649TI/sZXhkDu9A== 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)(13017025)(5005006)(13018025)(13023025)(13024025)(8121501046)(13015025)(10201501046)(3002001)(6055026); SRVR:BL2PR03MB513; BCL:0; PCL:0; RULEID:; SRVR:BL2PR03MB513; X-Forefront-PRVS: 0983EAD6B2 X-Microsoft-Exchange-Diagnostics: =?us-ascii?Q?1; BL2PR03MB513; 23:/4DwiLQs2iAULkdTIpyiWyHAp9ZFoezwRfWDaQkBFl?= =?us-ascii?Q?s8N0hfCAHclLwfuRBaxVp9NEmTlcXteDVUDOKrjvEjHliy0HyeNwll6Fh5vf?= =?us-ascii?Q?PEpeQfq2R621vwPVRin5uFRx+10HjUwzeCvOR1NPLNUDECfDR+TaMRFyxSsT?= =?us-ascii?Q?5NSVq5cpLNRyvi1NRwS2GJQOmU4DBwrf56lZ5LJPdIjEzN1aseXlJ+i6BjYH?= =?us-ascii?Q?6Day/bzTVXXvWDGkpH0ThKlwy7AxLeYewP/7lSqWb2sdQfVk2KsOLv9PzfUP?= =?us-ascii?Q?gi2T1tdFucNMlX3o2UIsez6zLjSNyK4/t3kWileQEZ+Mn/8V2wKkDdzcpRML?= =?us-ascii?Q?9LumxtQxsGl6ntLP1ImQ1G8bwPUzeDvvSW7ssC8YB6AI0hcmUHQzYnZIMeyH?= =?us-ascii?Q?0ZLqRv4phRXtnNh0oH9KyYOvAnotutKRERvxDXlsRCza7Rt/bRXGBY4vaNFf?= =?us-ascii?Q?zRwoTuLETOz1J4t0IpimTeVQ87k7El+XE9iYDBXsM1oooBqwHxdptQTtiWEU?= =?us-ascii?Q?xVL8L10LYy59iEnHpS95EkeBc6ALBrORhJFg9awOhXVxDlQ56E3sGA+/8jBq?= =?us-ascii?Q?5rCXSIN/n/lwgcmc17mF+WnRBA9Slim3ZZgtfJYnlfcC899fSqq//GnH54e/?= =?us-ascii?Q?OSO+V5jGXH1Bgi0QS1OGV/ZYR//JbElJcY6vrrIbCEresE6vdS05Irn3/TU0?= =?us-ascii?Q?+suyuCMbRGtBLoqjKP/DJx7G36l98flxBqYuVswKmKoViczkZ62MBtmg0eC9?= =?us-ascii?Q?HEjnSKZ4fCrZN8pbPCf9xhnO96AOV5+8QoU5wlfYUjkAcGQVvBzTouuSsyiy?= =?us-ascii?Q?Zzpl+ZQoMeMzalNdZQ3Q6R7Vdd5bBFMqdJUFcLiR7hkxedjLYSV93woVLiU5?= =?us-ascii?Q?OyP3sl+IhXRjhSRkOPqmZqzmod+NyPPpek0tf8TmFnr2TFnFd9EymyS7K1D4?= =?us-ascii?Q?+HaknvTHupeFMxQjON5r81n1PPGJFguCQW9BJBHw5E37V7s20DZJmuTHDGvd?= =?us-ascii?Q?q0TAbfMMx0QSrhBwPcQgwGeBcG8sJNGV/v9zs5T1FAeaWSJ2b7W8zGZecNSA?= =?us-ascii?Q?QSaWWyCbKd0t/MH4zrFW1xdHI/QDaLYu8lLVvDsce66R12iatAKoCQPJCDzF?= =?us-ascii?Q?M2/hzwPKlhG+qR6WF/oTJxTB7SI9ugClcM0oeu+Wc5oHKtZpya53/VHh4g2D?= =?us-ascii?Q?Zau+xDtquQ5HpE9VPR1N4QT0j3PPXKKsgVl70aJXyBqfHqwK19ckcED7vJDE?= =?us-ascii?Q?yjrVZy61dsdfr0ivQ=3D?= X-Microsoft-Exchange-Diagnostics: 1; BL2PR03MB513; 6:7qEP71EiCZbCArZ9A6U1M7dbSvGPeNyJkvudWR5D/a+x2MNBnTFs0SeuSkLipwRO8ElCWWyaudCwhqo53lhQ7Zke41BVXhq+TU1g6rkCqF/8A+O+pMXg6EtYG0d5N+hezsFCO6xDVip0KcZVIL75a1LCSATHJXQry1WiTgm288iLUuE6sHU3w0bGnH8zgI4H1HsoX38SlRj5yDsBNQ8lYy6NFReBQQlcyacF4ymDUZ0phWjIQRIi+oYYGHcg1+U//MapdxKEdbeOTTHEcbxcu8lG0C1U31Zh40SrlTClit3ZaPIdv07LiJVACypjElc2n+ImA83oAvCQhwe8kfO6k6G/C7ZKBB+1qEbJK38+9tM=; 5:9Lw4L3XeHhy7mfEiRIaI73wokC8kdtFXn/RcrcVOAGwMUM9Tv86NFgvy2zda7oct7RRcaMEQyP1i7qO6K40dtDw+Cei3dSop4kuCZ+s15AZ27E6z0xDSvDI9R3kCpKR18IS+IBFMGn9SspajqoUt1A==; 24:eoFsv/gp9px1ho8Z337Dj/vNEJQGoOf+F6hzp+tLP5OzuRqtJD5EKJfqYadSGuzyBq1BtONhC83Jk5bUIuHwt6h5kzonoJhL3RcS19JAkIo=; 7:9mreV87Y9ZPUlxLDcHHAe4IdL5MHQYFR1RrnFbHFWGxZKH10+t/G0M4q3nSppG0aBtF/efKmvHxXh/VyRIQKzG83yYbpzLSLnvaeYxNpjIRYSMZ7nklWSWtNBimgasHfjDkX5Rdn9ZAwb/Ds86cL/7BEtcxaORE398qryERIQzBEkOwco+7ocrEMxxB/xPhq4hwsvQm7Uf4aCCBFiqpIC0gardgzpbczwWyg9JoLC1jPw2Xg1mTDoErCzJ2dUSusOUbF+2b6YqTlKQ8xENgB6g== SpamDiagnosticOutput: 1:99 SpamDiagnosticMetadata: NSPM X-Microsoft-Exchange-Diagnostics: 1; BL2PR03MB513; 20:upS4/KA0eOzm8aEF5z2gZ5d/fjarI+Ro6oeolNN5RlWWOUKMpdPwlimhT1kaewGCcaLNPAq1iK54xAWBWcD/OC0xwJHokoiEHY4vMuqKOkNwrKJL7ZEKNAcr6ft5e2el3cvGJ4tpj3qNsLW1xY6WVkLjzN+bHwNej14l7O+sqd8= X-OriginatorOrg: altera.com X-MS-Exchange-CrossTenant-OriginalArrivalTime: 24 Jun 2016 09:14:12.1882 (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: BL2PR03MB513 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: Giuseppe Cavallaro 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 - --- .../devicetree/bindings/net/socfpga-dwmac.txt | 19 ++ drivers/net/ethernet/stmicro/stmmac/Makefile | 2 +- drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c | 276 +++++++++++++++++++++ drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.h | 36 +++ .../net/ethernet/stmicro/stmmac/dwmac-socfpga.c | 149 +++++++++-- 5 files changed, 460 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..0ff76e8 100644 --- a/drivers/net/ethernet/stmicro/stmmac/Makefile +++ b/drivers/net/ethernet/stmicro/stmmac/Makefile @@ -11,7 +11,7 @@ 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-socfpga.o altr_tse_pcs.o obj-$(CONFIG_DWMAC_STI) += dwmac-sti.o obj-$(CONFIG_DWMAC_SUNXI) += dwmac-sunxi.o obj-$(CONFIG_DWMAC_GENERIC) += dwmac-generic.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..40bfaac --- /dev/null +++ b/drivers/net/ethernet/stmicro/stmmac/altr_tse_pcs.c @@ -0,0 +1,276 @@ +/* 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..5c9313e 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,22 @@ 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->stmmac_rst = devm_reset_control_get(dev, + STMMAC_RESOURCE_NAME); + if (IS_ERR(dwmac->stmmac_rst)) { + dev_info(dev, "Could not get reset control!\n"); + if (PTR_ERR(dwmac->stmmac_rst) == -EPROBE_DEFER) + return -EPROBE_DEFER; + dwmac->stmmac_rst = NULL; + } dwmac->interface = of_get_phy_mode(np); @@ -128,6 +157,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 +251,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 +292,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; }