--- /dev/null
+From b91ef50f70e7c092c50c1b92e63ef3fb0041cdd4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Uwe=20Kleine-K=C3=B6nig?= <u.kleine-koenig@pengutronix.de>
+Date: Mon, 18 Sep 2023 21:19:12 +0200
+Subject: [PATCH 01/30] net: dsa: mt7530: Convert to platform remove callback
+ returning void
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The .remove() callback for a platform driver returns an int which makes
+many driver authors wrongly assume it's possible to do error handling by
+returning an error code. However the value returned is ignored (apart
+from emitting a warning) and this typically results in resource leaks.
+To improve here there is a quest to make the remove callback return
+void. In the first step of this quest all drivers are converted to
+.remove_new() which already returns void. Eventually after all drivers
+are converted, .remove_new() is renamed to .remove().
+
+Trivially convert this driver from always returning zero in the remove
+callback to the void returning variant.
+
+Signed-off-by: Uwe Kleine-König <u.kleine-koenig@pengutronix.de>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Acked-by: Daniel Golle <daniel@makrotopia.org>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/dsa/mt7530-mmio.c | 7 ++-----
+ 1 file changed, 2 insertions(+), 5 deletions(-)
+
+--- a/drivers/net/dsa/mt7530-mmio.c
++++ b/drivers/net/dsa/mt7530-mmio.c
+@@ -63,15 +63,12 @@ mt7988_probe(struct platform_device *pde
+ return dsa_register_switch(priv->ds);
+ }
+
+-static int
+-mt7988_remove(struct platform_device *pdev)
++static void mt7988_remove(struct platform_device *pdev)
+ {
+ struct mt7530_priv *priv = platform_get_drvdata(pdev);
+
+ if (priv)
+ mt7530_remove_common(priv);
+-
+- return 0;
+ }
+
+ static void mt7988_shutdown(struct platform_device *pdev)
+@@ -88,7 +85,7 @@ static void mt7988_shutdown(struct platf
+
+ static struct platform_driver mt7988_platform_driver = {
+ .probe = mt7988_probe,
+- .remove = mt7988_remove,
++ .remove_new = mt7988_remove,
+ .shutdown = mt7988_shutdown,
+ .driver = {
+ .name = "mt7530-mmio",
--- /dev/null
+From d22c85764665af931c5c61bbe282b4116a88e792 Mon Sep 17 00:00:00 2001
+From: "Russell King (Oracle)" <rmk+kernel@armlinux.org.uk>
+Date: Wed, 27 Sep 2023 13:13:56 +0100
+Subject: [PATCH 02/30] net: dsa: mt753x: remove mt753x_phylink_pcs_link_up()
+
+Remove the mt753x_phylink_pcs_link_up() function for two reasons:
+
+1) priv->pcs[i].pcs.neg_mode is set true, meaning it doesn't take a
+ MLO_AN_FIXED anymore, but one of PHYLINK_PCS_NEG_*. However, this
+ is inconsequential due to...
+2) priv->pcs[port].pcs.ops is always initialised to point at
+ mt7530_pcs_ops, which does not have a pcs_link_up() member.
+
+So, let's remove mt753x_phylink_pcs_link_up() entirely.
+
+Signed-off-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Reviewed-by: Vladimir Oltean <vladimir.oltean@nxp.com>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Link: https://lore.kernel.org/r/E1qlTQS-008BWe-Va@rmk-PC.armlinux.org.uk
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 11 -----------
+ 1 file changed, 11 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2860,15 +2860,6 @@ static void mt753x_phylink_mac_link_down
+ mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
+ }
+
+-static void mt753x_phylink_pcs_link_up(struct phylink_pcs *pcs,
+- unsigned int mode,
+- phy_interface_t interface,
+- int speed, int duplex)
+-{
+- if (pcs->ops->pcs_link_up)
+- pcs->ops->pcs_link_up(pcs, mode, interface, speed, duplex);
+-}
+-
+ static void mt753x_phylink_mac_link_up(struct dsa_switch *ds, int port,
+ unsigned int mode,
+ phy_interface_t interface,
+@@ -2956,8 +2947,6 @@ mt7531_cpu_port_config(struct dsa_switch
+ return ret;
+ mt7530_write(priv, MT7530_PMCR_P(port),
+ PMCR_CPU_PORT_SETTING(priv->id));
+- mt753x_phylink_pcs_link_up(&priv->pcs[port].pcs, MLO_AN_FIXED,
+- interface, speed, DUPLEX_FULL);
+ mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL,
+ speed, DUPLEX_FULL, true, true);
+
--- /dev/null
+From 9b4f1f5a0801652056670a38503b4049eb413caf Mon Sep 17 00:00:00 2001
+From: Justin Stitt <justinstitt@google.com>
+Date: Mon, 9 Oct 2023 18:29:19 +0000
+Subject: [PATCH 03/30] net: dsa: mt7530: replace deprecated strncpy with
+ ethtool_sprintf
+
+`strncpy` is deprecated for use on NUL-terminated destination strings
+[1] and as such we should prefer more robust and less ambiguous string
+interfaces.
+
+ethtool_sprintf() is designed specifically for get_strings() usage.
+Let's replace strncpy in favor of this more robust and easier to
+understand interface.
+
+Link: https://www.kernel.org/doc/html/latest/process/deprecated.html#strncpy-on-nul-terminated-strings [1]
+Link: https://manpages.debian.org/testing/linux-manual-4.8/strscpy.9.en.html [2]
+Link: https://github.com/KSPP/linux/issues/90
+Signed-off-by: Justin Stitt <justinstitt@google.com>
+Reviewed-by: Kees Cook <keescook@chromium.org>
+Acked-by: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: Florian Fainelli <florian.fainelli@broadcom.com>
+Reviewed-by: AngeloGioacchino Del Regno <angelogioacchino.delregno@collabora.com>
+Link: https://lore.kernel.org/r/20231009-strncpy-drivers-net-dsa-mt7530-c-v1-1-ec6677a6436a@google.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 3 +--
+ 1 file changed, 1 insertion(+), 2 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -836,8 +836,7 @@ mt7530_get_strings(struct dsa_switch *ds
+ return;
+
+ for (i = 0; i < ARRAY_SIZE(mt7530_mib); i++)
+- strncpy(data + i * ETH_GSTRING_LEN, mt7530_mib[i].name,
+- ETH_GSTRING_LEN);
++ ethtool_sprintf(&data, "%s", mt7530_mib[i].name);
+ }
+
+ static void
--- /dev/null
+From af26b0d1bf934bbaa7cafb871a51e95087a088a0 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Mon, 22 Jan 2024 08:34:31 +0300
+Subject: [PATCH 04/30] net: dsa: mt7530: support OF-based registration of
+ switch MDIO bus
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Currently the MDIO bus of the switches the MT7530 DSA subdriver controls
+can only be registered as non-OF-based. Bring support for registering the
+bus OF-based.
+
+The subdrivers that control switches [with MDIO bus] probed on OF must
+follow this logic to support all cases properly:
+
+No switch MDIO bus defined: Populate ds->user_mii_bus, register the MDIO
+bus, set the interrupts for PHYs if "interrupt-controller" is defined at
+the switch node. This case should only be covered for the switches which
+their dt-bindings documentation didn't document the MDIO bus from the
+start. This is to keep supporting the device trees that do not describe the
+MDIO bus on the device tree but the MDIO bus is being used nonetheless.
+
+Switch MDIO bus defined: Don't populate ds->user_mii_bus, register the MDIO
+bus, set the interrupts for PHYs if ["interrupt-controller" is defined at
+the switch node and "interrupts" is defined at the PHY nodes under the
+switch MDIO bus node].
+
+Switch MDIO bus defined but explicitly disabled: If the device tree says
+status = "disabled" for the MDIO bus, we shouldn't need an MDIO bus at all.
+Instead, just exit as early as possible and do not call any MDIO API.
+
+The use of ds->user_mii_bus is inappropriate when the MDIO bus of the
+switch is described on the device tree [1], which is why we don't populate
+ds->user_mii_bus in that case.
+
+Link: https://lore.kernel.org/netdev/20231213120656.x46fyad6ls7sqyzv@skbuf/ [1]
+Suggested-by: David Bauer <mail@david-bauer.net>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Link: https://lore.kernel.org/r/20240122053431.7751-1-arinc.unal@arinc9.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 34 ++++++++++++++++++++++++++--------
+ 1 file changed, 26 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2182,24 +2182,40 @@ mt7530_free_irq_common(struct mt7530_pri
+ static void
+ mt7530_free_irq(struct mt7530_priv *priv)
+ {
+- mt7530_free_mdio_irq(priv);
++ struct device_node *mnp, *np = priv->dev->of_node;
++
++ mnp = of_get_child_by_name(np, "mdio");
++ if (!mnp)
++ mt7530_free_mdio_irq(priv);
++ of_node_put(mnp);
++
+ mt7530_free_irq_common(priv);
+ }
+
+ static int
+ mt7530_setup_mdio(struct mt7530_priv *priv)
+ {
++ struct device_node *mnp, *np = priv->dev->of_node;
+ struct dsa_switch *ds = priv->ds;
+ struct device *dev = priv->dev;
+ struct mii_bus *bus;
+ static int idx;
+- int ret;
++ int ret = 0;
++
++ mnp = of_get_child_by_name(np, "mdio");
++
++ if (mnp && !of_device_is_available(mnp))
++ goto out;
+
+ bus = devm_mdiobus_alloc(dev);
+- if (!bus)
+- return -ENOMEM;
++ if (!bus) {
++ ret = -ENOMEM;
++ goto out;
++ }
++
++ if (!mnp)
++ ds->slave_mii_bus = bus;
+
+- ds->slave_mii_bus = bus;
+ bus->priv = priv;
+ bus->name = KBUILD_MODNAME "-mii";
+ snprintf(bus->id, MII_BUS_ID_SIZE, KBUILD_MODNAME "-%d", idx++);
+@@ -2210,16 +2226,18 @@ mt7530_setup_mdio(struct mt7530_priv *pr
+ bus->parent = dev;
+ bus->phy_mask = ~ds->phys_mii_mask;
+
+- if (priv->irq)
++ if (priv->irq && !mnp)
+ mt7530_setup_mdio_irq(priv);
+
+- ret = devm_mdiobus_register(dev, bus);
++ ret = devm_of_mdiobus_register(dev, bus, mnp);
+ if (ret) {
+ dev_err(dev, "failed to register MDIO bus: %d\n", ret);
+- if (priv->irq)
++ if (priv->irq && !mnp)
+ mt7530_free_mdio_irq(priv);
+ }
+
++out:
++ of_node_put(mnp);
+ return ret;
+ }
+
--- /dev/null
+From 617b07e08bcb1f69a72a085a7d847d1ca2999830 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Mon, 22 Jan 2024 08:35:52 +0300
+Subject: [PATCH 05/30] net: dsa: mt7530: always trap frames to active CPU port
+ on MT7530
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+On the MT7530 switch, the CPU_PORT field indicates which CPU port to trap
+frames to, regardless of the affinity of the inbound user port.
+
+When multiple CPU ports are in use, if the DSA conduit interface is down,
+trapped frames won't be passed to the conduit interface.
+
+To make trapping frames work including this case, implement
+ds->ops->conduit_state_change() on this subdriver and set the CPU_PORT
+field to the numerically smallest CPU port whose conduit interface is up.
+Introduce the active_cpu_ports field to store the information of the active
+CPU ports. Correct the macros, CPU_PORT is bits 4 through 6 of the
+register.
+
+Add a comment to explain frame trapping for this switch.
+
+Currently, the driver doesn't support the use of multiple CPU ports so this
+is not necessarily a bug fix.
+
+Suggested-by: Vladimir Oltean <olteanv@gmail.com>
+Suggested-by: Russell King (Oracle) <linux@armlinux.org.uk>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Link: https://lore.kernel.org/r/20240122-for-netnext-mt7530-improvements-1-v3-1-042401f2b279@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 35 +++++++++++++++++++++++++++++++----
+ drivers/net/dsa/mt7530.h | 6 ++++--
+ 2 files changed, 35 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -1071,10 +1071,6 @@ mt753x_cpu_port_enable(struct dsa_switch
+ mt7530_set(priv, MT7530_MFC, BC_FFP(BIT(port)) | UNM_FFP(BIT(port)) |
+ UNU_FFP(BIT(port)));
+
+- /* Set CPU port number */
+- if (priv->id == ID_MT7530 || priv->id == ID_MT7621)
+- mt7530_rmw(priv, MT7530_MFC, CPU_MASK, CPU_EN | CPU_PORT(port));
+-
+ /* Add the CPU port to the CPU port bitmap for MT7531 and the switch on
+ * the MT7988 SoC. Trapped frames will be forwarded to the CPU port that
+ * is affine to the inbound user port.
+@@ -3128,6 +3124,36 @@ static int mt753x_set_mac_eee(struct dsa
+ return 0;
+ }
+
++static void
++mt753x_conduit_state_change(struct dsa_switch *ds,
++ const struct net_device *conduit,
++ bool operational)
++{
++ struct dsa_port *cpu_dp = conduit->dsa_ptr;
++ struct mt7530_priv *priv = ds->priv;
++ int val = 0;
++ u8 mask;
++
++ /* Set the CPU port to trap frames to for MT7530. Trapped frames will be
++ * forwarded to the numerically smallest CPU port whose conduit
++ * interface is up.
++ */
++ if (priv->id != ID_MT7530 && priv->id != ID_MT7621)
++ return;
++
++ mask = BIT(cpu_dp->index);
++
++ if (operational)
++ priv->active_cpu_ports |= mask;
++ else
++ priv->active_cpu_ports &= ~mask;
++
++ if (priv->active_cpu_ports)
++ val = CPU_EN | CPU_PORT(__ffs(priv->active_cpu_ports));
++
++ mt7530_rmw(priv, MT7530_MFC, CPU_EN | CPU_PORT_MASK, val);
++}
++
+ static int mt7988_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
+ {
+ return 0;
+@@ -3183,6 +3209,7 @@ const struct dsa_switch_ops mt7530_switc
+ .phylink_mac_link_up = mt753x_phylink_mac_link_up,
+ .get_mac_eee = mt753x_get_mac_eee,
+ .set_mac_eee = mt753x_set_mac_eee,
++ .master_state_change = mt753x_conduit_state_change,
+ };
+ EXPORT_SYMBOL_GPL(mt7530_switch_ops);
+
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -41,8 +41,8 @@ enum mt753x_id {
+ #define UNU_FFP(x) (((x) & 0xff) << 8)
+ #define UNU_FFP_MASK UNU_FFP(~0)
+ #define CPU_EN BIT(7)
+-#define CPU_PORT(x) ((x) << 4)
+-#define CPU_MASK (0xf << 4)
++#define CPU_PORT_MASK GENMASK(6, 4)
++#define CPU_PORT(x) FIELD_PREP(CPU_PORT_MASK, x)
+ #define MIRROR_EN BIT(3)
+ #define MIRROR_PORT(x) ((x) & 0x7)
+ #define MIRROR_MASK 0x7
+@@ -780,6 +780,7 @@ struct mt753x_info {
+ * @irq_domain: IRQ domain of the switch irq_chip
+ * @irq_enable: IRQ enable bits, synced to SYS_INT_EN
+ * @create_sgmii: Pointer to function creating SGMII PCS instance(s)
++ * @active_cpu_ports: Holding the active CPU ports
+ */
+ struct mt7530_priv {
+ struct device *dev;
+@@ -806,6 +807,7 @@ struct mt7530_priv {
+ struct irq_domain *irq_domain;
+ u32 irq_enable;
+ int (*create_sgmii)(struct mt7530_priv *priv, bool dual_sgmii);
++ u8 active_cpu_ports;
+ };
+
+ struct mt7530_hw_vlan_entry {
--- /dev/null
+From 07f411e26f82d75723df1c0c072e5602d06f4e30 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Mon, 22 Jan 2024 08:35:53 +0300
+Subject: [PATCH 06/30] net: dsa: mt7530: use p5_interface_select as data type
+ for p5_intf_sel
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Use the p5_interface_select enumeration as the data type for the
+p5_intf_sel field. This ensures p5_intf_sel can only take the values
+defined in the p5_interface_select enumeration.
+
+Remove the explicit assignment of 0 to P5_DISABLED as the first enum item
+is automatically assigned 0.
+
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Acked-by: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Link: https://lore.kernel.org/r/20240122-for-netnext-mt7530-improvements-1-v3-2-042401f2b279@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.h | 4 ++--
+ 1 file changed, 2 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -703,7 +703,7 @@ struct mt7530_port {
+
+ /* Port 5 interface select definitions */
+ enum p5_interface_select {
+- P5_DISABLED = 0,
++ P5_DISABLED,
+ P5_INTF_SEL_PHY_P0,
+ P5_INTF_SEL_PHY_P4,
+ P5_INTF_SEL_GMAC5,
+@@ -796,7 +796,7 @@ struct mt7530_priv {
+ bool mcm;
+ phy_interface_t p6_interface;
+ phy_interface_t p5_interface;
+- unsigned int p5_intf_sel;
++ enum p5_interface_select p5_intf_sel;
+ u8 mirror_rx;
+ u8 mirror_tx;
+ struct mt7530_port ports[MT7530_NUM_PORTS];
--- /dev/null
+From 8f7db12efc189eedd196ed8d053236ce27add484 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Mon, 22 Jan 2024 08:35:54 +0300
+Subject: [PATCH 07/30] net: dsa: mt7530: store port 5 SGMII capability of
+ MT7531
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Introduce the p5_sgmii field to store the information for whether port 5
+has got SGMII or not. Instead of reading the MT7531_TOP_SIG_SR register
+multiple times, the register will be read once and the value will be
+stored on the p5_sgmii field. This saves unnecessary reads of the
+register.
+
+Move the comment about MT7531AE and MT7531BE to mt7531_setup(), where the
+switch is identified.
+
+Get rid of mt7531_dual_sgmii_supported() now that priv->p5_sgmii stores the
+information. Address the code where mt7531_dual_sgmii_supported() is used.
+
+Get rid of mt7531_is_rgmii_port() which just prints the opposite of
+priv->p5_sgmii.
+
+Instead of calling mt7531_pll_setup() then returning, do not call it if
+port 5 is SGMII.
+
+Remove P5_INTF_SEL_GMAC5_SGMII. The p5_interface_select enum is supposed to
+represent the mode that port 5 is being used in, not the hardware
+information of port 5. Set p5_intf_sel to P5_INTF_SEL_GMAC5 instead, if
+port 5 is not dsa_is_unused_port().
+
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Acked-by: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Link: https://lore.kernel.org/r/20240122-for-netnext-mt7530-improvements-1-v3-3-042401f2b279@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530-mdio.c | 7 ++---
+ drivers/net/dsa/mt7530.c | 48 ++++++++++++-----------------------
+ drivers/net/dsa/mt7530.h | 6 +++--
+ 3 files changed, 22 insertions(+), 39 deletions(-)
+
+--- a/drivers/net/dsa/mt7530-mdio.c
++++ b/drivers/net/dsa/mt7530-mdio.c
+@@ -81,17 +81,14 @@ static const struct regmap_bus mt7530_re
+ };
+
+ static int
+-mt7531_create_sgmii(struct mt7530_priv *priv, bool dual_sgmii)
++mt7531_create_sgmii(struct mt7530_priv *priv)
+ {
+ struct regmap_config *mt7531_pcs_config[2] = {};
+ struct phylink_pcs *pcs;
+ struct regmap *regmap;
+ int i, ret = 0;
+
+- /* MT7531AE has two SGMII units for port 5 and port 6
+- * MT7531BE has only one SGMII unit for port 6
+- */
+- for (i = dual_sgmii ? 0 : 1; i < 2; i++) {
++ for (i = priv->p5_sgmii ? 0 : 1; i < 2; i++) {
+ mt7531_pcs_config[i] = devm_kzalloc(priv->dev,
+ sizeof(struct regmap_config),
+ GFP_KERNEL);
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -487,15 +487,6 @@ mt7530_pad_clk_setup(struct dsa_switch *
+ return 0;
+ }
+
+-static bool mt7531_dual_sgmii_supported(struct mt7530_priv *priv)
+-{
+- u32 val;
+-
+- val = mt7530_read(priv, MT7531_TOP_SIG_SR);
+-
+- return (val & PAD_DUAL_SGMII_EN) != 0;
+-}
+-
+ static int
+ mt7531_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
+ {
+@@ -510,9 +501,6 @@ mt7531_pll_setup(struct mt7530_priv *pri
+ u32 xtal;
+ u32 val;
+
+- if (mt7531_dual_sgmii_supported(priv))
+- return;
+-
+ val = mt7530_read(priv, MT7531_CREV);
+ top_sig = mt7530_read(priv, MT7531_TOP_SIG_SR);
+ hwstrap = mt7530_read(priv, MT7531_HWTRAP);
+@@ -920,8 +908,6 @@ static const char *p5_intf_modes(unsigne
+ return "PHY P4";
+ case P5_INTF_SEL_GMAC5:
+ return "GMAC5";
+- case P5_INTF_SEL_GMAC5_SGMII:
+- return "GMAC5_SGMII";
+ default:
+ return "unknown";
+ }
+@@ -2524,6 +2510,12 @@ mt7531_setup(struct dsa_switch *ds)
+ return -ENODEV;
+ }
+
++ /* MT7531AE has got two SGMII units. One for port 5, one for port 6.
++ * MT7531BE has got only one SGMII unit which is for port 6.
++ */
++ val = mt7530_read(priv, MT7531_TOP_SIG_SR);
++ priv->p5_sgmii = !!(val & PAD_DUAL_SGMII_EN);
++
+ /* all MACs must be forced link-down before sw reset */
+ for (i = 0; i < MT7530_NUM_PORTS; i++)
+ mt7530_write(priv, MT7530_PMCR_P(i), MT7531_FORCE_LNK);
+@@ -2533,21 +2525,18 @@ mt7531_setup(struct dsa_switch *ds)
+ SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST |
+ SYS_CTRL_REG_RST);
+
+- mt7531_pll_setup(priv);
+-
+- if (mt7531_dual_sgmii_supported(priv)) {
+- priv->p5_intf_sel = P5_INTF_SEL_GMAC5_SGMII;
+-
++ if (!priv->p5_sgmii) {
++ mt7531_pll_setup(priv);
++ } else {
+ /* Let ds->slave_mii_bus be able to access external phy. */
+ mt7530_rmw(priv, MT7531_GPIO_MODE1, MT7531_GPIO11_RG_RXD2_MASK,
+ MT7531_EXT_P_MDC_11);
+ mt7530_rmw(priv, MT7531_GPIO_MODE1, MT7531_GPIO12_RG_RXD3_MASK,
+ MT7531_EXT_P_MDIO_12);
+- } else {
+- priv->p5_intf_sel = P5_INTF_SEL_GMAC5;
+ }
+- dev_dbg(ds->dev, "P5 support %s interface\n",
+- p5_intf_modes(priv->p5_intf_sel));
++
++ if (!dsa_is_unused_port(ds, 5))
++ priv->p5_intf_sel = P5_INTF_SEL_GMAC5;
+
+ mt7530_rmw(priv, MT7531_GPIO_MODE0, MT7531_GPIO0_MASK,
+ MT7531_GPIO0_INTERRUPT);
+@@ -2607,11 +2596,6 @@ static void mt7530_mac_port_get_caps(str
+ }
+ }
+
+-static bool mt7531_is_rgmii_port(struct mt7530_priv *priv, u32 port)
+-{
+- return (port == 5) && (priv->p5_intf_sel != P5_INTF_SEL_GMAC5_SGMII);
+-}
+-
+ static void mt7531_mac_port_get_caps(struct dsa_switch *ds, int port,
+ struct phylink_config *config)
+ {
+@@ -2624,7 +2608,7 @@ static void mt7531_mac_port_get_caps(str
+ break;
+
+ case 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */
+- if (mt7531_is_rgmii_port(priv, port)) {
++ if (!priv->p5_sgmii) {
+ phy_interface_set_rgmii(config->supported_interfaces);
+ break;
+ }
+@@ -2691,7 +2675,7 @@ static int mt7531_rgmii_setup(struct mt7
+ {
+ u32 val;
+
+- if (!mt7531_is_rgmii_port(priv, port)) {
++ if (priv->p5_sgmii) {
+ dev_err(priv->dev, "RGMII mode is not available for port %d\n",
+ port);
+ return -EINVAL;
+@@ -2934,7 +2918,7 @@ mt7531_cpu_port_config(struct dsa_switch
+
+ switch (port) {
+ case 5:
+- if (mt7531_is_rgmii_port(priv, port))
++ if (!priv->p5_sgmii)
+ interface = PHY_INTERFACE_MODE_RGMII;
+ else
+ interface = PHY_INTERFACE_MODE_2500BASEX;
+@@ -3086,7 +3070,7 @@ mt753x_setup(struct dsa_switch *ds)
+ mt7530_free_irq_common(priv);
+
+ if (priv->create_sgmii) {
+- ret = priv->create_sgmii(priv, mt7531_dual_sgmii_supported(priv));
++ ret = priv->create_sgmii(priv);
+ if (ret && priv->irq)
+ mt7530_free_irq(priv);
+ }
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -707,7 +707,6 @@ enum p5_interface_select {
+ P5_INTF_SEL_PHY_P0,
+ P5_INTF_SEL_PHY_P4,
+ P5_INTF_SEL_GMAC5,
+- P5_INTF_SEL_GMAC5_SGMII,
+ };
+
+ struct mt7530_priv;
+@@ -776,6 +775,8 @@ struct mt753x_info {
+ * registers
+ * @p6_interface Holding the current port 6 interface
+ * @p5_intf_sel: Holding the current port 5 interface select
++ * @p5_sgmii: Flag for distinguishing if port 5 of the MT7531 switch
++ * has got SGMII
+ * @irq: IRQ number of the switch
+ * @irq_domain: IRQ domain of the switch irq_chip
+ * @irq_enable: IRQ enable bits, synced to SYS_INT_EN
+@@ -797,6 +798,7 @@ struct mt7530_priv {
+ phy_interface_t p6_interface;
+ phy_interface_t p5_interface;
+ enum p5_interface_select p5_intf_sel;
++ bool p5_sgmii;
+ u8 mirror_rx;
+ u8 mirror_tx;
+ struct mt7530_port ports[MT7530_NUM_PORTS];
+@@ -806,7 +808,7 @@ struct mt7530_priv {
+ int irq;
+ struct irq_domain *irq_domain;
+ u32 irq_enable;
+- int (*create_sgmii)(struct mt7530_priv *priv, bool dual_sgmii);
++ int (*create_sgmii)(struct mt7530_priv *priv);
+ u8 active_cpu_ports;
+ };
+
--- /dev/null
+From c91b7fb8fbb2e18ebb497e67f4252cec78e3a29b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Mon, 22 Jan 2024 08:35:55 +0300
+Subject: [PATCH 08/30] net: dsa: mt7530: improve comments regarding switch
+ ports
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+There's no logic to numerically order the CPU ports. Just state the port
+number instead.
+
+Remove the irrelevant PHY muxing information from
+mt7530_mac_port_get_caps(). Explain the supported MII modes instead.
+
+Remove the out of place PHY muxing information from
+mt753x_phylink_mac_config(). The function is for MT7530, MT7531, and the
+switch on the MT7988 SoC but there's no PHY muxing on MT7531 or the switch
+on the MT7988 SoC.
+
+These comments were gradually introduced with the commits below.
+commit ca366d6c889b ("net: dsa: mt7530: Convert to PHYLINK API")
+commit 38f790a80560 ("net: dsa: mt7530: Add support for port 5")
+commit 88bdef8be9f6 ("net: dsa: mt7530: Extend device data ready for adding
+a new hardware")
+commit c288575f7810 ("net: dsa: mt7530: Add the support of MT7531 switch")
+
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Acked-by: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Link: https://lore.kernel.org/r/20240122-for-netnext-mt7530-improvements-1-v3-4-042401f2b279@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 30 ++++++++++++++++++++----------
+ 1 file changed, 20 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2574,12 +2574,14 @@ static void mt7530_mac_port_get_caps(str
+ struct phylink_config *config)
+ {
+ switch (port) {
+- case 0 ... 4: /* Internal phy */
++ /* Ports which are connected to switch PHYs. There is no MII pinout. */
++ case 0 ... 4:
+ __set_bit(PHY_INTERFACE_MODE_GMII,
+ config->supported_interfaces);
+ break;
+
+- case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */
++ /* Port 5 supports rgmii with delays, mii, and gmii. */
++ case 5:
+ phy_interface_set_rgmii(config->supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_MII,
+ config->supported_interfaces);
+@@ -2587,7 +2589,8 @@ static void mt7530_mac_port_get_caps(str
+ config->supported_interfaces);
+ break;
+
+- case 6: /* 1st cpu port */
++ /* Port 6 supports rgmii and trgmii. */
++ case 6:
+ __set_bit(PHY_INTERFACE_MODE_RGMII,
+ config->supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_TRGMII,
+@@ -2602,19 +2605,24 @@ static void mt7531_mac_port_get_caps(str
+ struct mt7530_priv *priv = ds->priv;
+
+ switch (port) {
+- case 0 ... 4: /* Internal phy */
++ /* Ports which are connected to switch PHYs. There is no MII pinout. */
++ case 0 ... 4:
+ __set_bit(PHY_INTERFACE_MODE_GMII,
+ config->supported_interfaces);
+ break;
+
+- case 5: /* 2nd cpu port supports either rgmii or sgmii/8023z */
++ /* Port 5 supports rgmii with delays on MT7531BE, sgmii/802.3z on
++ * MT7531AE.
++ */
++ case 5:
+ if (!priv->p5_sgmii) {
+ phy_interface_set_rgmii(config->supported_interfaces);
+ break;
+ }
+ fallthrough;
+
+- case 6: /* 1st cpu port supports sgmii/8023z only */
++ /* Port 6 supports sgmii/802.3z. */
++ case 6:
+ __set_bit(PHY_INTERFACE_MODE_SGMII,
+ config->supported_interfaces);
+ __set_bit(PHY_INTERFACE_MODE_1000BASEX,
+@@ -2633,11 +2641,13 @@ static void mt7988_mac_port_get_caps(str
+ phy_interface_zero(config->supported_interfaces);
+
+ switch (port) {
+- case 0 ... 4: /* Internal phy */
++ /* Ports which are connected to switch PHYs. There is no MII pinout. */
++ case 0 ... 4:
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
+ config->supported_interfaces);
+ break;
+
++ /* Port 6 is connected to SoC's XGMII MAC. There is no MII pinout. */
+ case 6:
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
+ config->supported_interfaces);
+@@ -2801,12 +2811,12 @@ mt753x_phylink_mac_config(struct dsa_swi
+ u32 mcr_cur, mcr_new;
+
+ switch (port) {
+- case 0 ... 4: /* Internal phy */
++ case 0 ... 4:
+ if (state->interface != PHY_INTERFACE_MODE_GMII &&
+ state->interface != PHY_INTERFACE_MODE_INTERNAL)
+ goto unsupported;
+ break;
+- case 5: /* 2nd cpu port with phy of port 0 or 4 / external phy */
++ case 5:
+ if (priv->p5_interface == state->interface)
+ break;
+
+@@ -2816,7 +2826,7 @@ mt753x_phylink_mac_config(struct dsa_swi
+ if (priv->p5_intf_sel != P5_DISABLED)
+ priv->p5_interface = state->interface;
+ break;
+- case 6: /* 1st cpu port */
++ case 6:
+ if (priv->p6_interface == state->interface)
+ break;
+
--- /dev/null
+From c1b2294a9b4b9b6c0cbe58666cb86e0a9cb0abfd Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Mon, 22 Jan 2024 08:35:56 +0300
+Subject: [PATCH 09/30] net: dsa: mt7530: improve code path for setting up port
+ 5
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+There're two code paths for setting up port 5:
+
+mt7530_setup()
+-> mt7530_setup_port5()
+
+mt753x_phylink_mac_config()
+-> mt753x_mac_config()
+ -> mt7530_mac_config()
+ -> mt7530_setup_port5()
+
+Currently mt7530_setup_port5() from mt7530_setup() always runs. If port 5
+is used as a CPU, DSA, or user port, mt7530_setup_port5() from
+mt753x_phylink_mac_config() won't run. That is because priv->p5_interface
+set on mt7530_setup_port5() will match state->interface on
+mt753x_phylink_mac_config() which will stop running mt7530_setup_port5()
+again.
+
+Therefore, mt7530_setup_port5() will never run from
+mt753x_phylink_mac_config().
+
+Address this by not running mt7530_setup_port5() from mt7530_setup() if
+port 5 is used as a CPU, DSA, or user port. This driver isn't in the
+dsa_switches_apply_workarounds[] array so phylink will always be present.
+
+To keep the cases where port 5 isn't controlled by phylink working as
+before, preserve the mt7530_setup_port5() call from mt7530_setup().
+
+Do not set priv->p5_intf_sel to P5_DISABLED. It is already set to that when
+"priv" is allocated.
+
+Move setting the interface to a more specific location. It's supposed to be
+overwritten if PHY muxing is detected.
+
+Improve the comment which explains the process.
+
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Link: https://lore.kernel.org/r/20240122-for-netnext-mt7530-improvements-1-v3-5-042401f2b279@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 17 ++++++++---------
+ 1 file changed, 8 insertions(+), 9 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2362,16 +2362,15 @@ mt7530_setup(struct dsa_switch *ds)
+ return ret;
+
+ /* Setup port 5 */
+- priv->p5_intf_sel = P5_DISABLED;
+- interface = PHY_INTERFACE_MODE_NA;
+-
+ if (!dsa_is_unused_port(ds, 5)) {
+ priv->p5_intf_sel = P5_INTF_SEL_GMAC5;
+- ret = of_get_phy_mode(dsa_to_port(ds, 5)->dn, &interface);
+- if (ret && ret != -ENODEV)
+- return ret;
+ } else {
+- /* Scan the ethernet nodes. look for GMAC1, lookup used phy */
++ /* Scan the ethernet nodes. Look for GMAC1, lookup the used PHY.
++ * Set priv->p5_intf_sel to the appropriate value if PHY muxing
++ * is detected.
++ */
++ interface = PHY_INTERFACE_MODE_NA;
++
+ for_each_child_of_node(dn, mac_np) {
+ if (!of_device_is_compatible(mac_np,
+ "mediatek,eth-mac"))
+@@ -2402,6 +2401,8 @@ mt7530_setup(struct dsa_switch *ds)
+ of_node_put(phy_node);
+ break;
+ }
++
++ mt7530_setup_port5(ds, interface);
+ }
+
+ #ifdef CONFIG_GPIOLIB
+@@ -2412,8 +2413,6 @@ mt7530_setup(struct dsa_switch *ds)
+ }
+ #endif /* CONFIG_GPIOLIB */
+
+- mt7530_setup_port5(ds, interface);
+-
+ /* Flush the FDB table */
+ ret = mt7530_fdb_cmd(priv, MT7530_FDB_FLUSH, NULL);
+ if (ret < 0)
--- /dev/null
+From cd1cee68e57eedb460a68d1f42abf9f740b17e94 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Mon, 22 Jan 2024 08:35:57 +0300
+Subject: [PATCH 10/30] net: dsa: mt7530: do not set priv->p5_interface on
+ mt7530_setup_port5()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Running mt7530_setup_port5() from mt7530_setup() used to handle all cases
+of configuring port 5, including phylink.
+
+Setting priv->p5_interface under mt7530_setup_port5() makes sure that
+mt7530_setup_port5() from mt753x_phylink_mac_config() won't run.
+
+The commit ("net: dsa: mt7530: improve code path for setting up port 5")
+makes so that mt7530_setup_port5() from mt7530_setup() runs only on
+non-phylink cases.
+
+Get rid of unnecessarily setting priv->p5_interface under
+mt7530_setup_port5() as port 5 phylink configuration will be done by
+running mt7530_setup_port5() from mt753x_phylink_mac_config() now.
+
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Link: https://lore.kernel.org/r/20240122-for-netnext-mt7530-improvements-1-v3-6-042401f2b279@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -978,8 +978,6 @@ static void mt7530_setup_port5(struct ds
+ dev_dbg(ds->dev, "Setup P5, HWTRAP=0x%x, intf_sel=%s, phy-mode=%s\n",
+ val, p5_intf_modes(priv->p5_intf_sel), phy_modes(interface));
+
+- priv->p5_interface = interface;
+-
+ unlock_exit:
+ mutex_unlock(&priv->reg_mutex);
+ }
--- /dev/null
+From e55a68aeb0f8b9c74b582b7a5e92b82988832bf8 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Mon, 22 Jan 2024 08:35:58 +0300
+Subject: [PATCH 11/30] net: dsa: mt7530: do not run mt7530_setup_port5() if
+ port 5 is disabled
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+There's no need to run all the code on mt7530_setup_port5() if port 5 is
+disabled. The only case for calling mt7530_setup_port5() from
+mt7530_setup() is when PHY muxing is enabled. That is because port 5 is not
+defined as a port on the devicetree, therefore, it cannot be controlled by
+phylink.
+
+Because of this, run mt7530_setup_port5() if priv->p5_intf_sel is
+P5_INTF_SEL_PHY_P0 or P5_INTF_SEL_PHY_P4. Remove the P5_DISABLED case from
+mt7530_setup_port5().
+
+Stop initialising the interface variable as the remaining cases will always
+call mt7530_setup_port5() with it initialised.
+
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Link: https://lore.kernel.org/r/20240122-for-netnext-mt7530-improvements-1-v3-7-042401f2b279@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 9 +++------
+ 1 file changed, 3 insertions(+), 6 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -942,9 +942,6 @@ static void mt7530_setup_port5(struct ds
+ /* MT7530_P5_MODE_GMAC: P5 -> External phy or 2nd GMAC */
+ val &= ~MHWTRAP_P5_DIS;
+ break;
+- case P5_DISABLED:
+- interface = PHY_INTERFACE_MODE_NA;
+- break;
+ default:
+ dev_err(ds->dev, "Unsupported p5_intf_sel %d\n",
+ priv->p5_intf_sel);
+@@ -2367,8 +2364,6 @@ mt7530_setup(struct dsa_switch *ds)
+ * Set priv->p5_intf_sel to the appropriate value if PHY muxing
+ * is detected.
+ */
+- interface = PHY_INTERFACE_MODE_NA;
+-
+ for_each_child_of_node(dn, mac_np) {
+ if (!of_device_is_compatible(mac_np,
+ "mediatek,eth-mac"))
+@@ -2400,7 +2395,9 @@ mt7530_setup(struct dsa_switch *ds)
+ break;
+ }
+
+- mt7530_setup_port5(ds, interface);
++ if (priv->p5_intf_sel == P5_INTF_SEL_PHY_P0 ||
++ priv->p5_intf_sel == P5_INTF_SEL_PHY_P4)
++ mt7530_setup_port5(ds, interface);
+ }
+
+ #ifdef CONFIG_GPIOLIB
--- /dev/null
+From 1f538cda24bcb69919da2fcac0211b66281d3d4e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Tue, 6 Feb 2024 01:08:02 +0300
+Subject: [PATCH 12/30] net: dsa: mt7530: empty default case on
+ mt7530_setup_port5()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+There're two code paths for setting up port 5:
+
+mt7530_setup()
+-> mt7530_setup_port5()
+
+mt753x_phylink_mac_config()
+-> mt753x_mac_config()
+ -> mt7530_mac_config()
+ -> mt7530_setup_port5()
+
+On the first code path, priv->p5_intf_sel is either set to
+P5_INTF_SEL_PHY_P0 or P5_INTF_SEL_PHY_P4 when mt7530_setup_port5() is run.
+
+On the second code path, priv->p5_intf_sel is set to P5_INTF_SEL_GMAC5 when
+mt7530_setup_port5() is run.
+
+Empty the default case which will never run but is needed nonetheless to
+handle all the remaining enumeration values.
+
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Link: https://lore.kernel.org/r/20240206-for-netnext-mt7530-improvements-2-v5-1-d7d92a185cb1@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 5 +----
+ 1 file changed, 1 insertion(+), 4 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -943,9 +943,7 @@ static void mt7530_setup_port5(struct ds
+ val &= ~MHWTRAP_P5_DIS;
+ break;
+ default:
+- dev_err(ds->dev, "Unsupported p5_intf_sel %d\n",
+- priv->p5_intf_sel);
+- goto unlock_exit;
++ break;
+ }
+
+ /* Setup RGMII settings */
+@@ -975,7 +973,6 @@ static void mt7530_setup_port5(struct ds
+ dev_dbg(ds->dev, "Setup P5, HWTRAP=0x%x, intf_sel=%s, phy-mode=%s\n",
+ val, p5_intf_modes(priv->p5_intf_sel), phy_modes(interface));
+
+-unlock_exit:
+ mutex_unlock(&priv->reg_mutex);
+ }
+
--- /dev/null
+From 12c511cd31c2dc6bd96e4a89f7709d515aa8a76b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Tue, 6 Feb 2024 01:08:03 +0300
+Subject: [PATCH 13/30] net: dsa: mt7530: move XTAL check to mt7530_setup()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The crystal frequency concerns the switch core. The frequency should be
+checked when the switch is being set up so the driver can reject the
+unsupported hardware earlier and without requiring port 6 to be used.
+
+Move it to mt7530_setup(). Drop the unnecessary function printing.
+
+Reviewed-by: Andrew Lunn <andrew@lunn.ch>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Link: https://lore.kernel.org/r/20240206-for-netnext-mt7530-improvements-2-v5-2-d7d92a185cb1@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 13 ++++++-------
+ 1 file changed, 6 insertions(+), 7 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -422,13 +422,6 @@ mt7530_pad_clk_setup(struct dsa_switch *
+
+ xtal = mt7530_read(priv, MT7530_MHWTRAP) & HWTRAP_XTAL_MASK;
+
+- if (xtal == HWTRAP_XTAL_20MHZ) {
+- dev_err(priv->dev,
+- "%s: MT7530 with a 20MHz XTAL is not supported!\n",
+- __func__);
+- return -EINVAL;
+- }
+-
+ switch (interface) {
+ case PHY_INTERFACE_MODE_RGMII:
+ trgint = 0;
+@@ -2295,6 +2288,12 @@ mt7530_setup(struct dsa_switch *ds)
+ return -ENODEV;
+ }
+
++ if ((val & HWTRAP_XTAL_MASK) == HWTRAP_XTAL_20MHZ) {
++ dev_err(priv->dev,
++ "MT7530 with a 20MHz XTAL is not supported!\n");
++ return -EINVAL;
++ }
++
+ /* Reset the switch through internal reset */
+ mt7530_write(priv, MT7530_SYS_CTRL,
+ SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST |
--- /dev/null
+From c33899a6a8c1a5723afbfc075600aba2e2bdbea7 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Tue, 6 Feb 2024 01:08:04 +0300
+Subject: [PATCH 14/30] net: dsa: mt7530: simplify mt7530_pad_clk_setup()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+This code is from before this driver was converted to phylink API. Phylink
+deals with the unsupported interface cases before mt7530_pad_clk_setup() is
+run. Therefore, the default case would never run. However, it must be
+defined nonetheless to handle all the remaining enumeration values, the
+phy-modes.
+
+Switch to if statement for RGMII and return which simplifies the code and
+saves an indent.
+
+Set P6_INTF_MODE, which is the three least significant bits of the
+MT7530_P6ECR register, to 0 for RGMII even though it will already be 0
+after reset. This is to keep supporting dynamic reconfiguration of the port
+in the case the interface changes from TRGMII to RGMII.
+
+Disable the TRGMII clocks for all cases. They will be enabled if TRGMII is
+being used.
+
+Read XTAL after checking for RGMII as it's only needed for the TRGMII
+interface mode.
+
+Reviewed-by: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Link: https://lore.kernel.org/r/20240206-for-netnext-mt7530-improvements-2-v5-3-d7d92a185cb1@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 91 ++++++++++++++++++----------------------
+ 1 file changed, 40 insertions(+), 51 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -418,65 +418,54 @@ static int
+ mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
+ {
+ struct mt7530_priv *priv = ds->priv;
+- u32 ncpo1, ssc_delta, trgint, xtal;
++ u32 ncpo1, ssc_delta, xtal;
+
+- xtal = mt7530_read(priv, MT7530_MHWTRAP) & HWTRAP_XTAL_MASK;
++ /* Disable the MT7530 TRGMII clocks */
++ core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN);
+
+- switch (interface) {
+- case PHY_INTERFACE_MODE_RGMII:
+- trgint = 0;
+- break;
+- case PHY_INTERFACE_MODE_TRGMII:
+- trgint = 1;
+- if (xtal == HWTRAP_XTAL_25MHZ)
+- ssc_delta = 0x57;
+- else
+- ssc_delta = 0x87;
+- if (priv->id == ID_MT7621) {
+- /* PLL frequency: 125MHz: 1.0GBit */
+- if (xtal == HWTRAP_XTAL_40MHZ)
+- ncpo1 = 0x0640;
+- if (xtal == HWTRAP_XTAL_25MHZ)
+- ncpo1 = 0x0a00;
+- } else { /* PLL frequency: 250MHz: 2.0Gbit */
+- if (xtal == HWTRAP_XTAL_40MHZ)
+- ncpo1 = 0x0c80;
+- if (xtal == HWTRAP_XTAL_25MHZ)
+- ncpo1 = 0x1400;
+- }
+- break;
+- default:
+- dev_err(priv->dev, "xMII interface %d not supported\n",
+- interface);
+- return -EINVAL;
++ if (interface == PHY_INTERFACE_MODE_RGMII) {
++ mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK,
++ P6_INTF_MODE(0));
++ return 0;
+ }
+
+- mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK,
+- P6_INTF_MODE(trgint));
++ mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK, P6_INTF_MODE(1));
+
+- if (trgint) {
+- /* Disable the MT7530 TRGMII clocks */
+- core_clear(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN);
+-
+- /* Setup the MT7530 TRGMII Tx Clock */
+- core_write(priv, CORE_PLL_GROUP5, RG_LCDDS_PCW_NCPO1(ncpo1));
+- core_write(priv, CORE_PLL_GROUP6, RG_LCDDS_PCW_NCPO0(0));
+- core_write(priv, CORE_PLL_GROUP10, RG_LCDDS_SSC_DELTA(ssc_delta));
+- core_write(priv, CORE_PLL_GROUP11, RG_LCDDS_SSC_DELTA1(ssc_delta));
+- core_write(priv, CORE_PLL_GROUP4,
+- RG_SYSPLL_DDSFBK_EN | RG_SYSPLL_BIAS_EN |
+- RG_SYSPLL_BIAS_LPF_EN);
+- core_write(priv, CORE_PLL_GROUP2,
+- RG_SYSPLL_EN_NORMAL | RG_SYSPLL_VODEN |
+- RG_SYSPLL_POSDIV(1));
+- core_write(priv, CORE_PLL_GROUP7,
+- RG_LCDDS_PCW_NCPO_CHG | RG_LCCDS_C(3) |
+- RG_LCDDS_PWDB | RG_LCDDS_ISO_EN);
++ xtal = mt7530_read(priv, MT7530_MHWTRAP) & HWTRAP_XTAL_MASK;
+
+- /* Enable the MT7530 TRGMII clocks */
+- core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN);
++ if (xtal == HWTRAP_XTAL_25MHZ)
++ ssc_delta = 0x57;
++ else
++ ssc_delta = 0x87;
++
++ if (priv->id == ID_MT7621) {
++ /* PLL frequency: 125MHz: 1.0GBit */
++ if (xtal == HWTRAP_XTAL_40MHZ)
++ ncpo1 = 0x0640;
++ if (xtal == HWTRAP_XTAL_25MHZ)
++ ncpo1 = 0x0a00;
++ } else { /* PLL frequency: 250MHz: 2.0Gbit */
++ if (xtal == HWTRAP_XTAL_40MHZ)
++ ncpo1 = 0x0c80;
++ if (xtal == HWTRAP_XTAL_25MHZ)
++ ncpo1 = 0x1400;
+ }
+
++ /* Setup the MT7530 TRGMII Tx Clock */
++ core_write(priv, CORE_PLL_GROUP5, RG_LCDDS_PCW_NCPO1(ncpo1));
++ core_write(priv, CORE_PLL_GROUP6, RG_LCDDS_PCW_NCPO0(0));
++ core_write(priv, CORE_PLL_GROUP10, RG_LCDDS_SSC_DELTA(ssc_delta));
++ core_write(priv, CORE_PLL_GROUP11, RG_LCDDS_SSC_DELTA1(ssc_delta));
++ core_write(priv, CORE_PLL_GROUP4, RG_SYSPLL_DDSFBK_EN |
++ RG_SYSPLL_BIAS_EN | RG_SYSPLL_BIAS_LPF_EN);
++ core_write(priv, CORE_PLL_GROUP2, RG_SYSPLL_EN_NORMAL |
++ RG_SYSPLL_VODEN | RG_SYSPLL_POSDIV(1));
++ core_write(priv, CORE_PLL_GROUP7, RG_LCDDS_PCW_NCPO_CHG |
++ RG_LCCDS_C(3) | RG_LCDDS_PWDB | RG_LCDDS_ISO_EN);
++
++ /* Enable the MT7530 TRGMII clocks */
++ core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN);
++
+ return 0;
+ }
+
--- /dev/null
+From e612922de7070a28802216650ee88128a57290de Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Tue, 6 Feb 2024 01:08:05 +0300
+Subject: [PATCH 15/30] net: dsa: mt7530: call port 6 setup from
+ mt7530_mac_config()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+mt7530_pad_clk_setup() is called if port 6 is enabled. It used to do more
+things than setting up port 6. That part was moved to more appropriate
+locations, mt7530_setup() and mt7530_pll_setup().
+
+Now that all it does is set up port 6, rename it to mt7530_setup_port6(),
+and move it to a more appropriate location, under mt7530_mac_config().
+
+Change mt7530_setup_port6() to void as there're no error cases.
+
+Leave an empty mt7530_pad_clk_setup() to satisfy the pad_setup function
+pointer.
+
+This is the code path for setting up the ports before:
+
+dsa_switch_ops :: phylink_mac_config() -> mt753x_phylink_mac_config()
+-> mt753x_mac_config()
+ -> mt753x_info :: mac_port_config() -> mt7530_mac_config()
+ -> mt7530_setup_port5()
+-> mt753x_pad_setup()
+ -> mt753x_info :: pad_setup() -> mt7530_pad_clk_setup()
+
+This is after:
+
+dsa_switch_ops :: phylink_mac_config() -> mt753x_phylink_mac_config()
+-> mt753x_mac_config()
+ -> mt753x_info :: mac_port_config() -> mt7530_mac_config()
+ -> mt7530_setup_port5()
+ -> mt7530_setup_port6()
+
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Link: https://lore.kernel.org/r/20240206-for-netnext-mt7530-improvements-2-v5-4-d7d92a185cb1@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 19 +++++++++++--------
+ 1 file changed, 11 insertions(+), 8 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -414,8 +414,8 @@ mt753x_preferred_default_local_cpu_port(
+ }
+
+ /* Setup port 6 interface mode and TRGMII TX circuit */
+-static int
+-mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
++static void
++mt7530_setup_port6(struct dsa_switch *ds, phy_interface_t interface)
+ {
+ struct mt7530_priv *priv = ds->priv;
+ u32 ncpo1, ssc_delta, xtal;
+@@ -426,7 +426,7 @@ mt7530_pad_clk_setup(struct dsa_switch *
+ if (interface == PHY_INTERFACE_MODE_RGMII) {
+ mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK,
+ P6_INTF_MODE(0));
+- return 0;
++ return;
+ }
+
+ mt7530_rmw(priv, MT7530_P6ECR, P6_INTF_MODE_MASK, P6_INTF_MODE(1));
+@@ -465,7 +465,11 @@ mt7530_pad_clk_setup(struct dsa_switch *
+
+ /* Enable the MT7530 TRGMII clocks */
+ core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN);
++}
+
++static int
++mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
++{
+ return 0;
+ }
+
+@@ -2649,11 +2653,10 @@ mt7530_mac_config(struct dsa_switch *ds,
+ {
+ struct mt7530_priv *priv = ds->priv;
+
+- /* Only need to setup port5. */
+- if (port != 5)
+- return 0;
+-
+- mt7530_setup_port5(priv->ds, interface);
++ if (port == 5)
++ mt7530_setup_port5(priv->ds, interface);
++ else if (port == 6)
++ mt7530_setup_port6(priv->ds, interface);
+
+ return 0;
+ }
--- /dev/null
+From af83e0c7d766078fcd5580c0c81b9e5b55ff5906 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Tue, 6 Feb 2024 01:08:06 +0300
+Subject: [PATCH 16/30] net: dsa: mt7530: remove pad_setup function pointer
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The pad_setup function pointer was introduced with 88bdef8be9f6 ("net: dsa:
+mt7530: Extend device data ready for adding a new hardware"). It was being
+used to set up the core clock and port 6 of the MT7530 switch, and pll of
+the MT7531 switch.
+
+All of these were moved to more appropriate locations, and it was never
+used for the switch on the MT7988 SoC. Therefore, this function pointer
+hasn't got a use anymore. Remove it.
+
+Acked-by: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Link: https://lore.kernel.org/r/20240206-for-netnext-mt7530-improvements-2-v5-5-d7d92a185cb1@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 36 ++----------------------------------
+ drivers/net/dsa/mt7530.h | 3 ---
+ 2 files changed, 2 insertions(+), 37 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -467,18 +467,6 @@ mt7530_setup_port6(struct dsa_switch *ds
+ core_set(priv, CORE_TRGMII_GSW_CLK_CG, REG_TRGMIICK_EN);
+ }
+
+-static int
+-mt7530_pad_clk_setup(struct dsa_switch *ds, phy_interface_t interface)
+-{
+- return 0;
+-}
+-
+-static int
+-mt7531_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
+-{
+- return 0;
+-}
+-
+ static void
+ mt7531_pll_setup(struct mt7530_priv *priv)
+ {
+@@ -2640,14 +2628,6 @@ static void mt7988_mac_port_get_caps(str
+ }
+
+ static int
+-mt753x_pad_setup(struct dsa_switch *ds, const struct phylink_link_state *state)
+-{
+- struct mt7530_priv *priv = ds->priv;
+-
+- return priv->info->pad_setup(ds, state->interface);
+-}
+-
+-static int
+ mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
+ phy_interface_t interface)
+ {
+@@ -2812,8 +2792,6 @@ mt753x_phylink_mac_config(struct dsa_swi
+ if (priv->p6_interface == state->interface)
+ break;
+
+- mt753x_pad_setup(ds, state);
+-
+ if (mt753x_mac_config(ds, port, mode, state) < 0)
+ goto unsupported;
+
+@@ -3130,11 +3108,6 @@ mt753x_conduit_state_change(struct dsa_s
+ mt7530_rmw(priv, MT7530_MFC, CPU_EN | CPU_PORT_MASK, val);
+ }
+
+-static int mt7988_pad_setup(struct dsa_switch *ds, phy_interface_t interface)
+-{
+- return 0;
+-}
+-
+ static int mt7988_setup(struct dsa_switch *ds)
+ {
+ struct mt7530_priv *priv = ds->priv;
+@@ -3198,7 +3171,6 @@ const struct mt753x_info mt753x_table[]
+ .phy_write_c22 = mt7530_phy_write_c22,
+ .phy_read_c45 = mt7530_phy_read_c45,
+ .phy_write_c45 = mt7530_phy_write_c45,
+- .pad_setup = mt7530_pad_clk_setup,
+ .mac_port_get_caps = mt7530_mac_port_get_caps,
+ .mac_port_config = mt7530_mac_config,
+ },
+@@ -3210,7 +3182,6 @@ const struct mt753x_info mt753x_table[]
+ .phy_write_c22 = mt7530_phy_write_c22,
+ .phy_read_c45 = mt7530_phy_read_c45,
+ .phy_write_c45 = mt7530_phy_write_c45,
+- .pad_setup = mt7530_pad_clk_setup,
+ .mac_port_get_caps = mt7530_mac_port_get_caps,
+ .mac_port_config = mt7530_mac_config,
+ },
+@@ -3222,7 +3193,6 @@ const struct mt753x_info mt753x_table[]
+ .phy_write_c22 = mt7531_ind_c22_phy_write,
+ .phy_read_c45 = mt7531_ind_c45_phy_read,
+ .phy_write_c45 = mt7531_ind_c45_phy_write,
+- .pad_setup = mt7531_pad_setup,
+ .cpu_port_config = mt7531_cpu_port_config,
+ .mac_port_get_caps = mt7531_mac_port_get_caps,
+ .mac_port_config = mt7531_mac_config,
+@@ -3235,7 +3205,6 @@ const struct mt753x_info mt753x_table[]
+ .phy_write_c22 = mt7531_ind_c22_phy_write,
+ .phy_read_c45 = mt7531_ind_c45_phy_read,
+ .phy_write_c45 = mt7531_ind_c45_phy_write,
+- .pad_setup = mt7988_pad_setup,
+ .cpu_port_config = mt7988_cpu_port_config,
+ .mac_port_get_caps = mt7988_mac_port_get_caps,
+ .mac_port_config = mt7988_mac_config,
+@@ -3265,9 +3234,8 @@ mt7530_probe_common(struct mt7530_priv *
+ /* Sanity check if these required device operations are filled
+ * properly.
+ */
+- if (!priv->info->sw_setup || !priv->info->pad_setup ||
+- !priv->info->phy_read_c22 || !priv->info->phy_write_c22 ||
+- !priv->info->mac_port_get_caps ||
++ if (!priv->info->sw_setup || !priv->info->phy_read_c22 ||
++ !priv->info->phy_write_c22 || !priv->info->mac_port_get_caps ||
+ !priv->info->mac_port_config)
+ return -EINVAL;
+
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -724,8 +724,6 @@ struct mt753x_pcs {
+ * @phy_write_c22: Holding the way writing PHY port using C22
+ * @phy_read_c45: Holding the way reading PHY port using C45
+ * @phy_write_c45: Holding the way writing PHY port using C45
+- * @pad_setup: Holding the way setting up the bus pad for a certain
+- * MAC port
+ * @phy_mode_supported: Check if the PHY type is being supported on a certain
+ * port
+ * @mac_port_validate: Holding the way to set addition validate type for a
+@@ -746,7 +744,6 @@ struct mt753x_info {
+ int regnum);
+ int (*phy_write_c45)(struct mt7530_priv *priv, int port, int devad,
+ int regnum, u16 val);
+- int (*pad_setup)(struct dsa_switch *ds, phy_interface_t interface);
+ int (*cpu_port_config)(struct dsa_switch *ds, int port);
+ void (*mac_port_get_caps)(struct dsa_switch *ds, int port,
+ struct phylink_config *config);
--- /dev/null
+From 9716e3e2c21547c97a9d79119da8fdce5659c2cc Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Tue, 6 Feb 2024 01:08:07 +0300
+Subject: [PATCH 17/30] net: dsa: mt7530: correct port capabilities of MT7988
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+On the switch on the MT7988 SoC, as shown in Block Diagram 8.1.1.3 on page
+125 of "MT7988A Wi-Fi 7 Generation Router Platform: Datasheet (Open
+Version) v0.1", there are only 4 PHYs. That's port 0 to 3. Set the case for
+ports which connect to switch PHYs to '0 ... 3'.
+
+Port 4 and 5 are not used at all in this design.
+
+Link: https://wiki.banana-pi.org/Banana_Pi_BPI-R4#Documents [1]
+Acked-by: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Link: https://lore.kernel.org/r/20240206-for-netnext-mt7530-improvements-2-v5-6-d7d92a185cb1@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2613,7 +2613,7 @@ static void mt7988_mac_port_get_caps(str
+
+ switch (port) {
+ /* Ports which are connected to switch PHYs. There is no MII pinout. */
+- case 0 ... 4:
++ case 0 ... 3:
+ __set_bit(PHY_INTERFACE_MODE_INTERNAL,
+ config->supported_interfaces);
+ break;
--- /dev/null
+From 4d7b17712513710778c0f2f83ea5d9b55ed58c36 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Tue, 6 Feb 2024 01:08:08 +0300
+Subject: [PATCH 18/30] net: dsa: mt7530: do not clear
+ config->supported_interfaces
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+There's no need to clear the config->supported_interfaces bitmap before
+reporting the supported interfaces as all bits in the bitmap will already
+be initialized to zero when the phylink_config structure is allocated. The
+"config" pointer points to &dp->phylink_config, and "dp" is allocated by
+dsa_port_touch() with kzalloc(), so all its fields are filled with zeroes.
+
+There's no code that would change the bitmap beforehand. Remove it.
+
+Acked-by: Daniel Golle <daniel@makrotopia.org>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Link: https://lore.kernel.org/r/20240206-for-netnext-mt7530-improvements-2-v5-7-d7d92a185cb1@arinc9.com
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 2 --
+ 1 file changed, 2 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2609,8 +2609,6 @@ static void mt7531_mac_port_get_caps(str
+ static void mt7988_mac_port_get_caps(struct dsa_switch *ds, int port,
+ struct phylink_config *config)
+ {
+- phy_interface_zero(config->supported_interfaces);
+-
+ switch (port) {
+ /* Ports which are connected to switch PHYs. There is no MII pinout. */
+ case 0 ... 3:
--- /dev/null
+From 69e689e28191f9a242de6821a85f2c5ae4dbd5ae Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Fri, 1 Mar 2024 12:42:57 +0200
+Subject: [PATCH 19/30] net: dsa: mt7530: remove .mac_port_config for MT7988
+ and make it optional
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+For the switch on the MT7988 SoC, the mac_port_config member for ID_MT7988
+in mt753x_table is not needed as the interfaces of all MACs are already
+handled on mt7988_mac_port_get_caps().
+
+Therefore, remove the mac_port_config member from ID_MT7988 in
+mt753x_table. Before calling priv->info->mac_port_config(), if there's no
+mac_port_config member in mt753x_table, exit mt753x_mac_config()
+successfully.
+
+Remove calling priv->info->mac_port_config() from the sanity check as the
+sanity check requires a pointer to a mac_port_config function to be
+non-NULL. This will fail for MT7988 as mac_port_config won't be a member of
+its info table.
+
+Co-developed-by: Daniel Golle <daniel@makrotopia.org>
+Signed-off-by: Daniel Golle <daniel@makrotopia.org>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Reviewed-by: Vladimir Oltean <olteanv@gmail.com>
+Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 18 ++++--------------
+ 1 file changed, 4 insertions(+), 14 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2692,17 +2692,6 @@ static bool mt753x_is_mac_port(u32 port)
+ }
+
+ static int
+-mt7988_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
+- phy_interface_t interface)
+-{
+- if (dsa_is_cpu_port(ds, port) &&
+- interface == PHY_INTERFACE_MODE_INTERNAL)
+- return 0;
+-
+- return -EINVAL;
+-}
+-
+-static int
+ mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
+ phy_interface_t interface)
+ {
+@@ -2742,6 +2731,9 @@ mt753x_mac_config(struct dsa_switch *ds,
+ {
+ struct mt7530_priv *priv = ds->priv;
+
++ if (!priv->info->mac_port_config)
++ return 0;
++
+ return priv->info->mac_port_config(ds, port, mode, state->interface);
+ }
+
+@@ -3205,7 +3197,6 @@ const struct mt753x_info mt753x_table[]
+ .phy_write_c45 = mt7531_ind_c45_phy_write,
+ .cpu_port_config = mt7988_cpu_port_config,
+ .mac_port_get_caps = mt7988_mac_port_get_caps,
+- .mac_port_config = mt7988_mac_config,
+ },
+ };
+ EXPORT_SYMBOL_GPL(mt753x_table);
+@@ -3233,8 +3224,7 @@ mt7530_probe_common(struct mt7530_priv *
+ * properly.
+ */
+ if (!priv->info->sw_setup || !priv->info->phy_read_c22 ||
+- !priv->info->phy_write_c22 || !priv->info->mac_port_get_caps ||
+- !priv->info->mac_port_config)
++ !priv->info->phy_write_c22 || !priv->info->mac_port_get_caps)
+ return -EINVAL;
+
+ priv->id = priv->info->id;
--- /dev/null
+From f8faa3a04ca860b31f22d7d526c5e3f3de511a8f Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Fri, 1 Mar 2024 12:42:58 +0200
+Subject: [PATCH 20/30] net: dsa: mt7530: set interrupt register only for
+ MT7530
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Setting this register related to interrupts is only needed for the MT7530
+switch. Make an exclusive check to ensure this.
+
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Acked-by: Daniel Golle <daniel@makrotopia.org>
+Tested-by: Daniel Golle <daniel@makrotopia.org>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 2 +-
+ 1 file changed, 1 insertion(+), 1 deletion(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2091,7 +2091,7 @@ mt7530_setup_irq(struct mt7530_priv *pri
+ }
+
+ /* This register must be set for MT7530 to properly fire interrupts */
+- if (priv->id != ID_MT7531)
++ if (priv->id == ID_MT7530 || priv->id == ID_MT7621)
+ mt7530_set(priv, MT7530_TOP_SIG_CTRL, TOP_SIG_CTRL_NORMAL);
+
+ ret = request_threaded_irq(priv->irq, NULL, mt7530_irq_thread_fn,
--- /dev/null
+From 80f4f866d7dad41b12cf37476c38766a89b8b5c4 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Fri, 1 Mar 2024 12:42:59 +0200
+Subject: [PATCH 21/30] net: dsa: mt7530: do not use SW_PHY_RST to reset MT7531
+ switch
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+According to the document MT7531 Reference Manual for Development Board
+v1.0, the SW_PHY_RST bit on the SYS_CTRL register doesn't exist for
+MT7531. This is likely why forcing link down on all ports is necessary for
+MT7531.
+
+Therefore, do not set SW_PHY_RST on mt7531_setup().
+
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 6 ++----
+ 1 file changed, 2 insertions(+), 4 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2487,14 +2487,12 @@ mt7531_setup(struct dsa_switch *ds)
+ val = mt7530_read(priv, MT7531_TOP_SIG_SR);
+ priv->p5_sgmii = !!(val & PAD_DUAL_SGMII_EN);
+
+- /* all MACs must be forced link-down before sw reset */
++ /* Force link down on all ports before internal reset */
+ for (i = 0; i < MT7530_NUM_PORTS; i++)
+ mt7530_write(priv, MT7530_PMCR_P(i), MT7531_FORCE_LNK);
+
+ /* Reset the switch through internal reset */
+- mt7530_write(priv, MT7530_SYS_CTRL,
+- SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST |
+- SYS_CTRL_REG_RST);
++ mt7530_write(priv, MT7530_SYS_CTRL, SYS_CTRL_SW_RST | SYS_CTRL_REG_RST);
+
+ if (!priv->p5_sgmii) {
+ mt7531_pll_setup(priv);
--- /dev/null
+From 58670652cacb7c5752e01f29979d0ca4cdbfcc0a Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Fri, 1 Mar 2024 12:43:00 +0200
+Subject: [PATCH 22/30] net: dsa: mt7530: get rid of useless error returns on
+ phylink code path
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+Remove error returns on the cases where they are already handled with the
+function the mac_port_get_caps member in mt753x_table points to.
+
+mt7531_mac_config() is also called from mt7531_cpu_port_config() outside of
+phylink but the port and interface modes are already handled there.
+
+Change the functions and the mac_port_config function pointer to void now
+that there're no error returns anymore.
+
+Remove mt753x_is_mac_port() that used to help the said error returns.
+
+On mt7531_mac_config(), switch to if statements to simplify the code.
+
+Remove internal phy cases from mt753x_phylink_mac_config(), there is no
+need to check the interface mode as that's already handled with the
+function the mac_port_get_caps member in mt753x_table points to.
+
+Acked-by: Daniel Golle <daniel@makrotopia.org>
+Tested-by: Daniel Golle <daniel@makrotopia.org>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Reviewed-by: Russell King (Oracle) <rmk+kernel@armlinux.org.uk>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 81 ++++++++--------------------------------
+ drivers/net/dsa/mt7530.h | 6 +--
+ 2 files changed, 19 insertions(+), 68 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2623,7 +2623,7 @@ static void mt7988_mac_port_get_caps(str
+ }
+ }
+
+-static int
++static void
+ mt7530_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
+ phy_interface_t interface)
+ {
+@@ -2633,22 +2633,14 @@ mt7530_mac_config(struct dsa_switch *ds,
+ mt7530_setup_port5(priv->ds, interface);
+ else if (port == 6)
+ mt7530_setup_port6(priv->ds, interface);
+-
+- return 0;
+ }
+
+-static int mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port,
+- phy_interface_t interface,
+- struct phy_device *phydev)
++static void mt7531_rgmii_setup(struct mt7530_priv *priv, u32 port,
++ phy_interface_t interface,
++ struct phy_device *phydev)
+ {
+ u32 val;
+
+- if (priv->p5_sgmii) {
+- dev_err(priv->dev, "RGMII mode is not available for port %d\n",
+- port);
+- return -EINVAL;
+- }
+-
+ val = mt7530_read(priv, MT7531_CLKGEN_CTRL);
+ val |= GP_CLK_EN;
+ val &= ~GP_MODE_MASK;
+@@ -2676,20 +2668,14 @@ static int mt7531_rgmii_setup(struct mt7
+ case PHY_INTERFACE_MODE_RGMII_ID:
+ break;
+ default:
+- return -EINVAL;
++ break;
+ }
+ }
+- mt7530_write(priv, MT7531_CLKGEN_CTRL, val);
+
+- return 0;
+-}
+-
+-static bool mt753x_is_mac_port(u32 port)
+-{
+- return (port == 5 || port == 6);
++ mt7530_write(priv, MT7531_CLKGEN_CTRL, val);
+ }
+
+-static int
++static void
+ mt7531_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
+ phy_interface_t interface)
+ {
+@@ -2697,42 +2683,21 @@ mt7531_mac_config(struct dsa_switch *ds,
+ struct phy_device *phydev;
+ struct dsa_port *dp;
+
+- if (!mt753x_is_mac_port(port)) {
+- dev_err(priv->dev, "port %d is not a MAC port\n", port);
+- return -EINVAL;
+- }
+-
+- switch (interface) {
+- case PHY_INTERFACE_MODE_RGMII:
+- case PHY_INTERFACE_MODE_RGMII_ID:
+- case PHY_INTERFACE_MODE_RGMII_RXID:
+- case PHY_INTERFACE_MODE_RGMII_TXID:
++ if (phy_interface_mode_is_rgmii(interface)) {
+ dp = dsa_to_port(ds, port);
+ phydev = dp->slave->phydev;
+- return mt7531_rgmii_setup(priv, port, interface, phydev);
+- case PHY_INTERFACE_MODE_SGMII:
+- case PHY_INTERFACE_MODE_NA:
+- case PHY_INTERFACE_MODE_1000BASEX:
+- case PHY_INTERFACE_MODE_2500BASEX:
+- /* handled in SGMII PCS driver */
+- return 0;
+- default:
+- return -EINVAL;
++ mt7531_rgmii_setup(priv, port, interface, phydev);
+ }
+-
+- return -EINVAL;
+ }
+
+-static int
++static void
+ mt753x_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
+ const struct phylink_link_state *state)
+ {
+ struct mt7530_priv *priv = ds->priv;
+
+- if (!priv->info->mac_port_config)
+- return 0;
+-
+- return priv->info->mac_port_config(ds, port, mode, state->interface);
++ if (priv->info->mac_port_config)
++ priv->info->mac_port_config(ds, port, mode, state->interface);
+ }
+
+ static struct phylink_pcs *
+@@ -2761,17 +2726,11 @@ mt753x_phylink_mac_config(struct dsa_swi
+ u32 mcr_cur, mcr_new;
+
+ switch (port) {
+- case 0 ... 4:
+- if (state->interface != PHY_INTERFACE_MODE_GMII &&
+- state->interface != PHY_INTERFACE_MODE_INTERNAL)
+- goto unsupported;
+- break;
+ case 5:
+ if (priv->p5_interface == state->interface)
+ break;
+
+- if (mt753x_mac_config(ds, port, mode, state) < 0)
+- goto unsupported;
++ mt753x_mac_config(ds, port, mode, state);
+
+ if (priv->p5_intf_sel != P5_DISABLED)
+ priv->p5_interface = state->interface;
+@@ -2780,16 +2739,10 @@ mt753x_phylink_mac_config(struct dsa_swi
+ if (priv->p6_interface == state->interface)
+ break;
+
+- if (mt753x_mac_config(ds, port, mode, state) < 0)
+- goto unsupported;
++ mt753x_mac_config(ds, port, mode, state);
+
+ priv->p6_interface = state->interface;
+ break;
+- default:
+-unsupported:
+- dev_err(ds->dev, "%s: unsupported %s port: %i\n",
+- __func__, phy_modes(state->interface), port);
+- return;
+ }
+
+ mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port));
+@@ -2872,7 +2825,6 @@ mt7531_cpu_port_config(struct dsa_switch
+ struct mt7530_priv *priv = ds->priv;
+ phy_interface_t interface;
+ int speed;
+- int ret;
+
+ switch (port) {
+ case 5:
+@@ -2897,9 +2849,8 @@ mt7531_cpu_port_config(struct dsa_switch
+ else
+ speed = SPEED_1000;
+
+- ret = mt7531_mac_config(ds, port, MLO_AN_FIXED, interface);
+- if (ret)
+- return ret;
++ mt7531_mac_config(ds, port, MLO_AN_FIXED, interface);
++
+ mt7530_write(priv, MT7530_PMCR_P(port),
+ PMCR_CPU_PORT_SETTING(priv->id));
+ mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL,
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -750,9 +750,9 @@ struct mt753x_info {
+ void (*mac_port_validate)(struct dsa_switch *ds, int port,
+ phy_interface_t interface,
+ unsigned long *supported);
+- int (*mac_port_config)(struct dsa_switch *ds, int port,
+- unsigned int mode,
+- phy_interface_t interface);
++ void (*mac_port_config)(struct dsa_switch *ds, int port,
++ unsigned int mode,
++ phy_interface_t interface);
+ };
+
+ /* struct mt7530_priv - This is the main data structure for holding the state
--- /dev/null
+From 859df5cf6ff07a9c930be4681284346aa73dd1fb Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Fri, 1 Mar 2024 12:43:01 +0200
+Subject: [PATCH 23/30] net: dsa: mt7530: get rid of
+ priv->info->cpu_port_config()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+priv->info->cpu_port_config() is used for MT7531 and the switch on the
+MT7988 SoC. It sets up the ports described as a CPU port earlier than the
+phylink code path would do.
+
+This function is useless as:
+- Configuring the MACs can be done from the phylink_mac_config code path
+ instead.
+- All the link configuration it does on the CPU ports are later undone with
+ the port_enable, phylink_mac_config, and then phylink_mac_link_up code
+ path [1].
+
+priv->p5_interface and priv->p6_interface were being used to prevent
+configuring the MACs from the phylink_mac_config code path. Remove them now
+that they hold no purpose.
+
+Remove priv->info->cpu_port_config(). On mt753x_phylink_mac_config, switch
+to if statements to simplify the code.
+
+Remove the overwriting of the speed and duplex interfaces for certain
+interface modes. Phylink already provides the speed and duplex variables
+with proper values. Phylink already sets the max speed of TRGMII to
+SPEED_1000. Add SPEED_2500 for PHY_INTERFACE_MODE_2500BASEX to where the
+speed and EEE bits are set instead.
+
+On the switch on the MT7988 SoC, PHY_INTERFACE_MODE_INTERNAL is being used
+to describe the interface mode of the 10G MAC, which is of port 6. On
+mt7988_cpu_port_config() PMCR_FORCE_SPEED_1000 was set via the
+PMCR_CPU_PORT_SETTING() mask. Add SPEED_10000 case to where the speed bits
+are set to cover this. No need to add it to where the EEE bits are set as
+the "MT7988A Wi-Fi 7 Generation Router Platform: Datasheet (Open Version)
+v0.1" document shows that these bits don't exist on the MT7530_PMCR_P(6)
+register.
+
+Remove the definition of PMCR_CPU_PORT_SETTING() now that it holds no
+purpose.
+
+Change mt753x_cpu_port_enable() to void now that there're no error cases
+left.
+
+Link: https://lore.kernel.org/netdev/ZHy2jQLesdYFMQtO@shell.armlinux.org.uk/ [1]
+Suggested-by: Russell King (Oracle) <linux@armlinux.org.uk>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 114 +++------------------------------------
+ drivers/net/dsa/mt7530.h | 11 ----
+ 2 files changed, 7 insertions(+), 118 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -1002,18 +1002,10 @@ mt753x_trap_frames(struct mt7530_priv *p
+ MT753X_BPDU_CPU_ONLY);
+ }
+
+-static int
++static void
+ mt753x_cpu_port_enable(struct dsa_switch *ds, int port)
+ {
+ struct mt7530_priv *priv = ds->priv;
+- int ret;
+-
+- /* Setup max capability of CPU port at first */
+- if (priv->info->cpu_port_config) {
+- ret = priv->info->cpu_port_config(ds, port);
+- if (ret)
+- return ret;
+- }
+
+ /* Enable Mediatek header mode on the cpu port */
+ mt7530_write(priv, MT7530_PVC_P(port),
+@@ -1039,8 +1031,6 @@ mt753x_cpu_port_enable(struct dsa_switch
+ /* Set to fallback mode for independent VLAN learning */
+ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_PORT_VLAN_MASK,
+ MT7530_PORT_FALLBACK_MODE);
+-
+- return 0;
+ }
+
+ static int
+@@ -2297,8 +2287,6 @@ mt7530_setup(struct dsa_switch *ds)
+ val |= MHWTRAP_MANUAL;
+ mt7530_write(priv, MT7530_MHWTRAP, val);
+
+- priv->p6_interface = PHY_INTERFACE_MODE_NA;
+-
+ mt753x_trap_frames(priv);
+
+ /* Enable and reset MIB counters */
+@@ -2313,9 +2301,7 @@ mt7530_setup(struct dsa_switch *ds)
+ mt7530_set(priv, MT7530_PSC_P(i), SA_DIS);
+
+ if (dsa_is_cpu_port(ds, i)) {
+- ret = mt753x_cpu_port_enable(ds, i);
+- if (ret)
+- return ret;
++ mt753x_cpu_port_enable(ds, i);
+ } else {
+ mt7530_port_disable(ds, i);
+
+@@ -2419,9 +2405,7 @@ mt7531_setup_common(struct dsa_switch *d
+ mt7530_set(priv, MT7531_DBG_CNT(i), MT7531_DIS_CLR);
+
+ if (dsa_is_cpu_port(ds, i)) {
+- ret = mt753x_cpu_port_enable(ds, i);
+- if (ret)
+- return ret;
++ mt753x_cpu_port_enable(ds, i);
+ } else {
+ mt7530_port_disable(ds, i);
+
+@@ -2510,10 +2494,6 @@ mt7531_setup(struct dsa_switch *ds)
+ mt7530_rmw(priv, MT7531_GPIO_MODE0, MT7531_GPIO0_MASK,
+ MT7531_GPIO0_INTERRUPT);
+
+- /* Let phylink decide the interface later. */
+- priv->p5_interface = PHY_INTERFACE_MODE_NA;
+- priv->p6_interface = PHY_INTERFACE_MODE_NA;
+-
+ /* Enable PHY core PLL, since phy_device has not yet been created
+ * provided for phy_[read,write]_mmd_indirect is called, we provide
+ * our own mt7531_ind_mmd_phy_[read,write] to complete this
+@@ -2725,26 +2705,9 @@ mt753x_phylink_mac_config(struct dsa_swi
+ struct mt7530_priv *priv = ds->priv;
+ u32 mcr_cur, mcr_new;
+
+- switch (port) {
+- case 5:
+- if (priv->p5_interface == state->interface)
+- break;
+-
++ if (port == 5 || port == 6)
+ mt753x_mac_config(ds, port, mode, state);
+
+- if (priv->p5_intf_sel != P5_DISABLED)
+- priv->p5_interface = state->interface;
+- break;
+- case 6:
+- if (priv->p6_interface == state->interface)
+- break;
+-
+- mt753x_mac_config(ds, port, mode, state);
+-
+- priv->p6_interface = state->interface;
+- break;
+- }
+-
+ mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port));
+ mcr_new = mcr_cur;
+ mcr_new &= ~PMCR_LINK_SETTINGS_MASK;
+@@ -2780,17 +2743,10 @@ static void mt753x_phylink_mac_link_up(s
+
+ mcr = PMCR_RX_EN | PMCR_TX_EN | PMCR_FORCE_LNK;
+
+- /* MT753x MAC works in 1G full duplex mode for all up-clocked
+- * variants.
+- */
+- if (interface == PHY_INTERFACE_MODE_TRGMII ||
+- (phy_interface_mode_is_8023z(interface))) {
+- speed = SPEED_1000;
+- duplex = DUPLEX_FULL;
+- }
+-
+ switch (speed) {
+ case SPEED_1000:
++ case SPEED_2500:
++ case SPEED_10000:
+ mcr |= PMCR_FORCE_SPEED_1000;
+ break;
+ case SPEED_100:
+@@ -2808,6 +2764,7 @@ static void mt753x_phylink_mac_link_up(s
+ if (mode == MLO_AN_PHY && phydev && phy_init_eee(phydev, false) >= 0) {
+ switch (speed) {
+ case SPEED_1000:
++ case SPEED_2500:
+ mcr |= PMCR_FORCE_EEE1G;
+ break;
+ case SPEED_100:
+@@ -2819,61 +2776,6 @@ static void mt753x_phylink_mac_link_up(s
+ mt7530_set(priv, MT7530_PMCR_P(port), mcr);
+ }
+
+-static int
+-mt7531_cpu_port_config(struct dsa_switch *ds, int port)
+-{
+- struct mt7530_priv *priv = ds->priv;
+- phy_interface_t interface;
+- int speed;
+-
+- switch (port) {
+- case 5:
+- if (!priv->p5_sgmii)
+- interface = PHY_INTERFACE_MODE_RGMII;
+- else
+- interface = PHY_INTERFACE_MODE_2500BASEX;
+-
+- priv->p5_interface = interface;
+- break;
+- case 6:
+- interface = PHY_INTERFACE_MODE_2500BASEX;
+-
+- priv->p6_interface = interface;
+- break;
+- default:
+- return -EINVAL;
+- }
+-
+- if (interface == PHY_INTERFACE_MODE_2500BASEX)
+- speed = SPEED_2500;
+- else
+- speed = SPEED_1000;
+-
+- mt7531_mac_config(ds, port, MLO_AN_FIXED, interface);
+-
+- mt7530_write(priv, MT7530_PMCR_P(port),
+- PMCR_CPU_PORT_SETTING(priv->id));
+- mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED, interface, NULL,
+- speed, DUPLEX_FULL, true, true);
+-
+- return 0;
+-}
+-
+-static int
+-mt7988_cpu_port_config(struct dsa_switch *ds, int port)
+-{
+- struct mt7530_priv *priv = ds->priv;
+-
+- mt7530_write(priv, MT7530_PMCR_P(port),
+- PMCR_CPU_PORT_SETTING(priv->id));
+-
+- mt753x_phylink_mac_link_up(ds, port, MLO_AN_FIXED,
+- PHY_INTERFACE_MODE_INTERNAL, NULL,
+- SPEED_10000, DUPLEX_FULL, true, true);
+-
+- return 0;
+-}
+-
+ static void mt753x_phylink_get_caps(struct dsa_switch *ds, int port,
+ struct phylink_config *config)
+ {
+@@ -3132,7 +3034,6 @@ const struct mt753x_info mt753x_table[]
+ .phy_write_c22 = mt7531_ind_c22_phy_write,
+ .phy_read_c45 = mt7531_ind_c45_phy_read,
+ .phy_write_c45 = mt7531_ind_c45_phy_write,
+- .cpu_port_config = mt7531_cpu_port_config,
+ .mac_port_get_caps = mt7531_mac_port_get_caps,
+ .mac_port_config = mt7531_mac_config,
+ },
+@@ -3144,7 +3045,6 @@ const struct mt753x_info mt753x_table[]
+ .phy_write_c22 = mt7531_ind_c22_phy_write,
+ .phy_read_c45 = mt7531_ind_c45_phy_read,
+ .phy_write_c45 = mt7531_ind_c45_phy_write,
+- .cpu_port_config = mt7988_cpu_port_config,
+ .mac_port_get_caps = mt7988_mac_port_get_caps,
+ },
+ };
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -331,13 +331,6 @@ enum mt7530_vlan_port_acc_frm {
+ PMCR_TX_FC_EN | PMCR_RX_FC_EN | \
+ PMCR_FORCE_FDX | PMCR_FORCE_LNK | \
+ PMCR_FORCE_EEE1G | PMCR_FORCE_EEE100)
+-#define PMCR_CPU_PORT_SETTING(id) (PMCR_FORCE_MODE_ID((id)) | \
+- PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | \
+- PMCR_BACKOFF_EN | PMCR_BACKPR_EN | \
+- PMCR_TX_EN | PMCR_RX_EN | \
+- PMCR_TX_FC_EN | PMCR_RX_FC_EN | \
+- PMCR_FORCE_SPEED_1000 | \
+- PMCR_FORCE_FDX | PMCR_FORCE_LNK)
+
+ #define MT7530_PMEEECR_P(x) (0x3004 + (x) * 0x100)
+ #define WAKEUP_TIME_1000(x) (((x) & 0xFF) << 24)
+@@ -744,7 +737,6 @@ struct mt753x_info {
+ int regnum);
+ int (*phy_write_c45)(struct mt7530_priv *priv, int port, int devad,
+ int regnum, u16 val);
+- int (*cpu_port_config)(struct dsa_switch *ds, int port);
+ void (*mac_port_get_caps)(struct dsa_switch *ds, int port,
+ struct phylink_config *config);
+ void (*mac_port_validate)(struct dsa_switch *ds, int port,
+@@ -770,7 +762,6 @@ struct mt753x_info {
+ * @ports: Holding the state among ports
+ * @reg_mutex: The lock for protecting among process accessing
+ * registers
+- * @p6_interface Holding the current port 6 interface
+ * @p5_intf_sel: Holding the current port 5 interface select
+ * @p5_sgmii: Flag for distinguishing if port 5 of the MT7531 switch
+ * has got SGMII
+@@ -792,8 +783,6 @@ struct mt7530_priv {
+ const struct mt753x_info *info;
+ unsigned int id;
+ bool mcm;
+- phy_interface_t p6_interface;
+- phy_interface_t p5_interface;
+ enum p5_interface_select p5_intf_sel;
+ bool p5_sgmii;
+ u8 mirror_rx;
--- /dev/null
+From c74a98baa8d098157975b3f94e496dd3a73e0864 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Fri, 1 Mar 2024 12:43:02 +0200
+Subject: [PATCH 24/30] net: dsa: mt7530: get rid of mt753x_mac_config()
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+There is no need for a separate function to call
+priv->info->mac_port_config(). Call it from mt753x_phylink_mac_config()
+instead and remove mt753x_mac_config().
+
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 14 ++------------
+ 1 file changed, 2 insertions(+), 12 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2670,16 +2670,6 @@ mt7531_mac_config(struct dsa_switch *ds,
+ }
+ }
+
+-static void
+-mt753x_mac_config(struct dsa_switch *ds, int port, unsigned int mode,
+- const struct phylink_link_state *state)
+-{
+- struct mt7530_priv *priv = ds->priv;
+-
+- if (priv->info->mac_port_config)
+- priv->info->mac_port_config(ds, port, mode, state->interface);
+-}
+-
+ static struct phylink_pcs *
+ mt753x_phylink_mac_select_pcs(struct dsa_switch *ds, int port,
+ phy_interface_t interface)
+@@ -2705,8 +2695,8 @@ mt753x_phylink_mac_config(struct dsa_swi
+ struct mt7530_priv *priv = ds->priv;
+ u32 mcr_cur, mcr_new;
+
+- if (port == 5 || port == 6)
+- mt753x_mac_config(ds, port, mode, state);
++ if ((port == 5 || port == 6) && priv->info->mac_port_config)
++ priv->info->mac_port_config(ds, port, mode, state->interface);
+
+ mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port));
+ mcr_new = mcr_cur;
--- /dev/null
+From ab1ddb241bc1cb3d80aa51207810edd5cb0bbdc5 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Fri, 1 Mar 2024 12:43:03 +0200
+Subject: [PATCH 25/30] net: dsa: mt7530: put initialising PCS devices code
+ back to original order
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The commit fae463084032 ("net: dsa: mt753x: fix pcs conversion regression")
+fixes regression caused by cpu_port_config manually calling phylink
+operations. cpu_port_config was deemed useless and was removed. Therefore,
+put initialising PCS devices code back to its original order.
+
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 20 ++++++++++----------
+ 1 file changed, 10 insertions(+), 10 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2848,17 +2848,9 @@ static int
+ mt753x_setup(struct dsa_switch *ds)
+ {
+ struct mt7530_priv *priv = ds->priv;
+- int i, ret;
++ int ret = priv->info->sw_setup(ds);
++ int i;
+
+- /* Initialise the PCS devices */
+- for (i = 0; i < priv->ds->num_ports; i++) {
+- priv->pcs[i].pcs.ops = priv->info->pcs_ops;
+- priv->pcs[i].pcs.neg_mode = true;
+- priv->pcs[i].priv = priv;
+- priv->pcs[i].port = i;
+- }
+-
+- ret = priv->info->sw_setup(ds);
+ if (ret)
+ return ret;
+
+@@ -2870,6 +2862,14 @@ mt753x_setup(struct dsa_switch *ds)
+ if (ret && priv->irq)
+ mt7530_free_irq_common(priv);
+
++ /* Initialise the PCS devices */
++ for (i = 0; i < priv->ds->num_ports; i++) {
++ priv->pcs[i].pcs.ops = priv->info->pcs_ops;
++ priv->pcs[i].pcs.neg_mode = true;
++ priv->pcs[i].priv = priv;
++ priv->pcs[i].port = i;
++ }
++
+ if (priv->create_sgmii) {
+ ret = priv->create_sgmii(priv);
+ if (ret && priv->irq)
--- /dev/null
+From aa474698f75f4790a4de2052dd487736d2361b2e Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Fri, 1 Mar 2024 12:43:04 +0200
+Subject: [PATCH 26/30] net: dsa: mt7530: sort link settings ops and force link
+ down on all ports
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+port_enable and port_disable clears the link settings. Move that to
+mt7530_setup() and mt7531_setup_common() which set up the switches. This
+way, the link settings are cleared on all ports at setup, and then only
+once with phylink_mac_link_down() when a link goes down.
+
+Enable force mode at setup to apply the force part of the link settings.
+This ensures that disabled ports will have their link down.
+
+Suggested-by: Vladimir Oltean <olteanv@gmail.com>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 14 ++++++++++++--
+ 1 file changed, 12 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -1054,7 +1054,6 @@ mt7530_port_enable(struct dsa_switch *ds
+ priv->ports[port].enable = true;
+ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
+ priv->ports[port].pm);
+- mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
+
+ mutex_unlock(&priv->reg_mutex);
+
+@@ -1074,7 +1073,6 @@ mt7530_port_disable(struct dsa_switch *d
+ priv->ports[port].enable = false;
+ mt7530_rmw(priv, MT7530_PCR_P(port), PCR_MATRIX_MASK,
+ PCR_MATRIX_CLR);
+- mt7530_clear(priv, MT7530_PMCR_P(port), PMCR_LINK_SETTINGS_MASK);
+
+ mutex_unlock(&priv->reg_mutex);
+ }
+@@ -2293,6 +2291,12 @@ mt7530_setup(struct dsa_switch *ds)
+ mt7530_mib_reset(ds);
+
+ for (i = 0; i < MT7530_NUM_PORTS; i++) {
++ /* Clear link settings and enable force mode to force link down
++ * on all ports until they're enabled later.
++ */
++ mt7530_rmw(priv, MT7530_PMCR_P(i), PMCR_LINK_SETTINGS_MASK |
++ PMCR_FORCE_MODE, PMCR_FORCE_MODE);
++
+ /* Disable forwarding by default on all ports */
+ mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
+ PCR_MATRIX_CLR);
+@@ -2395,6 +2399,12 @@ mt7531_setup_common(struct dsa_switch *d
+ UNU_FFP_MASK);
+
+ for (i = 0; i < MT7530_NUM_PORTS; i++) {
++ /* Clear link settings and enable force mode to force link down
++ * on all ports until they're enabled later.
++ */
++ mt7530_rmw(priv, MT7530_PMCR_P(i), PMCR_LINK_SETTINGS_MASK |
++ MT7531_FORCE_MODE, MT7531_FORCE_MODE);
++
+ /* Disable forwarding by default on all ports */
+ mt7530_rmw(priv, MT7530_PCR_P(i), PCR_MATRIX_MASK,
+ PCR_MATRIX_CLR);
--- /dev/null
+From 1ca89c2e349d7c5e045911d741dacf4c83d029e7 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Fri, 1 Mar 2024 12:43:05 +0200
+Subject: [PATCH 27/30] net: dsa: mt7530: simplify link operations
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The "MT7621 Giga Switch Programming Guide v0.3", "MT7531 Reference Manual
+for Development Board v1.0", and "MT7988A Wi-Fi 7 Generation Router
+Platform: Datasheet (Open Version) v0.1" documents show that these bits are
+enabled at reset:
+
+PMCR_IFG_XMIT(1) (not part of PMCR_LINK_SETTINGS_MASK)
+PMCR_MAC_MODE (not part of PMCR_LINK_SETTINGS_MASK)
+PMCR_TX_EN
+PMCR_RX_EN
+PMCR_BACKOFF_EN (not part of PMCR_LINK_SETTINGS_MASK)
+PMCR_BACKPR_EN (not part of PMCR_LINK_SETTINGS_MASK)
+PMCR_TX_FC_EN
+PMCR_RX_FC_EN
+
+These bits also don't exist on the MT7530_PMCR_P(6) register of the switch
+on the MT7988 SoC:
+
+PMCR_IFG_XMIT()
+PMCR_MAC_MODE
+PMCR_BACKOFF_EN
+PMCR_BACKPR_EN
+
+Remove the setting of the bits not part of PMCR_LINK_SETTINGS_MASK on
+phylink_mac_config as they're already set.
+
+The bit for setting the port on force mode is already done on
+mt7530_setup() and mt7531_setup_common(). So get rid of
+PMCR_FORCE_MODE_ID() which helped determine which bit to use for the switch
+model.
+
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 12 +-----------
+ drivers/net/dsa/mt7530.h | 2 --
+ 2 files changed, 1 insertion(+), 13 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2703,23 +2703,13 @@ mt753x_phylink_mac_config(struct dsa_swi
+ const struct phylink_link_state *state)
+ {
+ struct mt7530_priv *priv = ds->priv;
+- u32 mcr_cur, mcr_new;
+
+ if ((port == 5 || port == 6) && priv->info->mac_port_config)
+ priv->info->mac_port_config(ds, port, mode, state->interface);
+
+- mcr_cur = mt7530_read(priv, MT7530_PMCR_P(port));
+- mcr_new = mcr_cur;
+- mcr_new &= ~PMCR_LINK_SETTINGS_MASK;
+- mcr_new |= PMCR_IFG_XMIT(1) | PMCR_MAC_MODE | PMCR_BACKOFF_EN |
+- PMCR_BACKPR_EN | PMCR_FORCE_MODE_ID(priv->id);
+-
+ /* Are we connected to external phy */
+ if (port == 5 && dsa_is_user_port(ds, 5))
+- mcr_new |= PMCR_EXT_PHY;
+-
+- if (mcr_new != mcr_cur)
+- mt7530_write(priv, MT7530_PMCR_P(port), mcr_new);
++ mt7530_set(priv, MT7530_PMCR_P(port), PMCR_EXT_PHY);
+ }
+
+ static void mt753x_phylink_mac_link_down(struct dsa_switch *ds, int port,
+--- a/drivers/net/dsa/mt7530.h
++++ b/drivers/net/dsa/mt7530.h
+@@ -324,8 +324,6 @@ enum mt7530_vlan_port_acc_frm {
+ MT7531_FORCE_DPX | \
+ MT7531_FORCE_RX_FC | \
+ MT7531_FORCE_TX_FC)
+-#define PMCR_FORCE_MODE_ID(id) ((((id) == ID_MT7531) || ((id) == ID_MT7988)) ? \
+- MT7531_FORCE_MODE : PMCR_FORCE_MODE)
+ #define PMCR_LINK_SETTINGS_MASK (PMCR_TX_EN | PMCR_FORCE_SPEED_1000 | \
+ PMCR_RX_EN | PMCR_FORCE_SPEED_100 | \
+ PMCR_TX_FC_EN | PMCR_RX_FC_EN | \
--- /dev/null
+From de16cf680331cd0bd7db97c3f8d376f5eac39cae Mon Sep 17 00:00:00 2001
+From: Justin Swartz <justin.swartz@risingedge.co.za>
+Date: Tue, 5 Mar 2024 06:39:51 +0200
+Subject: [PATCH 28/30] net: dsa: mt7530: disable LEDs before reset
+
+Disable LEDs just before resetting the MT7530 to avoid
+situations where the ESW_P4_LED_0 and ESW_P3_LED_0 pin
+states may cause an unintended external crystal frequency
+to be selected.
+
+The HT_XTAL_FSEL (External Crystal Frequency Selection)
+field of HWTRAP (the Hardware Trap register) stores a
+2-bit value that represents the state of the ESW_P4_LED_0
+and ESW_P4_LED_0 pins (seemingly) sampled just after the
+MT7530 has been reset, as:
+
+ ESW_P4_LED_0 ESW_P3_LED_0 Frequency
+ -----------------------------------------
+ 0 1 20MHz
+ 1 0 40MHz
+ 1 1 25MHz
+
+The value of HT_XTAL_FSEL is bootstrapped by pulling
+ESW_P4_LED_0 and ESW_P3_LED_0 up or down accordingly,
+but:
+
+ if a 40MHz crystal has been selected and
+ the ESW_P3_LED_0 pin is high during reset,
+
+ or a 20MHz crystal has been selected and
+ the ESW_P4_LED_0 pin is high during reset,
+
+ then the value of HT_XTAL_FSEL will indicate
+ that a 25MHz crystal is present.
+
+By default, the state of the LED pins is PHY controlled
+to reflect the link state.
+
+To illustrate, if a board has:
+
+ 5 ports with active low LED control,
+ and HT_XTAL_FSEL bootstrapped for 40MHz.
+
+When the MT7530 is powered up without any external
+connection, only the LED associated with Port 3 is
+illuminated as ESW_P3_LED_0 is low.
+
+In this state, directly after mt7530_setup()'s reset
+is performed, the HWTRAP register (0x7800) reflects
+the intended HT_XTAL_FSEL (HWTRAP bits 10:9) of 40MHz:
+
+ mt7530-mdio mdio-bus:1f: mt7530_read: 00007800 == 00007dcf
+
+ >>> bin(0x7dcf >> 9 & 0b11)
+ '0b10'
+
+But if a cable is connected to Port 3 and the link
+is active before mt7530_setup()'s reset takes place,
+then HT_XTAL_FSEL seems to be set for 25MHz:
+
+ mt7530-mdio mdio-bus:1f: mt7530_read: 00007800 == 00007fcf
+
+ >>> bin(0x7fcf >> 9 & 0b11)
+ '0b11'
+
+Once HT_XTAL_FSEL reflects 25MHz, none of the ports
+are functional until the MT7621 (or MT7530 itself)
+is reset.
+
+By disabling the LED pins just before reset, the chance
+of an unintended HT_XTAL_FSEL value is reduced.
+
+Signed-off-by: Justin Swartz <justin.swartz@risingedge.co.za>
+Link: https://lore.kernel.org/r/20240305043952.21590-1-justin.swartz@risingedge.co.za
+Signed-off-by: Jakub Kicinski <kuba@kernel.org>
+---
+ drivers/net/dsa/mt7530.c | 6 ++++++
+ 1 file changed, 6 insertions(+)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2228,6 +2228,12 @@ mt7530_setup(struct dsa_switch *ds)
+ }
+ }
+
++ /* Disable LEDs before reset to prevent the MT7530 sampling a
++ * potentially incorrect HT_XTAL_FSEL value.
++ */
++ mt7530_write(priv, MT7530_LED_EN, 0);
++ usleep_range(1000, 1100);
++
+ /* Reset whole chip through gpio pin or memory-mapped registers for
+ * different type of hardware
+ */
--- /dev/null
+From fa14c96eab3ec5b7cb44b06c0a54a851849a9810 Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Wed, 20 Mar 2024 23:45:30 +0300
+Subject: [PATCH 29/30] net: dsa: mt7530: fix improper frames on all 25MHz and
+ 40MHz XTAL MT7530
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+The MT7530 switch after reset initialises with a core clock frequency that
+works with a 25MHz XTAL connected to it. For 40MHz XTAL, the core clock
+frequency must be set to 500MHz.
+
+The mt7530_pll_setup() function is responsible of setting the core clock
+frequency. Currently, it runs on MT7530 with 25MHz and 40MHz XTAL. This
+causes MT7530 switch with 25MHz XTAL to egress and ingress frames
+improperly.
+
+Introduce a check to run it only on MT7530 with 40MHz XTAL.
+
+The core clock frequency is set by writing to a switch PHY's register.
+Access to the PHY's register is done via the MDIO bus the switch is also
+on. Therefore, it works only when the switch makes switch PHYs listen on
+the MDIO bus the switch is on. This is controlled either by the state of
+the ESW_P1_LED_1 pin after reset deassertion or modifying bit 5 of the
+modifiable trap register.
+
+When ESW_P1_LED_1 is pulled high, PHY indirect access is used. That means
+accessing PHY registers via the PHY indirect access control register of the
+switch.
+
+When ESW_P1_LED_1 is pulled low, PHY direct access is used. That means
+accessing PHY registers via the MDIO bus the switch is on.
+
+For MT7530 switch with 40MHz XTAL on a board with ESW_P1_LED_1 pulled high,
+the core clock frequency won't be set to 500MHz, causing the switch to
+egress and ingress frames improperly.
+
+Run mt7530_pll_setup() after PHY direct access is set on the modifiable
+trap register.
+
+With these two changes, all MT7530 switches with 25MHz and 40MHz, and
+P1_LED_1 pulled high or low, will egress and ingress frames properly.
+
+Link: https://github.com/BPI-SINOVOIP/BPI-R2-bsp/blob/4a5dd143f2172ec97a2872fa29c7c4cd520f45b5/linux-mt/drivers/net/ethernet/mediatek/gsw_mt7623.c#L1039
+Fixes: b8f126a8d543 ("net-next: dsa: add dsa support for Mediatek MT7530 switch")
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Link: https://lore.kernel.org/r/20240320-for-net-mt7530-fix-25mhz-xtal-with-direct-phy-access-v1-1-d92f605f1160@arinc9.com
+Signed-off-by: Paolo Abeni <pabeni@redhat.com>
+---
+ drivers/net/dsa/mt7530.c | 5 +++--
+ 1 file changed, 3 insertions(+), 2 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2274,8 +2274,6 @@ mt7530_setup(struct dsa_switch *ds)
+ SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST |
+ SYS_CTRL_REG_RST);
+
+- mt7530_pll_setup(priv);
+-
+ /* Lower Tx driving for TRGMII path */
+ for (i = 0; i < NUM_TRGMII_CTRL; i++)
+ mt7530_write(priv, MT7530_TRGMII_TD_ODT(i),
+@@ -2291,6 +2289,9 @@ mt7530_setup(struct dsa_switch *ds)
+ val |= MHWTRAP_MANUAL;
+ mt7530_write(priv, MT7530_MHWTRAP, val);
+
++ if ((val & HWTRAP_XTAL_MASK) == HWTRAP_XTAL_40MHZ)
++ mt7530_pll_setup(priv);
++
+ mt753x_trap_frames(priv);
+
+ /* Enable and reset MIB counters */
--- /dev/null
+From b9547109205c5e0a27e5bed568b0fc183fff906b Mon Sep 17 00:00:00 2001
+From: =?UTF-8?q?Ar=C4=B1n=C3=A7=20=C3=9CNAL?= <arinc.unal@arinc9.com>
+Date: Thu, 14 Mar 2024 12:28:35 +0300
+Subject: [PATCH 30/30] net: dsa: mt7530: prevent possible incorrect XTAL
+ frequency selection
+MIME-Version: 1.0
+Content-Type: text/plain; charset=UTF-8
+Content-Transfer-Encoding: 8bit
+
+On MT7530, the HT_XTAL_FSEL field of the HWTRAP register stores a 2-bit
+value that represents the frequency of the crystal oscillator connected to
+the switch IC. The field is populated by the state of the ESW_P4_LED_0 and
+ESW_P4_LED_0 pins, which is done right after reset is deasserted.
+
+ ESW_P4_LED_0 ESW_P3_LED_0 Frequency
+ -----------------------------------------
+ 0 0 Reserved
+ 0 1 20MHz
+ 1 0 40MHz
+ 1 1 25MHz
+
+On MT7531, the XTAL25 bit of the STRAP register stores this. The LAN0LED0
+pin is used to populate the bit. 25MHz when the pin is high, 40MHz when
+it's low.
+
+These pins are also used with LEDs, therefore, their state can be set to
+something other than the bootstrapping configuration. For example, a link
+may be established on port 3 before the DSA subdriver takes control of the
+switch which would set ESW_P3_LED_0 to high.
+
+Currently on mt7530_setup() and mt7531_setup(), 1000 - 1100 usec delay is
+described between reset assertion and deassertion. Some switch ICs in real
+life conditions cannot always have these pins set back to the bootstrapping
+configuration before reset deassertion in this amount of delay. This causes
+wrong crystal frequency to be selected which puts the switch in a
+nonfunctional state after reset deassertion.
+
+The tests below are conducted on an MT7530 with a 40MHz crystal oscillator
+by Justin Swartz.
+
+With a cable from an active peer connected to port 3 before reset, an
+incorrect crystal frequency (0b11 = 25MHz) is selected:
+
+ [1] [3] [5]
+ : : :
+ _____________________________ __________________
+ESW_P4_LED_0 |_______|
+ _____________________________
+ESW_P3_LED_0 |__________________________
+
+ : : : :
+ : : [4]...:
+ : :
+ [2]................:
+
+[1] Reset is asserted.
+[2] Period of 1000 - 1100 usec.
+[3] Reset is deasserted.
+[4] Period of 315 usec. HWTRAP register is populated with incorrect
+ XTAL frequency.
+[5] Signals reflect the bootstrapped configuration.
+
+Increase the delay between reset_control_assert() and
+reset_control_deassert(), and gpiod_set_value_cansleep(priv->reset, 0) and
+gpiod_set_value_cansleep(priv->reset, 1) to 5000 - 5100 usec. This amount
+ensures a higher possibility that the switch IC will have these pins back
+to the bootstrapping configuration before reset deassertion.
+
+With a cable from an active peer connected to port 3 before reset, the
+correct crystal frequency (0b10 = 40MHz) is selected:
+
+ [1] [2-1] [3] [5]
+ : : : :
+ _____________________________ __________________
+ESW_P4_LED_0 |_______|
+ ___________________ _______
+ESW_P3_LED_0 |_________| |__________________
+
+ : : : : :
+ : [2-2]...: [4]...:
+ [2]................:
+
+[1] Reset is asserted.
+[2] Period of 5000 - 5100 usec.
+[2-1] ESW_P3_LED_0 goes low.
+[2-2] Remaining period of 5000 - 5100 usec.
+[3] Reset is deasserted.
+[4] Period of 310 usec. HWTRAP register is populated with bootstrapped
+ XTAL frequency.
+[5] Signals reflect the bootstrapped configuration.
+
+ESW_P3_LED_0 low period before reset deassertion:
+
+ 5000 usec
+ - 5100 usec
+ TEST RESET HOLD
+ # (usec)
+ ---------------------
+ 1 5410
+ 2 5440
+ 3 4375
+ 4 5490
+ 5 5475
+ 6 4335
+ 7 4370
+ 8 5435
+ 9 4205
+ 10 4335
+ 11 3750
+ 12 3170
+ 13 4395
+ 14 4375
+ 15 3515
+ 16 4335
+ 17 4220
+ 18 4175
+ 19 4175
+ 20 4350
+
+ Min 3170
+ Max 5490
+
+ Median 4342.500
+ Avg 4466.500
+
+Revert commit 2920dd92b980 ("net: dsa: mt7530: disable LEDs before reset").
+Changing the state of pins via reset assertion is simpler and more
+efficient than doing so by setting the LED controller off.
+
+Fixes: b8f126a8d543 ("net-next: dsa: add dsa support for Mediatek MT7530 switch")
+Fixes: c288575f7810 ("net: dsa: mt7530: Add the support of MT7531 switch")
+Co-developed-by: Justin Swartz <justin.swartz@risingedge.co.za>
+Signed-off-by: Justin Swartz <justin.swartz@risingedge.co.za>
+Signed-off-by: Arınç ÜNAL <arinc.unal@arinc9.com>
+Signed-off-by: David S. Miller <davem@davemloft.net>
+---
+ drivers/net/dsa/mt7530.c | 6 ------
+ 1 file changed, 6 deletions(-)
+
+--- a/drivers/net/dsa/mt7530.c
++++ b/drivers/net/dsa/mt7530.c
+@@ -2228,12 +2228,6 @@ mt7530_setup(struct dsa_switch *ds)
+ }
+ }
+
+- /* Disable LEDs before reset to prevent the MT7530 sampling a
+- * potentially incorrect HT_XTAL_FSEL value.
+- */
+- mt7530_write(priv, MT7530_LED_EN, 0);
+- usleep_range(1000, 1100);
+-
+ /* Reset whole chip through gpio pin or memory-mapped registers for
+ * different type of hardware
+ */
+++ /dev/null
-From 3fb8841513c4ec3a2e5d366df86230c45f239a57 Mon Sep 17 00:00:00 2001
-From: Alexander Couzens <lynxis@fe80.eu>
-Date: Sat, 13 Aug 2022 13:08:22 +0200
-Subject: [PATCH 03/10] net: mt7531: ensure all MACs are powered down before
- reset
-
-The datasheet [1] explicit describes it as requirement for a reset.
-
-[1] MT7531 Reference Manual for Development Board rev 1.0, page 735
-
-Signed-off-by: Alexander Couzens <lynxis@fe80.eu>
----
- drivers/net/dsa/mt7530.c | 4 ++++
- 1 file changed, 4 insertions(+)
-
---- a/drivers/net/dsa/mt7530.c
-+++ b/drivers/net/dsa/mt7530.c
-@@ -2304,6 +2304,10 @@ mt7530_setup(struct dsa_switch *ds)
- return -ENODEV;
- }
-
-+ /* all MACs must be forced link-down before sw reset */
-+ for (i = 0; i < MT7530_NUM_PORTS; i++)
-+ mt7530_write(priv, MT7530_PMCR_P(i), MT7531_FORCE_LNK);
-+
- /* Reset the switch through internal reset */
- mt7530_write(priv, MT7530_SYS_CTRL,
- SYS_CTRL_PHY_RST | SYS_CTRL_SW_RST |
+++ /dev/null
-From 1d81e51d6d79d9098013b2e8cdd677bae998c5d8 Mon Sep 17 00:00:00 2001
-From: David Bauer <mail@david-bauer.net>
-Date: Fri, 28 Apr 2023 02:22:59 +0200
-Subject: [PATCH 1/2] mt7530: register OF node for internal MDIO bus
-
-The MT753x switches provide a switch-internal MDIO bus for the embedded
-PHYs.
-
-Register a OF sub-node on the switch OF-node for this internal MDIO bus.
-This allows to configure the embedded PHYs using device-tree.
-
-Signed-off-by: David Bauer <mail@david-bauer.net>
----
- drivers/net/dsa/mt7530.c | 7 ++++++-
- 1 file changed, 6 insertions(+), 1 deletion(-)
-
---- a/drivers/net/dsa/mt7530.c
-+++ b/drivers/net/dsa/mt7530.c
-@@ -2192,10 +2192,13 @@ mt7530_setup_mdio(struct mt7530_priv *pr
- {
- struct dsa_switch *ds = priv->ds;
- struct device *dev = priv->dev;
-+ struct device_node *np, *mnp;
- struct mii_bus *bus;
- static int idx;
- int ret;
-
-+ np = priv->dev->of_node;
-+
- bus = devm_mdiobus_alloc(dev);
- if (!bus)
- return -ENOMEM;
-@@ -2214,7 +2217,9 @@ mt7530_setup_mdio(struct mt7530_priv *pr
- if (priv->irq)
- mt7530_setup_mdio_irq(priv);
-
-- ret = devm_mdiobus_register(dev, bus);
-+ mnp = of_get_child_by_name(np, "mdio");
-+ ret = devm_of_mdiobus_register(dev, bus, mnp);
-+ of_node_put(mnp);
- if (ret) {
- dev_err(dev, "failed to register MDIO bus: %d\n", ret);
- if (priv->irq)