[<prev] [next>] [<thread-prev] [thread-next>] [day] [month] [year] [list]
Message-Id: <20260122105654.105600-7-vladimir.oltean@nxp.com>
Date: Thu, 22 Jan 2026 12:56:45 +0200
From: Vladimir Oltean <vladimir.oltean@....com>
To: netdev@...r.kernel.org
Cc: Andrew Lunn <andrew@...n.ch>,
Heiner Kallweit <hkallweit1@...il.com>,
Russell King <linux@...linux.org.uk>,
"David S. Miller" <davem@...emloft.net>,
Eric Dumazet <edumazet@...gle.com>,
Jakub Kicinski <kuba@...nel.org>,
Paolo Abeni <pabeni@...hat.com>,
linux-kernel@...r.kernel.org,
Andy Shevchenko <andriy.shevchenko@...ux.intel.com>,
Herve Codina <herve.codina@...tlin.com>,
Mark Brown <broonie@...nel.org>,
Serge Semin <fancer.lancer@...il.com>,
Maxime Chevallier <maxime.chevallier@...tlin.com>,
Lee Jones <lee@...nel.org>,
Rob Herring <robh@...nel.org>,
Krzysztof Kozlowski <krzk+dt@...nel.org>,
Conor Dooley <conor+dt@...nel.org>,
devicetree@...r.kernel.org,
Choong Yong Liang <yong.liang.choong@...ux.intel.com>,
Jiawen Wu <jiawenwu@...stnetic.com>
Subject: [PATCH v2 net-next 06/15] net: dsa: sja1105: transition OF-based MDIO controllers to standalone sub-devices
The switch driver never interacts directly with the PHYs from its
internal 100Base-T1 or 100Base-TX MDIO buses, but rather, uses the
generic phylink library to follow "phy-handle" fwnode references to
them.
These MDIO buses are currently created by the DSA driver for historical
reasons, but they have well-defined address space regions for their
registers, which do not collide with the DSA switch registers. In the
SJA1110 memory map, the important resources look something like this:
Name Description Start End
SWITCH Ethernet Switch Subsystem 0x000000 0x3ffffc
100BASE-T1 Internal MDIO bus for 100BASE-T1 PHY (port 5 - 10) 0x704000 0x704ffc
SGMII1 SGMII Port 1 0x705000 0x705ffc
SGMII2 SGMII Port 2 0x706000 0x706ffc
SGMII3 SGMII Port 3 0x707000 0x707ffc
SGMII4 SGMII Port 4 0x708000 0x708ffc
100BASE-TX Internal MDIO bus for 100BASE-TX PHY 0x709000 0x709ffc
ACU Auxiliary Control Unit 0x711000 0x711ffc
GPIO General Purpose Input/Output 0x712000 0x712ffc
OTOH, dedicated standalone platform_device drivers now exist for the two
controllers found in the 100BASE-T1 and 100BASE-TX regions. If we could
leverage them, we could simplify the DSA driver code by removing the
weakly coupled components.
There was an initial attempt to use mfd_add_devices() to probe these
children, but:
- Using mfd_add_devices() liberally outside of drivers/mfd/ causes
"minor chaos" in the words of the maintainer
- The SJA1110 dt-bindings, where there exists one more hierarchical
level between the OF node of the parent and the OF nodes of the
children (aka the "mdios" container node), is too unconventional for
MFD:
https://lore.kernel.org/netdev/20251118190530.580267-8-vladimir.oltean@nxp.com/
So I turned to something custom based on platform_device_register_full()
instead. The OF nodes of the known MDIO controllers are searched for,
platform devices are created for them, and they are given hardcoded
resources which correspond to the above 100BASE-T1 and 100BASE-TX regions.
The platform drivers will use these regions to segment the SPI device's
regmap in order to access just their own registers.
Delete the duplicated drivers for 100base-T1 and 100base-TX from the DSA
driver, which are now unnecessary.
Cc: Lee Jones <lee@...nel.org>
Signed-off-by: Vladimir Oltean <vladimir.oltean@....com>
---
v1->v2:
- replace mfd_add_devices() with devm_sja1105_add_subdevs()
drivers/net/dsa/sja1105/Makefile | 1 +
drivers/net/dsa/sja1105/sja1105.h | 4 -
drivers/net/dsa/sja1105/sja1105_main.c | 8 +
drivers/net/dsa/sja1105/sja1105_mdio.c | 270 +----------------------
drivers/net/dsa/sja1105/sja1105_spi.c | 6 -
drivers/net/dsa/sja1105/sja1105_subdev.c | 154 +++++++++++++
drivers/net/dsa/sja1105/sja1105_subdev.h | 9 +
7 files changed, 173 insertions(+), 279 deletions(-)
create mode 100644 drivers/net/dsa/sja1105/sja1105_subdev.c
create mode 100644 drivers/net/dsa/sja1105/sja1105_subdev.h
diff --git a/drivers/net/dsa/sja1105/Makefile b/drivers/net/dsa/sja1105/Makefile
index 40d69e6c0bae..7b5537d67072 100644
--- a/drivers/net/dsa/sja1105/Makefile
+++ b/drivers/net/dsa/sja1105/Makefile
@@ -5,6 +5,7 @@ sja1105-objs := \
sja1105_spi.o \
sja1105_main.o \
sja1105_mdio.o \
+ sja1105_subdev.o \
sja1105_flower.o \
sja1105_ethtool.o \
sja1105_devlink.o \
diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h
index 30903fb62302..cf718e7c2b7b 100644
--- a/drivers/net/dsa/sja1105/sja1105.h
+++ b/drivers/net/dsa/sja1105/sja1105.h
@@ -91,8 +91,6 @@ struct sja1105_regs {
u64 rmii_ref_clk[SJA1105_MAX_NUM_PORTS];
u64 rmii_ext_tx_clk[SJA1105_MAX_NUM_PORTS];
u64 stats[__MAX_SJA1105_STATS_AREA][SJA1105_MAX_NUM_PORTS];
- u64 mdio_100base_tx;
- u64 mdio_100base_t1;
u64 pcs_base[SJA1105_MAX_NUM_PORTS];
};
@@ -278,8 +276,6 @@ struct sja1105_private {
struct mutex dynamic_config_lock;
struct devlink_region **regions;
struct sja1105_cbs_entry *cbs;
- struct mii_bus *mdio_base_t1;
- struct mii_bus *mdio_base_tx;
struct mii_bus *mdio_pcs;
struct phylink_pcs *pcs[SJA1105_MAX_NUM_PORTS];
struct sja1105_ptp_data ptp_data;
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index e9e091cf8998..d3fb42772071 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -23,6 +23,7 @@
#include <linux/units.h>
#include "sja1105.h"
+#include "sja1105_subdev.h"
#include "sja1105_tas.h"
#define SJA1105_UNKNOWN_MULTICAST 0x010000000000ull
@@ -3329,6 +3330,13 @@ static int sja1105_probe(struct spi_device *spi)
return rc;
}
+ rc = devm_sja1105_add_subdevs(ds);
+ if (rc) {
+ dev_err(ds->dev, "Failed to create child devices: %pe\n",
+ ERR_PTR(rc));
+ return rc;
+ }
+
if (IS_ENABLED(CONFIG_NET_SCH_CBS)) {
priv->cbs = devm_kcalloc(dev, priv->info->num_cbs_shapers,
sizeof(struct sja1105_cbs_entry),
diff --git a/drivers/net/dsa/sja1105/sja1105_mdio.c b/drivers/net/dsa/sja1105/sja1105_mdio.c
index 8d535c033cef..b803ce71f5cc 100644
--- a/drivers/net/dsa/sja1105/sja1105_mdio.c
+++ b/drivers/net/dsa/sja1105/sja1105_mdio.c
@@ -133,238 +133,6 @@ int sja1110_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int mmd, int reg,
&tmp, NULL);
}
-enum sja1105_mdio_opcode {
- SJA1105_C45_ADDR = 0,
- SJA1105_C22 = 1,
- SJA1105_C45_DATA = 2,
- SJA1105_C45_DATA_AUTOINC = 3,
-};
-
-static u64 sja1105_base_t1_encode_addr(struct sja1105_private *priv,
- int phy, enum sja1105_mdio_opcode op,
- int xad)
-{
- const struct sja1105_regs *regs = priv->info->regs;
-
- return regs->mdio_100base_t1 | (phy << 7) | (op << 5) | (xad << 0);
-}
-
-static int sja1105_base_t1_mdio_read_c22(struct mii_bus *bus, int phy, int reg)
-{
- struct sja1105_mdio_private *mdio_priv = bus->priv;
- struct sja1105_private *priv = mdio_priv->priv;
- u64 addr;
- u32 tmp;
- int rc;
-
- addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
-
- rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
- if (rc < 0)
- return rc;
-
- return tmp & 0xffff;
-}
-
-static int sja1105_base_t1_mdio_read_c45(struct mii_bus *bus, int phy,
- int mmd, int reg)
-{
- struct sja1105_mdio_private *mdio_priv = bus->priv;
- struct sja1105_private *priv = mdio_priv->priv;
- u64 addr;
- u32 tmp;
- int rc;
-
- addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR, mmd);
-
- rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, ®, NULL);
- if (rc < 0)
- return rc;
-
- addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA, mmd);
-
- rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
- if (rc < 0)
- return rc;
-
- return tmp & 0xffff;
-}
-
-static int sja1105_base_t1_mdio_write_c22(struct mii_bus *bus, int phy, int reg,
- u16 val)
-{
- struct sja1105_mdio_private *mdio_priv = bus->priv;
- struct sja1105_private *priv = mdio_priv->priv;
- u64 addr;
- u32 tmp;
-
- addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C22, reg & 0x1f);
-
- tmp = val & 0xffff;
-
- return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
-}
-
-static int sja1105_base_t1_mdio_write_c45(struct mii_bus *bus, int phy,
- int mmd, int reg, u16 val)
-{
- struct sja1105_mdio_private *mdio_priv = bus->priv;
- struct sja1105_private *priv = mdio_priv->priv;
- u64 addr;
- u32 tmp;
- int rc;
-
- addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_ADDR, mmd);
-
- rc = sja1105_xfer_u32(priv, SPI_WRITE, addr, ®, NULL);
- if (rc < 0)
- return rc;
-
- addr = sja1105_base_t1_encode_addr(priv, phy, SJA1105_C45_DATA, mmd);
-
- tmp = val & 0xffff;
-
- return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
-}
-
-static int sja1105_base_tx_mdio_read(struct mii_bus *bus, int phy, int reg)
-{
- struct sja1105_mdio_private *mdio_priv = bus->priv;
- struct sja1105_private *priv = mdio_priv->priv;
- const struct sja1105_regs *regs = priv->info->regs;
- u32 tmp;
- int rc;
-
- rc = sja1105_xfer_u32(priv, SPI_READ, regs->mdio_100base_tx + reg,
- &tmp, NULL);
- if (rc < 0)
- return rc;
-
- return tmp & 0xffff;
-}
-
-static int sja1105_base_tx_mdio_write(struct mii_bus *bus, int phy, int reg,
- u16 val)
-{
- struct sja1105_mdio_private *mdio_priv = bus->priv;
- struct sja1105_private *priv = mdio_priv->priv;
- const struct sja1105_regs *regs = priv->info->regs;
- u32 tmp = val;
-
- return sja1105_xfer_u32(priv, SPI_WRITE, regs->mdio_100base_tx + reg,
- &tmp, NULL);
-}
-
-static int sja1105_mdiobus_base_tx_register(struct sja1105_private *priv,
- struct device_node *mdio_node)
-{
- struct sja1105_mdio_private *mdio_priv;
- struct device_node *np;
- struct mii_bus *bus;
- int rc = 0;
-
- np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-tx-mdio");
- if (!np)
- return 0;
-
- if (!of_device_is_available(np))
- goto out_put_np;
-
- bus = mdiobus_alloc_size(sizeof(*mdio_priv));
- if (!bus) {
- rc = -ENOMEM;
- goto out_put_np;
- }
-
- bus->name = "SJA1110 100base-TX MDIO bus";
- snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-tx",
- dev_name(priv->ds->dev));
- bus->read = sja1105_base_tx_mdio_read;
- bus->write = sja1105_base_tx_mdio_write;
- bus->parent = priv->ds->dev;
- mdio_priv = bus->priv;
- mdio_priv->priv = priv;
-
- rc = of_mdiobus_register(bus, np);
- if (rc) {
- mdiobus_free(bus);
- goto out_put_np;
- }
-
- priv->mdio_base_tx = bus;
-
-out_put_np:
- of_node_put(np);
-
- return rc;
-}
-
-static void sja1105_mdiobus_base_tx_unregister(struct sja1105_private *priv)
-{
- if (!priv->mdio_base_tx)
- return;
-
- mdiobus_unregister(priv->mdio_base_tx);
- mdiobus_free(priv->mdio_base_tx);
- priv->mdio_base_tx = NULL;
-}
-
-static int sja1105_mdiobus_base_t1_register(struct sja1105_private *priv,
- struct device_node *mdio_node)
-{
- struct sja1105_mdio_private *mdio_priv;
- struct device_node *np;
- struct mii_bus *bus;
- int rc = 0;
-
- np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-t1-mdio");
- if (!np)
- return 0;
-
- if (!of_device_is_available(np))
- goto out_put_np;
-
- bus = mdiobus_alloc_size(sizeof(*mdio_priv));
- if (!bus) {
- rc = -ENOMEM;
- goto out_put_np;
- }
-
- bus->name = "SJA1110 100base-T1 MDIO bus";
- snprintf(bus->id, MII_BUS_ID_SIZE, "%s-base-t1",
- dev_name(priv->ds->dev));
- bus->read = sja1105_base_t1_mdio_read_c22;
- bus->write = sja1105_base_t1_mdio_write_c22;
- bus->read_c45 = sja1105_base_t1_mdio_read_c45;
- bus->write_c45 = sja1105_base_t1_mdio_write_c45;
- bus->parent = priv->ds->dev;
- mdio_priv = bus->priv;
- mdio_priv->priv = priv;
-
- rc = of_mdiobus_register(bus, np);
- if (rc) {
- mdiobus_free(bus);
- goto out_put_np;
- }
-
- priv->mdio_base_t1 = bus;
-
-out_put_np:
- of_node_put(np);
-
- return rc;
-}
-
-static void sja1105_mdiobus_base_t1_unregister(struct sja1105_private *priv)
-{
- if (!priv->mdio_base_t1)
- return;
-
- mdiobus_unregister(priv->mdio_base_t1);
- mdiobus_free(priv->mdio_base_t1);
- priv->mdio_base_t1 = NULL;
-}
-
static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
{
struct sja1105_mdio_private *mdio_priv;
@@ -459,49 +227,13 @@ static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv)
int sja1105_mdiobus_register(struct dsa_switch *ds)
{
struct sja1105_private *priv = ds->priv;
- const struct sja1105_regs *regs = priv->info->regs;
- struct device_node *switch_node = ds->dev->of_node;
- struct device_node *mdio_node;
- int rc;
-
- rc = sja1105_mdiobus_pcs_register(priv);
- if (rc)
- return rc;
-
- mdio_node = of_get_available_child_by_name(switch_node, "mdios");
- if (!mdio_node)
- return 0;
- if (regs->mdio_100base_tx != SJA1105_RSV_ADDR) {
- rc = sja1105_mdiobus_base_tx_register(priv, mdio_node);
- if (rc)
- goto err_put_mdio_node;
- }
-
- if (regs->mdio_100base_t1 != SJA1105_RSV_ADDR) {
- rc = sja1105_mdiobus_base_t1_register(priv, mdio_node);
- if (rc)
- goto err_free_base_tx_mdiobus;
- }
-
- of_node_put(mdio_node);
-
- return 0;
-
-err_free_base_tx_mdiobus:
- sja1105_mdiobus_base_tx_unregister(priv);
-err_put_mdio_node:
- of_node_put(mdio_node);
- sja1105_mdiobus_pcs_unregister(priv);
-
- return rc;
+ return sja1105_mdiobus_pcs_register(priv);
}
void sja1105_mdiobus_unregister(struct dsa_switch *ds)
{
struct sja1105_private *priv = ds->priv;
- sja1105_mdiobus_base_t1_unregister(priv);
- sja1105_mdiobus_base_tx_unregister(priv);
sja1105_mdiobus_pcs_unregister(priv);
}
diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c
index 856a751de53a..20757e166b08 100644
--- a/drivers/net/dsa/sja1105/sja1105_spi.c
+++ b/drivers/net/dsa/sja1105/sja1105_spi.c
@@ -495,8 +495,6 @@ static const struct sja1105_regs sja1105et_regs = {
.ptpclkval = 0x18, /* Spans 0x18 to 0x19 */
.ptpclkrate = 0x1A,
.ptpclkcorp = 0x1D,
- .mdio_100base_tx = SJA1105_RSV_ADDR,
- .mdio_100base_t1 = SJA1105_RSV_ADDR,
};
static const struct sja1105_regs sja1105pqrs_regs = {
@@ -534,8 +532,6 @@ static const struct sja1105_regs sja1105pqrs_regs = {
.ptpclkrate = 0x1B,
.ptpclkcorp = 0x1E,
.ptpsyncts = 0x1F,
- .mdio_100base_tx = SJA1105_RSV_ADDR,
- .mdio_100base_t1 = SJA1105_RSV_ADDR,
};
static const struct sja1105_regs sja1110_regs = {
@@ -618,8 +614,6 @@ static const struct sja1105_regs sja1110_regs = {
.ptpclkrate = SJA1110_SPI_ADDR(0x74),
.ptpclkcorp = SJA1110_SPI_ADDR(0x80),
.ptpsyncts = SJA1110_SPI_ADDR(0x84),
- .mdio_100base_tx = 0x1c2400,
- .mdio_100base_t1 = 0x1c1000,
.pcs_base = {SJA1105_RSV_ADDR, 0x1c1400, 0x1c1800, 0x1c1c00, 0x1c2000,
SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR,
SJA1105_RSV_ADDR, SJA1105_RSV_ADDR, SJA1105_RSV_ADDR},
diff --git a/drivers/net/dsa/sja1105/sja1105_subdev.c b/drivers/net/dsa/sja1105/sja1105_subdev.c
new file mode 100644
index 000000000000..06957d44f084
--- /dev/null
+++ b/drivers/net/dsa/sja1105/sja1105_subdev.c
@@ -0,0 +1,154 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright 2025 NXP
+ */
+#include <linux/device/devres.h>
+#include <linux/ioport.h>
+#include <linux/platform_device.h>
+
+#include "sja1105.h"
+#include "sja1105_subdev.h"
+
+static const struct resource sja1110_mdio_cbt1_res =
+ DEFINE_RES_REG_NAMED(0x704000, 0x4000, "mdio_cbt1");
+
+static const struct resource sja1110_mdio_cbtx_res =
+ DEFINE_RES_REG_NAMED(0x709000, 0x1000, "mdio_cbtx");
+
+static bool fwnode_is_hierarchical_child(struct fwnode_handle *child,
+ struct fwnode_handle *parent)
+{
+ struct fwnode_handle *next = child;
+
+ do {
+ if (next == parent)
+ return true;
+ next = fwnode_get_parent(next);
+ } while (next);
+
+ return false;
+}
+
+static void of_subdev_del(void *data)
+{
+ struct platform_device *pdev = data;
+
+ platform_device_unregister(pdev);
+}
+
+/**
+ * devm_of_subdev_add() - Register an OF sub-device as a managed platform device
+ * @pdevinfo: Platform device information structure containing parent, fwnode,
+ * name, resources, etc.
+ *
+ * This function registers a platform device as a sub-device of
+ * @pdevinfo.parent using the information provided in @pdevinfo. The sub-device
+ * will be automatically unregistered when @pdevinfo.parent is removed, thanks
+ * to devres management.
+ *
+ * If the fwnode specified in @pdevinfo is not available (disabled in device
+ * tree), this function returns success without creating the device.
+ *
+ * For the sub-device drivers to access their registers, a form of
+ * devm_regmap_init(parent) should have been called prior to this, which
+ * makes the parent regmap visible via dev_get_regmap(&pdev->dev.parent)
+ * in the sub-device driver. The entire address space is made available through
+ * this regmap to all sub-devices, although they are expected to segment it
+ * according to the given resources.
+ *
+ * Return: 0 on success, negative error code on failure
+ */
+static int devm_of_subdev_add(const struct platform_device_info *pdevinfo)
+{
+ struct device *parent = pdevinfo->parent;
+ struct platform_device *pdev;
+
+ if (!fwnode_device_is_available(pdevinfo->fwnode))
+ return 0;
+
+ /* To avoid API abuse, ensure that the sub-device fwnode is,
+ * in fact, related to the parent.
+ */
+ if (!fwnode_is_hierarchical_child(pdevinfo->fwnode, dev_fwnode(parent)))
+ return -EINVAL;
+
+ pdev = platform_device_register_full(pdevinfo);
+ if (IS_ERR(pdev))
+ return PTR_ERR(pdev);
+
+ return devm_add_action_or_reset(parent, of_subdev_del, pdev);
+}
+
+static int devm_sja1105_add_mdio_subdev(struct device *parent,
+ struct device_node *np,
+ const struct resource *res,
+ size_t num_res)
+{
+ struct platform_device_info subdev;
+ char name[64];
+ u32 reg;
+ int err;
+
+ err = of_property_read_u32(np, "reg", ®);
+ if (err)
+ return err;
+
+ snprintf(name, sizeof(name), "%s.%pOFn", dev_name(parent), np);
+ subdev = (struct platform_device_info) {
+ .parent = parent,
+ .fwnode = of_fwnode_handle(np),
+ .name = name,
+ .id = reg,
+ .res = res,
+ .num_res = num_res,
+ };
+
+ return devm_of_subdev_add(&subdev);
+}
+
+/* Legacy nodes which lack a proper resource description in the device tree,
+ * so we need to specify it manually.
+ */
+static int devm_sja1105_add_mdio_subdevs(struct dsa_switch *ds,
+ struct device_node *mdio_node)
+{
+ struct device *parent = ds->dev;
+ struct device_node *np;
+ int err;
+
+ np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-tx-mdio");
+ if (np) {
+ err = devm_sja1105_add_mdio_subdev(parent, np,
+ &sja1110_mdio_cbtx_res, 1);
+ of_node_put(np);
+ if (err)
+ return err;
+ }
+
+ np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-t1-mdio");
+ if (np) {
+ err = devm_sja1105_add_mdio_subdev(parent, np,
+ &sja1110_mdio_cbt1_res, 1);
+ of_node_put(np);
+ if (err)
+ return err;
+ }
+
+ return 0;
+}
+
+int devm_sja1105_add_subdevs(struct dsa_switch *ds)
+{
+ struct device_node *switch_node = dev_of_node(ds->dev);
+ struct device_node *mdio_node;
+ int rc = 0;
+
+ mdio_node = of_get_available_child_by_name(switch_node, "mdios");
+ if (mdio_node) {
+ rc = devm_sja1105_add_mdio_subdevs(ds, mdio_node);
+ of_node_put(mdio_node);
+ if (rc)
+ return rc;
+ }
+
+ return 0;
+}
diff --git a/drivers/net/dsa/sja1105/sja1105_subdev.h b/drivers/net/dsa/sja1105/sja1105_subdev.h
new file mode 100644
index 000000000000..9b5a02401399
--- /dev/null
+++ b/drivers/net/dsa/sja1105/sja1105_subdev.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright 2025-2026 NXP
+ */
+#ifndef _SJA1105_SUBDEV_H
+#define _SJA1105_SUBDEV_H
+
+int devm_sja1105_add_subdevs(struct dsa_switch *ds);
+
+#endif
--
2.34.1
Powered by blists - more mailing lists