From nobody Thu Nov 5 05:11:45 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=115.124.28.217 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793848502; b=CYZTy3k2PvTAlbBv7Xm8OsYoxR5IXK77Pp9SGIH7ctTnnD/s1ozCkhzbIOuqGwv4e8lN TNe62Ln9DPzL/6hccF2dBzd8l2YpCQr1N/mSeL1nMOjeCrCXsdsTzUjoaH0eZVBBjCP7d UGFml8kwzyj8uRd+c7vTByE4b/WdOoWU7Q0y2Om2EMXrSVYkH78Z1+J9i0VLjdTqGJIV3 HI/641EsWltX1ZaVO4e+WXV3CByHBl5oHsYoq80CHwSdEdrk2aVjpvcuDX3UIFwTFaL1M e5u6OGqwHlO8EkjCz5rqFcCCHl3fX1xVX9UQB1JMkwtgfJOd3Th7G3QX2n+MmKz6ZQg== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793848502; h=DMARC-Filter:X-Alimail-AntiSpam:Received:From:To:Cc:Subject:Date: Message-Id:X-Mailer:In-Reply-To:References:MIME-Version: Content-Transfer-Encoding; bh=x9iSpbhGIj8JBA245J5cxgtHj7UMy2YV69ktT0NZPQU=; b=I39g6h19ueFGtb+CiPeXprTol6q7CrPje33m1rlJxHHY9o9Aa3GdGN4gaE3RWbI57fP9 0Mq009LtVCBfrzpnI7aWVYgyrUBX38CI/83dc+Tvv5TEy7pkcgEewpQKz3qkcyZIP80rl 1rPSiahXWdj1TwVivytmb+AoTZD2SzjqWXDtLHaArifVNEf+fHI2q/8oRH+uiHsxrWy8n VszqQzBLlsa0M4uy4rxnSIsRv7rOwG0DL6wouHbWOMbMAo5YDHLTgjBVG+tnY1yW60Qo3 Dyg5xcxt+59LFVE0cUTOJwzr93HeGNX4GeJO5LmA+vpc1Jrnjc6DLC4D6aqfkzLBbEg== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=motor-comm.com; spf=pass smtp.mailfrom=motor-comm.com; arc=none smtp.remote-ip=115.124.28.217 Received: from out28-217.mail.aliyun.com (out28-217.mail.aliyun.com [115.124.28.217]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 91EA8606A329; Thu, 5 Nov 2026 03:15:00 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 91EA8606A329 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=motor-comm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=motor-comm.com X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07452728|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.138644-0.000463989-0.860892;FP=13861984445566424724|0|0|0|0|-1|-1|-1;HT=maildocker-contentspam033037071049;MF=kyle.switch@motor-comm.com;NM=1;PH=DS;RN=16;RT=16;SR=0;TI=SMTPD_---.jx7-i05_1793848490; Received: from motor-comm.com(mailfrom:kyle.switch@motor-comm.com fp:SMTPD_---.jx7-i05_1793848490 cluster:ay29) by smtp.aliyun-inc.com; Thu, 05 Nov 2026 11:14:50 +0800 From: Kyle Switch To: andrew@lunn.ch, olteanv@gmail.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mmyangfl@gmail.com, horms@kernel.org, linux@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ming.xu@motor-comm.com, xiaolin.xu@motor-comm.com, jianmin.wang@motor-comm.com, wei.zhang@gl-inet.com, sijia.huang@gl-inet.com Subject: [PATCH net-next v17 1/5] net: dsa: motorcomm: initialize dsa_switch based on chipid Date: Thu, 5 Nov 2026 11:14:38 +0800 Message-Id: <20261105031442.4164960-2-kyle.switch@motor-comm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20261105031442.4164960-1-kyle.switch@motor-comm.com> References: <20261105031442.4164960-1-kyle.switch@motor-comm.com> 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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Replace the hardcoded chip handling in yt92xx_register_switch() with a data-driven loopup based on the chip ID. Reviewed-by: Andrew Lunn Signed-off-by: Kyle Switch --- drivers/net/dsa/motorcomm/chip.c | 73 ++++++++++++++++++++++++++++---- drivers/net/dsa/motorcomm/chip.h | 19 +++++++++ 2 files changed, 84 insertions(+), 8 deletions(-) diff --git a/drivers/net/dsa/motorcomm/chip.c b/drivers/net/dsa/motorcomm/c= hip.c index 33e5fc127244..2dd4240ee246 100644 --- a/drivers/net/dsa/motorcomm/chip.c +++ b/drivers/net/dsa/motorcomm/chip.c @@ -2574,6 +2574,67 @@ static const struct dsa_switch_ops yt921x_dsa_switch= _ops =3D { .setup =3D yt921x_dsa_setup, }; =20 +static const struct yt92xx_series yt92xx_series_table[] =3D { + [YT92XX_MODE_YT921X] =3D { + .name =3D "YT921x", + .max_ports =3D YT921X_PORT_NUM, + .num_lag_ids =3D YT921X_LAG_NUM, + .ageing_time_min =3D 1 * 5000, + .ageing_time_max =3D U16_MAX * 5000, + .dscp_prio_mapping_is_global =3D true, + .assisted_learning_on_cpu_port =3D true, + .switch_ops =3D &yt921x_dsa_switch_ops, + .mac_ops =3D &yt921x_phylink_mac_ops + }, +}; + +static const struct yt92xx_series *yt92xx_series_lookup(u32 major) +{ + if (major =3D=3D YT9215_MAJOR || major =3D=3D YT9218_MAJOR) + return &yt92xx_series_table[YT92XX_MODE_YT921X]; + else + return NULL; +} + +static int yt92xx_register_switch(struct dsa_switch *ds) +{ + struct yt921x_priv *priv =3D dsa_to_yt921x_priv(ds); + struct device *dev =3D yt921x_priv_to_device(priv); + const struct yt92xx_series *series; + u32 chipid; + u32 major; + int res; + + mutex_lock(&priv->reg_lock); + res =3D yt921x_reg_read(priv, YT921X_CHIP_ID, &chipid); + mutex_unlock(&priv->reg_lock); + if (res) { + dev_err(dev, "Unexpected chipid 0x%x\n", chipid); + return res; + } + + major =3D FIELD_GET(YT921X_CHIP_ID_MAJOR, chipid); + series =3D yt92xx_series_lookup(major); + if (!series) { + dev_err(dev, "Undefined series info for the corresponding major\n"); + return -ENODEV; + } + priv->series =3D series; + + ds->assisted_learning_on_cpu_port =3D + priv->series->assisted_learning_on_cpu_port; + ds->dscp_prio_mapping_is_global =3D + priv->series->dscp_prio_mapping_is_global; + ds->ageing_time_min =3D priv->series->ageing_time_min; + ds->ageing_time_max =3D priv->series->ageing_time_max; + ds->num_lag_ids =3D priv->series->num_lag_ids; + ds->num_ports =3D priv->series->max_ports; + ds->ops =3D priv->series->switch_ops; + ds->phylink_mac_ops =3D priv->series->mac_ops; + + return 0; +} + static void yt921x_mdio_shutdown(struct mdio_device *mdiodev) { struct yt921x_priv *priv =3D mdiodev_get_drvdata(mdiodev); @@ -2616,6 +2677,7 @@ static int yt921x_mdio_probe(struct mdio_device *mdio= dev) struct yt921x_reg_mdio *mdio; struct yt921x_priv *priv; struct dsa_switch *ds; + int res; =20 priv =3D devm_kzalloc(dev, sizeof(*priv), GFP_KERNEL); if (!priv) @@ -2642,15 +2704,10 @@ static int yt921x_mdio_probe(struct mdio_device *md= iodev) =20 ds =3D &priv->ds; ds->dev =3D dev; - ds->assisted_learning_on_cpu_port =3D true; - ds->dscp_prio_mapping_is_global =3D true; ds->priv =3D priv; - ds->ops =3D &yt921x_dsa_switch_ops; - ds->ageing_time_min =3D 1 * 5000; - ds->ageing_time_max =3D U16_MAX * 5000; - ds->phylink_mac_ops =3D &yt921x_phylink_mac_ops; - ds->num_lag_ids =3D YT921X_LAG_NUM; - ds->num_ports =3D YT921X_PORT_NUM; + res =3D yt92xx_register_switch(ds); + if (res) + return res; =20 mdiodev_set_drvdata(mdiodev, priv); =20 diff --git a/drivers/net/dsa/motorcomm/chip.h b/drivers/net/dsa/motorcomm/c= hip.h index fc315f1d8f87..fd6a0021e98e 100644 --- a/drivers/net/dsa/motorcomm/chip.h +++ b/drivers/net/dsa/motorcomm/chip.h @@ -503,9 +503,28 @@ static inline u16 yt921x_info_ports_mask(const struct = yt921x_info *info) return info->internal_mask | info->xmii_mask | info->serdes_mask; } =20 +enum yt92xx_mode { + YT92XX_MODE_YT921X, + YT92XX_MODE_YT922X, + YT92XX_MODE_MAX, +}; + +struct yt92xx_series { + const char *name; + unsigned int max_ports; + unsigned int num_lag_ids; + unsigned int ageing_time_min; + unsigned int ageing_time_max; + u32 dscp_prio_mapping_is_global; + u32 assisted_learning_on_cpu_port; + const struct dsa_switch_ops *switch_ops; + const struct phylink_mac_ops *mac_ops; +}; + struct yt921x_priv { struct dsa_switch ds; =20 + const struct yt92xx_series *series; const struct yt921x_info *info; unsigned int meter_slot_ns; unsigned int port_shape_slot_ns; --=20 2.25.1 From nobody Thu Nov 5 05:11:45 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=115.124.28.172 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793848499; b=iIwPe8E20LaaAejyrlWJyMk9BE4GLf703f+WkRnNtcOpDGLv7nPqOEmrnDIO6NMqrBBA Bzxelatm6oj2WjWs5jfKKtjEhtNku6P/6RM2VQ8X/T1fiuPh3EjShkxmgDcnkJGYz2rw2 zVifjyWLxpAuXQYHVunQSrTuMcO9SMfR8u6uy1Tz1JDdp147PazgpkXDF/96LUerV245j X8fTMRfkoSe3Rp0TXcal2yo3AS7N57S5Rb0IU50Wpwl/HDAdvpgUHyIPMWzcKZ0qDwj+g 61bPr16bEevwdSBwSxaTWELdnirqT2LI5Z2UIUp50qxj31bJWBzY2Lp7Juy9SLD5gug== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793848499; h=DMARC-Filter:X-Alimail-AntiSpam:Received:From:To:Cc:Subject:Date: Message-Id:X-Mailer:In-Reply-To:References:MIME-Version: Content-Transfer-Encoding; bh=zOO21uz9MwUO2eNDkgr3BLnA+IJI4wMV/UkAs/11CkE=; b=2PC0uORXBjf/nmTif4J2LHHIrJ+TLqoPXyJjxPfbuxX35dvr/Fp/YyQwtUn+jvqMQYOP 1xHnr4AD64r9NxXjLQEe4S4NaymheZ9t8xwDybfEET1uoKQKGKDr2GVMkS29Wc0jzhdLu WhnDcA9OUzJnsGv+Bb9RncWyrgw+BzjF76keO6eQhiyTvtGi9t4PMT1OR56KoUYFQ37aC dHIG18A8ewlc27bO+u3IsT/rOK/CzFukncnEo56iWIRnBtF+sP5ueHcXVhFV5Sy6LykZF MydqB1I/PWiDoLP2ymFaWXOF3LUAj0NcEK6KpiWaGO766ZWscqT3r7o5B8fmFJSKpOg== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=motor-comm.com; spf=pass smtp.mailfrom=motor-comm.com; arc=none smtp.remote-ip=115.124.28.172 Received: from out28-172.mail.aliyun.com (out28-172.mail.aliyun.com [115.124.28.172]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D2C1A606A32E; Thu, 5 Nov 2026 03:14:55 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org D2C1A606A32E Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=motor-comm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=motor-comm.com X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07852332|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.00587506-7.46963e-05-0.99405;FP=11562893469595389074|0|0|0|0|-1|-1|-1;HT=maildocker-contentspam033071099199;MF=kyle.switch@motor-comm.com;NM=1;PH=DS;RN=16;RT=16;SR=0;TI=SMTPD_---.jx7-i0o_1793848491; Received: from motor-comm.com(mailfrom:kyle.switch@motor-comm.com fp:SMTPD_---.jx7-i0o_1793848491 cluster:ay29) by smtp.aliyun-inc.com; Thu, 05 Nov 2026 11:14:51 +0800 From: Kyle Switch To: andrew@lunn.ch, olteanv@gmail.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mmyangfl@gmail.com, horms@kernel.org, linux@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ming.xu@motor-comm.com, xiaolin.xu@motor-comm.com, jianmin.wang@motor-comm.com, wei.zhang@gl-inet.com, sijia.huang@gl-inet.com Subject: [PATCH net-next v17 2/5] net: dsa: motorcomm: use max_ports in series for port bounds checking Date: Thu, 5 Nov 2026 11:14:39 +0800 Message-Id: <20261105031442.4164960-3-kyle.switch@motor-comm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20261105031442.4164960-1-kyle.switch@motor-comm.com> References: <20261105031442.4164960-1-kyle.switch@motor-comm.com> 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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Replace the hardcoded YT921X_PORT_NUM macro with the per-series max_ports field in port validation. This removes family-specific constants from the common code path and simplifies adding new switch families with different port counts. No functional change for existing YT921X devices. Reviewed-by: Andrew Lunn Signed-off-by: Kyle Switch --- drivers/net/dsa/motorcomm/mdio_bus.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/dsa/motorcomm/mdio_bus.c b/drivers/net/dsa/motorco= mm/mdio_bus.c index dd6c52f37bbf..83f0212551ff 100644 --- a/drivers/net/dsa/motorcomm/mdio_bus.c +++ b/drivers/net/dsa/motorcomm/mdio_bus.c @@ -113,7 +113,7 @@ static int yt921x_mbus_int_read(struct mii_bus *mbus, i= nt port, int reg) u16 val; int res; =20 - if (port >=3D YT921X_PORT_NUM) + if (port >=3D priv->series->max_ports) return U16_MAX; =20 mutex_lock(&priv->reg_lock); @@ -131,7 +131,7 @@ yt921x_mbus_int_write(struct mii_bus *mbus, int port, i= nt reg, u16 data) struct yt921x_priv *priv =3D mbus->priv; int res; =20 - if (port >=3D YT921X_PORT_NUM) + if (port >=3D priv->series->max_ports) return -ENODEV; =20 mutex_lock(&priv->reg_lock); @@ -145,6 +145,7 @@ int yt921x_mbus_int_init(struct yt921x_priv *priv, stru= ct device_node *mnp) { struct device *dev =3D yt921x_priv_to_device(priv); struct mii_bus *mbus; + u32 max_ports; int res; =20 mbus =3D devm_mdiobus_alloc(dev); @@ -157,7 +158,8 @@ int yt921x_mbus_int_init(struct yt921x_priv *priv, stru= ct device_node *mnp) mbus->read =3D yt921x_mbus_int_read; mbus->write =3D yt921x_mbus_int_write; mbus->parent =3D dev; - mbus->phy_mask =3D (u32)~GENMASK(YT921X_PORT_NUM - 1, 0); + max_ports =3D priv->series->max_ports; + mbus->phy_mask =3D (u32)~GENMASK(max_ports - 1, 0); =20 res =3D devm_of_mdiobus_register(dev, mbus, mnp); if (res) --=20 2.25.1 From nobody Thu Nov 5 05:11:45 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=115.124.28.76 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793848508; b=Db8nwLwUGUhLDqdcQggaXkjisNmuLBCPv/XAxnhhXiPRpwuI4E7x3FNPOvl1mWGMWey9 R6Ns3b6hh8cmwWbXAzJcRPwhjkdLCZYJg3O4GWeW+6J0S8CPzIRd4Xv5AxE3KpRpJ8b3S JwwimA9Um7Yz8Rq7IFkOj9HK7poj4OhkGNlYpm6mmTN1LmnnLN1b9/xXYJUu0fO+RkgHh EsE2TM7Oo9iYpia6EfIZOqqE4sPKXjh8qiQXj7KNZw/6jh3tTjZ5XT1VrOHfGyH0gSMKX RyRFNFYpo6gf4YDlXxZCHMQBnd6vavk8rCEIun0hW6fqX7VZtgPuUmEz6kLJqYWT2rg== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793848508; h=DMARC-Filter:X-Alimail-AntiSpam:Received:From:To:Cc:Subject:Date: Message-Id:X-Mailer:In-Reply-To:References:MIME-Version: Content-Transfer-Encoding; bh=V5RlhqgKhlTlth2eFxHvAB9iHeMZyhFFICDXcLOzhqQ=; b=PiEdqHTltTOWllCMuuSa2hvUT6r9j3JmrJnypNot3r5tm7MGlGc3J/79UysZyVGgPpzh aa47rgS9UnAmM/xiI+hWGI+PILIptwwFQ2h6+/nlUKwgOEqrqwIRUocPy8L7gEzzb1r1t zk/ZHY5p/mqGPm9GUhz6HhJL5bYrjaAUMzvQAr625l/0aap0rkhqKqjXozqgqZ1CW9esl kiJdmu31pwHGl9gj13UhJqxRqbf4bbA9edHQw9VJEPLBjKKMqYPa4l3C9ihy+lEs2AJ6n 2BW1CIw+iksyXGNGI+AmFhM2gaD40sKPWRp9RqLiptm3sIeOeDiw6V2NU/0h2muOYcA== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=motor-comm.com; spf=pass smtp.mailfrom=motor-comm.com; arc=none smtp.remote-ip=115.124.28.76 Received: from out28-76.mail.aliyun.com (out28-76.mail.aliyun.com [115.124.28.76]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id D8BA8606A334; Thu, 5 Nov 2026 03:15:05 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org D8BA8606A334 Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=motor-comm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=motor-comm.com X-Alimail-AntiSpam: AC=CONTINUE;BC=0.2046428|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.0277549-0.000560708-0.971684;FP=12422888191386374020|0|0|0|0|-1|-1|-1;HT=maildocker-contentspam033025068124;MF=kyle.switch@motor-comm.com;NM=1;PH=DS;RN=16;RT=16;SR=0;TI=SMTPD_---.jx7-i1g_1793848492; Received: from motor-comm.com(mailfrom:kyle.switch@motor-comm.com fp:SMTPD_---.jx7-i1g_1793848492 cluster:ay29) by smtp.aliyun-inc.com; Thu, 05 Nov 2026 11:14:52 +0800 From: Kyle Switch To: andrew@lunn.ch, olteanv@gmail.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mmyangfl@gmail.com, horms@kernel.org, linux@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ming.xu@motor-comm.com, xiaolin.xu@motor-comm.com, jianmin.wang@motor-comm.com, wei.zhang@gl-inet.com, sijia.huang@gl-inet.com Subject: [PATCH net-next v17 3/5] net: dsa: motorcomm: use fixed-width GENMASK_U*() helpers Date: Thu, 5 Nov 2026 11:14:40 +0800 Message-Id: <20261105031442.4164960-4-kyle.switch@motor-comm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20261105031442.4164960-1-kyle.switch@motor-comm.com> References: <20261105031442.4164960-1-kyle.switch@motor-comm.com> 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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Some masks assigned to u16 and u32 fields are defined with GENMASK(),which is an unsigned long constant and wider than the field type on 64-bit builds. Convert the YT921X_MBUS_CTRL_* masks used by mdio_bus.c to fixed-width helpers. This is a type cleanup only, with no functional change. Other GENMASK() uses in the driver are intentionally left untouched. Reviewed-by: Andrew Lunn Signed-off-by: Kyle Switch --- drivers/net/dsa/motorcomm/chip.c | 2 +- drivers/net/dsa/motorcomm/mdio_bus.c | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/motorcomm/chip.c b/drivers/net/dsa/motorcomm/c= hip.c index 2dd4240ee246..059775fd184d 100644 --- a/drivers/net/dsa/motorcomm/chip.c +++ b/drivers/net/dsa/motorcomm/chip.c @@ -2285,7 +2285,7 @@ static int yt921x_chip_setup_dsa(struct yt921x_priv *= priv) if (res) return res; =20 - ctrl =3D GENMASK(10, 0); + ctrl =3D GENMASK_U32(10, 0); res =3D yt921x_reg_write(priv, YT921X_FILTER_UNK_UCAST, ctrl); if (res) return res; diff --git a/drivers/net/dsa/motorcomm/mdio_bus.c b/drivers/net/dsa/motorco= mm/mdio_bus.c index 83f0212551ff..3aa1111efaa4 100644 --- a/drivers/net/dsa/motorcomm/mdio_bus.c +++ b/drivers/net/dsa/motorcomm/mdio_bus.c @@ -159,7 +159,7 @@ int yt921x_mbus_int_init(struct yt921x_priv *priv, stru= ct device_node *mnp) mbus->write =3D yt921x_mbus_int_write; mbus->parent =3D dev; max_ports =3D priv->series->max_ports; - mbus->phy_mask =3D (u32)~GENMASK(max_ports - 1, 0); + mbus->phy_mask =3D ~GENMASK_U32(max_ports - 1, 0); =20 res =3D devm_of_mdiobus_register(dev, mbus, mnp); if (res) --=20 2.25.1 From nobody Thu Nov 5 05:11:45 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=115.124.28.194 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793848500; b=wPNPxtTjKy+/8zaF1N+vFJjoHYaUMeQOWBcA75V/60ISgwjblI3ij56Q8TdKIiXxquY/ OMYRVV0I+3b61H4LRsZ2nw/2PA3vq9DjlmGH5hcEZjUBRvg9UQxo+vjSb4eNpJFGhuQF3 buQjepRXXXPgoAGKM4IYEUTDsQ6MBEyTD8zAEhRIic6uF4v6r0b+ls559LZH9wjCn92Ji RnWfCVWj2XP0Jb9O343W2RI+W9BRwLq8enJCLzXmtj3+i0mxm0o97oMPyl7HtPd5eJOdQ yVpw+cFcpGUpnMDOP7kxe7z3D1vkhRKa8ThdAREI+jXNqQkoG3apj5EhSWe4fRQQgyw== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793848500; h=DMARC-Filter:X-Alimail-AntiSpam:Received:From:To:Cc:Subject:Date: Message-Id:X-Mailer:In-Reply-To:References:MIME-Version: Content-Transfer-Encoding; bh=89HJq3j17qfXSpuvYLC/yhuEvLNw+77pM0D/ZB41kWk=; b=ubI+nt510cImIYcTgCmFpVKVTVAPSMxNHrPtcRqlrvN5zlaxVWQQ8QK95qT/IjI/FAv0 JLLSEopbGUlOlgsyRinQKZWkbyevzkmKoAyR5771WMflkKjbl1iYmMLbZb0SVZdp3T9Eb SNtrQ6aaJqUb9EpPW9iJM9lRTceevCBhSPDBytvadJDRKQFQOp/q8AyAQ+TDUmde8TyoH ojQyyTE0buy38WhNc1vWCPaRwooSTeqgxsqeb+g22NOjcpx218qWP552qZ0SSj7UqjT9x Jhs5t03OjMRkQd8NhiGsv0xusUD58KGK2cj7mgXI6EISVb014rApmx83bxejQtZxqNQ== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=motor-comm.com; spf=pass smtp.mailfrom=motor-comm.com; arc=none smtp.remote-ip=115.124.28.194 Received: from out28-194.mail.aliyun.com (out28-194.mail.aliyun.com [115.124.28.194]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5FC72606A33E; Thu, 5 Nov 2026 03:14:56 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 5FC72606A33E Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=motor-comm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=motor-comm.com X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436306|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_alarm|0.0208765-0.00028719-0.978836;FP=13141431387832458768|0|0|0|0|-1|-1|-1;HT=maildocker-contentspam033040092104;MF=kyle.switch@motor-comm.com;NM=1;PH=DS;RN=16;RT=16;SR=0;TI=SMTPD_---.jx7-i2e_1793848492; Received: from motor-comm.com(mailfrom:kyle.switch@motor-comm.com fp:SMTPD_---.jx7-i2e_1793848492 cluster:ay29) by smtp.aliyun-inc.com; Thu, 05 Nov 2026 11:14:53 +0800 From: Kyle Switch To: andrew@lunn.ch, olteanv@gmail.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mmyangfl@gmail.com, horms@kernel.org, linux@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ming.xu@motor-comm.com, xiaolin.xu@motor-comm.com, jianmin.wang@motor-comm.com, wei.zhang@gl-inet.com, sijia.huang@gl-inet.com Subject: [PATCH net-next v17 4/5] net: dsa: tag_yt922x: add support for Motorcomm YT922x tags Date: Thu, 5 Nov 2026 11:14:41 +0800 Message-Id: <20261105031442.4164960-5-kyle.switch@motor-comm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20261105031442.4164960-1-kyle.switch@motor-comm.com> References: <20261105031442.4164960-1-kyle.switch@motor-comm.com> 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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add DSA tag support for Motorcomm YT922x switches. YT922x uses the same ETH_P_YT921X EtherType and the same 8-byte tag length as YT921x, but the tag layout differs, so a separate tag driver is needed instead of extending tag_yt921x.c. The new driver documents both the to-CPU and from-CPU tag layouts. Update the co-maintainer for the Motorcomm DSA driver. Reviewed-by: Andrew Lunn Signed-off-by: Kyle Switch --- MAINTAINERS | 2 + include/net/dsa.h | 2 + net/dsa/Kconfig | 6 +++ net/dsa/Makefile | 1 + net/dsa/tag_yt922x.c | 122 +++++++++++++++++++++++++++++++++++++++++++ 5 files changed, 133 insertions(+) create mode 100644 net/dsa/tag_yt922x.c diff --git a/MAINTAINERS b/MAINTAINERS index 09713dc4c6a7..1ebe978115f4 100644 --- a/MAINTAINERS +++ b/MAINTAINERS @@ -18817,11 +18817,13 @@ F: drivers/net/phy/motorcomm.c =20 MOTORCOMM YT921X ETHERNET SWITCH DRIVER M: David Yang +M: Kyle Switch L: netdev@vger.kernel.org S: Maintained F: Documentation/devicetree/bindings/net/dsa/motorcomm,yt921x.yaml F: drivers/net/dsa/motorcomm/ F: net/dsa/tag_yt921x.c +F: net/dsa/tag_yt922x.c =20 MOXA SMARTIO/INDUSTIO SERIAL CARD M: Jiri Slaby diff --git a/include/net/dsa.h b/include/net/dsa.h index 5d12191b6f6f..5a173fe2bb87 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -62,6 +62,7 @@ struct tc_action; #define DSA_TAG_PROTO_KSZ8463_VALUE 34 #define DSA_TAG_PROTO_MT7628_VALUE 35 #define DSA_TAG_PROTO_KS8995_VALUE 36 +#define DSA_TAG_PROTO_YT922X_VALUE 37 =20 enum dsa_tag_protocol { DSA_TAG_PROTO_NONE =3D DSA_TAG_PROTO_NONE_VALUE, @@ -101,6 +102,7 @@ enum dsa_tag_protocol { DSA_TAG_PROTO_KSZ8463 =3D DSA_TAG_PROTO_KSZ8463_VALUE, DSA_TAG_PROTO_MT7628 =3D DSA_TAG_PROTO_MT7628_VALUE, DSA_TAG_PROTO_KS8995 =3D DSA_TAG_PROTO_KS8995_VALUE, + DSA_TAG_PROTO_YT922X =3D DSA_TAG_PROTO_YT922X_VALUE, }; =20 struct dsa_switch; diff --git a/net/dsa/Kconfig b/net/dsa/Kconfig index 4f44bf3ede23..06d8d6526054 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -233,4 +233,10 @@ config NET_DSA_TAG_YT921X Say Y or M if you want to enable support for tagging frames for Motorcomm YT921x switches. =20 +config NET_DSA_TAG_YT922X + tristate "Tag driver for Motorcomm YT922x switches" + help + Say Y or M if you want to enable support for tagging frames for + Motorcomm YT922x switches. + endif diff --git a/net/dsa/Makefile b/net/dsa/Makefile index 1f9cc30e9988..0ef6dfce3b92 100644 --- a/net/dsa/Makefile +++ b/net/dsa/Makefile @@ -45,6 +45,7 @@ obj-$(CONFIG_NET_DSA_TAG_TRAILER) +=3D tag_trailer.o obj-$(CONFIG_NET_DSA_TAG_VSC73XX_8021Q) +=3D tag_vsc73xx_8021q.o obj-$(CONFIG_NET_DSA_TAG_XRS700X) +=3D tag_xrs700x.o obj-$(CONFIG_NET_DSA_TAG_YT921X) +=3D tag_yt921x.o +obj-$(CONFIG_NET_DSA_TAG_YT922X) +=3D tag_yt922x.o =20 # for tracing framework to find trace.h CFLAGS_trace.o :=3D -I$(src) diff --git a/net/dsa/tag_yt922x.c b/net/dsa/tag_yt922x.c new file mode 100644 index 000000000000..b6146a9af98b --- /dev/null +++ b/net/dsa/tag_yt922x.c @@ -0,0 +1,122 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Motorcomm YT922x Switch Extended CPU Port Tagging + * + * Copyright (c) 2026 Kyle switch + * + */ + +#include + +#include "tag.h" + +#define YT922X_TAG_LEN 8 + +/* + * To define the from cpu tag format 8 bytes. + * + * To-CPU (RX) tag format, 8 bytes: + * + * tag[0]: TPID (default: 0x9988) + * tag[1]: VID lookup + * tag[2]: bit 5:2 - RX source port + * + * From-CPU (TX) tag format, 8 bytes: + * + * tag[0]: TPID (default: 0x9988) + * tag[1]: bit 8:0 - Dst port mask + * tag[2]: bit 15 - Dst port 0 + * + */ +#define YT922X_TAG_NAME "yt922x" +#define YT922X_TAG_PORTMASK_0 BIT(15) +#define YT922X_TAG_PORTMASK_M GENMASK(8, 0) +#define YT922X_TAG_PORTS(x) FIELD_PREP(YT922X_TAG_PORTMASK_M, (x)) +#define YT922X_TAG_FORCE_DST BIT(9) +#define YT922X_TAG_PRIO_M GENMASK(12, 10) +#define YT922X_TAG_PRIO_EN BIT(13) +#define YT922X_TAG_PRIO(x) (FIELD_PREP(YT922X_TAG_PRIO_M, (x)) | YT922X_T= AG_PRIO_EN) +#define YT922X_TAG_RX_PORT_M GENMASK(5, 2) + +static struct sk_buff * +yt922x_tag_xmit(struct sk_buff *skb, struct net_device *netdev) +{ + unsigned long ports; + __be16 *tag; + u16 ctrl; + + skb_push(skb, YT922X_TAG_LEN); + dsa_alloc_etype_header(skb, YT922X_TAG_LEN); + tag =3D dsa_etype_header_pos_tx(skb); + + tag[0] =3D htons(ETH_P_YT921X); + ports =3D dsa_xmit_port_mask(skb, netdev); + /*To fill in the case where the port index is not 0 */ + ctrl =3D YT922X_TAG_PRIO(skb->priority) | YT922X_TAG_FORCE_DST | + YT922X_TAG_PORTS(ports >> 1); + tag[1] =3D htons(ctrl); + if (ports & BIT(0)) { + /* To fill in the case where the port index is 0 */ + ctrl =3D YT922X_TAG_PORTMASK_0; + tag[2] =3D htons(ctrl); + } else { + tag[2] =3D 0; + } + tag[3] =3D 0; + + return skb; +} + +static struct sk_buff * +yt922x_tag_rcv(struct sk_buff *skb, struct net_device *netdev) +{ + unsigned int port; + __be16 *tag; + u16 rx; + + if (unlikely(!pskb_may_pull(skb, YT922X_TAG_LEN))) { + kfree_skb(skb); + return NULL; + } + + tag =3D dsa_etype_header_pos_rx(skb); + + if (unlikely(tag[0] !=3D htons(ETH_P_YT921X))) { + dev_warn_ratelimited(&netdev->dev, + "Unexpected EtherType 0x%04x\n", + ntohs(tag[0])); + kfree_skb(skb); + return NULL; + } + + /* Locate which port this is coming from */ + rx =3D ntohs(tag[2]); + port =3D FIELD_GET(YT922X_TAG_RX_PORT_M, rx); + skb->dev =3D dsa_conduit_find_user(netdev, 0, port); + if (unlikely(!skb->dev)) { + dev_warn_ratelimited(&netdev->dev, + "Couldn't decode source port %u\n", port); + kfree_skb(skb); + return NULL; + } + + /* Remove tag and update checksum */ + skb_pull_rcsum(skb, YT922X_TAG_LEN); + dsa_strip_etype_header(skb, YT922X_TAG_LEN); + + return skb; +} + +static const struct dsa_device_ops yt922x_netdev_ops =3D { + .name =3D YT922X_TAG_NAME, + .proto =3D DSA_TAG_PROTO_YT922X, + .xmit =3D yt922x_tag_xmit, + .rcv =3D yt922x_tag_rcv, + .needed_headroom =3D YT922X_TAG_LEN, +}; + +MODULE_DESCRIPTION("DSA tag driver for Motorcomm YT922x switches"); +MODULE_LICENSE("GPL"); +MODULE_ALIAS_DSA_TAG_DRIVER(DSA_TAG_PROTO_YT922X, YT922X_TAG_NAME); + +module_dsa_tag_driver(yt922x_netdev_ops); --=20 2.25.1 From nobody Thu Nov 5 05:11:45 2026 Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.remote-ip=115.124.28.194 ARC-Seal: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; cv=none; t=1793848501; b=Z3/2tkS0cGDWWA1Soc4FVUVFDTFz+dj5HxeHYdj2m5Px0LlSNQZlIXn0tCNtt1IjaXGY 1FTvloasXPEIsy1/xq3ZzuQBh4bOOKRpduhp89WZY7xU+BxYjYys3nZm+qkrMhYWNN6kI mnmclSZixRGdAXuhadS8LbTmgogqDP0oJuKCpUYxPYzDe/Wlm/qzI4dfb4dnWMqvI21LT x3rrNpTflNd4rzI3PXPGqjXtRB0A1GFmx8dS/3njlwXnrWr32ByB4V+zlySspW1Ljyqw+ NWV7Ze5A43IdgUB6hajBOE4gh6pnMj7FFgGbOnhNHZ6tIhyIWS2RVa4b5ARG342v9VQ== ARC-Message-Signature: i=1; d=subspace.kernel.org; s=arc20261015; a=rsa-sha256; c=relaxed/relaxed; t=1793848501; h=DMARC-Filter:X-Alimail-AntiSpam:Received:From:To:Cc:Subject:Date: Message-Id:X-Mailer:In-Reply-To:References:MIME-Version: Content-Transfer-Encoding; bh=lmAZ4IM/qe4VPK3uGOfMRWdB+TlKTYJPxL76dGofK4I=; b=y8vdgG83axQTpjhf5WD4U5elkuERITr5YJMCMWRsyYRYHVVmqo01KiaD5L3SmRPfZgXn JUfzGosB/59GzvPYo3gOXLcczki3BLS9pSX2XlpgxiDSSh4igLrsTQMNSisOfqaN0e+wQ hpp0SDNjhKnoZHNjB81T7DL9YL/f08WzQwkAs3cl2E9ytzkF1v4JeF3SokpwtRr2jpfLC WVLWJuFERHdEwcKL199jAsYmqqx6nMtCebAiS7pR0W5q3g6HOYDs8t1PRZ/0b4eVlduMD 3gVLDE+LcHSBrxtxVFA1vGSLDf1CsxQPMe8MqnfZSmhxR1Kp2Cgmh93nkGdRN6uxJcg== ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass header.from=motor-comm.com; spf=pass smtp.mailfrom=motor-comm.com; arc=none smtp.remote-ip=115.124.28.194 Received: from out28-194.mail.aliyun.com (out28-194.mail.aliyun.com [115.124.28.194]) (using TLSv1.3 with cipher TLS_AES_256_GCM_SHA384 (256/256 bits) key-exchange X25519 server-signature ECDSA (prime256v1) server-digest SHA256) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 48E5E606A32D; Thu, 5 Nov 2026 03:14:57 +0000 (UTC) DMARC-Filter: OpenDMARC Filter v1.4.2 smtp.subspace.kernel.org 48E5E606A32D Authentication-Results: smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=motor-comm.com Authentication-Results: smtp.subspace.kernel.org; spf=pass smtp.mailfrom=motor-comm.com X-Alimail-AntiSpam: AC=CONTINUE;BC=0.07436259|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.00959794-0.00190441-0.988498;FP=15148842890321019572|0|0|0|0|-1|-1|-1;HT=maildocker-contentspam033032065030;MF=kyle.switch@motor-comm.com;NM=1;PH=DS;RN=16;RT=16;SR=0;TI=SMTPD_---.jx7-i3U_1793848493; Received: from motor-comm.com(mailfrom:kyle.switch@motor-comm.com fp:SMTPD_---.jx7-i3U_1793848493 cluster:ay29) by smtp.aliyun-inc.com; Thu, 05 Nov 2026 11:14:54 +0800 From: Kyle Switch To: andrew@lunn.ch, olteanv@gmail.com, davem@davemloft.net, edumazet@google.com, kuba@kernel.org, pabeni@redhat.com, mmyangfl@gmail.com, horms@kernel.org, linux@armlinux.org.uk, netdev@vger.kernel.org, linux-kernel@vger.kernel.org Cc: ming.xu@motor-comm.com, xiaolin.xu@motor-comm.com, jianmin.wang@motor-comm.com, wei.zhang@gl-inet.com, sijia.huang@gl-inet.com Subject: [PATCH net-next v17 5/5] net: dsa: motorcomm: Add support for Motorcomm YT922x Date: Thu, 5 Nov 2026 11:14:42 +0800 Message-Id: <20261105031442.4164960-6-kyle.switch@motor-comm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20261105031442.4164960-1-kyle.switch@motor-comm.com> References: <20261105031442.4164960-1-kyle.switch@motor-comm.com> 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 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support for Motorcomm YT922X, which is series of ethernet switches developed by Motorcomm Electronic Technology, includes YT9224 and YT9228. This patch only adds support for the YT9224 variant. YT9228 is not supported yet. This patch adds basic support for a working DSA switch, includes .port_setup, .setup, .phylink_get_caps, .get_tag_protocol. Reviewed-by: Andrew Lunn Signed-off-by: Kyle Switch --- drivers/net/dsa/motorcomm/Kconfig | 7 +- drivers/net/dsa/motorcomm/Makefile | 1 + drivers/net/dsa/motorcomm/chip.c | 508 ++++++++++++++++++++++++++- drivers/net/dsa/motorcomm/chip.h | 82 +++++ drivers/net/dsa/motorcomm/mdio_bus.c | 40 +++ drivers/net/dsa/motorcomm/mdio_bus.h | 4 + drivers/net/dsa/motorcomm/pcs-922x.c | 282 +++++++++++++++ drivers/net/dsa/motorcomm/pcs.h | 1 + 8 files changed, 916 insertions(+), 9 deletions(-) create mode 100644 drivers/net/dsa/motorcomm/pcs-922x.c diff --git a/drivers/net/dsa/motorcomm/Kconfig b/drivers/net/dsa/motorcomm/= Kconfig index 79cdd79a1fd2..648c49d6c527 100644 --- a/drivers/net/dsa/motorcomm/Kconfig +++ b/drivers/net/dsa/motorcomm/Kconfig @@ -1,11 +1,12 @@ # SPDX-License-Identifier: GPL-2.0-only config NET_DSA_YT921X - tristate "Motorcomm YT9215 ethernet switch chip support" + tristate "Motorcomm YT9215 and YT9224 ethernet switch chip support" select NET_DSA_TAG_YT921X + select NET_DSA_TAG_YT922X select NET_IEEE8021Q_HELPERS if DCB help - This enables support for the Motorcomm YT9215 ethernet switch - chip. + This enables support for the Motorcomm YT9215 and YT9224 + ethernet switch chip. =20 config NET_DSA_YT921X_LEDS bool "LED support for Motorcomm YT9215" diff --git a/drivers/net/dsa/motorcomm/Makefile b/drivers/net/dsa/motorcomm= /Makefile index 9eaa59f699e8..3ca151358d19 100644 --- a/drivers/net/dsa/motorcomm/Makefile +++ b/drivers/net/dsa/motorcomm/Makefile @@ -4,6 +4,7 @@ yt921x-objs :=3D chip.o yt921x-$(CONFIG_NET_DSA_YT921X_LEDS) +=3D leds.o yt921x-objs +=3D mdio_bus.o yt921x-objs +=3D mib.o +yt921x-objs +=3D pcs-922x.o yt921x-objs +=3D pcs-921x.o yt921x-objs +=3D smi.o yt921x-objs +=3D tc.o diff --git a/drivers/net/dsa/motorcomm/chip.c b/drivers/net/dsa/motorcomm/c= hip.c index 059775fd184d..9d92c71205f8 100644 --- a/drivers/net/dsa/motorcomm/chip.c +++ b/drivers/net/dsa/motorcomm/chip.c @@ -1,6 +1,6 @@ // SPDX-License-Identifier: GPL-2.0-or-later /* - * Driver for Motorcomm YT921x Switch + * Driver for Motorcomm YT921x and YT922x Switch * * Should work on YT9213/YT9214/YT9215/YT9218, but only tested on YT9215+S= GMII, * be sure to do your own checks before porting to another chip. @@ -76,6 +76,12 @@ static const struct yt921x_info yt921x_infos[] =3D { BIT(8) | BIT(9), BIT(8) | BIT(9), }, + { + "YT9224", YT9224_MAJOR, 0, 0, + GENMASK(7, 4), + 0, + BIT(8) | BIT(0), + }, {} }; =20 @@ -2150,6 +2156,11 @@ static void yt921x_dsa_teardown(struct dsa_switch *d= s) #endif } =20 +static bool yt921x_needs_extmode_check(u32 major) +{ + return (major =3D=3D YT9224_MAJOR) ? false : true; +} + static int yt921x_chip_detect(struct yt921x_priv *priv) { struct device *dev =3D yt921x_priv_to_device(priv); @@ -2175,6 +2186,14 @@ static int yt921x_chip_detect(struct yt921x_priv *pr= iv) return -ENODEV; } =20 + if (!yt921x_needs_extmode_check(major)) { + dev_info(dev, + "Motorcomm %s ethernet switch, chipid: 0x%x\n", + info->name, chipid); + priv->info =3D info; + return 0; + } + res =3D yt921x_reg_read(priv, YT921X_CHIP_MODE, &mode); if (res) return res; @@ -2574,6 +2593,470 @@ static const struct dsa_switch_ops yt921x_dsa_switc= h_ops =3D { .setup =3D yt921x_dsa_setup, }; =20 +static int yt922x_port_down(struct yt921x_priv *priv, int port) +{ + u32 mask; + int res; + + /* mac force down */ + mask =3D YT922X_PORT_LINK | YT922X_PORT_RX_MAC_EN | + YT922X_PORT_TX_MAC_EN | YT922X_PORT_LINK_AN; + res =3D yt921x_reg_clear_bits(priv, YT922X_PORTn_CTRL(port), mask); + if (res) + return res; + /* Need force op to make soft configuration effective */ + mask =3D YT922X_PORT_FORCE_OP; + res =3D yt921x_reg_set_bits(priv, YT922X_PORTn_CTRL(port), mask); + if (res) + return res; + + /* disable en_phy */ + res =3D yt921x_reg_clear_bits(priv, YT922X_EN_PHY_VALUE, BIT(port)); + if (res) + return res; + res =3D yt921x_reg_set_bits(priv, YT922X_EN_PHY_OVERWRITE, BIT(port)); + if (res) + return res; + + return 0; +} + +static void +yt922x_phylink_mac_link_down(struct phylink_config *config, unsigned int m= ode, + phy_interface_t interface) +{ + struct dsa_port *dp =3D dsa_phylink_to_port(config); + struct yt921x_priv *priv =3D dsa_to_yt921x_priv(dp->ds); + int port =3D dp->index; + int res; + + mutex_lock(&priv->reg_lock); + res =3D yt922x_port_down(priv, port); + mutex_unlock(&priv->reg_lock); + + if (res) + dev_err(dp->ds->dev, "Failed to %s port %d: %i\n", "bring down", + port, res); +} + +static int +yt922x_port_up(struct yt921x_priv *priv, int port, unsigned int mode, + phy_interface_t interface, int speed, int duplex, + bool tx_pause, bool rx_pause) +{ + struct yt921x_port *pp =3D &priv->ports[port]; + int ps =3D ethtool_speed_to_yt921x(speed); + u32 ctrl =3D 0; + u32 mask; + int res; + + if (ps =3D=3D YT921X_SPEED_INVALID) + return -EINVAL; + + mask =3D YT922X_PORT_SPEED_M | YT922X_PORT_TX_MAC_EN | + YT922X_PORT_RX_MAC_EN | YT922X_PORT_TX_PAUSE | + YT922X_PORT_RX_PAUSE | YT922X_PORT_DUPLEX_FULL | + YT922X_PORT_LINK_AN | YT922X_PORT_CFG_RX_EN | + YT922X_PORT_CFG_TX_EN | YT922X_PORT_FC_AN | + YT922X_PORT_LINK; + + ctrl |=3D ps; + + if (duplex =3D=3D DUPLEX_FULL) + ctrl |=3D YT922X_PORT_DUPLEX_FULL; + if (tx_pause) + ctrl |=3D YT922X_PORT_TX_PAUSE; + if (rx_pause) + ctrl |=3D YT922X_PORT_RX_PAUSE; + ctrl |=3D YT922X_PORT_RX_MAC_EN | YT922X_PORT_TX_MAC_EN | + YT922X_PORT_CFG_TX_EN | YT922X_PORT_CFG_RX_EN; + + /* + * Self-negotiation: the LINK/AN bits in ctrl are set based to inband. + * Forced mode: set LINK, keep the AN bit at 0 and clear it via the mask + */ + if (pp->inband) + ctrl |=3D (YT922X_PORT_FC_AN | YT922X_PORT_LINK_AN); + else + ctrl |=3D YT922X_PORT_LINK; + + res =3D yt921x_reg_update_bits(priv, YT922X_PORTn_CTRL(port), mask, ctrl); + if (res) + return res; + + /* force op */ + mask =3D YT922X_PORT_FORCE_OP; + res =3D yt921x_reg_set_bits(priv, YT922X_PORTn_CTRL(port), mask); + if (res) + return res; + + /* enable en_phy */ + res =3D yt921x_reg_set_bits(priv, YT922X_EN_PHY_VALUE, BIT(port)); + if (res) + return res; + res =3D yt921x_reg_set_bits(priv, YT922X_EN_PHY_OVERWRITE, BIT(port)); + if (res) + return res; + + return 0; +} + +static void +yt922x_phylink_mac_link_up(struct phylink_config *config, + struct phy_device *phydev, unsigned int mode, + phy_interface_t interface, int speed, int duplex, + bool tx_pause, bool rx_pause) +{ + struct dsa_port *dp =3D dsa_phylink_to_port(config); + struct yt921x_priv *priv =3D dsa_to_yt921x_priv(dp->ds); + int port =3D dp->index; + int res; + + mutex_lock(&priv->reg_lock); + res =3D yt922x_port_up(priv, port, mode, interface, speed, duplex, + tx_pause, rx_pause); + mutex_unlock(&priv->reg_lock); + + if (res) + dev_err(dp->ds->dev, "Failed to %s port %d: %i\n", "bring up", + port, res); +} + +static int +yt922x_port_config(struct yt921x_priv *priv, int port, unsigned int mode, + phy_interface_t interface) +{ + struct device *dev =3D yt921x_priv_to_device(priv); + const struct yt921x_info *info =3D priv->info; + struct yt921x_port *pp =3D &priv->ports[port]; + + if (BIT(port) & info->internal_mask) { + if (interface !=3D PHY_INTERFACE_MODE_INTERNAL) + goto err; + return 0; + } + + switch (interface) { + /* SERDES */ + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_100BASEX: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: + case PHY_INTERFACE_MODE_USXGMII: + if (!(BIT(port) & info->serdes_mask)) + goto err; + pp->serdes =3D true; + break; + default: + goto err; + } + + return 0; + +err: + dev_err(dev, "Wrong mode %d on port %d\n", interface, port); + return -EINVAL; +} + +static void +yt922x_phylink_mac_config(struct phylink_config *config, unsigned int mode, + const struct phylink_link_state *state) +{ + struct dsa_port *dp =3D dsa_phylink_to_port(config); + struct yt921x_priv *priv =3D dsa_to_yt921x_priv(dp->ds); + int port =3D dp->index; + int res; + + mutex_lock(&priv->reg_lock); + res =3D yt922x_port_config(priv, port, mode, state->interface); + mutex_unlock(&priv->reg_lock); + + if (res) + dev_err(dp->ds->dev, "Failed to %s port %d: %i\n", "config", + port, res); +} + +static struct phylink_pcs * +yt922x_phylink_mac_select_pcs(struct phylink_config *config, + phy_interface_t interface) +{ + struct dsa_port *dp =3D dsa_phylink_to_port(config); + struct yt921x_priv *priv =3D dsa_to_yt921x_priv(dp->ds); + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: + case PHY_INTERFACE_MODE_USXGMII: + return &priv->ports[dp->index].pcs; + + default: + return NULL; + } +} + +static const struct phylink_mac_ops yt922x_phylink_mac_ops =3D { + .mac_select_pcs =3D yt922x_phylink_mac_select_pcs, + .mac_link_down =3D yt922x_phylink_mac_link_down, + .mac_link_up =3D yt922x_phylink_mac_link_up, + .mac_config =3D yt922x_phylink_mac_config, +}; + +static enum dsa_tag_protocol +yt922x_dsa_get_tag_protocol(struct dsa_switch *ds, int port, + enum dsa_tag_protocol m) +{ + return DSA_TAG_PROTO_YT922X; +} + +static void +yt922x_dsa_phylink_get_caps(struct dsa_switch *ds, int port, + struct phylink_config *config) +{ + struct yt921x_priv *priv =3D dsa_to_yt921x_priv(ds); + const struct yt921x_info *info =3D priv->info; + + config->mac_capabilities =3D MAC_ASYM_PAUSE | MAC_SYM_PAUSE | + MAC_10 | MAC_100 | MAC_1000; + + if (info->internal_mask & BIT(port)) { + /* port 4 to port 7, internal utp */ + __set_bit(PHY_INTERFACE_MODE_INTERNAL, + config->supported_interfaces); + config->mac_capabilities |=3D MAC_2500FD; + } + if (info->serdes_mask & BIT(port)) { + /* serdes */ + __set_bit(PHY_INTERFACE_MODE_SGMII, + config->supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_1000BASEX, + config->supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_2500BASEX, + config->supported_interfaces); + config->mac_capabilities |=3D MAC_2500FD; + __set_bit(PHY_INTERFACE_MODE_USXGMII, + config->supported_interfaces); + config->mac_capabilities |=3D MAC_5000FD; + config->mac_capabilities |=3D MAC_10000FD; + } +} + +static int yt922x_port_setup(struct yt921x_priv *priv, int port) +{ + struct dsa_switch *ds =3D &priv->ds; + u32 mask; + u32 ctrl; + int res; + + /* enable user port isolation and disable fdb learning */ + ctrl =3D ~priv->cpu_ports_mask; + res =3D yt921x_reg_write(priv, YT922X_PORTn_ISOLATION(port), ctrl); + if (res) + return res; + + mask =3D YT922X_PORT_LEARN_DIS; + res =3D yt921x_reg_set_bits(priv, YT922X_PORTn_LEARN(port), mask); + if (res) + return res; + + if (dsa_is_cpu_port(ds, port)) { + ctrl =3D ~(u32)0; + res =3D yt921x_reg_write(priv, YT922X_PORTn_ISOLATION(port), + ctrl); + if (res) + return res; + } + + return 0; +} + +static int yt922x_dsa_port_setup(struct dsa_switch *ds, int port) +{ + struct yt921x_priv *priv =3D dsa_to_yt921x_priv(ds); + int res; + + mutex_lock(&priv->reg_lock); + res =3D yt922x_port_setup(priv, port); + mutex_unlock(&priv->reg_lock); + + return res; +} + +static int yt922x_cpu_tag_mode_set_8b(struct yt921x_priv *priv) +{ + u32 val; + u32 val1; + int res; + + /* cpu tag mode set to 8b */ + res =3D yt921x_reg_read(priv, YT922X_CPU_TAG_RX_CTRL, &val); + if (res) + return res; + res =3D yt921x_reg_read(priv, YT922X_CPU_TAG_TX_CTRL, &val1); + if (res) + return res; + val &=3D ~YT922X_CPU_TAG_RX_MODE; + val1 &=3D ~YT922X_CPU_TAG_TX_MODE; + val1 &=3D ~YT922X_CPU_TAG_TX_TYPE; + res =3D yt921x_reg_write(priv, YT922X_CPU_TAG_RX_CTRL, val); + if (res) + return res; + res =3D yt921x_reg_write(priv, YT922X_CPU_TAG_TX_CTRL, val1); + if (res) + return res; + + return 0; +} + +static int yt922x_cpu_port_set(struct yt921x_priv *priv) +{ + struct dsa_switch *ds =3D &priv->ds; + u32 ctrl; + int res; + + /* cpu tag mode */ + res =3D yt922x_cpu_tag_mode_set_8b(priv); + if (res) + return res; + + /* Enable DSA */ + priv->cpu_ports_mask =3D dsa_cpu_ports(ds); + ctrl =3D YT921X_EXT_CPU_PORT_TAG_EN | YT921X_EXT_CPU_PORT_PORT_EN | + YT921X_EXT_CPU_PORT_PORT(__ffs(priv->cpu_ports_mask)); + res =3D yt921x_reg_write(priv, YT921X_EXT_CPU_PORT, ctrl); + if (res) + return res; + + /* Setup software switch */ + ctrl =3D YT922X_CPU_COPY_TO_EXT_CPU; + res =3D yt921x_reg_write(priv, YT922X_CPU_COPY, ctrl); + if (res) + return res; + + return res; +} + +static int yt922x_chip_setup_dsa(struct yt921x_priv *priv) +{ + unsigned long cpu_ports_mask; + u32 ctrl; + int port; + int res; + + /* cpu port set */ + res =3D yt922x_cpu_port_set(priv); + if (res) + return res; + + ctrl =3D GENMASK_U32(8, 0); + res =3D yt921x_reg_write(priv, YT922X_FILTER_UNK_UCAST, ctrl); + if (res) + return res; + + ctrl =3D 0; + for (int i =3D 0; i < priv->series->max_ports; i++) + ctrl |=3D YT922X_ACT_UNK_ACTn_TRAP(i); + cpu_ports_mask =3D priv->cpu_ports_mask; + for_each_set_bit(port, &cpu_ports_mask, priv->series->max_ports) { + ctrl &=3D ~YT922X_ACT_UNK_ACTn_M(port); + ctrl |=3D YT922X_ACT_UNK_ACTn_DROP(port); + } + res =3D yt921x_reg_write(priv, YT922X_ACT_UNK_UCAST, ctrl); + if (res) + return res; + res =3D yt921x_reg_write(priv, YT922X_ACT_UNK_MCAST, ctrl); + if (res) + return res; + + return 0; +} + +static int yt922x_chip_setup(struct yt921x_priv *priv) +{ + u32 ctrl; + int res; + + ctrl =3D YT922X_FUNC_MIB | YT922X_FUNC_ACL; + res =3D yt921x_reg_set_bits(priv, YT921X_FUNC, ctrl); + if (res) + return res; + + res =3D yt922x_chip_setup_dsa(priv); + if (res) + return res; + + return 0; +} + +static void yt922x_pcs_setup(struct dsa_switch *ds) +{ + struct yt921x_priv *priv =3D dsa_to_yt921x_priv(ds); + const struct yt921x_info *info =3D priv->info; + unsigned long mask; + int port; + + mask =3D info->serdes_mask; + for_each_set_bit(port, &mask, priv->series->max_ports) { + struct yt921x_port *pp =3D &priv->ports[port]; + + pp->pcs.ops =3D &yt922x_phylink_pcs_ops; + pp->pcs.poll =3D true; + + __set_bit(PHY_INTERFACE_MODE_SGMII, + pp->pcs.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_1000BASEX, + pp->pcs.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_2500BASEX, + pp->pcs.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_USXGMII, + pp->pcs.supported_interfaces); + } +} + +static int yt922x_dsa_setup(struct dsa_switch *ds) +{ + struct yt921x_priv *priv =3D dsa_to_yt921x_priv(ds); + struct device *dev =3D yt921x_priv_to_device(priv); + struct device_node *np =3D dev->of_node; + struct device_node *child; + int res; + + mutex_lock(&priv->reg_lock); + res =3D yt921x_chip_reset(priv); + mutex_unlock(&priv->reg_lock); + if (res) + return res; + + /* Register the internal mdio bus. */ + child =3D of_get_child_by_name(np, "mdio"); + if (child) { + res =3D yt921x_mbus_int_init(priv, child); + of_node_put(child); + if (res) + return res; + } + + mutex_lock(&priv->reg_lock); + res =3D yt922x_chip_setup(priv); + mutex_unlock(&priv->reg_lock); + if (res) + return res; + + /* switch sds pcs setup */ + yt922x_pcs_setup(ds); + + return 0; +} + +static const struct dsa_switch_ops yt922x_dsa_switch_ops =3D { + /* port */ + .get_tag_protocol =3D yt922x_dsa_get_tag_protocol, + .phylink_get_caps =3D yt922x_dsa_phylink_get_caps, + .port_setup =3D yt922x_dsa_port_setup, + /* chip */ + .setup =3D yt922x_dsa_setup, +}; + static const struct yt92xx_series yt92xx_series_table[] =3D { [YT92XX_MODE_YT921X] =3D { .name =3D "YT921x", @@ -2586,12 +3069,25 @@ static const struct yt92xx_series yt92xx_series_tab= le[] =3D { .switch_ops =3D &yt921x_dsa_switch_ops, .mac_ops =3D &yt921x_phylink_mac_ops }, + [YT92XX_MODE_YT922X] =3D { + .name =3D "YT922x", + .max_ports =3D YT922X_PORT_NUM, + .num_lag_ids =3D YT922X_LAG_NUM, + .ageing_time_min =3D 1 * 6000, + .ageing_time_max =3D U16_MAX * 6000, + .dscp_prio_mapping_is_global =3D true, + .assisted_learning_on_cpu_port =3D true, + .switch_ops =3D &yt922x_dsa_switch_ops, + .mac_ops =3D &yt922x_phylink_mac_ops, + }, }; =20 static const struct yt92xx_series *yt92xx_series_lookup(u32 major) { if (major =3D=3D YT9215_MAJOR || major =3D=3D YT9218_MAJOR) return &yt92xx_series_table[YT92XX_MODE_YT921X]; + else if (major =3D=3D YT9224_MAJOR) + return &yt92xx_series_table[YT92XX_MODE_YT922X]; else return NULL; } @@ -2608,15 +3104,13 @@ static int yt92xx_register_switch(struct dsa_switch= *ds) mutex_lock(&priv->reg_lock); res =3D yt921x_reg_read(priv, YT921X_CHIP_ID, &chipid); mutex_unlock(&priv->reg_lock); - if (res) { - dev_err(dev, "Unexpected chipid 0x%x\n", chipid); + if (res) return res; - } =20 major =3D FIELD_GET(YT921X_CHIP_ID_MAJOR, chipid); series =3D yt92xx_series_lookup(major); if (!series) { - dev_err(dev, "Undefined series info for the corresponding major\n"); + dev_err(dev, "Chip ID: 0x%x, and Unknown major.\n", chipid); return -ENODEV; } priv->series =3D series; @@ -2716,6 +3210,7 @@ static int yt921x_mdio_probe(struct mdio_device *mdio= dev) =20 static const struct of_device_id yt921x_of_match[] =3D { { .compatible =3D "motorcomm,yt9215" }, + { .compatible =3D "motorcomm,yt9224" }, {} }; MODULE_DEVICE_TABLE(of, yt921x_of_match); @@ -2733,5 +3228,6 @@ static struct mdio_driver yt921x_mdio_driver =3D { mdio_module_driver(yt921x_mdio_driver); =20 MODULE_AUTHOR("David Yang "); -MODULE_DESCRIPTION("Driver for Motorcomm YT921x Switch"); +MODULE_AUTHOR("Kyle Switch "); +MODULE_DESCRIPTION("Driver for Motorcomm YT921x and YT922x Switch"); MODULE_LICENSE("GPL"); diff --git a/drivers/net/dsa/motorcomm/chip.h b/drivers/net/dsa/motorcomm/c= hip.h index fd6a0021e98e..b29fb549ab34 100644 --- a/drivers/net/dsa/motorcomm/chip.h +++ b/drivers/net/dsa/motorcomm/chip.h @@ -119,6 +119,7 @@ enum yt921x_speed { YT921X_SPEED_1000, YT921X_SPEED_10000, YT921X_SPEED_2500, + YT921X_SPEED_5000, YT921X_SPEED_INVALID }; =20 @@ -431,6 +432,7 @@ enum yt921x_fdb_entry_status { =20 #define YT9215_MAJOR 0x9002 #define YT9218_MAJOR 0x9001 +#define YT9224_MAJOR 0x9004 =20 /* required for a hard reset */ #define YT921X_RST_DELAY_US 10000 @@ -450,6 +452,84 @@ enum yt921x_fdb_entry_status { =20 #define YT921X_NAME "yt921x" =20 +/* yt922x register lists */ +#define YT92XX_PAGE_SELECT 0x1e +#define YT92XX_PAGE 0x1f +#define YT922X_EN_PHY_OVERWRITE (0x80040) +#define YT922X_EN_PHY_VALUE (0x8003c) +/* CTRL: force op to make soft configuration effective */ +#define YT922X_PORTn_CTRL(port) (0x80080 + 4 * (port)) +#define YT922X_PORT_FORCE_OP BIT(14) +#define YT922X_PORT_CFG_TX_EN BIT(13) +#define YT922X_PORT_CFG_RX_EN BIT(12) +#define YT922X_PORT_FC_AN BIT(11) +#define YT922X_PORT_LINK_AN BIT(10) /* CTRL: auto negotiation */ +#define YT922X_PORT_LINK BIT(9) /* CTRL: link status */ +#define YT922X_PORT_HALF_PAUSE BIT(8) /* Half-duplex back pressure mod= e */ +#define YT922X_PORT_DUPLEX_FULL BIT(7) +#define YT922X_PORT_RX_PAUSE BIT(6) +#define YT922X_PORT_TX_PAUSE BIT(5) +#define YT922X_PORT_RX_MAC_EN BIT(4) +#define YT922X_PORT_TX_MAC_EN BIT(3) +#define YT922X_PORT_SPEED_M GENMASK(2, 0) +#define YT922X_PORT_SDSn 0x400 +#define YT922X_SERDES_MODE_M GENMASK(6, 4) +#define YT922X_SERDES_MODE(x) FIELD_PREP(YT922X_SERDES_MODE_M, (x)) +#define YT922X_SERDES_MODE_SGMII YT922X_SERDES_MODE(0) +#define YT922X_SERDES_MODE_REVSGMII YT922X_SERDES_MODE(1) +#define YT922X_SERDES_MODE_1000BASEX YT922X_SERDES_MODE(2) +#define YT922X_SERDES_MODE_100BASEX YT922X_SERDES_MODE(3) +#define YT922X_SERDES_MODE_2500BASEX YT922X_SERDES_MODE(4) +#define YT922X_SERDES_MODE_USXGMII YT922X_SERDES_MODE(6) +#define YT922X_PORT_NUM 9 +#define YT922X_PCS_LINK_CTRL 0x11 +#define YT922X_PCS_LINK_STATUS BIT(10) +#define YT922X_PCS_AN_COMPLETE BIT(11) +#define YT922X_PCS_WRITE_PROTECT 0x4be + +#define YT922X_LAG_NUM 4 + +#define YT922X_PORTn_ISOLATION(port) (0x180d80 + 0x4 * (port)) + +#define YT922X_PORTn_LEARN(port) (0x180300 + 4 * (port)) +#define YT922X_PORT_LEARN_DIS BIT(18) + +#define YT922X_FUNC_ACL BIT(5) +#define YT922X_FUNC_MIB BIT(4) + +#define YT922X_FILTER_UNK_UCAST 0x180ec8 +#define YT922X_ACT_UNK_UCAST 0x180ed8 +#define YT922X_ACT_UNK_MCAST 0x180ee0 +#define YT922X_ACT_UNK_MCAST_BYPASS_DROP_PIM BIT(22) +#define YT922X_ACT_UNK_MCAST_BYPASS_DROP_MLD BIT(21) +#define YT922X_ACT_UNK_MCAST_BYPASS_DROP_IGMP BIT(20) +#define YT922X_ACT_UNK_ACTn_M(port) GENMASK(2 * (port) + 1, 2 * (port)) +#define YT922X_ACT_UNK_ACTn(port, x) ((x) << (2 * (port))) +#define YT922X_ACT_UNK_ACTn_FORWARD(port) YT922X_ACT_UNK_ACTn(port, 0) = /* flood */ +#define YT922X_ACT_UNK_ACTn_DROP(port) YT922X_ACT_UNK_ACTn(port, 1) /*= discard */ +#define YT922X_ACT_UNK_ACTn_TRAP(port) YT922X_ACT_UNK_ACTn(port, 3) /*= steer to CPU */ + +#define YT922X_CPU_COPY 0x181100 +#define YT922X_CPU_COPY_TO_INT_CPU BIT(1) +#define YT922X_CPU_COPY_TO_EXT_CPU BIT(0) +#define YT922X_CPU_TAG_RX_CTRL 0x80504 +#define YT922X_CPU_TAG_RX_MODE BIT(0) +#define YT922X_CPU_TAG_TX_CTRL 0x100710 +#define YT922X_CPU_TAG_TX_TYPE BIT(0) +#define YT922X_CPU_TAG_TX_MODE BIT(1) +#define YT922X_CPU_TAG_TX_CTAG_OP BIT(2) +#define YT922X_CPU_TAG_TX_STAG_OP BIT(3) +/* Define top ext addr for yt922x */ +#define YT922X_COMMON_EXT_PHYADDR 9 + +enum yt922x_phy_reg_type { + YT922X_PHY_REG_TYPE_COMMON_EXT, + YT922X_PHY_REG_TYPE_SDS_COMMON_EXT, + YT922X_PHY_REG_TYPE_MII, + YT922X_PHY_REG_TYPE_EXT, + YT922X_PHY_REG_TYPE_MAX +}; + struct yt921x_port { unsigned char index; =20 @@ -569,6 +649,8 @@ static inline int ethtool_speed_to_yt921x(int speed) return YT921X_SPEED_2500; case SPEED_10000: return YT921X_SPEED_10000; + case SPEED_5000: + return YT921X_SPEED_5000; default: return YT921X_SPEED_INVALID; } diff --git a/drivers/net/dsa/motorcomm/mdio_bus.c b/drivers/net/dsa/motorco= mm/mdio_bus.c index 3aa1111efaa4..d545f338bd9d 100644 --- a/drivers/net/dsa/motorcomm/mdio_bus.c +++ b/drivers/net/dsa/motorcomm/mdio_bus.c @@ -107,6 +107,45 @@ yt921x_intif_modify_changed(struct yt921x_priv *priv, = int port, int reg, return 1; } =20 +/* intif extend register read/write api */ +int +yt921x_intif_ext_write(struct yt921x_priv *priv, int port, int reg, u16 va= l) +{ + int res; + + if (port > priv->series->max_ports) + return -ENODEV; + + res =3D yt921x_intif_write(priv, port, YT92XX_PAGE_SELECT, reg); + if (res) + return res; + + res =3D yt921x_intif_write(priv, port, YT92XX_PAGE, val); + if (res) + return res; + + return 0; +} + +int +yt921x_intif_ext_read(struct yt921x_priv *priv, int port, int reg, u16 *va= lp) +{ + int res; + + if (port > priv->series->max_ports) + return -ENODEV; + + res =3D yt921x_intif_write(priv, port, YT92XX_PAGE_SELECT, reg); + if (res) + return res; + + res =3D yt921x_intif_read(priv, port, YT92XX_PAGE, valp); + if (res) + return res; + + return 0; +} + static int yt921x_mbus_int_read(struct mii_bus *mbus, int port, int reg) { struct yt921x_priv *priv =3D mbus->priv; @@ -299,3 +338,4 @@ int yt921x_mbus_ext_init(struct yt921x_priv *priv, stru= ct device_node *mnp) =20 return 0; } + diff --git a/drivers/net/dsa/motorcomm/mdio_bus.h b/drivers/net/dsa/motorco= mm/mdio_bus.h index e79b725d435b..238a35891cb1 100644 --- a/drivers/net/dsa/motorcomm/mdio_bus.h +++ b/drivers/net/dsa/motorcomm/mdio_bus.h @@ -35,6 +35,10 @@ struct yt921x_priv; =20 int yt921x_intif_read(struct yt921x_priv *priv, int port, int reg, u16 *va= lp); int yt921x_intif_write(struct yt921x_priv *priv, int port, int reg, u16 va= l); +int yt921x_intif_ext_write(struct yt921x_priv *priv, int port, int reg, + u16 val); +int yt921x_intif_ext_read(struct yt921x_priv *priv, int port, int reg, + u16 *valp); int yt921x_intif_modify_changed(struct yt921x_priv *priv, int port, int re= g, u16 mask, u16 val); =20 diff --git a/drivers/net/dsa/motorcomm/pcs-922x.c b/drivers/net/dsa/motorco= mm/pcs-922x.c new file mode 100644 index 000000000000..5ad7873e0df7 --- /dev/null +++ b/drivers/net/dsa/motorcomm/pcs-922x.c @@ -0,0 +1,282 @@ +// SPDX-License-Identifier: GPL-2.0-or-later +/* + * Copyright (c) 2026 Kyle Switch + */ + +#include "chip.h" +#include "mdio_bus.h" +#include "pcs.h" +#include "smi.h" + +#define to_device(priv) ((priv)->ds.dev) + +static int yt922x_sds_phyaddr_get(int port, + enum yt922x_phy_reg_type reg_type) +{ + if (reg_type =3D=3D YT922X_PHY_REG_TYPE_COMMON_EXT) + return YT922X_COMMON_EXT_PHYADDR; + + return port; +} + +static void yt922x_pcs_get_state(struct phylink_pcs *pcs, unsigned int neg= _mode, + struct phylink_link_state *state) +{ + struct yt921x_port *pp =3D pcs_to_yt921x_port(pcs); + struct yt921x_priv *priv =3D yt921x_port_to_priv(pp); + int port =3D pp->index; + u16 link_ctrl; + int res; + u16 bmsr; + int addr; + u16 lp; + + addr =3D yt922x_sds_phyaddr_get(port, YT922X_PHY_REG_TYPE_MII); + if (addr < 0) { + state->link =3D false; + return; + } + + mutex_lock(&priv->reg_lock); + switch (state->interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: + res =3D yt921x_intif_read(priv, addr, MII_BMSR, &bmsr); + if (res) + goto err; + res =3D yt921x_intif_read(priv, addr, MII_LPA, &lp); + if (res) + goto err; + phylink_mii_c22_pcs_decode_state(state, neg_mode, bmsr, lp); + break; + case PHY_INTERFACE_MODE_100BASEX: + res =3D yt921x_intif_read(priv, addr, MII_BMSR, &bmsr); + if (res) + goto err; + state->speed =3D SPEED_100; + state->duplex =3D DUPLEX_FULL; + state->pause |=3D MLO_PAUSE_TX | MLO_PAUSE_RX; + state->link =3D !!(bmsr & BMSR_LSTATUS); + break; + case PHY_INTERFACE_MODE_USXGMII: + res =3D yt921x_intif_read(priv, addr, YT922X_PCS_LINK_CTRL, + &link_ctrl); + if (res) + goto err; + state->link =3D FIELD_GET(YT922X_PCS_LINK_STATUS, link_ctrl); + state->an_complete =3D FIELD_GET(YT922X_PCS_AN_COMPLETE, + link_ctrl); + res =3D yt921x_intif_read(priv, addr, MII_LPA, &lp); + if (res) + goto err; + if (state->link) + phylink_decode_usxgmii_word(state, lp); + break; + default: + state->link =3D false; + break; + } + mutex_unlock(&priv->reg_lock); + return; + +err: + mutex_unlock(&priv->reg_lock); + state->link =3D false; +} + +static void yt922x_pcs_an_restart(struct phylink_pcs *pcs) +{ + struct yt921x_port *pp =3D pcs_to_yt921x_port(pcs); + struct yt921x_priv *priv =3D yt921x_port_to_priv(pp); + struct device *dev =3D to_device(priv); + int port =3D pp->index; + u16 bmcr; + int addr; + int res; + + addr =3D yt922x_sds_phyaddr_get(port, YT922X_PHY_REG_TYPE_MII); + if (addr < 0) { + dev_err(dev, "Invalid SDS PHY addr for port %d\n", port); + return; + } + + mutex_lock(&priv->reg_lock); + res =3D yt921x_intif_read(priv, addr, MII_BMCR, &bmcr); + if (res) + goto err; + bmcr |=3D BMCR_ANRESTART; + bmcr |=3D BMCR_RESET; + res =3D yt921x_intif_write(priv, addr, MII_BMCR, bmcr); + if (res) + goto err; + mutex_unlock(&priv->reg_lock); + return; + +err: + mutex_unlock(&priv->reg_lock); + dev_err(dev, "Failed to an restart PCS port %d: %i\n", port, res); +} + +static int yt922x_pcs_config(struct phylink_pcs *pcs, unsigned int neg_mod= e, + phy_interface_t interface, + const unsigned long *advertising, + bool permit_pause_to_mac) +{ + bool inband =3D neg_mode & PHYLINK_PCS_NEG_INBAND; + struct yt921x_port *pp =3D pcs_to_yt921x_port(pcs); + struct yt921x_priv *priv =3D yt921x_port_to_priv(pp); + bool changed =3D false; + int res, port; + u16 bmcr_old; + u16 bmcr_new; + u16 data; + u16 ctrl; + int addr; + int adv; + + port =3D pp->index; + addr =3D yt922x_sds_phyaddr_get + (port, YT922X_PHY_REG_TYPE_SDS_COMMON_EXT); + if (addr < 0) + return addr; + + mutex_lock(&priv->reg_lock); + + /* write protect */ + res =3D yt921x_intif_ext_write(priv, addr, YT922X_PCS_WRITE_PROTECT, 0xd); + if (res) + goto err; + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + ctrl =3D YT922X_SERDES_MODE_SGMII; + break; + case PHY_INTERFACE_MODE_100BASEX: + ctrl =3D YT922X_SERDES_MODE_100BASEX; + break; + case PHY_INTERFACE_MODE_1000BASEX: + ctrl =3D YT922X_SERDES_MODE_1000BASEX; + break; + case PHY_INTERFACE_MODE_2500BASEX: + ctrl =3D YT922X_SERDES_MODE_2500BASEX; + break; + case PHY_INTERFACE_MODE_USXGMII: + ctrl =3D YT922X_SERDES_MODE_USXGMII; + break; + default: + res =3D -EINVAL; + goto err; + } + res =3D yt921x_intif_ext_read(priv, addr, YT922X_PORT_SDSn, &data); + if (res) + goto err; + data &=3D ~YT922X_SERDES_MODE_M; + data |=3D ctrl; + res =3D yt921x_intif_ext_write(priv, addr, YT922X_PORT_SDSn, data); + if (res) + goto err; + + if (inband) { + adv =3D phylink_mii_c22_pcs_encode_advertisement(interface, + advertising); + if (adv >=3D 0) { + res =3D yt921x_intif_modify_changed(priv, port, + MII_ADVERTISE, + U16_MAX, adv); + if (res < 0) + goto err; + + changed =3D !!res; + } + } + + res =3D yt921x_intif_read(priv, port, MII_BMCR, &bmcr_old); + if (res) + goto err; + + bmcr_new =3D bmcr_old; + if (neg_mode =3D=3D PHYLINK_PCS_NEG_INBAND_ENABLED) + bmcr_new |=3D BMCR_ANENABLE; + else + bmcr_new &=3D ~BMCR_ANENABLE; + + changed |=3D (bmcr_new !=3D bmcr_old); + + res =3D yt921x_intif_write(priv, port, MII_BMCR, bmcr_new); + if (res) + goto err; + pp->inband =3D inband; + mutex_unlock(&priv->reg_lock); + + return changed; + +err: + mutex_unlock(&priv->reg_lock); + + return res; +} + +static int yt922x_pcs_enable(struct phylink_pcs *pcs) +{ + struct yt921x_port *pp =3D pcs_to_yt921x_port(pcs); + struct yt921x_priv *priv =3D yt921x_port_to_priv(pp); + struct device *dev =3D yt921x_priv_to_device(priv); + int port =3D pp->index; + int addr; + u16 bmcr; + int res; + + addr =3D yt922x_sds_phyaddr_get(port, YT922X_PHY_REG_TYPE_MII); + if (addr < 0) + return addr; + + mutex_lock(&priv->reg_lock); + + res =3D yt921x_intif_read(priv, addr, MII_BMCR, &bmcr); + if (res) + goto end; + + bmcr &=3D ~BMCR_PDOWN; + bmcr |=3D BMCR_ANRESTART; + res =3D yt921x_intif_write(priv, addr, MII_BMCR, bmcr); + +end: + mutex_unlock(&priv->reg_lock); + + if (res) + dev_err(dev, "Failed to enable PCS port %d: %i\n", port, res); + + return res; +} + +static void yt922x_pcs_disable(struct phylink_pcs *pcs) +{ + struct yt921x_port *pp =3D pcs_to_yt921x_port(pcs); + struct yt921x_priv *priv =3D yt921x_port_to_priv(pp); + struct device *dev =3D yt921x_priv_to_device(priv); + int port =3D pp->index; + int addr; + int res; + + addr =3D yt922x_sds_phyaddr_get(port, YT922X_PHY_REG_TYPE_MII); + if (addr < 0) { + dev_err(dev, "Invalid SDS PHY addr for port %d\n", port); + return; + } + + mutex_lock(&priv->reg_lock); + res =3D yt921x_intif_modify(priv, addr, MII_BMCR, BMCR_PDOWN, BMCR_PDOWN); + mutex_unlock(&priv->reg_lock); + + if (res) + dev_err(dev, "Failed to power down PCS port %d: %i\n", port, + res); +} + +const struct phylink_pcs_ops yt922x_phylink_pcs_ops =3D { + .pcs_get_state =3D yt922x_pcs_get_state, + .pcs_config =3D yt922x_pcs_config, + .pcs_an_restart =3D yt922x_pcs_an_restart, + .pcs_enable =3D yt922x_pcs_enable, + .pcs_disable =3D yt922x_pcs_disable, +}; diff --git a/drivers/net/dsa/motorcomm/pcs.h b/drivers/net/dsa/motorcomm/pc= s.h index 42426558086a..c85caa7bf212 100644 --- a/drivers/net/dsa/motorcomm/pcs.h +++ b/drivers/net/dsa/motorcomm/pcs.h @@ -9,5 +9,6 @@ #include =20 extern const struct phylink_pcs_ops yt921x_phylink_pcs_ops; +extern const struct phylink_pcs_ops yt922x_phylink_pcs_ops; =20 #endif --=20 2.25.1