From nobody Fri Sep 25 10:04:09 2026 Received: from out28-196.mail.aliyun.com (out28-196.mail.aliyun.com [115.124.28.196]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 14B1B43802E; Mon, 14 Sep 2026 10:30:23 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.196 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789381827; cv=none; b=AH87q22D3HmXW63h6PkTpC2Pqoqkof0GlYNSHVXQSjw3Ro218sQ+hCz/okNKHoI2BjvCMyFaLjy7AOLsLQNJRvHTK2NvcHF9Qdw0fy4Lbcgfyo5HIsxNfGLbvmEhBPAleu21mRR2qMYC1apbn8Y4x7QV6of3CBDgFHydn+lEBW4= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789381827; c=relaxed/simple; bh=PWSCwWhdYjr30m64WSuX9aXTMEFHksAvQ5i69/b+kYU=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=G5OOmynl0vUod1u4olZjRWlXeXuDvKjpmCqIyBjgknXO2xPeigHQExalloO+SwxkR/Tv+QAyU/B8ddhxQm/JAsAOmkf5pzIzv71tvJq7BXhgOAKiCv4DLJ146YLqU/GlOEx+y5lqsJwiE+wkXr9Sogm/dhcO3AdR6ZoyTnb8YKw= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=motor-comm.com; spf=pass smtp.mailfrom=motor-comm.com; arc=none smtp.client-ip=115.124.28.196 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.07503052|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.111835-0.000323507-0.887841;FP=13871053214251095700|0|0|0|0|-1|-1|-1;HT=maildocker-contentspam033023018039;MF=kyle.switch@motor-comm.com;NM=1;PH=DS;RN=16;RT=16;SR=0;TI=SMTPD_---.jDMP.hl_1789381814; Received: from motor-comm.com(mailfrom:kyle.switch@motor-comm.com fp:SMTPD_---.jDMP.hl_1789381814 cluster:ay29) by smtp.aliyun-inc.com; Mon, 14 Sep 2026 18:30:15 +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 v7 1/6] net: dsa: motorcomm: initialize dsa_switch based on chipid Date: Mon, 14 Sep 2026 18:30:04 +0800 Message-Id: <20260914103009.3007019-2-kyle.switch@motor-comm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260914103009.3007019-1-kyle.switch@motor-comm.com> References: <20260914103009.3007019-1-kyle.switch@motor-comm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Introduce yt92xx_series structure to hold private data for different switch families, replacing hardcoded logic in probe(). This makes the driver more extensible for future switch support. Signed-off-by: Kyle Switch --- drivers/net/dsa/motorcomm/chip.c | 71 +++++++++++++++++++++++++++----- drivers/net/dsa/motorcomm/chip.h | 20 +++++++++ 2 files changed, 81 insertions(+), 10 deletions(-) diff --git a/drivers/net/dsa/motorcomm/chip.c b/drivers/net/dsa/motorcomm/c= hip.c index d663af010f43..1f9c0c67ad4a 100644 --- a/drivers/net/dsa/motorcomm/chip.c +++ b/drivers/net/dsa/motorcomm/chip.c @@ -4679,6 +4679,61 @@ 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 { + .mode =3D YT92XX_MODE_YT921X, + .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 to_yt921x_priv(ds); + const struct yt92xx_series *series; + u32 chipid; + u32 major; + int res; + + res =3D yt921x_reg_read(priv, YT921X_CHIP_ID, &chipid); + if (res) + return res; + + major =3D FIELD_GET(YT921X_CHIP_ID_MAJOR, chipid); + series =3D yt92xx_series_lookup(major); + if (!series) + 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); @@ -4727,6 +4782,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) @@ -4754,15 +4810,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 @@ -4770,8 +4821,8 @@ 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,yt9215", }, + { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, yt921x_of_match); =20 diff --git a/drivers/net/dsa/motorcomm/chip.h b/drivers/net/dsa/motorcomm/c= hip.h index 83cd454955dd..c446aea449ed 100644 --- a/drivers/net/dsa/motorcomm/chip.h +++ b/drivers/net/dsa/motorcomm/chip.h @@ -960,9 +960,29 @@ struct yt921x_reg_ops { int (*write)(void *context, u32 reg, u32 val); }; =20 +enum yt92xx_mode { + YT92XX_MODE_YT921X, + YT92XX_MODE_YT922X, + YT92XX_MODE_MAX, +}; + +struct yt92xx_series { + enum yt92xx_mode mode; + 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 Fri Sep 25 10:04:09 2026 Received: from out28-121.mail.aliyun.com (out28-121.mail.aliyun.com [115.124.28.121]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id EDFF6438036; Mon, 14 Sep 2026 10:30:24 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.121 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789381827; cv=none; b=PXyflRsPmb8u4BbysTRDrpSXZ7EZpXAvo9yrj5MFJEG6mWPXD6tpaNk58piKCcH/tXR3P8+YL4CQ4gzdT1x6rlStjCxVb9eayQoEantARlmtuWhB8M5YlEzFhrb6Ii4XcsOGM6fqirwtN3n+XB93hA5jQCLXO6YMPDIHepiD7as= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789381827; c=relaxed/simple; bh=YxOPeZ7y4cd3eiKeilX+GHHcP7fBaREigJVEDIido1g=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=sFAVw2A8tg9jmNq0Pgp3WlflcsbLl6rwyzseMneqxIorAQh45YuDqBSldMeGjy0xETrxC0JGiR+uUZfuZD3EXuSPW92gDx+VltMtCwKrlGViV9ZjwOlcbVjhlE/S6/Chn93D8DFOpbI5CRo3GNat5GyRq6SBVqTwTpJ37jVPafg= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=motor-comm.com; spf=pass smtp.mailfrom=motor-comm.com; arc=none smtp.client-ip=115.124.28.121 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.08751547|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.00731352-9.94324e-05-0.992587;FP=16390769864486842006|0|0|0|0|-1|-1|-1;HT=maildocker-contentspam033032053168;MF=kyle.switch@motor-comm.com;NM=1;PH=DS;RN=16;RT=16;SR=0;TI=SMTPD_---.jDMP.j-_1789381815; Received: from motor-comm.com(mailfrom:kyle.switch@motor-comm.com fp:SMTPD_---.jDMP.j-_1789381815 cluster:ay29) by smtp.aliyun-inc.com; Mon, 14 Sep 2026 18:30:16 +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 v7 2/6] net: dsa: motorcomm: use max_ports in series for port bounds checking Date: Mon, 14 Sep 2026 18:30:05 +0800 Message-Id: <20260914103009.3007019-3-kyle.switch@motor-comm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260914103009.3007019-1-kyle.switch@motor-comm.com> References: <20260914103009.3007019-1-kyle.switch@motor-comm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: 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. Signed-off-by: Kyle Switch --- drivers/net/dsa/motorcomm/chip.c | 8 +++++--- 1 file changed, 5 insertions(+), 3 deletions(-) diff --git a/drivers/net/dsa/motorcomm/chip.c b/drivers/net/dsa/motorcomm/c= hip.c index 1f9c0c67ad4a..4479bb1c3c2b 100644 --- a/drivers/net/dsa/motorcomm/chip.c +++ b/drivers/net/dsa/motorcomm/chip.c @@ -357,7 +357,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); @@ -375,7 +375,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); @@ -390,6 +390,7 @@ yt921x_mbus_int_init(struct yt921x_priv *priv, struct d= evice_node *mnp) { struct device *dev =3D to_device(priv); struct mii_bus *mbus; + u32 max_ports; int res; =20 mbus =3D devm_mdiobus_alloc(dev); @@ -402,7 +403,8 @@ yt921x_mbus_int_init(struct yt921x_priv *priv, struct d= evice_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 Fri Sep 25 10:04:09 2026 Received: from out28-1.mail.aliyun.com (out28-1.mail.aliyun.com [115.124.28.1]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id F20E2438493; Mon, 14 Sep 2026 10:30:25 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.1 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789381828; cv=none; b=JI1DMANMWF8N6tFDJDD+o9qRb1qnMmKXeqc2it/O5gizddS2SuDB1Dv4Y3e7QjZz7bC06GPsZq3Bd935TRPhwb2uph2w7bvw4IarIQ5w2Pz+TNT6sJAFsWl4wQQW3GLYfXc5TF9FKvE/vQL7NSR8zHHViAd5aiAQhH+YZHprIwk= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789381828; c=relaxed/simple; bh=0rTLb1g6wyCCpNc+mbOO+/sX93Z+xvX5PIU7M0k8o3Y=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=p2R1V5k7chwNmYVJD2In+4MdiYbXc05ZOkrPDcQECQYCjSWVeqnE2gk7oXglRvHZRr7+TfAz4EjHCXZUhdRwekeA1GcXmKUk1dvZRd+CH4Hk0xPYujDJygO7K9BE8UYX2oXzIRpwh07w8WmxX1r3hTkiLC0TbzafHavTOpS4vO4= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=motor-comm.com; spf=pass smtp.mailfrom=motor-comm.com; arc=none smtp.client-ip=115.124.28.1 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.1159184|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.0201756-0.000204846-0.97962;FP=11706605139178063524|0|0|0|0|-1|-1|-1;HT=maildocker-contentspam033037028158;MF=kyle.switch@motor-comm.com;NM=1;PH=DS;RN=16;RT=16;SR=0;TI=SMTPD_---.jDMP.jl_1789381816; Received: from motor-comm.com(mailfrom:kyle.switch@motor-comm.com fp:SMTPD_---.jDMP.jl_1789381816 cluster:ay29) by smtp.aliyun-inc.com; Mon, 14 Sep 2026 18:30:17 +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 v7 3/6] net: dsa: motorcomm: move mib start from probe() to dsa_setup() Date: Mon, 14 Sep 2026 18:30:06 +0800 Message-Id: <20260914103009.3007019-4-kyle.switch@motor-comm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260914103009.3007019-1-kyle.switch@motor-comm.com> References: <20260914103009.3007019-1-kyle.switch@motor-comm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Move MIB polling start from probe() to dsa_setup().so that it can be enabled based on the actual switch family support. Signed-off-by: Kyle Switch --- drivers/net/dsa/motorcomm/chip.c | 15 ++++++++------- 1 file changed, 8 insertions(+), 7 deletions(-) diff --git a/drivers/net/dsa/motorcomm/chip.c b/drivers/net/dsa/motorcomm/c= hip.c index 4479bb1c3c2b..49729db9993b 100644 --- a/drivers/net/dsa/motorcomm/chip.c +++ b/drivers/net/dsa/motorcomm/chip.c @@ -4553,6 +4553,14 @@ static int yt921x_dsa_setup(struct dsa_switch *ds) struct device_node *child; int res; =20 + /* mib polling init */ + for (size_t i =3D 0; i < ARRAY_SIZE(priv->ports); i++) { + struct yt921x_port *pp =3D &priv->ports[i]; + + pp->index =3D i; + INIT_DELAYED_WORK(&pp->mib_read, yt921x_poll_mib); + } + mutex_lock(&priv->reg_lock); res =3D yt921x_chip_reset(priv); mutex_unlock(&priv->reg_lock); @@ -4803,13 +4811,6 @@ static int yt921x_mdio_probe(struct mdio_device *mdi= odev) priv->reg_ops =3D &yt921x_reg_ops_mdio; priv->reg_ctx =3D mdio; =20 - for (size_t i =3D 0; i < ARRAY_SIZE(priv->ports); i++) { - struct yt921x_port *pp =3D &priv->ports[i]; - - pp->index =3D i; - INIT_DELAYED_WORK(&pp->mib_read, yt921x_poll_mib); - } - ds =3D &priv->ds; ds->dev =3D dev; ds->priv =3D priv; --=20 2.25.1 From nobody Fri Sep 25 10:04:09 2026 Received: from out28-171.mail.aliyun.com (out28-171.mail.aliyun.com [115.124.28.171]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 277EA439F98; Mon, 14 Sep 2026 10:30:27 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.171 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789381830; cv=none; b=LdGLXOckI9O+lkk6NlunfkKyFU+3bI/iBEgPQ+WXrVW/hgVAlaE2s2LSYO2lVb0Pe9qFm+ypVhoHbGnDl47KYGGKZdNLcu9W/1OXsPmrchRu3DHb1w9C4WRgDM/PZB3pe36LVOVteDzX5TmjVMD7FRtBjyv8Mu2dgR1n7B6xi1g= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789381830; c=relaxed/simple; bh=ckVaGW28ZIIYhmeR1PVp3/ImlxvhY5AwYYvOxljlUjY=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=XYxobQyIXmVd/eqsfG6DkVms2ZiLbbuEaHvJIuyqehDmRv5h3hegAlVDxm5yNWdTvsHKjk/iCRNDoP+6HIArNXCXsnFgO4ezXijjjM3xpaeCBlXyapLKVmdkHsE++3fZNtO+lBOxa4lnxXV61wE3oQL/58M1o+igszxqUsmdK1I= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=motor-comm.com; spf=pass smtp.mailfrom=motor-comm.com; arc=none smtp.client-ip=115.124.28.171 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.1265506|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_system_inform|0.220266-0.00123502-0.778499;FP=11814690448842735232|0|0|0|0|-1|-1|-1;HT=maildocker-contentspam033068005250;MF=kyle.switch@motor-comm.com;NM=1;PH=DS;RN=16;RT=16;SR=0;TI=SMTPD_---.jDMP.ku_1789381817; Received: from motor-comm.com(mailfrom:kyle.switch@motor-comm.com fp:SMTPD_---.jDMP.ku_1789381817 cluster:ay29) by smtp.aliyun-inc.com; Mon, 14 Sep 2026 18:30:18 +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 v7 4/6] net: dsa: motorcomm: move mib stop from remove() to teardown() Date: Mon, 14 Sep 2026 18:30:07 +0800 Message-Id: <20260914103009.3007019-5-kyle.switch@motor-comm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260914103009.3007019-1-kyle.switch@motor-comm.com> References: <20260914103009.3007019-1-kyle.switch@motor-comm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" This change ensures symmetry with the MIB start operation, which is already invoked in the setup(). Additionally, it consolidates per-switch operation into the appropriate DSA ops, improving code organization and maintainability. Signed-off-by: Kyle Switch --- drivers/net/dsa/motorcomm/chip.c | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/drivers/net/dsa/motorcomm/chip.c b/drivers/net/dsa/motorcomm/c= hip.c index 49729db9993b..3f56d60da8ea 100644 --- a/drivers/net/dsa/motorcomm/chip.c +++ b/drivers/net/dsa/motorcomm/chip.c @@ -4233,6 +4233,11 @@ static void yt921x_dsa_teardown(struct dsa_switch *d= s) #if IS_ENABLED(CONFIG_NET_DSA_YT921X_LEDS) yt921x_leds_remove(priv); #endif + for (size_t i =3D ARRAY_SIZE(priv->ports); i-- > 0; ) { + struct yt921x_port *pp =3D &priv->ports[i]; + + disable_delayed_work_sync(&pp->mib_read); + } } =20 static int yt921x_chip_detect(struct yt921x_priv *priv) @@ -4761,12 +4766,6 @@ static void yt921x_mdio_remove(struct mdio_device *m= diodev) if (!priv) return; =20 - for (size_t i =3D ARRAY_SIZE(priv->ports); i-- > 0; ) { - struct yt921x_port *pp =3D &priv->ports[i]; - - disable_delayed_work_sync(&pp->mib_read); - } - dsa_unregister_switch(&priv->ds); =20 for (unsigned int i =3D 0; i < ARRAY_SIZE(priv->acl_blks); i++) { --=20 2.25.1 From nobody Fri Sep 25 10:04:09 2026 Received: from out28-99.mail.aliyun.com (out28-99.mail.aliyun.com [115.124.28.99]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 5DD5E43A812; Mon, 14 Sep 2026 10:30:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.99 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789381831; cv=none; b=hssRJYVYIzQbTC3OG2BDK9HjlnCkMTgq2pFaUZwj1CUdoe/UOJLnycurW/QvH7jWyED9CVigiHIorqhvAYAXjxPh6M94TussCLwjAvxo/A3XmXdVi9kUVwVzOvexy2O0rajNy+SYybd8DAqsxPT76OtlKINh6lnnzBVBucJEOws= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789381831; c=relaxed/simple; bh=cWcR3NF6dmpZ5N01x5Daet1Ub7pZTU2NTOVNzaxZaqQ=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=YWGHscI7hvYhNaxNLvsGpzSQ3NeD8s+i0sWv37x86KgkvItBZFBcB6YpoKaWsRf/EeJsXiQVp8o9CUA3Be7RNHuPIV/D58zT+KyqO39y5TyIc05Kd00+IQKXer78zeTz2KFNtHcRRy+n/sTRH1I5ZKRUhnB9iVnDQe7iJEIxF3M= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=motor-comm.com; spf=pass smtp.mailfrom=motor-comm.com; arc=none smtp.client-ip=115.124.28.99 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.07437167|-1;CH=green;DM=|CONTINUE|false|;DS=CONTINUE|ham_alarm|0.0202984-0.000282288-0.979419;FP=10833301415773638288|0|0|0|0|-1|-1|-1;HT=maildocker-contentspam033023018039;MF=kyle.switch@motor-comm.com;NM=1;PH=DS;RN=16;RT=16;SR=0;TI=SMTPD_---.jDMP.ln_1789381818; Received: from motor-comm.com(mailfrom:kyle.switch@motor-comm.com fp:SMTPD_---.jDMP.ln_1789381818 cluster:ay29) by smtp.aliyun-inc.com; Mon, 14 Sep 2026 18:30:18 +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 v7 5/6] net: dsa: tag_yt922x: add support for Motorcomm YT922x tags Date: Mon, 14 Sep 2026 18:30:08 +0800 Message-Id: <20260914103009.3007019-6-kyle.switch@motor-comm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260914103009.3007019-1-kyle.switch@motor-comm.com> References: <20260914103009.3007019-1-kyle.switch@motor-comm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: MIME-Version: 1.0 Content-Transfer-Encoding: quoted-printable Content-Type: text/plain; charset="utf-8" Add support for Motorcomm YT922x tags with 8bytes. which includes ethertype field (default to 0x9988). Signed-off-by: Kyle Switch --- include/net/dsa.h | 2 + net/dsa/Kconfig | 6 +++ net/dsa/Makefile | 1 + net/dsa/tag_yt922x.c | 111 +++++++++++++++++++++++++++++++++++++++++++ 4 files changed, 120 insertions(+) create mode 100644 net/dsa/tag_yt922x.c diff --git a/include/net/dsa.h b/include/net/dsa.h index 7507d632e7c6..0807a595aaad 100644 --- a/include/net/dsa.h +++ b/include/net/dsa.h @@ -61,6 +61,7 @@ struct tc_action; #define DSA_TAG_PROTO_NETC_VALUE 33 #define DSA_TAG_PROTO_KSZ8463_VALUE 34 #define DSA_TAG_PROTO_MT7628_VALUE 35 +#define DSA_TAG_PROTO_YT922X_VALUE 36 =20 enum dsa_tag_protocol { DSA_TAG_PROTO_NONE =3D DSA_TAG_PROTO_NONE_VALUE, @@ -99,6 +100,7 @@ enum dsa_tag_protocol { DSA_TAG_PROTO_NETC =3D DSA_TAG_PROTO_NETC_VALUE, DSA_TAG_PROTO_KSZ8463 =3D DSA_TAG_PROTO_KSZ8463_VALUE, DSA_TAG_PROTO_MT7628 =3D DSA_TAG_PROTO_MT7628_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 23b4b74004ed..0b9f8a632cf2 100644 --- a/net/dsa/Kconfig +++ b/net/dsa/Kconfig @@ -227,4 +227,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 d15bcf5c68f0..0c53f4184bdb 100644 --- a/net/dsa/Makefile +++ b/net/dsa/Makefile @@ -44,6 +44,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..1ee9d1773598 --- /dev/null +++ b/net/dsa/tag_yt922x.c @@ -0,0 +1,111 @@ +// 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: + */ +#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_= TAG_PRIO_EN) +#define YT922X_TAG_RX_PORT_M GENMASK(5, 2) +#define YT922X_TAG_RX_PRIO_M GENMASK(15, 13) + +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 Fri Sep 25 10:04:09 2026 Received: from out28-149.mail.aliyun.com (out28-149.mail.aliyun.com [115.124.28.149]) (using TLSv1.2 with cipher ECDHE-RSA-AES256-GCM-SHA384 (256/256 bits)) (No client certificate requested) by smtp.subspace.kernel.org (Postfix) with ESMTPS id 0724C43900F; Mon, 14 Sep 2026 10:30:28 +0000 (UTC) Authentication-Results: smtp.subspace.kernel.org; arc=none smtp.client-ip=115.124.28.149 ARC-Seal: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789381832; cv=none; b=cRIEDoWHGaSjMfhZECqugJfRO0sTVlB2iJpIY2cfoiroCLC0d3i0IDNu1jskTJOSwgdsmaXuLENu2rNVzVI42m1Bns+ItOJ36u2nIhhJfiUFd5rEzExYlkl6B8RL7I0BbNFaEZ1uKzg417e5yZmfu34zJL5FL4mgLb/VY3W4UWg= ARC-Message-Signature: i=1; a=rsa-sha256; d=subspace.kernel.org; s=arc-20240116; t=1789381832; c=relaxed/simple; bh=6ZeWEsO08EsaNFRCnWIhC+NkOxYyKxkGVU9+bYP5Z6A=; h=From:To:Cc:Subject:Date:Message-Id:In-Reply-To:References: MIME-Version; b=IItYnslgTLhqb2oryj6noxBFeCEDqdloNIVbGuGH7PmnJwkeeFmC7cduLLRNcZOsVZo/DF/uqG94Nh3ZSCu4cRVM0iRtp7sv+eHXA7HogUgbSezktFzswxLA/6uPmwa8wqV8iSBnANsJaCJlVQD3H8aM4C1OwDT5eixGrprOVLY= ARC-Authentication-Results: i=1; smtp.subspace.kernel.org; dmarc=pass (p=none dis=none) header.from=motor-comm.com; spf=pass smtp.mailfrom=motor-comm.com; arc=none smtp.client-ip=115.124.28.149 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.0754911-0.000834194-0.923675;FP=15184873885425945268|0|0|0|0|-1|-1|-1;HT=maildocker-contentspam033032053168;MF=kyle.switch@motor-comm.com;NM=1;PH=DS;RN=16;RT=16;SR=0;TI=SMTPD_---.jDMP.mn_1789381819; Received: from motor-comm.com(mailfrom:kyle.switch@motor-comm.com fp:SMTPD_---.jDMP.mn_1789381819 cluster:ay29) by smtp.aliyun-inc.com; Mon, 14 Sep 2026 18:30:19 +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 v7 6/6] net: dsa: motorcomm: Add support for Motorcomm YT922x Date: Mon, 14 Sep 2026 18:30:09 +0800 Message-Id: <20260914103009.3007019-7-kyle.switch@motor-comm.com> X-Mailer: git-send-email 2.25.1 In-Reply-To: <20260914103009.3007019-1-kyle.switch@motor-comm.com> References: <20260914103009.3007019-1-kyle.switch@motor-comm.com> Precedence: bulk X-Mailing-List: linux-kernel@vger.kernel.org List-Id: List-Subscribe: List-Unsubscribe: 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 adds basic support for a working DSA switch. Signed-off-by: Kyle Switch --- drivers/net/dsa/motorcomm/Kconfig | 1 + drivers/net/dsa/motorcomm/chip.c | 874 +++++++++++++++++++++++++++++- drivers/net/dsa/motorcomm/chip.h | 99 ++++ 3 files changed, 972 insertions(+), 2 deletions(-) diff --git a/drivers/net/dsa/motorcomm/Kconfig b/drivers/net/dsa/motorcomm/= Kconfig index 79cdd79a1fd2..f690de4c7a7c 100644 --- a/drivers/net/dsa/motorcomm/Kconfig +++ b/drivers/net/dsa/motorcomm/Kconfig @@ -2,6 +2,7 @@ config NET_DSA_YT921X tristate "Motorcomm YT9215 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 diff --git a/drivers/net/dsa/motorcomm/chip.c b/drivers/net/dsa/motorcomm/c= hip.c index 3f56d60da8ea..d8218f9f93aa 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. @@ -38,6 +38,9 @@ struct yt921x_mib_desc { #define MIB_DESC(_size, _offset, _name) \ {_size, _offset, _name} =20 +#define pcs_to_yt921x_port(_pcs) container_of((_pcs), struct yt921x_port, = pcs) +#define yt921x_port_to_priv(pp) \ + container_of_const((pp), struct yt921x_priv, ports[(pp)->index]) /* Must agree with yt921x_mib * * Unstructured fields (name !=3D NULL) will appear in get_ethtool_stats(), @@ -112,6 +115,9 @@ struct yt921x_info { #define YT921X_PORT_MASK_INT0_n(n) GENMASK((n) - 1, 0) #define YT921X_PORT_MASK_EXT0 BIT(8) #define YT921X_PORT_MASK_EXT1 BIT(9) +#define YT922X_PORT_MASK_INTm_n(m, n) GENMASK((n), (m)) +#define YT922X_PORT_MASK_EXT0 BIT(0) +#define YT922X_PORT_MASK_EXT1 BIT(8) =20 static const struct yt921x_info yt921x_infos[] =3D { { @@ -149,9 +155,17 @@ static const struct yt921x_info yt921x_infos[] =3D { YT921X_PORT_MASK_INT0_n(8), YT921X_PORT_MASK_EXT0 | YT921X_PORT_MASK_EXT1, }, + { + "YT9224", YT9224_MAJOR, 0, 0, + YT922X_PORT_MASK_INTm_n(4, 7), + YT922X_PORT_MASK_EXT0 | YT922X_PORT_MASK_EXT1, + }, {} }; =20 +/* Define top ext addr */ +#define YT922X_COMMON_EXT_PHYADDR 9 + #define YT921X_VID_UNWARE 4095 =20 /* The interval should be small enough to avoid overflow of 32bit MIBs. @@ -4240,6 +4254,17 @@ static void yt921x_dsa_teardown(struct dsa_switch *d= s) } } =20 +static bool yt921x_needs_extmode_check(u32 major) +{ + switch (major) { + case YT9215_MAJOR: + case YT9218_MAJOR: + return true; + default: + return false; + } +} + static int yt921x_chip_detect(struct yt921x_priv *priv) { struct device *dev =3D to_device(priv); @@ -4265,6 +4290,9 @@ static int yt921x_chip_detect(struct yt921x_priv *pri= v) return -ENODEV; } =20 + if (!yt921x_needs_extmode_check(major)) + goto skip_extmode_check; + res =3D yt921x_reg_read(priv, YT921X_CHIP_MODE, &mode); if (res) return res; @@ -4304,6 +4332,15 @@ static int yt921x_chip_detect(struct yt921x_priv *pr= iv) =20 priv->info =3D info; =20 + return 0; + +skip_extmode_check: + dev_info(dev, + "Motorcomm %s ethernet switch, chipid: 0x%x\n", + info->name, chipid); + + priv->info =3D info; + return 0; } =20 @@ -4694,6 +4731,823 @@ 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 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) +{ + u32 mask; + u32 ctrl; + int res; + + switch (speed) { + case SPEED_10: + ctrl =3D YT921X_PORT_SPEED_10; + break; + case SPEED_100: + ctrl =3D YT921X_PORT_SPEED_100; + break; + case SPEED_1000: + ctrl =3D YT921X_PORT_SPEED_1000; + break; + case SPEED_2500: + ctrl =3D YT921X_PORT_SPEED_2500; + break; + case SPEED_5000: + ctrl =3D YT921X_PORT_SPEED_5000; + break; + case SPEED_10000: + ctrl =3D YT921X_PORT_SPEED_10000; + break; + default: + return -EINVAL; + } + 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_LINK | + YT922X_PORT_CFG_RX_EN; + ctrl &=3D ~(YT922X_PORT_FC_AN | YT922X_PORT_LINK_AN); + res =3D yt921x_reg_write(priv, YT922X_PORTn_CTRL(port), 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 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 +yt921x_intif_ext_write(struct yt921x_priv *priv, int port, int reg, u16 va= l) +{ + int res; + + if (port >=3D 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; +} + +static int +yt921x_intif_ext_read(struct yt921x_priv *priv, int port, int reg, u16 *va= lp) +{ + int res; + + if (port >=3D 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 yt922x_sds_phyaddr_get(int port, + enum yt922x_phy_reg_type reg_type, + enum yt922x_phy_reg_space reg_space) +{ + int res =3D port; + + /* + * sds phyaddr mapping depend on reg_type and reg_space + */ + if (!yt922x_port_is_internal_sds(port)) + return -EOPNOTSUPP; + if (reg_type =3D=3D YT922X_PHY_REG_TYPE_COMMON_EXT) { + res =3D YT922X_COMMON_EXT_PHYADDR; + return res; + } + + return res; +} + +/* + * Initialize serdes configuration based on interface mode. + */ +static int yt922x_sds_init(struct yt921x_priv *priv, int port, + phy_interface_t interface) +{ + int addr; + u16 data; + int res; + + addr =3D yt922x_sds_phyaddr_get + (port, YT922X_PHY_REG_TYPE_SDS_COMMON_EXT, + YT922X_PHY_REG_SPACE_SGMII); + if (addr < 0) + return -EINVAL; + /* write protect */ + res =3D yt921x_intif_ext_write(priv, addr, 0x4be, 0xd); + if (res) + return res; + /* CDR */ + if (interface =3D=3D PHY_INTERFACE_MODE_100BASEX) { + res =3D yt921x_intif_ext_write(priv, addr, 0x406, 0x0); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x416, 0x3458); + if (res) + return res; + } else { + res =3D yt921x_intif_ext_write(priv, addr, 0x406, 0x800); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x416, 0x4558); + if (res) + return res; + } + /* PLL */ + if (interface =3D=3D PHY_INTERFACE_MODE_USXGMII) { + res =3D yt921x_intif_ext_write(priv, addr, 0x43a, 0x1006); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x43f, 0x3029); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x42a, 0xf070); + if (res) + return res; + } else { + res =3D yt921x_intif_ext_write(priv, addr, 0x43d, 0x207d); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x43c, 0x207d); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x43f, 0x3032); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x43a, 0x6); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x42a, 0xf070); + if (res) + return res; + } + /* VCO */ + res =3D yt921x_intif_ext_write(priv, addr, 0x439, 0xC0); + if (res) + return res; + /* Vdac */ + res =3D yt921x_intif_ext_write(priv, addr, 0x492, 0x7f7f); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x491, 0x7f); + if (res) + return res; + /* Eye */ + res =3D yt921x_intif_ext_write(priv, addr, 0x454, 0xf14); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x497, 0xa44); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x4cd, 0x0); + if (res) + return res; + + res =3D yt921x_intif_ext_write(priv, addr, 0x4af, 0x45e3); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x48a, 0xfff); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x408, 0x7c00); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x4d6, 0x7f); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x44f, 0xff08); + if (res) + return res; + /* FFE */ + res =3D yt921x_intif_ext_write(priv, addr, 0x48e, 0x7d00); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0xd, 0x60f); + if (res) + return res; + /* CTLE */ + res =3D yt921x_intif_ext_write(priv, addr, 0x4b0, 0x804); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x4b1, 0x7774); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x4af, 0x45e7); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x3, 0x5603); + if (res) + return res; + + msleep(20); + res =3D yt921x_intif_ext_write(priv, addr, 0x492, 0x7fff); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x492, 0x7f7f); + if (res) + return res; + /* CTLE */ + res =3D yt921x_intif_ext_write(priv, addr, 0x2000, 0x40); + if (res) + return res; + res =3D yt921x_intif_ext_write(priv, addr, 0x2000, 0x0); + if (res) + return res; + + if (interface =3D=3D PHY_INTERFACE_MODE_SGMII) { + res =3D yt921x_intif_ext_write(priv, addr, 0x1042, 0x48c); + if (res) + return res; + } + /* soft reset */ + addr =3D yt922x_sds_phyaddr_get(port, YT922X_PHY_REG_TYPE_MII, + YT922X_PHY_REG_SPACE_SGMII); + if (addr < 0) + return res; + res =3D yt921x_intif_read(priv, addr, 0x0, &data); + if (res) + return res; + data &=3D ~(1 << 15); + res =3D yt921x_intif_write(priv, addr, 0x0, data); + if (res) + return res; + addr =3D yt922x_sds_phyaddr_get(port, YT922X_PHY_REG_TYPE_MII, + YT922X_PHY_REG_SPACE_USXGMII); + if (addr < 0) + return res; + res =3D yt921x_intif_read(priv, addr, 0x0, &data); + if (res) + return res; + data |=3D 1 << 15; + res =3D yt921x_intif_write(priv, addr, 0x0, data); + if (res) + return res; + + return 0; +} + +static void +yt922x_phylink_mac_config(struct phylink_config *config, unsigned int mode, + const struct phylink_link_state *state) +{ +} + +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 to_yt921x_priv(dp->ds); + + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_100BASEX: + 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 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; + int res =3D 0; + u16 data; + int addr; + u16 lp; + + mutex_lock(&priv->reg_lock); + switch (state->interface) { + case PHY_INTERFACE_MODE_SGMII: + case PHY_INTERFACE_MODE_100BASEX: + case PHY_INTERFACE_MODE_1000BASEX: + case PHY_INTERFACE_MODE_2500BASEX: + addr =3D yt922x_sds_phyaddr_get + (port, YT922X_PHY_REG_TYPE_SDS_COMMON_EXT, + YT922X_PHY_REG_SPACE_SGMII); + res =3D yt921x_intif_read(priv, addr, MII_BMSR, &data); + 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, data, lp); + break; + case PHY_INTERFACE_MODE_USXGMII: + addr =3D yt922x_sds_phyaddr_get + (port, YT922X_PHY_REG_TYPE_SDS_COMMON_EXT, + YT922X_PHY_REG_SPACE_USXGMII); + res =3D yt921x_intif_read(priv, addr, YT922X_PCS_LINK_CTRL, + &data); + if (res) + goto err; + state->link =3D FIELD_GET(YT922X_PCS_LINK_STATUS, data); + state->an_complete =3D FIELD_GET(YT922X_PCS_AN_COMPLETE, data); + 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 data; + int addr; + int res; + + mutex_lock(&priv->reg_lock); + addr =3D yt922x_sds_phyaddr_get + (port, YT922X_PHY_REG_TYPE_MII, + YT922X_PHY_REG_SPACE_SGMII); + res =3D yt921x_intif_read(priv, addr, MII_BMCR, &data); + if (res) + goto err; + data |=3D BMCR_ANRESTART; + res =3D yt921x_intif_write(priv, addr, MII_BMCR, data); + if (res) + goto err; + addr =3D yt922x_sds_phyaddr_get + (port, YT922X_PHY_REG_TYPE_MII, + YT922X_PHY_REG_SPACE_USXGMII); + res =3D yt921x_intif_read(priv, addr, MII_BMCR, &data); + if (res) + goto err; + data |=3D BMCR_ANRESTART; + res =3D yt921x_intif_write(priv, addr, MII_BMCR, data); + if (res) + goto err; + mutex_unlock(&priv->reg_lock); + return; + +err: + mutex_unlock(&priv->reg_lock); + if (res) + dev_err(dev, "Failed to %s PCS port %d: %i\n", "an restart", + 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) +{ + struct yt921x_port *pp =3D pcs_to_yt921x_port(pcs); + struct yt921x_priv *priv =3D yt921x_port_to_priv(pp); + int res, port; + u16 data; + u16 ctrl; + int addr; + + port =3D pp->index; + if (port !=3D 0 && port !=3D 8) + return -EINVAL; + + mutex_lock(&priv->reg_lock); + switch (interface) { + case PHY_INTERFACE_MODE_SGMII: + ctrl =3D YT92XX_SERDES_MODE_SGMII; + break; + case PHY_INTERFACE_MODE_100BASEX: + ctrl =3D YT92XX_SERDES_MODE_100BASEX; + break; + case PHY_INTERFACE_MODE_1000BASEX: + ctrl =3D YT92XX_SERDES_MODE_1000BASEX; + break; + case PHY_INTERFACE_MODE_2500BASEX: + ctrl =3D YT92XX_SERDES_MODE_2500BASEX; + break; + case PHY_INTERFACE_MODE_USXGMII: + ctrl =3D YT92XX_SERDES_MODE_USXGMII; + break; + default: + res =3D -EINVAL; + goto err; + } + addr =3D yt922x_sds_phyaddr_get + (port, YT922X_PHY_REG_TYPE_SDS_COMMON_EXT, + YT922X_PHY_REG_SPACE_SGMII); + if (addr < 0) { + res =3D addr; + 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; + /* SERDES init and interface configuration */ + res =3D yt922x_sds_init(priv, port, interface); + if (res) + goto err; + mutex_unlock(&priv->reg_lock); + + return res; + +err: + mutex_unlock(&priv->reg_lock); + + return res; +} + +static const struct phylink_pcs_ops yt922x_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, +}; + +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 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->external_mask & BIT(port)) { + /* serdes */ + __set_bit(PHY_INTERFACE_MODE_SGMII, + config->supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_100BASEX, + 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 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 */ + mutex_lock(&priv->reg_lock); + res =3D yt922x_cpu_port_set(priv); + mutex_unlock(&priv->reg_lock); + if (res) + return res; + + ctrl =3D GENMASK(9, 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 to_yt921x_priv(ds); + const struct yt921x_info *info =3D priv->info; + unsigned long mask; + int port; + + mask =3D info->external_mask; + for_each_set_bit(port, &mask, priv->series->max_ports) { + struct yt921x_port *pp =3D &priv->ports[port]; + + pp->pcs.ops =3D &yt922x_pcs_ops; + pp->pcs.poll =3D true; + + __set_bit(PHY_INTERFACE_MODE_SGMII, + pp->pcs.supported_interfaces); + __set_bit(PHY_INTERFACE_MODE_100BASEX, + 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 to_yt921x_priv(ds); + struct device *dev =3D 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 { .mode =3D YT92XX_MODE_YT921X, @@ -4707,12 +5561,26 @@ 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 { + .mode =3D YT92XX_MODE_YT922X, + .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; } @@ -4824,6 +5692,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", }, { /* sentinel */ } }; MODULE_DEVICE_TABLE(of, yt921x_of_match); @@ -4841,5 +5710,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 c446aea449ed..3a8ce801aabd 100644 --- a/drivers/net/dsa/motorcomm/chip.h +++ b/drivers/net/dsa/motorcomm/chip.h @@ -111,6 +111,7 @@ #define YT921X_PORT_SPEED_1000 YT921X_PORT_SPEED(2) #define YT921X_PORT_SPEED_10000 YT921X_PORT_SPEED(3) #define YT921X_PORT_SPEED_2500 YT921X_PORT_SPEED(4) +#define YT921X_PORT_SPEED_5000 YT921X_PORT_SPEED(5) #define YT921X_PON_STRAP_FUNC 0x80320 #define YT921X_PON_STRAP_VAL 0x80324 #define YT921X_PON_STRAP_CAP 0x80328 @@ -837,6 +838,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 @@ -861,6 +863,102 @@ enum yt921x_fdb_entry_status { #define yt921x_port_is_internal(port) ((port) < 8) #define yt921x_port_is_external(port) ((port) =3D=3D 8 || (port) =3D=3D 9) =20 +/* yt922x register lists */ +#define YT92XX_PAGE_SELECT 0x1e +#define YT92XX_PAGE 0x1f +#define YT922X_PORTn_STATUS(port) (0x80200 + 4 * (port)) +#define YT922X_PORT_LINK_STATE BIT(8) +#define YT922X_PORT_LINK_DUPLEX BIT(7) +#define YT922X_PORT_RX_FC_EN BIT(6) +#define YT922X_PORT_TX_FC_EN BIT(5) +#define YT922X_PORT_SPEED_10 0 +#define YT922X_PORT_SPEED_100 1 +#define YT922X_PORT_SPEED_1000 2 +#define YT922X_PORT_SPEED_10000 3 +#define YT922X_PORT_SPEED_2500 4 +#define YT922X_PORT_SPEED_5000 5 +#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 YT92XX_SERDES_MODE_SGMII YT922X_SERDES_MODE(0) +#define YT92XX_SERDES_MODE_REVSGMII YT921X_SERDES_MODE(1) +#define YT92XX_SERDES_MODE_1000BASEX YT921X_SERDES_MODE(2) +#define YT92XX_SERDES_MODE_100BASEX YT921X_SERDES_MODE(3) +#define YT92XX_SERDES_MODE_2500BASEX YT921X_SERDES_MODE(4) +#define YT92XX_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) + +/* LAG */ +#define YT922X_LAG_NUM 4 +/* ISO */ +#define YT922X_PORTn_ISOLATION(port) (0x4 * (port) + 0x180d80) +/* FDB */ +#define YT922X_PORTn_LEARN(port) (0x180300 + 4 * (port)) +#define YT922X_PORT_LEARN_DIS BIT(18) +/* GLOBAL CTRL */ +#define YT922X_FUNC_ACL BIT(5) +#define YT922X_FUNC_MIB BIT(4) +/* CTRL PKT */ +#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 */ + +/* CPU PORT */ +#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 yt922x_port_is_internal_sds(port) ((port) =3D=3D 0 || (port) =3D= =3D 8) + +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 +}; + +enum yt922x_phy_reg_space { + YT922X_PHY_REG_SPACE_SGMII, + YT922X_PHY_REG_SPACE_USXGMII, + YT922X_PHY_REG_SPACE_MAX +}; + struct yt921x_mib { u64 rx_broadcast; u64 rx_pause; @@ -953,6 +1051,7 @@ struct yt921x_port { =20 struct yt921x_led *leds[YT921X_LED_GROUP_NUM]; #endif + struct phylink_pcs pcs; }; =20 struct yt921x_reg_ops { --=20 2.25.1