From mboxrd@z Thu Jan 1 00:00:00 1970 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=66.163.190.146 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1794505167; b=LvKNFXYREqs2gr9Bolfng326WUZNVCLrWPrAio8tRIwccOgKbJn9z//LQULIhO5FgKnq TXllF9j1045RFmWXSi4a/uwwq0HOzo5ITu93TC8WkClVX7DjF+324QUF97cyp8Hs7YGm7 gEfgbD7Bm4c7cY1NFMRlKyyg005bhr1MFmanoufxbYXHk2TWL6B1syv+P3Lcay/RU3EHN LC0UC8wRloh8+JzgE2zTQbD1ZfhpkVCI/UNijNKt8cc2uHT9pkcx6BBY81gjS629NVga6 zDXOrcuI/YbWvvJQTNrovFMdyiGvpLgb3ml7QQWGZPfHd/2qRkfHYrl7ivR2K4p+fGg== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1794505167; h=DMARC-Filter:DKIM-Signature:X-SONIC-DKIM-SIGN:X-YMail-OSG:X-Sonic-MF: X-Sonic-ID:Received:Received:Message-ID:Date:MIME-Version:User-Agent: Subject:From:To:References:Content-Language:In-Reply-To:Content-Type: Content-Transfer-Encoding:X-Mailer; bh=nMPV84htfHw3HFCQ9vI42g100eUmTFSohndLYYTuQvM=; b=SkAIxBL+8zs27MpCSqTwQrQQDEHMAasXxPwq3awABxGXPGwGx3eU5DN1ZhZx2Qg9+AlV WIurkzzOtMWqtw0+7EC4UdWwdI9LGrANW/Qpf2FXPGKvsLlchJufkoetk4czGMPTIe0Gs vcCnJnP4En364qfNqTktVOxh/GeCuX8x+YFxX6ZZmz3yAF/tarU0NS2XA6aISSByHccH7 ye/JeGSgqEnlQy5fLCq4w1JL1wpw8DWy4xvi97/9o1ZCVnT/HFoN3DUU+SZSodnitTY/i E3TQfn3sBqjsaErI25ihxyjYjeyGSlbqDdIdARqOF4gzb3C/5u++9UQfCpcYjH+nz/A== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=yahoo.com; spf=pass smtp.mailfrom=yahoo.com; dkim=pass header.d=yahoo.com header.i=@yahoo.com header.a=rsa-sha256 header.s=s2048 header.b=tKJHyaZM; arc=none smtp.remote-ip=66.163.190.146 Received: from sonic315-20.consmr.mail.ne1.yahoo.com (sonic315-20.consmr.mail.ne1.yahoo.com [66.163.190.146]) (using TLSv1.3 with cipher TLS_AES_128_GCM_SHA256 (128/128 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 34B27606A8A3 for ; Thu, 12 Nov 2026 17:39:27 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 34B27606A8A3 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=reject dis=none) header.from=yahoo.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=yahoo.com Authentication-Results: smtp.subspace.kernel.org; dkim=pass (2048-bit key) header.d=yahoo.com header.i=@yahoo.com header.a=rsa-sha256 header.s=s2048 header.b=tKJHyaZM DKIM-Signature: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1794505166; bh=nMPV84htfHw3HFCQ9vI42g100eUmTFSohndLYYTuQvM=; h=Date:Subject:From:To:References:In-Reply-To:Content-Type:From:Subject:Reply-To:Content-Type; b=tKJHyaZMbvF/07uK/OR6NwDzM3/7Kw1Rp5BtLhjo/OR93pZGwvvPEX5w4d1RQIIumgQZwPuF/oF6MP9WZ0uLQg0EraymFTc2POtHCDelkSqMxRhpSyETIuq+oIa0pUrRatYr2EqLOYVAvhe3MxRp7DZ7BlJafsBkfNDeHrWf9hJ5FGRmgeBjouP4t3ypBCzVdqgyBRZcBtSkwMT5v6pE/vhJwqYLj3UqDPfxXjex0AfwazQ8CchZPtd4Z0yODh8RPpZyR2rm+0sPXsJoO4iJxrIsiW0qjT73MO6AvNom/fRI+UyvGPa/x/1EDSnzc7lx1y/Mkkd+aKrf/WHGaz9p+Q== X-SONIC-DKIM-SIGN: v=1; a=rsa-sha256; c=relaxed/relaxed; d=yahoo.com; s=s2048; t=1794505166; bh=VpcccfBCmJa8GEdy2CRows9FFlQfeJ0l1PDHWtNl0zF=; h=X-Sonic-MF:Date:Subject:From:To:From:Subject; b=WcThLJWgq6+ouUYDYpqFqApIvhrnAId5mb3AQq4vKbJPnAWWbIr8ACU1vLku1p7rCplG1iWegO3UQAVzfS+URgTThOwMFhTiwRp1IkUvXLZezDOE/sFRXKytUUqInbZHQd7prhewtP6FT2VQYuI2I0gX552dWhsZ24AE7FINsRkoe8NdWkFjPrloP9TUVlA4tD8Gmn4Btnkjuf7xfTcssCL79BRUu9IzexGHNY+x/c8yzKOOagO80aM33XxZ+QqCRNTZ086L8pXNXRBb9XgcKoeZobi35tyhwzkFZxbKfYI/6jjQTVwAKUxLgQsKHxQ3g7ZKxEr2xTOF2h4WAQyVQA== X-YMail-OSG: ZnUllf8VM1nc.zkQkmGog2iGNkkR.PxQuC.HF81rAnhsm2EgtH625dtSJbdD8PO e31326yKNPpizK36775_X4bObi895ho9ar5U4K0.0j_DlEzX3nR8npKw.DzldySvPRrIgnPyHdal ZWMrdEaB.7t93qF77g7GcTHGl30r46YI_XUJhzvqeLy84gbgfhtmRC6AvZAmGHqkEqTAN.z7khX_ wPke6Su0m4xZhTOKMQZFueHo6YEfCmKazrEQD5mNnRrR21dxtgnf5CJ5r5GUIziswUCVxgrkQMf9 _MtfpS2Uq_J4NGcFSvAXO8BJePX.j6GZeG_BhQGfma.dJ5P7MvCS1qAWGYo8xx7zBbMHGZlBySzP .QY501LSD9FvPw_h.gxwYUct7H4Yi7wM256mbqIdJ36aQGWxEbIpiilgqEnPexSokzBuUsq2tnE1 LpgWtt8WpOAqi5QeYDanBRMOg.FbFksA8Ckf3jeOS2E3_rF4fAKSet_bVWgLph4u_fKQRDsmH4af zNIb0PI2Jfe.VJ0o62wjvvU.6_BeS.1GwcfkahOoh5Z21pXwau7uWVAO2y6KYq2pagVeCXvg.A70 7nCCu9Bk3eMb9IsDVJlOKXb5tv.4lbiZU1RcmP9rJ7IN8QFOGCAL4DyPOaX40E5h9L_irfe2G4SZ IT8oK07wgKXw.sdhq.a5dmoBXjMeQ5xFB2o9f7XFSkfXdo5tfP7R5NZ2b1IVMYMJw6T0Ga.w6Plw NiIUnqX142.rehrw6eF3Kp9a9g7qcD8TbMfv8QjzdsdNaxQ5XIuz_64l6WA_ME40R.0Xh_nadnnm vawZ1YyAmiXVt8MnFhU_Mw05tNEe9jUdEyHmH3RF0L0gqhOKa60OTDFGveQ5eh8tHjmvPCWQ1oaq TuQ9l5y5whrN4VqKcfSHITbzzMiQH9kErbt.ddQywe1GzUjcoRiOrqvWpCoMEEnneETpV433PIGk l5Vthuf8h542ItO6NSGpnA45LaEPpUAifZtyJ5v3sqU7AaEBlS.EADs4Wf_IqhusadzsChlLDCud FUzfvt1GCh8Gwhq_BjuEnFxiYU_b9FZdyri8Ow.f022YfgxK2UZBscBnPvyUyGB.UEgXl6kw.azz CzdiGtq8zmrdc7fh8UdE8tjrZDPpdyzNZLjVOQJyB3yVA0Vt8L.BVDybXiOPt9ImdkBfUp4fSTgv Fg.h_2ifS4HNJ4TfyY3w_WorpagN7CrSdKatbCKzK61X95FrlFB3RRAR44OC04gp6bB5iQ4iD7ux 5hei1bqD3Y.vz_EsZoqWFO2s2sNsAvWCOCDdvCiw0NV7ri22Imo_0KZWaC3ooxTcMzVImnrWLDD9 UIZYHCPvE7oyDszn37Zqonj8Oyu802YAc5M5r4nnwLX.0.c8ZLSp03i4oHtGWLYluWweld82v7TS gPE7CWB_Bjry2UTvo4CxO90Kd3m9N.MOa_3YYgLxlDNAi25EXv8KGVaAgx_kUvKhEemVZOC3E1dO Teat_N5KjtyQN39OxUcaz2yrkMl78rxjHEHxGeXV0D3dw64_h3PyYxXqyapPwbNnQPp6LpswlM.7 eit4oqWwHwEOfvhea1m9BENknLDdYW6bgXdr55_sZij4rCN9lHUCHg5q_ll_v0nZPAo6rVI7O_er SGVeMMH7avNNQL1DLcy1oLG0_TRHOO8KSm.d59JF3Voi_V96tUaWLKIey5fhP4XIB4snIAPsYs22 ZfOp.eAY4sRjURwbaPW4pdRounHnlWCMYqyzUt1gT9RJn2CG1Y2ZczvkJLjGxoBfH0mAq7VHm.zb IV4vR1L2tdtjuEo96OC4V0YTrm6zYFlaWv4OniCdl0KMSs0DlNnF0DXN37dsJI_Yvn8FeR7TZkQQ jErLQr79toCRIah4Sg7bxChosZNbwSijXzheILj7vl4h2pGp_ZJS_6.tteT12.XjiG1QS9gJ3ujV 0WmGWi52Cc0oRVQKeDftb0_0gEPk6P3Mz1jnx89eHkEE9J2jxpOtIAZiultPsmA_DrRjCd_UKzm0 q05voqLdjf_r4OY.mnTKF0_lT_nC59LpfhuGOOA-- X-Sonic-MF: X-Sonic-ID: 8cd0fa28-3062-4cdf-a7a4-462dba1ecd53 Received: from sonic.gate.mail.ne1.yahoo.com by sonic315.consmr.mail.ne1.yahoo.com with HTTP; Thu, 12 Nov 2026 17:39:26 +0000 Received: by hermes--production-ir2-5dd9bf4598-9c455 (Yahoo Inc. Hermes SMTP Server) with ESMTPA ID 956c0be46d9874644bce18b762fef5a5; Thu, 12 Nov 2026 17:39:22 +0000 (UTC) Message-ID: <1545f0c7-b413-4fc7-9563-baeb808720c9@yahoo.com> Date: Thu, 12 Nov 2026 18:39:20 +0100 X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Post: List-Help: List-Subscribe: List-Unsubscribe: List-Owner: Precedence: list MIME-Version: 1.0 User-Agent: Mozilla Thunderbird Subject: [PATCH net-next v10 09/12] net: dsa: realtek: rtl8365mb: add family D SDS13 PCS support From: Mieczyslaw Nalewaj To: linusw@kernel.org, andrew@lunn.ch, olteanv@gmail.com, kuba@kernel.org, davem@davemloft.net, edumazet@google.com, pabeni@redhat.com, linux@armlinux.org.uk, luizluca@gmail.com, maxime.chevallier@bootlin.com, netdev@vger.kernel.org, linux-kernel@vger.kernel.org, alvin.sipraga@analog.com, gusfmora@gmail.com, kuncy7@gmail.com, fabianotassotti@gmail.com, gabonpivovich@gmail.com, contact@c127.dev References: Content-Language: pl In-Reply-To: Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 7bit X-Mailer: WebService/1.1.26943 mail.backend.jedi.jws.acl:role.jedi.acl.token.atz.jws.hermes.yahoo Extend the existing RTL8367S SGMII/HSGMII PCS implementation in this driver for family D switches, whose CPU SerDes is reached through the indexed SDS13 window and whose SDS_MISC fields differ from family C. The register sequence and tuning tables are derived from the GPL-licensed Realtek RTL8367D port API distributed in the Mercusys MR80X GPL release. Keep the existing family C path unchanged and select the new behavior from the driver's chip-family metadata, making the implementation reusable by other family D boards. This patch only prepares the family D paths; they become reachable when the RTL8367S-VB chip entry is added in the last patch. On family D rtl8365mb_sds_probe_option() does not read the family C option register and always sets sds_supported, so the port 6 rate limits are raised for every family D chip. The only family D chip in this series, the RTL8367S-VB, has a SerDes interface on port 6. Nothing on family D programs a SerDes rate for 10 and 100 Mbit/s: pcs_link_up() does nothing and the MAC force register only sets the MAC side. It is not known whether the SerDes follows that register, and only 1G SGMII and 2500base-x were tested, so do not advertise 10 and 100 Mbit/s on the SerDes port of family D. Tested-by: Gustavo Foletto Mora Tested-by: Stanislaw Pal Co-developed-by: Fabiano Tassotti Signed-off-by: Fabiano Tassotti Signed-off-by: Mieczyslaw Nalewaj Reviewed-by: Linus Walleij --- drivers/net/dsa/realtek/rtl8365mb_main.c | 257 ++++++++++++++++++----- 1 file changed, 199 insertions(+), 58 deletions(-) diff --git a/drivers/net/dsa/realtek/rtl8365mb_main.c b/drivers/net/dsa/realtek/rtl8365mb_main.c index a13a5e9..6f9c12f 100644 --- a/drivers/net/dsa/realtek/rtl8365mb_main.c +++ b/drivers/net/dsa/realtek/rtl8365mb_main.c @@ -264,7 +264,8 @@ * interface, indexed by the external port number with port 5 (the first * external port) as the base. Other RTL8367 families index this register * differently (e.g. the RTL8367R uses (id + 1) % 2), so this mapping only - * holds for the RTL8367C-style parts this driver supports. + * holds for the RTL8367C-style parts and for family D, where it is the same + * (one bit per external port, base port 5), as in the vendor RTL8367D API. */ #define RTL8365MB_BYPASS_LINE_RATE_REG 0x03F7 #define RTL8365MB_BYPASS_LINE_RATE_MASK(_port) BIT((_port) - 5) @@ -286,6 +287,7 @@ #define RTL8365MB_SDS_INDACS_CMD_BUSY_MASK BIT(8) #define RTL8365MB_SDS_INDACS_CMD_RUN_MASK BIT(7) #define RTL8365MB_SDS_INDACS_CMD_WR_MASK BIT(6) +#define RTL8365MB_SDS_INDACS_CMD_INDEX_MASK GENMASK(5, 0) #define RTL8365MB_SDS_INDACS_ADR_REG 0x6601 #define RTL8365MB_SDS_INDACS_DATA_REG 0x6602 @@ -315,8 +317,10 @@ #define RTL8365MB_SDS_REG_LINK_STATUS 0x003d #define RTL8365MB_SDS_LINK_STATUS_LINK_MASK BIT(4) -/* The embedded SerDes can only be muxed to external interface 1 (MAC8), - * which is port 6. +/* On family C the embedded SerDes can only be muxed to external interface + * 1 (MAC8), which is port 6. Family D has it on external interface 0 + * (MAC6), see RTL8365MB_D_SDS_EXT0_INDEX. RTL8365MB_SDS_EXT_INTERFACE_ID + * below is the family C id; the SerDes port is 6 on both families. */ #define RTL8365MB_SDS_EXT_INTERFACE_ID 1 #define RTL8365MB_SDS_EXT_INTERFACE_PORT 6 @@ -334,7 +338,22 @@ #define RTL8365MB_SDS_OPTION_ARM_KEY 0x0249 #define RTL8365MB_SDS_OPTION_REG 0x13C1 +/* Family D uses the SDS13 indirect window for its MAC6 SerDes. */ +#define RTL8365MB_D_SDS_EXT0_INDEX 13 +#define RTL8365MB_D_FIBER_CFG2_REG 0x13E8 +#define RTL8365MB_D_FIBER_CFG2_RX_DISABLE_MASK GENMASK(7, 6) +#define RTL8365MB_D_FIBER_CFG2_RX_DISABLE_SDS0 BIT(6) +#define RTL8365MB_D_SDS_MISC_PA33PC_EN BIT(11) +#define RTL8365MB_D_SDS_MISC_PA12PC_EN BIT(10) +#define RTL8365MB_D_SDS_MISC_MAC6_SEL_SDS0 BIT(9) #define RTL8365MB_D_SDS_MISC_MODE_FIELD_MASK GENMASK(4, 0) +#define RTL8365MB_D_SDS_MISC_MODE_SGMII 0x02 +#define RTL8365MB_D_SDS_MISC_MODE_HSGMII 0x12 +#define RTL8365MB_D_SDS_MISC_CFG_MASK \ + (RTL8365MB_D_SDS_MISC_PA33PC_EN | \ + RTL8365MB_D_SDS_MISC_PA12PC_EN | \ + RTL8365MB_D_SDS_MISC_MAC6_SEL_SDS0 | \ + RTL8365MB_D_SDS_MISC_MODE_FIELD_MASK) /* Shared "disable" encoding for both SDS_MISC's and SDS1_MISC0's * 5-bit mode fields. */ @@ -721,6 +740,21 @@ static const struct rtl8365mb_jam_tbl_entry rtl8365mb_sds_jam_hsgmii[] = { { 0x0424, 0xD810 }, { 0x0001, 0x0F80 }, { 0x002E, 0x83F2 }, }; +/* Family D tuning tables from the Realtek vendor port API. */ +static const struct rtl8365mb_jam_tbl_entry rtl8365mb_d_sds_jam_sgmii[] = { + { 0x0427, 0x4E0C }, { 0x0428, 0xAA00 }, { 0x0425, 0x5189 }, + { 0x0424, 0x8414 }, { 0x0423, 0x1020 }, { 0x0410, 0x0002 }, + { 0x0484, 0x011B }, { 0x0421, 0x8E13 }, { 0x0422, 0x1140 }, + { 0x0004, 0x074F }, +}; + +static const struct rtl8365mb_jam_tbl_entry rtl8365mb_d_sds_jam_hsgmii[] = { + { 0x0427, 0x4E0C }, { 0x0428, 0xAA00 }, { 0x0425, 0x5189 }, + { 0x0424, 0x8414 }, { 0x0423, 0x1020 }, { 0x0410, 0x0002 }, + { 0x0504, 0x051B }, { 0x0421, 0x8E13 }, { 0x0422, 0x1140 }, + { 0x0004, 0x074F }, +}; + enum rtl8365mb_phy_interface_mode { RTL8365MB_PHY_INTERFACE_MODE_INVAL = 0, RTL8365MB_PHY_INTERFACE_MODE_INTERNAL = BIT(0), @@ -909,8 +943,9 @@ struct rtl8365mb_port { * @mib_lock: prevent concurrent reads of MIB counters * @ports: per-port data * @pcs: PCS for the SerDes external interface - * @sds_supported: SerDes tuning parameters match the chip option, so the - * SerDes interface modes can be advertised + * @sds_supported: SerDes interface modes can be advertised: the tuning + * parameters match the chip option (family C), or the chip + * is family D, which does not use the option * * Private data for this driver. */ @@ -1323,7 +1358,8 @@ static int rtl8365mb_ext_config_rgmii(struct realtek_priv *priv, int port, return 0; } -static int rtl8365mb_sds_write(struct realtek_priv *priv, u16 addr, u16 data) +static int rtl8365mb_sds_write(struct realtek_priv *priv, u8 index, + u16 addr, u16 data) { int ret; @@ -1341,10 +1377,13 @@ static int rtl8365mb_sds_write(struct realtek_priv *priv, u16 addr, u16 data) */ return regmap_write(priv->map, RTL8365MB_SDS_INDACS_CMD_REG, RTL8365MB_SDS_INDACS_CMD_RUN_MASK | - RTL8365MB_SDS_INDACS_CMD_WR_MASK); + RTL8365MB_SDS_INDACS_CMD_WR_MASK | + FIELD_PREP(RTL8365MB_SDS_INDACS_CMD_INDEX_MASK, + index)); } -static int rtl8365mb_sds_read(struct realtek_priv *priv, u16 addr, u16 *data) +static int rtl8365mb_sds_read(struct realtek_priv *priv, u8 index, + u16 addr, u16 *data) { u32 val; int ret; @@ -1354,7 +1393,9 @@ static int rtl8365mb_sds_read(struct realtek_priv *priv, u16 addr, u16 *data) return ret; ret = regmap_write(priv->map, RTL8365MB_SDS_INDACS_CMD_REG, - RTL8365MB_SDS_INDACS_CMD_RUN_MASK); + RTL8365MB_SDS_INDACS_CMD_RUN_MASK | + FIELD_PREP(RTL8365MB_SDS_INDACS_CMD_INDEX_MASK, + index)); if (ret) return ret; @@ -1394,6 +1435,14 @@ static int rtl8365mb_sds_probe_option(struct realtek_priv *priv) int ret; int i; + /* Family D has a fixed SDS13 programming model and does not use the + * family C option register to select its tuning table. + */ + if (rtl8365mb_is_d(priv)) { + mb->sds_supported = true; + return 0; + } + /* Nothing to probe if no external interface is wired to the SerDes */ for (i = 0; i < RTL8365MB_MAX_NUM_EXTINTS; i++) { extint = &mb->chip_info->extints[i]; @@ -1475,25 +1524,44 @@ static int rtl8365mb_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, const struct rtl8365mb_jam_tbl_entry *sds_jam; const int id = RTL8365MB_SDS_EXT_INTERFACE_ID; struct rtl8365mb *mb = pcs_to_rtl8365mb(pcs); - struct realtek_priv *priv; + struct realtek_priv *priv = mb->priv; size_t sds_jam_size; - u32 mode; + u32 misc_mask; + u32 misc_val; + u32 sds_mode; + u8 sds_index; + bool is_d; u16 val; int ret; int i; - priv = mb->priv; + is_d = rtl8365mb_is_d(priv); + /* Select the appropriate tuning table and SDS mode */ if (interface == PHY_INTERFACE_MODE_2500BASEX) { - sds_jam = rtl8365mb_sds_jam_hsgmii; - sds_jam_size = ARRAY_SIZE(rtl8365mb_sds_jam_hsgmii); - mode = RTL8365MB_EXT_PORT_MODE_HSGMII; + if (is_d) { + sds_jam = rtl8365mb_d_sds_jam_hsgmii; + sds_jam_size = ARRAY_SIZE(rtl8365mb_d_sds_jam_hsgmii); + sds_mode = RTL8365MB_D_SDS_MISC_MODE_HSGMII; + } else { + sds_jam = rtl8365mb_sds_jam_hsgmii; + sds_jam_size = ARRAY_SIZE(rtl8365mb_sds_jam_hsgmii); + sds_mode = RTL8365MB_EXT_PORT_MODE_HSGMII; + } } else { - sds_jam = rtl8365mb_sds_jam_sgmii; - sds_jam_size = ARRAY_SIZE(rtl8365mb_sds_jam_sgmii); - mode = RTL8365MB_EXT_PORT_MODE_SGMII; + if (is_d) { + sds_jam = rtl8365mb_d_sds_jam_sgmii; + sds_jam_size = ARRAY_SIZE(rtl8365mb_d_sds_jam_sgmii); + sds_mode = RTL8365MB_D_SDS_MISC_MODE_SGMII; + } else { + sds_jam = rtl8365mb_sds_jam_sgmii; + sds_jam_size = ARRAY_SIZE(rtl8365mb_sds_jam_sgmii); + sds_mode = RTL8365MB_EXT_PORT_MODE_SGMII; + } } + sds_index = is_d ? RTL8365MB_D_SDS_EXT0_INDEX : 0; + /* Hold the embedded DW8051 microcontroller in reset and keep it * disabled. The vendor driver loads firmware into it to manage the * SerDes link, but the firmware only duplicates work that phylink @@ -1522,34 +1590,58 @@ static int rtl8365mb_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, /* Tune the SerDes with vendor-prescribed parameters */ for (i = 0; i < sds_jam_size; i++) { - ret = rtl8365mb_sds_write(priv, sds_jam[i].reg, - sds_jam[i].val); + ret = rtl8365mb_sds_write(priv, sds_index, + sds_jam[i].reg, sds_jam[i].val); if (ret) return ret; } - /* Mux the SerDes to MAC8 in the requested mode */ + /* Family-specific post-tuning configuration */ + if (is_d) { + /* The register and field names follow the vendor RTL8367D API, + * whose SDS numbering differs from the SDS13 window used + * here. As in the vendor sequence the whole 2-bit field + * (bits 7:6) is written, so bit 7 is cleared as well. + */ + ret = regmap_update_bits(priv->map, RTL8365MB_D_FIBER_CFG2_REG, + RTL8365MB_D_FIBER_CFG2_RX_DISABLE_MASK, + RTL8365MB_D_FIBER_CFG2_RX_DISABLE_SDS0); + if (ret) + return ret; + + misc_mask = RTL8365MB_D_SDS_MISC_CFG_MASK; + misc_val = RTL8365MB_D_SDS_MISC_PA33PC_EN | + RTL8365MB_D_SDS_MISC_PA12PC_EN | + RTL8365MB_D_SDS_MISC_MAC6_SEL_SDS0 | sds_mode; + } else { + /* Mux the SerDes to MAC8 in the requested mode */ + misc_mask = RTL8365MB_SDS_MISC_MAC8_SEL_SGMII_MASK | + RTL8365MB_SDS_MISC_MAC8_SEL_HSGMII_MASK; + misc_val = (sds_mode == RTL8365MB_EXT_PORT_MODE_SGMII) ? + RTL8365MB_SDS_MISC_MAC8_SEL_SGMII_MASK : + RTL8365MB_SDS_MISC_MAC8_SEL_HSGMII_MASK; + } + ret = regmap_update_bits(priv->map, RTL8365MB_SDS_MISC_REG, - RTL8365MB_SDS_MISC_MAC8_SEL_SGMII_MASK | - RTL8365MB_SDS_MISC_MAC8_SEL_HSGMII_MASK, - mode == RTL8365MB_EXT_PORT_MODE_SGMII ? - RTL8365MB_SDS_MISC_MAC8_SEL_SGMII_MASK : - RTL8365MB_SDS_MISC_MAC8_SEL_HSGMII_MASK); + misc_mask, misc_val); if (ret) return ret; - val = mode << RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_OFFSET(id); - ret = regmap_update_bits(priv->map, - RTL8365MB_DIGITAL_INTERFACE_SELECT_REG(id), - RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_MASK(id), - val); - if (ret) - return ret; + if (!is_d) { + val = sds_mode << RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_OFFSET(id); + ret = regmap_update_bits(priv->map, + RTL8365MB_DIGITAL_INTERFACE_SELECT_REG(id), + RTL8365MB_DIGITAL_INTERFACE_SELECT_MODE_MASK(id), + val); + if (ret) + return ret; + } /* Take the SerDes out of reset. The vendor driver does this only * after the SerDes mux and the interface mode are configured. */ - ret = rtl8365mb_sds_write(priv, RTL8365MB_SDS_REG_RESET, + ret = rtl8365mb_sds_write(priv, sds_index, + RTL8365MB_SDS_REG_RESET, RTL8365MB_SDS_RESET_DEASSERT); if (ret) return ret; @@ -1559,27 +1651,32 @@ static int rtl8365mb_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mode, * This flushes the FIFOs and ensures a clean state for the link, * preventing silent drops and CRC errors. */ - ret = rtl8365mb_sds_write(priv, RTL8365MB_SDS_REG_BMCR, + ret = rtl8365mb_sds_write(priv, sds_index, + RTL8365MB_SDS_REG_BMCR, RTL8365MB_SDS_BMCR_DPRST_PHASE1); if (ret) return ret; - ret = rtl8365mb_sds_write(priv, RTL8365MB_SDS_REG_BMCR, + ret = rtl8365mb_sds_write(priv, sds_index, + RTL8365MB_SDS_REG_BMCR, RTL8365MB_SDS_BMCR_DPRST_PHASE2); if (ret) return ret; /* Keep SGMII in-band autonegotiation disabled: the link parameters are - * forced from rtl8365mb_pcs_link_up() instead. + * forced from rtl8365mb_pcs_link_up() instead (family C), or from + * mac_link_up() (family D). */ - ret = rtl8365mb_sds_read(priv, RTL8365MB_SDS_REG_NWAY, &val); + ret = rtl8365mb_sds_read(priv, sds_index, + RTL8365MB_SDS_REG_NWAY, &val); if (ret) return ret; val &= ~RTL8365MB_SDS_NWAY_EN_MASK; val |= RTL8365MB_SDS_NWAY_RESTART_MASK; - return rtl8365mb_sds_write(priv, RTL8365MB_SDS_REG_NWAY, val); + return rtl8365mb_sds_write(priv, sds_index, + RTL8365MB_SDS_REG_NWAY, val); } static bool rtl8365mb_interface_is_serdes(phy_interface_t interface) @@ -1604,18 +1701,27 @@ static void rtl8365mb_pcs_get_state(struct phylink_pcs *pcs, { struct rtl8365mb *mb = pcs_to_rtl8365mb(pcs); struct realtek_priv *priv = mb->priv; + u8 sds_index = 0; u16 status; + bool is_d; u32 val; int ret; - /* In-band autonegotiation is not implemented, so the link parameters are - * forced from rtl8365mb_pcs_link_up(). The real link state must still be - * read from the SerDes itself: the embedded DW8051 microcontroller that + is_d = rtl8365mb_is_d(priv); + + /* In-band autonegotiation is not implemented, so the link parameters + * are forced from rtl8365mb_pcs_link_up() on family C, and from + * mac_link_up() on family D. The real link state must still be read + * from the SerDes itself: the embedded DW8051 microcontroller that * the vendor firmware uses to poll the SerDes is kept disabled (see * rtl8365mb_pcs_config()), so the link status register can be read * directly through the SDS_INDACS window without racing the auto-poll. */ - ret = rtl8365mb_sds_read(priv, RTL8365MB_SDS_REG_LINK_STATUS, &status); + if (is_d) + sds_index = RTL8365MB_D_SDS_EXT0_INDEX; + + ret = rtl8365mb_sds_read(priv, sds_index, + RTL8365MB_SDS_REG_LINK_STATUS, &status); if (ret) { state->link = false; return; @@ -1626,6 +1732,23 @@ static void rtl8365mb_pcs_get_state(struct phylink_pcs *pcs, if (!state->link) return; + if (is_d) { + if (state->interface == PHY_INTERFACE_MODE_2500BASEX) { + state->duplex = DUPLEX_FULL; + state->speed = SPEED_2500; + } else { + /* Keep what phylink passed in, but never report the + * link up with an unknown speed: mac_link_up() cannot + * force the port with it. + */ + if (state->speed == SPEED_UNKNOWN) + state->speed = SPEED_1000; + if (state->duplex == DUPLEX_UNKNOWN) + state->duplex = DUPLEX_FULL; + } + return; + } + /* The speed and duplex are forced; read them back from the values * programmed into the SerDes MISC register. */ @@ -1667,6 +1790,12 @@ static void rtl8365mb_pcs_link_up(struct phylink_pcs *pcs, u32 r_speed; int ret; + /* Family D forces the external MAC ability from mac_link_up(); its + * SDS_MISC fields do not share the family C link-force layout. + */ + if (rtl8365mb_is_d(priv)) + return; + /* The speed field has no value for 2.5 Gbps: the rate is determined by * the HSGMII SerDes configuration, and the vendor driver programs the * 1 Gbps value here. @@ -1931,10 +2060,17 @@ static void rtl8365mb_phylink_get_caps(struct dsa_switch *ds, int port, } if (extint->supported_interfaces & RTL8365MB_PHY_INTERFACE_MODE_SGMII && - mb->sds_supported) + mb->sds_supported) { __set_bit(PHY_INTERFACE_MODE_SGMII, config->supported_interfaces); + /* The SerDes rate is not programmed for 10 and 100 Mbit/s on + * family D, see rtl8365mb_pcs_link_up(). + */ + if (rtl8365mb_is_d(priv)) + config->mac_capabilities &= ~(MAC_10 | MAC_100); + } + if (extint->supported_interfaces & RTL8365MB_PHY_INTERFACE_MODE_HSGMII && mb->sds_supported) { __set_bit(PHY_INTERFACE_MODE_2500BASEX, @@ -2013,7 +2149,7 @@ static void rtl8365mb_phylink_mac_link_down(struct phylink_config *config, /* phylink has no pcs_link_down callback, so on the SerDes path only the * MAC external interface force is reset here. Clearing the MAC force is * enough to bring the link down; the SerDes keeps presenting its last - * forced state until the next pcs_link_up() reprograms it. + * forced state (family C) until the next pcs_link_up() reprograms it. */ if (phy_interface_mode_is_rgmii(interface) || rtl8365mb_interface_is_serdes(interface)) { @@ -2048,9 +2184,11 @@ static void rtl8365mb_phylink_mac_link_up(struct phylink_config *config, p = &mb->ports[port]; schedule_delayed_work(&p->mib_work, 0); - /* The SerDes forced link state is programmed by the PCS in + /* On family C the SerDes forced link state is programmed by the PCS in * rtl8365mb_pcs_link_up(); here only the MAC external interface force - * is configured, for both RGMII and SerDes. + * is configured. On family D pcs_link_up() does nothing, and the MAC + * external interface force is the only forced link state, for both + * RGMII and SerDes. */ if (phy_interface_mode_is_rgmii(interface) || rtl8365mb_interface_is_serdes(interface)) { @@ -2063,18 +2201,21 @@ static void rtl8365mb_phylink_mac_link_up(struct phylink_config *config, return; } - /* The SerDes has its own pause enables; program them from - * the resolved pause modes, as the vendor driver does when - * forcing the link on a SerDes external interface. These - * bits, not the MAC force pause bits, gate pause on the - * SerDes external interface: flow control testing shows - * that pause frames are only emitted with the SerDes TXFC - * bit set, while the MAC force pause bits alone have no - * effect on this port. This is done here rather than in - * rtl8365mb_pcs_link_up() because pcs_link_up() carries no - * pause information. + /* Family C: the SerDes has its own pause enables; program + * them from the resolved pause modes, as the vendor driver + * does when forcing the link on a SerDes external + * interface. These bits, not the MAC force pause bits, gate + * pause on the SerDes external interface: flow control + * testing shows that pause frames are only emitted with the + * SerDes TXFC bit set, while the MAC force pause bits alone + * have no effect on this port. This is done here rather + * than in rtl8365mb_pcs_link_up() because pcs_link_up() + * carries no pause information. Family D does not use this + * path: its pause bits are set in the forced-mode register + * by rtl8365mb_d_ext_config_forcemode(). */ - if (rtl8365mb_interface_is_serdes(interface)) { + if (rtl8365mb_interface_is_serdes(interface) && + !rtl8365mb_is_d(priv)) { u32 val = 0; if (tx_pause) -- 2.53.0