mirror of https://lore.kernel.org/lkml/
 help / color / mirror / Atom feed
From: "Bastien Curutchet (Schneider Electric)" <bastien.curutchet@bootlin.com>
To: Woojung Huh <woojung.huh@microchip.com>,
	UNGLinuxDriver@microchip.com,  Andrew Lunn <andrew@lunn.ch>,
	Vladimir Oltean <olteanv@gmail.com>,
	 "David S. Miller" <davem@davemloft.net>,
	Eric Dumazet <edumazet@google.com>,
	 Jakub Kicinski <kuba@kernel.org>,
	Paolo Abeni <pabeni@redhat.com>,
	 Russell King <linux@armlinux.org.uk>
Cc: "Pascal Eberhard" <pascal.eberhard@se.com>,
	"Miquèl Raynal" <miquel.raynal@bootlin.com>,
	"Thomas Petazzoni" <thomas.petazzoni@bootlin.com>,
	"Tristram Ha" <tristram.ha@microchip.com>,
	netdev@vger.kernel.org, linux-kernel@vger.kernel.org,
	"Bastien Curutchet (Schneider Electric)"
	<bastien.curutchet@bootlin.com>
Subject: [PATCH net-next v2 09/10] net: dsa: microchip: implement lan937x-specific MDIO registration
Date: Mon, 08 Jun 2026 16:10:12 +0200	[thread overview]
Message-ID: <20260608-clean-ksz-3rd-v2-9-6e61b7be23c4@bootlin.com> (raw)
In-Reply-To: <20260608-clean-ksz-3rd-v2-0-6e61b7be23c4@bootlin.com>

All the switches use a common mdio_register() function that uses two
ksz_dev_ops callbacks (.mdio_bus_preinit() and .create_phy_addr_map())
to handle the lan937x specific case. These two callbacks are used only
at this place in the code.

Implement a new lan937x-specific MDIO registration functions that uses
these two lan937x-specific functions. The lan937x bindings don't
have any 'interrupts' property so this lan937x_mdio_register() doesn't
call ksz_irq_phy_setup().
Expose the common ksz_*_mdio_{read/write} functions so they can be used
in lan937x.c
Remove the callbacks from ksz_dev_ops.

Signed-off-by: Bastien Curutchet (Schneider Electric) <bastien.curutchet@bootlin.com>
---
 drivers/net/dsa/microchip/ksz_common.c   |  30 +++-------
 drivers/net/dsa/microchip/ksz_common.h   |  42 ++-----------
 drivers/net/dsa/microchip/lan937x_main.c | 100 ++++++++++++++++++++++++++++++-
 3 files changed, 111 insertions(+), 61 deletions(-)

diff --git a/drivers/net/dsa/microchip/ksz_common.c b/drivers/net/dsa/microchip/ksz_common.c
index 7dc8e4ffacdd..d08659ffa442 100644
--- a/drivers/net/dsa/microchip/ksz_common.c
+++ b/drivers/net/dsa/microchip/ksz_common.c
@@ -2256,7 +2256,7 @@ static void ksz_update_port_member(struct ksz_device *dev, int port)
 	dev->dev_ops->cfg_port_member(dev, port, port_member | cpu_port);
 }
 
-static int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
+int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
 {
 	struct ksz_device *dev = bus->priv;
 	struct dsa_switch *ds = dev->ds;
@@ -2264,8 +2264,7 @@ static int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum)
 	return ds->ops->phy_read(ds, addr, regnum);
 }
 
-static int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
-			     u16 val)
+int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
 {
 	struct ksz_device *dev = bus->priv;
 	struct dsa_switch *ds = dev->ds;
@@ -2286,7 +2285,7 @@ static int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum,
  *
  * Return: Value of the PHY register, or a negative error code on failure.
  */
-static int ksz_parent_mdio_read(struct mii_bus *bus, int addr, int regnum)
+int ksz_parent_mdio_read(struct mii_bus *bus, int addr, int regnum)
 {
 	struct ksz_device *dev = bus->priv;
 
@@ -2306,8 +2305,7 @@ static int ksz_parent_mdio_read(struct mii_bus *bus, int addr, int regnum)
  *
  * Return: 0 on success, or a negative error code on failure.
  */
-static int ksz_parent_mdio_write(struct mii_bus *bus, int addr, int regnum,
-				 u16 val)
+int ksz_parent_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val)
 {
 	struct ksz_device *dev = bus->priv;
 
@@ -2415,8 +2413,8 @@ static void ksz_irq_phy_free(struct ksz_device *dev)
  *
  * Return: 0 on success, or a negative error code on failure.
  */
-static int ksz_parse_dt_phy_config(struct ksz_device *dev, struct mii_bus *bus,
-				   struct device_node *mdio_np)
+int ksz_parse_dt_phy_config(struct ksz_device *dev, struct mii_bus *bus,
+			    struct device_node *mdio_np)
 {
 	struct device_node *phy_node, *phy_parent_node;
 	bool phys_are_valid = true;
@@ -2519,20 +2517,8 @@ int ksz_mdio_register(struct ksz_device *dev)
 		goto put_mdio_node;
 	}
 
-	if (dev->dev_ops->mdio_bus_preinit) {
-		ret = dev->dev_ops->mdio_bus_preinit(dev, !!parent_bus);
-		if (ret)
-			goto put_mdio_node;
-	}
-
-	if (dev->dev_ops->create_phy_addr_map) {
-		ret = dev->dev_ops->create_phy_addr_map(dev, !!parent_bus);
-		if (ret)
-			goto put_mdio_node;
-	} else {
-		for (i = 0; i < dev->info->port_cnt; i++)
-			dev->phy_addr_map[i] = i;
-	}
+	for (i = 0; i < dev->info->port_cnt; i++)
+		dev->phy_addr_map[i] = i;
 
 	bus->priv = dev;
 	if (parent_bus) {
diff --git a/drivers/net/dsa/microchip/ksz_common.h b/drivers/net/dsa/microchip/ksz_common.h
index 2c118eaddd75..7b9a12648e85 100644
--- a/drivers/net/dsa/microchip/ksz_common.h
+++ b/drivers/net/dsa/microchip/ksz_common.h
@@ -362,42 +362,6 @@ struct ksz_dev_ops {
 	u32 (*get_port_addr)(int port, int offset);
 	void (*cfg_port_member)(struct ksz_device *dev, int port, u8 member);
 
-	/**
-	 * @mdio_bus_preinit: Function pointer to pre-initialize the MDIO bus
-	 *                    for accessing PHYs.
-	 * @dev: Pointer to device structure.
-	 * @side_mdio: Boolean indicating if the PHYs are accessed over a side
-	 *             MDIO bus.
-	 *
-	 * This function pointer is used to configure the MDIO bus for PHY
-	 * access before initiating regular PHY operations. It enables either
-	 * SPI/I2C or side MDIO access modes by unlocking necessary registers
-	 * and setting up access permissions for the selected mode.
-	 *
-	 * Return:
-	 *  - 0 on success.
-	 *  - Negative error code on failure.
-	 */
-	int (*mdio_bus_preinit)(struct ksz_device *dev, bool side_mdio);
-
-	/**
-	 * @create_phy_addr_map: Function pointer to create a port-to-PHY
-	 *                       address map.
-	 * @dev: Pointer to device structure.
-	 * @side_mdio: Boolean indicating if the PHYs are accessed over a side
-	 *             MDIO bus.
-	 *
-	 * This function pointer is responsible for mapping switch ports to PHY
-	 * addresses according to the configured access mode (SPI or side MDIO)
-	 * and the device’s strap configuration. The mapping setup may vary
-	 * depending on the chip variant and configuration. Ensures the correct
-	 * address mapping for PHY communication.
-	 *
-	 * Return:
-	 *  - 0 on success.
-	 *  - Negative error code on failure (e.g., invalid configuration).
-	 */
-	int (*create_phy_addr_map)(struct ksz_device *dev, bool side_mdio);
 	void (*r_mib_cnt)(struct ksz_device *dev, int port, u16 addr,
 			  u64 *cnt);
 	void (*r_mib_pkt)(struct ksz_device *dev, int port, u16 addr,
@@ -494,6 +458,12 @@ int ksz_port_set_mac_address(struct dsa_switch *ds, int port,
 int ksz_suspend(struct dsa_switch *ds);
 int ksz_resume(struct dsa_switch *ds);
 
+int ksz_parse_dt_phy_config(struct ksz_device *dev, struct mii_bus *bus,
+			    struct device_node *mdio_np);
+int ksz_sw_mdio_read(struct mii_bus *bus, int addr, int regnum);
+int ksz_sw_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val);
+int ksz_parent_mdio_read(struct mii_bus *bus, int addr, int regnum);
+int ksz_parent_mdio_write(struct mii_bus *bus, int addr, int regnum, u16 val);
 int ksz_mdio_register(struct ksz_device *dev);
 int ksz_pirq_setup(struct ksz_device *dev, u8 p);
 int ksz_girq_setup(struct ksz_device *dev);
diff --git a/drivers/net/dsa/microchip/lan937x_main.c b/drivers/net/dsa/microchip/lan937x_main.c
index d45798de4ce9..48cd367455c3 100644
--- a/drivers/net/dsa/microchip/lan937x_main.c
+++ b/drivers/net/dsa/microchip/lan937x_main.c
@@ -7,6 +7,7 @@
 #include <linux/module.h>
 #include <linux/iopoll.h>
 #include <linux/phy.h>
+#include <linux/of_mdio.h>
 #include <linux/of_net.h>
 #include <linux/if_bridge.h>
 #include <linux/if_vlan.h>
@@ -669,6 +670,101 @@ static int lan937x_switch_init(struct ksz_device *dev)
 	return 0;
 }
 
+/**
+ * lan937x_mdio_register - Register and configure the MDIO bus for the LAN937x.
+ * @dev: Pointer to the KSZ device structure.
+ *
+ * This function sets up and registers an MDIO bus for a LAN937x switch,
+ * allowing access to its internal PHYs. If the device supports side MDIO,
+ * the function will configure the external MDIO controller specified by the
+ * "mdio-parent-bus" device tree property to directly manage internal PHYs.
+ * Otherwise, SPI or I2C access is set up for PHY access.
+ *
+ * Return: 0 on success, or a negative error code on failure.
+ */
+static int lan937x_mdio_register(struct ksz_device *dev)
+{
+	struct device_node *parent_bus_node;
+	struct mii_bus *parent_bus = NULL;
+	struct dsa_switch *ds = dev->ds;
+	struct device_node *mdio_np;
+	struct mii_bus *bus;
+	int ret;
+
+	mdio_np = of_get_child_by_name(dev->dev->of_node, "mdio");
+	if (!mdio_np)
+		return 0;
+
+	parent_bus_node = of_parse_phandle(mdio_np, "mdio-parent-bus", 0);
+	if (parent_bus_node && !dev->info->phy_side_mdio_supported) {
+		dev_err(dev->dev, "Side MDIO bus is not supported for this HW, ignoring 'mdio-parent-bus' property.\n");
+		ret = -EINVAL;
+
+		goto put_mdio_node;
+	} else if (parent_bus_node) {
+		parent_bus = of_mdio_find_bus(parent_bus_node);
+		if (!parent_bus) {
+			ret = -EPROBE_DEFER;
+
+			goto put_mdio_node;
+		}
+
+		dev->parent_mdio_bus = parent_bus;
+	}
+
+	bus = devm_mdiobus_alloc(ds->dev);
+	if (!bus) {
+		ret = -ENOMEM;
+		goto put_mdio_node;
+	}
+
+	ret = lan937x_mdio_bus_preinit(dev, !!parent_bus);
+	if (ret)
+		goto put_mdio_node;
+
+	ret = lan937x_create_phy_addr_map(dev, !!parent_bus);
+	if (ret)
+		goto put_mdio_node;
+
+	bus->priv = dev;
+	if (parent_bus) {
+		bus->read = ksz_parent_mdio_read;
+		bus->write = ksz_parent_mdio_write;
+		bus->name = "KSZ side MDIO";
+		snprintf(bus->id, MII_BUS_ID_SIZE, "ksz-side-mdio-%d",
+			 ds->index);
+	} else {
+		bus->read = ksz_sw_mdio_read;
+		bus->write = ksz_sw_mdio_write;
+		bus->name = "ksz user smi";
+		if (ds->dst->index != 0)
+			snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d-%d",
+				 ds->dst->index, ds->index);
+		else
+			snprintf(bus->id, MII_BUS_ID_SIZE, "SMI-%d", ds->index);
+	}
+
+	ret = ksz_parse_dt_phy_config(dev, bus, mdio_np);
+	if (ret)
+		goto put_mdio_node;
+
+	ds->phys_mii_mask = bus->phy_mask;
+	bus->parent = ds->dev;
+
+	ds->user_mii_bus = bus;
+
+	ret = devm_of_mdiobus_register(ds->dev, bus, mdio_np);
+	if (ret)
+		dev_err(ds->dev, "unable to register MDIO bus %s\n",
+			bus->id);
+
+put_mdio_node:
+	of_node_put(mdio_np);
+	of_node_put(parent_bus_node);
+
+	return ret;
+}
+
 static int lan937x_setup(struct dsa_switch *ds)
 {
 	struct ksz_device *dev = ds->priv;
@@ -782,7 +878,7 @@ static int lan937x_setup(struct dsa_switch *ds)
 		goto port_release;
 	}
 
-	ret = ksz_mdio_register(dev);
+	ret = lan937x_mdio_register(dev);
 	if (ret < 0) {
 		dev_err(dev->dev, "failed to register the mdio");
 		goto out_ptp_clock_unregister;
@@ -845,8 +941,6 @@ const struct phylink_mac_ops lan937x_phylink_mac_ops = {
 const struct ksz_dev_ops lan937x_dev_ops = {
 	.get_port_addr = ksz9477_get_port_addr,
 	.cfg_port_member = ksz9477_cfg_port_member,
-	.mdio_bus_preinit = lan937x_mdio_bus_preinit,
-	.create_phy_addr_map = lan937x_create_phy_addr_map,
 	.r_mib_cnt = ksz9477_r_mib_cnt,
 	.r_mib_pkt = ksz9477_r_mib_pkt,
 	.r_mib_stat64 = ksz_r_mib_stats64,

-- 
2.54.0


  parent reply	other threads:[~2026-06-08 14:10 UTC|newest]

Thread overview: 14+ messages / expand[flat|nested]  mbox.gz  Atom feed  top
2026-06-08 14:10 [PATCH net-next v2 00/10] net: dsa: microchip: remove unnecessary dsa_switch_ops callbacks Bastien Curutchet (Schneider Electric)
2026-06-08 14:10 ` [PATCH net-next v2 01/10] net: dsa: microchip: remove useless common cls_flower_{add/del} operations Bastien Curutchet (Schneider Electric)
2026-06-08 14:10 ` [PATCH net-next v2 02/10] net: dsa: microchip: remove VLAN operations for ksz8463 Bastien Curutchet
2026-06-08 14:10 ` [PATCH net-next v2 03/10] net: dsa: microchip: implement get_phy_flags only if needed Bastien Curutchet (Schneider Electric)
2026-06-08 14:10 ` [PATCH net-next v2 04/10] net: dsa: microchip: wrap the MAC configuration checks in a function Bastien Curutchet (Schneider Electric)
2026-06-08 14:10 ` [PATCH net-next v2 05/10] net: dsa: microchip: remove setup_rgmii_delay() KSZ operation Bastien Curutchet (Schneider Electric)
2026-06-08 14:10 ` [PATCH net-next v2 06/10] net: dsa: microchip: implement .support_eee() only if needed Bastien Curutchet (Schneider Electric)
2026-06-08 14:10 ` [PATCH net-next v2 07/10] net: dsa: microchip: implement .{get/set}_wol " Bastien Curutchet (Schneider Electric)
2026-06-08 14:10 ` [PATCH net-next v2 08/10] net: dsa: microchip: implement port_hsr_join for KSZ9477 only Bastien Curutchet (Schneider Electric)
2026-06-08 14:10 ` Bastien Curutchet (Schneider Electric) [this message]
2026-06-11 10:54   ` [PATCH net-next v2 09/10] net: dsa: microchip: implement lan937x-specific MDIO registration Paolo Abeni
2026-06-12  9:18     ` Bastien Curutchet
2026-06-08 14:10 ` [PATCH net-next v2 10/10] net: dsa: microchip: implement port_teardown only if needed Bastien Curutchet (Schneider Electric)
2026-06-13  1:20 ` [PATCH net-next v2 00/10] net: dsa: microchip: remove unnecessary dsa_switch_ops callbacks patchwork-bot+netdevbpf

Reply instructions:

You may reply publicly to this message via plain-text email
using any one of the following methods:

* Save the following mbox file, import it into your mail client,
  and reply-to-all from there: mbox

  Avoid top-posting and favor interleaved quoting:
  https://en.wikipedia.org/wiki/Posting_style#Interleaved_style

* Reply using the --to, --cc, and --in-reply-to
  switches of git-send-email(1):

  git send-email \
    --in-reply-to=20260608-clean-ksz-3rd-v2-9-6e61b7be23c4@bootlin.com \
    --to=bastien.curutchet@bootlin.com \
    --cc=UNGLinuxDriver@microchip.com \
    --cc=andrew@lunn.ch \
    --cc=davem@davemloft.net \
    --cc=edumazet@google.com \
    --cc=kuba@kernel.org \
    --cc=linux-kernel@vger.kernel.org \
    --cc=linux@armlinux.org.uk \
    --cc=miquel.raynal@bootlin.com \
    --cc=netdev@vger.kernel.org \
    --cc=olteanv@gmail.com \
    --cc=pabeni@redhat.com \
    --cc=pascal.eberhard@se.com \
    --cc=thomas.petazzoni@bootlin.com \
    --cc=tristram.ha@microchip.com \
    --cc=woojung.huh@microchip.com \
    /path/to/YOUR_REPLY

  https://kernel.org/pub/software/scm/git/docs/git-send-email.html

* If your mail client supports setting the In-Reply-To header
  via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox

all inboxes | Powered by JetHome®