* [PATCH net-next 01/15] net: dsa: sja1105: let phylink help with the replay of link callbacks
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
2025-11-18 19:05 ` [PATCH net-next 02/15] net: mdio-regmap: permit working with non-MMIO regmaps Vladimir Oltean
` (13 subsequent siblings)
14 siblings, 0 replies; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel
sja1105_static_config_reload() changes major settings in the switch and
it requires a reset. A use case is to change things like Qdiscs (but see
sja1105_reset_reasons[] for full list) while PTP synchronization is
running, and the servo loop must not exit the locked state (s2).
Therefore, stopping and restarting the phylink instances of all ports is
not desirable, because that also stops the phylib state machine, and
retriggers a seconds-long auto-negotiation process that breaks PTP.
Thus, saving and restoring the link management settings is handled
privately by the driver.
The method got progressively more complex as SGMII support got added,
because this is handled through the xpcs phylink_pcs component, to which
we don't have unfettered access. Nonetheless, the switch reset line is
hardwired to also reset the XPCS, creating a situation where it loses
state and needs to be reprogrammed at a moment in time outside phylink's
control.
Although commits 907476c66d73 ("net: dsa: sja1105: call PCS
config/link_up via pcs_ops structure") and 41bf58314b17 ("net: dsa:
sja1105: use phylink_pcs internally") made the sja1105 <-> xpcs
interaction slightly prettier, we still depend heavily on the PCS being
"XPCS-like", because to back up its settings, we read the MII_BMCR
register, through a mdiobus_c45_read() operation, breaking all layering
separation.
But the phylink instance already has all that state, and more. It's just
that it's private. In this proposal, phylink offers 2 helpers for
walking the MAC and PCS drivers again through the callbacks required
during a destructive reset operation: mac_link_down() -> pcs_link_down()
-> mac_config() -> pcs_config() -> mac_link_up() -> pcs_link_up().
This creates the unique opportunity to simplify away even more code than
just the xpcs handling from sja1105_static_config_reload().
The sja1105_set_port_config() method is also invoked from
sja1105_mac_link_up(). And since that is now called directly by
phylink.. we can just remove it from sja1105_static_config_reload().
This makes it possible to re-merge sja1105_set_port_speed() and
sja1105_set_port_config() in a later change.
Note that my only setups with sja1105 where the xpcs is used is with the
xpcs on the CPU-facing port (fixed-link). Thus, I cannot test xpcs + PHY.
But the replay procedure walks through all ports, and I did test a
regular RGMII user port + a PHY.
ptp4l[54.552]: master offset 5 s2 freq -931 path delay 764
ptp4l[55.551]: master offset 22 s2 freq -913 path delay 764
ptp4l[56.551]: master offset 13 s2 freq -915 path delay 765
ptp4l[57.552]: master offset 5 s2 freq -919 path delay 765
ptp4l[58.553]: master offset 13 s2 freq -910 path delay 765
ptp4l[59.553]: master offset 13 s2 freq -906 path delay 765
ptp4l[60.553]: master offset 6 s2 freq -909 path delay 765
ptp4l[61.553]: master offset 6 s2 freq -907 path delay 765
ptp4l[62.553]: master offset 6 s2 freq -906 path delay 765
ptp4l[63.553]: master offset 14 s2 freq -896 path delay 765
$ ip link set br0 type bridge vlan_filtering 1
[ 63.983283] sja1105 spi2.0 sw0p0: Link is Down
[ 63.991913] sja1105 spi2.0: Link is Down
[ 64.009784] sja1105 spi2.0: Reset switch and programmed static config. Reason: VLAN filtering
[ 64.020217] sja1105 spi2.0 sw0p0: Link is Up - 1Gbps/Full - flow control off
[ 64.030683] sja1105 spi2.0: Link is Up - 1Gbps/Full - flow control off
ptp4l[64.554]: master offset 7397 s2 freq +6491 path delay 765
ptp4l[65.554]: master offset 38 s2 freq +1352 path delay 765
ptp4l[66.554]: master offset -2225 s2 freq -900 path delay 764
ptp4l[67.555]: master offset -2226 s2 freq -1569 path delay 765
ptp4l[68.555]: master offset -1553 s2 freq -1563 path delay 765
ptp4l[69.555]: master offset -865 s2 freq -1341 path delay 765
ptp4l[70.555]: master offset -401 s2 freq -1137 path delay 765
ptp4l[71.556]: master offset -145 s2 freq -1001 path delay 765
ptp4l[72.558]: master offset -26 s2 freq -926 path delay 765
ptp4l[73.557]: master offset 30 s2 freq -877 path delay 765
ptp4l[74.557]: master offset 47 s2 freq -851 path delay 765
ptp4l[75.557]: master offset 29 s2 freq -855 path delay 765
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
Change previously submitted here:
https://lore.kernel.org/netdev/20241212172026.ivjkhm7s2qt6ejyz@skbuf/
I've implemented Russell's feedback given back then, which he hasn't
confirmed back.
drivers/net/dsa/sja1105/sja1105_main.c | 58 +++-----------------
drivers/net/phy/phylink.c | 75 ++++++++++++++++++++++----
include/linux/phylink.h | 5 ++
3 files changed, 77 insertions(+), 61 deletions(-)
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index f674c400f05b..9f62cc7e1bd1 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -2287,14 +2287,12 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
{
struct ptp_system_timestamp ptp_sts_before;
struct ptp_system_timestamp ptp_sts_after;
- u16 bmcr[SJA1105_MAX_NUM_PORTS] = {0};
- u64 mac_speed[SJA1105_MAX_NUM_PORTS];
struct sja1105_mac_config_entry *mac;
struct dsa_switch *ds = priv->ds;
+ struct dsa_port *dp;
s64 t1, t2, t3, t4;
- s64 t12, t34;
- int rc, i;
- s64 now;
+ s64 t12, t34, now;
+ int rc;
mutex_lock(&priv->fdb_lock);
mutex_lock(&priv->mgmt_lock);
@@ -2306,13 +2304,9 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
* switch wants to see in the static config in order to allow us to
* change it through the dynamic interface later.
*/
- for (i = 0; i < ds->num_ports; i++) {
- mac_speed[i] = mac[i].speed;
- mac[i].speed = priv->info->port_speed[SJA1105_SPEED_AUTO];
-
- if (priv->pcs[i])
- bmcr[i] = mdiobus_c45_read(priv->mdio_pcs, i,
- MDIO_MMD_VEND2, MDIO_CTRL1);
+ dsa_switch_for_each_available_port(dp, ds) {
+ phylink_replay_link_begin(dp->pl);
+ mac[dp->index].speed = priv->info->port_speed[SJA1105_SPEED_AUTO];
}
/* No PTP operations can run right now */
@@ -2366,44 +2360,8 @@ int sja1105_static_config_reload(struct sja1105_private *priv,
goto out;
}
- for (i = 0; i < ds->num_ports; i++) {
- struct phylink_pcs *pcs = priv->pcs[i];
- unsigned int neg_mode;
-
- mac[i].speed = mac_speed[i];
- rc = sja1105_set_port_config(priv, i);
- if (rc < 0)
- goto out;
-
- if (!pcs)
- continue;
-
- if (bmcr[i] & BMCR_ANENABLE)
- neg_mode = PHYLINK_PCS_NEG_INBAND_ENABLED;
- else
- neg_mode = PHYLINK_PCS_NEG_OUTBAND;
-
- rc = pcs->ops->pcs_config(pcs, neg_mode, priv->phy_mode[i],
- NULL, true);
- if (rc < 0)
- goto out;
-
- if (neg_mode == PHYLINK_PCS_NEG_OUTBAND) {
- int speed = SPEED_UNKNOWN;
-
- if (priv->phy_mode[i] == PHY_INTERFACE_MODE_2500BASEX)
- speed = SPEED_2500;
- else if (bmcr[i] & BMCR_SPEED1000)
- speed = SPEED_1000;
- else if (bmcr[i] & BMCR_SPEED100)
- speed = SPEED_100;
- else
- speed = SPEED_10;
-
- pcs->ops->pcs_link_up(pcs, neg_mode, priv->phy_mode[i],
- speed, DUPLEX_FULL);
- }
- }
+ dsa_switch_for_each_available_port(dp, ds)
+ phylink_replay_link_end(dp->pl);
rc = sja1105_reload_cbs(priv);
if (rc < 0)
diff --git a/drivers/net/phy/phylink.c b/drivers/net/phy/phylink.c
index 6e1243bf68aa..19b8ddabee03 100644
--- a/drivers/net/phy/phylink.c
+++ b/drivers/net/phy/phylink.c
@@ -28,6 +28,7 @@ enum {
PHYLINK_DISABLE_STOPPED,
PHYLINK_DISABLE_LINK,
PHYLINK_DISABLE_MAC_WOL,
+ PHYLINK_DISABLE_REPLAY,
PCS_STATE_DOWN = 0,
PCS_STATE_STARTING,
@@ -77,6 +78,7 @@ struct phylink {
bool link_failed;
bool suspend_link_up;
+ bool force_major_config;
bool major_config_failed;
bool mac_supports_eee_ops;
bool mac_supports_eee;
@@ -1680,18 +1682,18 @@ static void phylink_resolve(struct work_struct *w)
if (pl->act_link_an_mode != MLO_AN_FIXED)
phylink_apply_manual_flow(pl, &link_state);
- if (mac_config) {
- if (link_state.interface != pl->link_config.interface) {
- /* The interface has changed, force the link down and
- * then reconfigure.
- */
- if (cur_link_state) {
- phylink_link_down(pl);
- cur_link_state = false;
- }
- phylink_major_config(pl, false, &link_state);
- pl->link_config.interface = link_state.interface;
+ if ((mac_config && link_state.interface != pl->link_config.interface) ||
+ pl->force_major_config) {
+ /* The interface has changed or a forced major configuration
+ * was requested, so force the link down and then reconfigure.
+ */
+ if (cur_link_state) {
+ phylink_link_down(pl);
+ cur_link_state = false;
}
+ phylink_major_config(pl, false, &link_state);
+ pl->link_config.interface = link_state.interface;
+ pl->force_major_config = false;
}
/* If configuration of the interface failed, force the link down
@@ -4355,6 +4357,57 @@ void phylink_mii_c45_pcs_get_state(struct mdio_device *pcs,
}
EXPORT_SYMBOL_GPL(phylink_mii_c45_pcs_get_state);
+/**
+ * phylink_replay_link_begin() - begin replay of link callbacks for driver
+ * which loses state
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * Helper for MAC drivers which may perform a destructive reset at runtime.
+ * Both the own driver's mac_link_down() method is called, as well as the
+ * pcs_link_down() method of the split PCS (if any).
+ *
+ * This is similar to phylink_stop(), except it does not alter the state of
+ * the phylib PHY (it is assumed that it is not affected by the MAC destructive
+ * reset).
+ */
+void phylink_replay_link_begin(struct phylink *pl)
+{
+ ASSERT_RTNL();
+
+ phylink_run_resolve_and_disable(pl, PHYLINK_DISABLE_REPLAY);
+}
+EXPORT_SYMBOL_GPL(phylink_replay_link_begin);
+
+/**
+ * phylink_replay_link_end() - end replay of link callbacks for driver
+ * which lost state
+ * @pl: a pointer to a &struct phylink returned from phylink_create()
+ *
+ * Helper for MAC drivers which may perform a destructive reset at runtime.
+ * Both the own driver's mac_config() and mac_link_up() methods, as well as the
+ * pcs_config() and pcs_link_up() method of the split PCS (if any), are called.
+ *
+ * This is similar to phylink_start(), except it does not alter the state of
+ * the phylib PHY.
+ *
+ * One must call this method only within the same rtnl_lock() critical section
+ * as a previous phylink_replay_link_start().
+ */
+void phylink_replay_link_end(struct phylink *pl)
+{
+ ASSERT_RTNL();
+
+ if (WARN(!test_bit(PHYLINK_DISABLE_REPLAY,
+ &pl->phylink_disable_state),
+ "phylink_replay_link_end() called without a prior phylink_replay_link_begin()\n"))
+ return;
+
+ pl->force_major_config = true;
+ phylink_enable_and_run_resolve(pl, PHYLINK_DISABLE_REPLAY);
+ flush_work(&pl->resolve);
+}
+EXPORT_SYMBOL_GPL(phylink_replay_link_end);
+
static int __init phylink_init(void)
{
for (int i = 0; i < ARRAY_SIZE(phylink_sfp_interface_preference); ++i)
diff --git a/include/linux/phylink.h b/include/linux/phylink.h
index 38363e566ac3..d6ea817abcda 100644
--- a/include/linux/phylink.h
+++ b/include/linux/phylink.h
@@ -836,4 +836,9 @@ void phylink_mii_c45_pcs_get_state(struct mdio_device *pcs,
void phylink_decode_usxgmii_word(struct phylink_link_state *state,
uint16_t lpa);
+
+void phylink_replay_link_begin(struct phylink *pl);
+
+void phylink_replay_link_end(struct phylink *pl);
+
#endif
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread* [PATCH net-next 02/15] net: mdio-regmap: permit working with non-MMIO regmaps
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
2025-11-18 19:05 ` [PATCH net-next 01/15] net: dsa: sja1105: let phylink help with the replay of link callbacks Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
2025-11-20 14:35 ` Maxime Chevallier
2025-11-18 19:05 ` [PATCH net-next 03/15] net: mdio: add driver for NXP SJA1110 100BASE-T1 embedded PHYs Vladimir Oltean
` (12 subsequent siblings)
14 siblings, 1 reply; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel,
Mark Brown, Maxime Chevallier
The regmap world is seemingly split into two groups which attempt to
solve different problems. Effectively, this means that not all regmap
providers are compatible with all regmap consumers.
First, we have the group where the current mdio-regmap users fit:
altera_tse_main.c and dwmac-socfpga.c use devm_regmap_init_mmio() to
ioremap their pcs_base and obtain a regmap where address zero is the
first PCS register.
Second, we have the group where MFD parent drivers call
mfd_add_devices(), having previously initialized a non-MMIO (SPI, I2C)
regmap and added it to their devres list, and MFD child drivers use
dev_get_regmap(dev->parent, NULL) in their probe function, to find the
first (and single) regmap of the MFD parent. The address zero of this
regmap is global to the entire parent, so the children need to be
parent-aware and add their own offsets for the registers that they
should manage.
This is essentially because MFD is seemingly coming from a world where
peripheral registers are all entangled with each other, but what I'm
trying to support via MFD are potentially multiple instances of the same
kind of device, at well separated address space regions.
To use MFD but provide isolated regmaps for each child device would
essentially mean to fight against the system. The problem that needs to
be now solved is that each child device needs to find the correct
regmap, which means that "dev_get_regmap(dev->parent, NULL)" transforms
either in:
- dev_get_regmap(dev, NULL): search in the child device's devres list,
not in the parent's. But MFD does not give us a hook in between
platform_device_alloc() and platform_device_add() where we could make
the devm_regmap_init_spi() call for the child device. We have to make
it for the parent.
- dev_get_regmap(dev->parent, "unique-regmap-name"): now the child
device needs to know, in case there are multiple instances of it,
which one is it, to ask for the right one. I've seen
drivers/mfd/ocelot-core.c work around this rather elegantly, providing
a resource to the child, and then the child uses resource->name to
find the regmap of the same name in the parent. But then I also
stumbled upon drivers/net/pcs/pcs-xpcs-plat.c which I need to support
as an MFD child, and that superimposes its own naming scheme for the
resources: "direct" or "indirect" - scheme which is obviously
incompatible with namespacing per instance.
So a MFD parent needs to decide whether it is in the boat that provides
one isolated regmap for each child, or one big regmap for all. The "one
big regmap" is the lowest common denominator when considering children
like pcs-xpcs-plat.c.
This means that from mdio-regmap's perspective, it needs to deal with
regmaps coming from both kinds of providers, as neither of them is going
away.
Users who provide a big regmap but want to access only a window into it
should provide as a struct mdio_regmap_config field a resource that
describes the start and end of that window. Currently we only use the
start as an offset into the regmap, and hope that MDIO reads and writes
won't go past the end.
Cc: Mark Brown <broonie@kernel.org>
Cc: Maxime Chevallier <maxime.chevallier@bootlin.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
drivers/net/mdio/mdio-regmap.c | 7 +++++--
include/linux/mdio/mdio-regmap.h | 2 ++
2 files changed, 7 insertions(+), 2 deletions(-)
diff --git a/drivers/net/mdio/mdio-regmap.c b/drivers/net/mdio/mdio-regmap.c
index 8a742a8d6387..2a0e9c519fa3 100644
--- a/drivers/net/mdio/mdio-regmap.c
+++ b/drivers/net/mdio/mdio-regmap.c
@@ -19,6 +19,7 @@
struct mdio_regmap_priv {
struct regmap *regmap;
+ unsigned int base;
u8 valid_addr;
};
@@ -31,7 +32,7 @@ static int mdio_regmap_read_c22(struct mii_bus *bus, int addr, int regnum)
if (ctx->valid_addr != addr)
return -ENODEV;
- ret = regmap_read(ctx->regmap, regnum, &val);
+ ret = regmap_read(ctx->regmap, ctx->base + regnum, &val);
if (ret < 0)
return ret;
@@ -46,7 +47,7 @@ static int mdio_regmap_write_c22(struct mii_bus *bus, int addr, int regnum,
if (ctx->valid_addr != addr)
return -ENODEV;
- return regmap_write(ctx->regmap, regnum, val);
+ return regmap_write(ctx->regmap, ctx->base + regnum, val);
}
struct mii_bus *devm_mdio_regmap_register(struct device *dev,
@@ -66,6 +67,8 @@ struct mii_bus *devm_mdio_regmap_register(struct device *dev,
mr = mii->priv;
mr->regmap = config->regmap;
mr->valid_addr = config->valid_addr;
+ if (config->resource)
+ mr->base = config->resource->start;
mii->name = DRV_NAME;
strscpy(mii->id, config->name, MII_BUS_ID_SIZE);
diff --git a/include/linux/mdio/mdio-regmap.h b/include/linux/mdio/mdio-regmap.h
index 679d9069846b..441cead97936 100644
--- a/include/linux/mdio/mdio-regmap.h
+++ b/include/linux/mdio/mdio-regmap.h
@@ -11,10 +11,12 @@
struct device;
struct regmap;
+struct resource;
struct mdio_regmap_config {
struct device *parent;
struct regmap *regmap;
+ const struct resource *resource;
char name[MII_BUS_ID_SIZE];
u8 valid_addr;
bool autoscan;
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread* Re: [PATCH net-next 02/15] net: mdio-regmap: permit working with non-MMIO regmaps
2025-11-18 19:05 ` [PATCH net-next 02/15] net: mdio-regmap: permit working with non-MMIO regmaps Vladimir Oltean
@ 2025-11-20 14:35 ` Maxime Chevallier
0 siblings, 0 replies; 54+ messages in thread
From: Maxime Chevallier @ 2025-11-20 14:35 UTC (permalink / raw)
To: Vladimir Oltean, netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel,
Mark Brown
Hi Vladimir,
On 18/11/2025 20:05, Vladimir Oltean wrote:
> The regmap world is seemingly split into two groups which attempt to
> solve different problems. Effectively, this means that not all regmap
> providers are compatible with all regmap consumers.
>
> First, we have the group where the current mdio-regmap users fit:
> altera_tse_main.c and dwmac-socfpga.c use devm_regmap_init_mmio() to
> ioremap their pcs_base and obtain a regmap where address zero is the
> first PCS register.
>
> Second, we have the group where MFD parent drivers call
> mfd_add_devices(), having previously initialized a non-MMIO (SPI, I2C)
> regmap and added it to their devres list, and MFD child drivers use
> dev_get_regmap(dev->parent, NULL) in their probe function, to find the
> first (and single) regmap of the MFD parent. The address zero of this
> regmap is global to the entire parent, so the children need to be
> parent-aware and add their own offsets for the registers that they
> should manage.
>
> This is essentially because MFD is seemingly coming from a world where
> peripheral registers are all entangled with each other, but what I'm
> trying to support via MFD are potentially multiple instances of the same
> kind of device, at well separated address space regions.
>
> To use MFD but provide isolated regmaps for each child device would
> essentially mean to fight against the system. The problem that needs to
> be now solved is that each child device needs to find the correct
> regmap, which means that "dev_get_regmap(dev->parent, NULL)" transforms
> either in:
> - dev_get_regmap(dev, NULL): search in the child device's devres list,
> not in the parent's. But MFD does not give us a hook in between
> platform_device_alloc() and platform_device_add() where we could make
> the devm_regmap_init_spi() call for the child device. We have to make
> it for the parent.
> - dev_get_regmap(dev->parent, "unique-regmap-name"): now the child
> device needs to know, in case there are multiple instances of it,
> which one is it, to ask for the right one. I've seen
> drivers/mfd/ocelot-core.c work around this rather elegantly, providing
> a resource to the child, and then the child uses resource->name to
> find the regmap of the same name in the parent. But then I also
> stumbled upon drivers/net/pcs/pcs-xpcs-plat.c which I need to support
> as an MFD child, and that superimposes its own naming scheme for the
> resources: "direct" or "indirect" - scheme which is obviously
> incompatible with namespacing per instance.
>
> So a MFD parent needs to decide whether it is in the boat that provides
> one isolated regmap for each child, or one big regmap for all. The "one
> big regmap" is the lowest common denominator when considering children
> like pcs-xpcs-plat.c.
>
> This means that from mdio-regmap's perspective, it needs to deal with
> regmaps coming from both kinds of providers, as neither of them is going
> away.
>
> Users who provide a big regmap but want to access only a window into it
> should provide as a struct mdio_regmap_config field a resource that
> describes the start and end of that window. Currently we only use the
> start as an offset into the regmap, and hope that MDIO reads and writes
> won't go past the end.
>
> Cc: Mark Brown <broonie@kernel.org>
> Cc: Maxime Chevallier <maxime.chevallier@bootlin.com>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
That sounds good to me ! Thanks for expanding this driver :) I agree
with keeping the entire resource instead of just 'start'.
Reviewed-by: Maxime Chevallier <maxime.chevallier@bootlin.com>
Maxime
^ permalink raw reply [flat|nested] 54+ messages in thread
* [PATCH net-next 03/15] net: mdio: add driver for NXP SJA1110 100BASE-T1 embedded PHYs
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
2025-11-18 19:05 ` [PATCH net-next 01/15] net: dsa: sja1105: let phylink help with the replay of link callbacks Vladimir Oltean
2025-11-18 19:05 ` [PATCH net-next 02/15] net: mdio-regmap: permit working with non-MMIO regmaps Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
2025-11-18 19:05 ` [PATCH net-next 04/15] net: mdio: add generic driver for NXP SJA1110 100BASE-TX " Vladimir Oltean
` (11 subsequent siblings)
14 siblings, 0 replies; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel
This driver is the standalone variant of drivers/net/dsa/sja1105/sja1105_mdio.c.
In terms of differences:
- this one uses regmaps provided by the parent as a method to abstract
away the sja1105_xfer_u32() calls for register access
- the driver prefix has been changed from sja1105 to sja1110 (this MDIO
controller is not present on the older SJA1105 family)
- in the sja1105 driver, each memory word has 32 bits, so addresses as
seen by regmap need to be multiplied by 4. This affects what
sja1110_base_t1_encode_addr() returns, and is different compared to
sja1105_base_t1_encode_addr().
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
MAINTAINERS | 1 +
drivers/net/mdio/Kconfig | 7 ++
drivers/net/mdio/Makefile | 1 +
drivers/net/mdio/mdio-sja1110-cbt1.c | 173 +++++++++++++++++++++++++++
4 files changed, 182 insertions(+)
create mode 100644 drivers/net/mdio/mdio-sja1110-cbt1.c
diff --git a/MAINTAINERS b/MAINTAINERS
index 37f4278db851..c41b9d86c144 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -18679,6 +18679,7 @@ M: Vladimir Oltean <olteanv@gmail.com>
L: linux-kernel@vger.kernel.org
S: Maintained
F: drivers/net/dsa/sja1105
+F: drivers/net/mdio/mdio-sja1110-cbt1.c
F: drivers/net/pcs/pcs-xpcs-nxp.c
NXP TDA998X DRM DRIVER
diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig
index 44380378911b..9819d1dc18de 100644
--- a/drivers/net/mdio/Kconfig
+++ b/drivers/net/mdio/Kconfig
@@ -136,6 +136,13 @@ config MDIO_MOXART
This driver supports the MDIO interface found in the network
interface units of the MOXA ART SoC
+config MDIO_SJA1110_CBT1
+ tristate "NXP SJA1110 100BASE-T1 MDIO bus"
+ help
+ This driver supports the MDIO controller embedded in the NXP SJA1110
+ automotive Ethernet switches, which is used to access the internal
+ 100BASE-T1 PHYs over SPI.
+
config MDIO_OCTEON
tristate "Octeon and some ThunderX SOCs MDIO buses"
depends on (64BIT && OF_MDIO) || COMPILE_TEST
diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile
index fbec636700e7..9abf20d1b030 100644
--- a/drivers/net/mdio/Makefile
+++ b/drivers/net/mdio/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_MDIO_MVUSB) += mdio-mvusb.o
obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
obj-$(CONFIG_MDIO_REALTEK_RTL9300) += mdio-realtek-rtl9300.o
obj-$(CONFIG_MDIO_REGMAP) += mdio-regmap.o
+obj-$(CONFIG_MDIO_SJA1110_CBT1) += mdio-sja1110-cbt1.o
obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o
obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o
obj-$(CONFIG_MDIO_XGENE) += mdio-xgene.o
diff --git a/drivers/net/mdio/mdio-sja1110-cbt1.c b/drivers/net/mdio/mdio-sja1110-cbt1.c
new file mode 100644
index 000000000000..a5f7830a6257
--- /dev/null
+++ b/drivers/net/mdio/mdio-sja1110-cbt1.c
@@ -0,0 +1,173 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright 2022 NXP
+ *
+ * NXP SJA1110 100BASE-T1 MDIO bus driver
+ */
+#include <linux/module.h>
+#include <linux/of_mdio.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+
+struct sja1110_base_t1_private {
+ struct regmap *regmap;
+ struct mii_bus *bus;
+ unsigned int base;
+};
+
+enum sja1110_mdio_opcode {
+ SJA1110_C45_ADDR = 0,
+ SJA1110_C22 = 1,
+ SJA1110_C45_DATA = 2,
+ SJA1110_C45_DATA_AUTOINC = 3,
+};
+
+static unsigned int sja1110_base_t1_encode_addr(unsigned int phy,
+ enum sja1110_mdio_opcode op,
+ unsigned int xad)
+{
+ return (phy << 9) | (op << 7) | (xad << 2);
+}
+
+static int sja1110_base_t1_mdio_read_c22(struct mii_bus *bus, int phy, int reg)
+{
+ struct sja1110_base_t1_private *priv = bus->priv;
+ struct regmap *regmap = priv->regmap;
+ unsigned int addr, val;
+ int err;
+
+ addr = sja1110_base_t1_encode_addr(phy, SJA1110_C22, reg & 0x1f);
+
+ err = regmap_read(regmap, priv->base + addr, &val);
+ if (err)
+ return err;
+
+ return val & 0xffff;
+}
+
+static int sja1110_base_t1_mdio_read_c45(struct mii_bus *bus, int phy,
+ int mmd, int reg)
+{
+ struct sja1110_base_t1_private *priv = bus->priv;
+ struct regmap *regmap = priv->regmap;
+ unsigned int addr, val;
+ int err;
+
+ addr = sja1110_base_t1_encode_addr(phy, SJA1110_C45_ADDR, mmd);
+ err = regmap_write(regmap, priv->base + addr, reg);
+ if (err)
+ return err;
+
+ addr = sja1110_base_t1_encode_addr(phy, SJA1110_C45_DATA, mmd);
+ err = regmap_read(regmap, priv->base + addr, &val);
+ if (err)
+ return err;
+
+ return val & 0xffff;
+}
+
+static int sja1110_base_t1_mdio_write_c22(struct mii_bus *bus, int phy, int reg,
+ u16 val)
+{
+ struct sja1110_base_t1_private *priv = bus->priv;
+ struct regmap *regmap = priv->regmap;
+ unsigned int addr;
+
+ addr = sja1110_base_t1_encode_addr(phy, SJA1110_C22, reg & 0x1f);
+ return regmap_write(regmap, priv->base + addr, val & 0xffff);
+}
+
+static int sja1110_base_t1_mdio_write_c45(struct mii_bus *bus, int phy,
+ int mmd, int reg, u16 val)
+{
+ struct sja1110_base_t1_private *priv = bus->priv;
+ struct regmap *regmap = priv->regmap;
+ unsigned int addr;
+ int err;
+
+ addr = sja1110_base_t1_encode_addr(phy, SJA1110_C45_ADDR, mmd);
+ err = regmap_write(regmap, priv->base + addr, reg);
+ if (err)
+ return err;
+
+ addr = sja1110_base_t1_encode_addr(phy, SJA1110_C45_DATA, mmd);
+ return regmap_write(regmap, priv->base + addr, val & 0xffff);
+}
+
+static int sja1110_base_t1_mdio_probe(struct platform_device *pdev)
+{
+ struct sja1110_base_t1_private *priv;
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap;
+ struct resource *res;
+ struct mii_bus *bus;
+ int err;
+
+ if (!dev->of_node || !dev->parent)
+ return -ENODEV;
+
+ regmap = dev_get_regmap(dev->parent, NULL);
+ if (!regmap)
+ return -ENODEV;
+
+ bus = mdiobus_alloc_size(sizeof(*priv));
+ if (!bus)
+ return -ENOMEM;
+
+ bus->name = "SJA1110 100base-T1 MDIO bus";
+ snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev));
+ bus->read = sja1110_base_t1_mdio_read_c22;
+ bus->write = sja1110_base_t1_mdio_write_c22;
+ bus->read_c45 = sja1110_base_t1_mdio_read_c45;
+ bus->write_c45 = sja1110_base_t1_mdio_write_c45;
+ bus->parent = dev;
+ priv = bus->priv;
+ priv->regmap = regmap;
+
+ res = platform_get_resource(pdev, IORESOURCE_REG, 0);
+ if (res)
+ priv->base = res->start;
+
+ err = of_mdiobus_register(bus, dev->of_node);
+ if (err)
+ goto err_free_bus;
+
+ priv->bus = bus;
+ platform_set_drvdata(pdev, priv);
+
+ return 0;
+
+err_free_bus:
+ mdiobus_free(bus);
+
+ return err;
+}
+
+static void sja1110_base_t1_mdio_remove(struct platform_device *pdev)
+{
+ struct sja1110_base_t1_private *priv = platform_get_drvdata(pdev);
+
+ mdiobus_unregister(priv->bus);
+ mdiobus_free(priv->bus);
+}
+
+static const struct of_device_id sja1110_base_t1_mdio_match[] = {
+ { .compatible = "nxp,sja1110-base-t1-mdio", },
+ {},
+};
+MODULE_DEVICE_TABLE(of, sja1110_base_t1_mdio_match);
+
+static struct platform_driver sja1110_base_t1_mdio_driver = {
+ .probe = sja1110_base_t1_mdio_probe,
+ .remove = sja1110_base_t1_mdio_remove,
+ .driver = {
+ .name = "sja1110-base-t1-mdio",
+ .of_match_table = sja1110_base_t1_mdio_match,
+ },
+};
+
+module_platform_driver(sja1110_base_t1_mdio_driver);
+
+MODULE_DESCRIPTION("NXP SJA1110 100BASE-T1 MDIO bus driver");
+MODULE_AUTHOR("Vladimir Oltean <vladimir.oltean@nxp.com>");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread* [PATCH net-next 04/15] net: mdio: add generic driver for NXP SJA1110 100BASE-TX embedded PHYs
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
` (2 preceding siblings ...)
2025-11-18 19:05 ` [PATCH net-next 03/15] net: mdio: add driver for NXP SJA1110 100BASE-T1 embedded PHYs Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
2025-11-20 17:55 ` Maxime Chevallier
2025-11-18 19:05 ` [PATCH net-next 05/15] net: dsa: sja1105: prepare regmap for passing to child devices Vladimir Oltean
` (10 subsequent siblings)
14 siblings, 1 reply; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel,
Maxime Chevallier
This is the standalone variant of drivers/net/dsa/sja1105/sja1105_mdio.c.
Same kind of differences between this driver and the embedded DSA one
apply: regmap is being used for register access, and addresses are
multiplied by 4 with regmap.
In fact this is so generic that there is nothing NXP SJA1110 specific
about it at all, and just instantiates mdio-regmap. I decided to name it
mdio-regmap-simple.c in the style of drivers/mfd/simple-mfd-i2c.c which
has support for various vendor compatible strings.
Cc: Maxime Chevallier <maxime.chevallier@bootlin.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
MAINTAINERS | 1 +
drivers/net/mdio/Kconfig | 14 +++--
drivers/net/mdio/Makefile | 1 +
drivers/net/mdio/mdio-regmap-simple.c | 77 +++++++++++++++++++++++++++
4 files changed, 90 insertions(+), 3 deletions(-)
create mode 100644 drivers/net/mdio/mdio-regmap-simple.c
diff --git a/MAINTAINERS b/MAINTAINERS
index c41b9d86c144..81c3dba6acd0 100644
--- a/MAINTAINERS
+++ b/MAINTAINERS
@@ -15473,6 +15473,7 @@ M: Maxime Chevallier <maxime.chevallier@bootlin.com>
L: netdev@vger.kernel.org
S: Maintained
F: drivers/net/mdio/mdio-regmap.c
+F: drivers/net/mdio/mdio-regmap-simple.c
F: include/linux/mdio/mdio-regmap.h
MEASUREMENT COMPUTING CIO-DAC IIO DRIVER
diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig
index 9819d1dc18de..2f86a438a2a7 100644
--- a/drivers/net/mdio/Kconfig
+++ b/drivers/net/mdio/Kconfig
@@ -179,14 +179,22 @@ config MDIO_REALTEK_RTL9300
config MDIO_REGMAP
tristate
help
- This driver allows using MDIO devices that are not sitting on a
- regular MDIO bus, but still exposes the standard 802.3 register
+ This support module allows using MDIO devices that are not sitting on
+ a regular MDIO bus, but still exposes the standard 802.3 register
layout. It's regmap-based so that it can be used on integrated,
memory-mapped PHYs, SPI PHYs and so on. A new virtual MDIO bus is
created, and its read/write operations are mapped to the underlying
- regmap. Users willing to use this driver must explicitly select
+ regmap. Users willing to use this module must explicitly select
REGMAP.
+config MDIO_REGMAP_SIMPLE
+ tristate
+ help
+ Generic platform driver for MDIO buses with a linear address space
+ that can be directly accessed using the MDIO_REGMAP support code and
+ need no special handling. The regmap is provided by the parent
+ device.
+
config MDIO_THUNDER
tristate "ThunderX SOCs MDIO buses"
depends on 64BIT
diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile
index 9abf20d1b030..95f201b73a7d 100644
--- a/drivers/net/mdio/Makefile
+++ b/drivers/net/mdio/Makefile
@@ -22,6 +22,7 @@ obj-$(CONFIG_MDIO_MVUSB) += mdio-mvusb.o
obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
obj-$(CONFIG_MDIO_REALTEK_RTL9300) += mdio-realtek-rtl9300.o
obj-$(CONFIG_MDIO_REGMAP) += mdio-regmap.o
+obj-$(CONFIG_MDIO_REGMAP_SIMPLE) += mdio-regmap-simple.o
obj-$(CONFIG_MDIO_SJA1110_CBT1) += mdio-sja1110-cbt1.o
obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o
obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o
diff --git a/drivers/net/mdio/mdio-regmap-simple.c b/drivers/net/mdio/mdio-regmap-simple.c
new file mode 100644
index 000000000000..6ac390ec759b
--- /dev/null
+++ b/drivers/net/mdio/mdio-regmap-simple.c
@@ -0,0 +1,77 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright 2025 NXP
+ *
+ * Generic MDIO bus driver for simple regmap-based MDIO devices
+ *
+ * This driver creates MDIO buses for devices that expose their internal
+ * PHYs or PCS through a regmap interface. It's intended to be a simple,
+ * generic driver similar to simple-mfd-i2c.c.
+ */
+#include <linux/module.h>
+#include <linux/of_mdio.h>
+#include <linux/phy.h>
+#include <linux/platform_device.h>
+#include <linux/regmap.h>
+#include <linux/mdio/mdio-regmap.h>
+
+struct mdio_regmap_simple_data {
+ u8 valid_addr;
+ bool autoscan;
+};
+
+static const struct mdio_regmap_simple_data nxp_sja1110_base_tx = {
+ .valid_addr = 0,
+ .autoscan = false,
+};
+
+static int mdio_regmap_simple_probe(struct platform_device *pdev)
+{
+ const struct mdio_regmap_simple_data *data;
+ struct mdio_regmap_config config = {};
+ struct device *dev = &pdev->dev;
+ struct regmap *regmap;
+ struct mii_bus *bus;
+
+ if (!dev->of_node || !dev->parent)
+ return -ENODEV;
+
+ regmap = dev_get_regmap(dev->parent, NULL);
+ if (!regmap)
+ return -ENODEV;
+
+ data = device_get_match_data(dev);
+
+ config.regmap = regmap;
+ config.parent = dev;
+ config.name = dev_name(dev);
+ config.resource = platform_get_resource(pdev, IORESOURCE_REG, 0);
+ if (data) {
+ config.valid_addr = data->valid_addr;
+ config.autoscan = data->autoscan;
+ }
+
+ return PTR_ERR_OR_ZERO(devm_mdio_regmap_register(dev, &config));
+}
+
+static const struct of_device_id mdio_regmap_simple_match[] = {
+ {
+ .compatible = "nxp,sja1110-base-tx-mdio",
+ .data = &nxp_sja1110_base_tx,
+ },
+ {}
+};
+MODULE_DEVICE_TABLE(of, mdio_regmap_simple_match);
+
+static struct platform_driver mdio_regmap_simple_driver = {
+ .probe = mdio_regmap_simple_probe,
+ .driver = {
+ .name = "mdio-regmap-simple",
+ .of_match_table = mdio_regmap_simple_match,
+ },
+};
+
+module_platform_driver(mdio_regmap_simple_driver);
+
+MODULE_DESCRIPTION("Generic MDIO bus driver for simple regmap-based devices");
+MODULE_AUTHOR("Vladimir Oltean <vladimir.oltean@nxp.com>");
+MODULE_LICENSE("GPL");
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread* Re: [PATCH net-next 04/15] net: mdio: add generic driver for NXP SJA1110 100BASE-TX embedded PHYs
2025-11-18 19:05 ` [PATCH net-next 04/15] net: mdio: add generic driver for NXP SJA1110 100BASE-TX " Vladimir Oltean
@ 2025-11-20 17:55 ` Maxime Chevallier
2025-11-20 18:49 ` Vladimir Oltean
0 siblings, 1 reply; 54+ messages in thread
From: Maxime Chevallier @ 2025-11-20 17:55 UTC (permalink / raw)
To: Vladimir Oltean, netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel
Hi Vladimir,
On 18/11/2025 20:05, Vladimir Oltean wrote:
> This is the standalone variant of drivers/net/dsa/sja1105/sja1105_mdio.c.
> Same kind of differences between this driver and the embedded DSA one
> apply: regmap is being used for register access, and addresses are
> multiplied by 4 with regmap.
>
> In fact this is so generic that there is nothing NXP SJA1110 specific
> about it at all, and just instantiates mdio-regmap. I decided to name it
> mdio-regmap-simple.c in the style of drivers/mfd/simple-mfd-i2c.c which
> has support for various vendor compatible strings.
>
> Cc: Maxime Chevallier <maxime.chevallier@bootlin.com>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
> MAINTAINERS | 1 +
> drivers/net/mdio/Kconfig | 14 +++--
> drivers/net/mdio/Makefile | 1 +
> drivers/net/mdio/mdio-regmap-simple.c | 77 +++++++++++++++++++++++++++
> 4 files changed, 90 insertions(+), 3 deletions(-)
> create mode 100644 drivers/net/mdio/mdio-regmap-simple.c
>
> diff --git a/MAINTAINERS b/MAINTAINERS
> index c41b9d86c144..81c3dba6acd0 100644
> --- a/MAINTAINERS
> +++ b/MAINTAINERS
> @@ -15473,6 +15473,7 @@ M: Maxime Chevallier <maxime.chevallier@bootlin.com>
> L: netdev@vger.kernel.org
> S: Maintained
> F: drivers/net/mdio/mdio-regmap.c
> +F: drivers/net/mdio/mdio-regmap-simple.c
> F: include/linux/mdio/mdio-regmap.h
>
> MEASUREMENT COMPUTING CIO-DAC IIO DRIVER
> diff --git a/drivers/net/mdio/Kconfig b/drivers/net/mdio/Kconfig
> index 9819d1dc18de..2f86a438a2a7 100644
> --- a/drivers/net/mdio/Kconfig
> +++ b/drivers/net/mdio/Kconfig
> @@ -179,14 +179,22 @@ config MDIO_REALTEK_RTL9300
> config MDIO_REGMAP
> tristate
> help
> - This driver allows using MDIO devices that are not sitting on a
> - regular MDIO bus, but still exposes the standard 802.3 register
> + This support module allows using MDIO devices that are not sitting on
> + a regular MDIO bus, but still exposes the standard 802.3 register
> layout. It's regmap-based so that it can be used on integrated,
> memory-mapped PHYs, SPI PHYs and so on. A new virtual MDIO bus is
> created, and its read/write operations are mapped to the underlying
> - regmap. Users willing to use this driver must explicitly select
> + regmap. Users willing to use this module must explicitly select
> REGMAP.
Thans for fixing these mistakes
>
> +config MDIO_REGMAP_SIMPLE
> + tristate
> + help
> + Generic platform driver for MDIO buses with a linear address space
> + that can be directly accessed using the MDIO_REGMAP support code and
> + need no special handling. The regmap is provided by the parent
> + device.
> +
It would probably make sense to add "select MDIO_REGMAP" here
> config MDIO_THUNDER
> tristate "ThunderX SOCs MDIO buses"
> depends on 64BIT
> diff --git a/drivers/net/mdio/Makefile b/drivers/net/mdio/Makefile
> index 9abf20d1b030..95f201b73a7d 100644
> --- a/drivers/net/mdio/Makefile
> +++ b/drivers/net/mdio/Makefile
> @@ -22,6 +22,7 @@ obj-$(CONFIG_MDIO_MVUSB) += mdio-mvusb.o
> obj-$(CONFIG_MDIO_OCTEON) += mdio-octeon.o
> obj-$(CONFIG_MDIO_REALTEK_RTL9300) += mdio-realtek-rtl9300.o
> obj-$(CONFIG_MDIO_REGMAP) += mdio-regmap.o
> +obj-$(CONFIG_MDIO_REGMAP_SIMPLE) += mdio-regmap-simple.o
> obj-$(CONFIG_MDIO_SJA1110_CBT1) += mdio-sja1110-cbt1.o
> obj-$(CONFIG_MDIO_SUN4I) += mdio-sun4i.o
> obj-$(CONFIG_MDIO_THUNDER) += mdio-thunder.o
> diff --git a/drivers/net/mdio/mdio-regmap-simple.c b/drivers/net/mdio/mdio-regmap-simple.c
> new file mode 100644
> index 000000000000..6ac390ec759b
> --- /dev/null
> +++ b/drivers/net/mdio/mdio-regmap-simple.c
> @@ -0,0 +1,77 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright 2025 NXP
> + *
> + * Generic MDIO bus driver for simple regmap-based MDIO devices
> + *
> + * This driver creates MDIO buses for devices that expose their internal
> + * PHYs or PCS through a regmap interface. It's intended to be a simple,
> + * generic driver similar to simple-mfd-i2c.c.
> + */
> +#include <linux/module.h>
> +#include <linux/of_mdio.h>
> +#include <linux/phy.h>
> +#include <linux/platform_device.h>
> +#include <linux/regmap.h>
> +#include <linux/mdio/mdio-regmap.h>
> +
> +struct mdio_regmap_simple_data {
> + u8 valid_addr;
> + bool autoscan;
> +};
> +
> +static const struct mdio_regmap_simple_data nxp_sja1110_base_tx = {
> + .valid_addr = 0,
> + .autoscan = false,
> +};
> +
> +static int mdio_regmap_simple_probe(struct platform_device *pdev)
> +{
> + const struct mdio_regmap_simple_data *data;
> + struct mdio_regmap_config config = {};
> + struct device *dev = &pdev->dev;
> + struct regmap *regmap;
> + struct mii_bus *bus;
> +
> + if (!dev->of_node || !dev->parent)
> + return -ENODEV;
> +
> + regmap = dev_get_regmap(dev->parent, NULL);
> + if (!regmap)
> + return -ENODEV;
> +
> + data = device_get_match_data(dev);
> +
> + config.regmap = regmap;
> + config.parent = dev;
> + config.name = dev_name(dev);
> + config.resource = platform_get_resource(pdev, IORESOURCE_REG, 0);
Just to clarify, a small comment to say that it's OK of
platform_get_resource() returns NULL maybe ?
> + if (data) {
> + config.valid_addr = data->valid_addr;
> + config.autoscan = data->autoscan;
> + }
> +
> + return PTR_ERR_OR_ZERO(devm_mdio_regmap_register(dev, &config));
> +}
> +
> +static const struct of_device_id mdio_regmap_simple_match[] = {
> + {
> + .compatible = "nxp,sja1110-base-tx-mdio",
> + .data = &nxp_sja1110_base_tx,
> + },
> + {}
> +};
> +MODULE_DEVICE_TABLE(of, mdio_regmap_simple_match);
> +
> +static struct platform_driver mdio_regmap_simple_driver = {
> + .probe = mdio_regmap_simple_probe,
> + .driver = {
> + .name = "mdio-regmap-simple",
> + .of_match_table = mdio_regmap_simple_match,
> + },
> +};
> +
> +module_platform_driver(mdio_regmap_simple_driver);
> +
> +MODULE_DESCRIPTION("Generic MDIO bus driver for simple regmap-based devices");
> +MODULE_AUTHOR("Vladimir Oltean <vladimir.oltean@nxp.com>");
> +MODULE_LICENSE("GPL");
Thanks for this,
Maxime
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 04/15] net: mdio: add generic driver for NXP SJA1110 100BASE-TX embedded PHYs
2025-11-20 17:55 ` Maxime Chevallier
@ 2025-11-20 18:49 ` Vladimir Oltean
0 siblings, 0 replies; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-20 18:49 UTC (permalink / raw)
To: Maxime Chevallier
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
On Thu, Nov 20, 2025 at 06:55:56PM +0100, Maxime Chevallier wrote:
> > + config.regmap = regmap;
> > + config.parent = dev;
> > + config.name = dev_name(dev);
> > + config.resource = platform_get_resource(pdev, IORESOURCE_REG, 0);
>
> Just to clarify, a small comment to say that it's OK of
> platform_get_resource() returns NULL maybe ?
Good forethought. I can already imagine tens of patches to 'fix' this if
merged like that..
Thanks for the review!
^ permalink raw reply [flat|nested] 54+ messages in thread
* [PATCH net-next 05/15] net: dsa: sja1105: prepare regmap for passing to child devices
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
` (3 preceding siblings ...)
2025-11-18 19:05 ` [PATCH net-next 04/15] net: mdio: add generic driver for NXP SJA1110 100BASE-TX " Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
2025-11-18 19:05 ` [PATCH net-next 06/15] net: dsa: sja1105: include spi.h from sja1105.h Vladimir Oltean
` (9 subsequent siblings)
14 siblings, 0 replies; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel
Prepare a single regmap covering the entire SPI address space of the
SJA1105 and SJA1110 switches which can be given to MDIO buses, XPCS,
irqchip drivers etc.
This regmap is zero-based, can access the entire switch address space,
and child devices are supposed to access their respective memory region
with the help of struct resource (IORESOURCE_REG, to be precise).
Nothing is currently done with the regmap, it is just allocated and
added to the device's devres list, so it doesn't need to be freed.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
drivers/net/dsa/sja1105/sja1105.h | 4 ++
drivers/net/dsa/sja1105/sja1105_main.c | 6 +++
drivers/net/dsa/sja1105/sja1105_spi.c | 58 ++++++++++++++++++++++++++
3 files changed, 68 insertions(+)
diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h
index dceb96ae9c83..e952917b67b6 100644
--- a/drivers/net/dsa/sja1105/sja1105.h
+++ b/drivers/net/dsa/sja1105/sja1105.h
@@ -11,6 +11,8 @@
#include <linux/dsa/8021q.h>
#include <net/dsa.h>
#include <linux/mutex.h>
+#include <linux/regmap.h>
+
#include "sja1105_static_config.h"
#define SJA1105ET_FDB_BIN_SIZE 4
@@ -273,6 +275,7 @@ struct sja1105_private {
u8 ts_id;
/* Serializes access to the dynamic config interface */
struct mutex dynamic_config_lock;
+ struct regmap *regmap;
struct devlink_region **regions;
struct sja1105_cbs_entry *cbs;
struct mii_bus *mdio_base_t1;
@@ -338,6 +341,7 @@ int static_config_buf_prepare_for_upload(struct sja1105_private *priv,
int sja1105_static_config_upload(struct sja1105_private *priv);
int sja1105_inhibit_tx(const struct sja1105_private *priv,
unsigned long port_bitmap, bool tx_inhibited);
+int sja1105_create_regmap(struct sja1105_private *priv);
extern const struct sja1105_info sja1105e_info;
extern const struct sja1105_info sja1105t_info;
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 9f62cc7e1bd1..622264c13fdb 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -3318,6 +3318,12 @@ static int sja1105_probe(struct spi_device *spi)
priv->info = of_device_get_match_data(dev);
+ rc = sja1105_create_regmap(priv);
+ if (rc < 0) {
+ dev_err(dev, "Failed to create regmap: %pe\n", ERR_PTR(rc));
+ return rc;
+ }
+
/* Detect hardware device */
rc = sja1105_check_device_id(priv);
if (rc < 0) {
diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c
index 834b5c1b4db0..cfc76af8a65b 100644
--- a/drivers/net/dsa/sja1105/sja1105_spi.c
+++ b/drivers/net/dsa/sja1105/sja1105_spi.c
@@ -408,6 +408,64 @@ int sja1105_static_config_upload(struct sja1105_private *priv)
return rc;
}
+static int sja1105_regmap_bus_reg_read(void *ctx, unsigned int reg,
+ unsigned int *val)
+{
+ struct sja1105_private *priv = ctx;
+ u32 tmp;
+ int rc;
+
+ rc = sja1105_xfer_u32(priv, SPI_READ, SJA1110_SPI_ADDR(reg), &tmp,
+ NULL);
+ if (rc)
+ return rc;
+
+ *val = tmp;
+
+ return 0;
+}
+
+static int sja1105_regmap_bus_reg_write(void *ctx, unsigned int reg,
+ unsigned int val)
+{
+ struct sja1105_private *priv = ctx;
+ u32 tmp = val;
+
+ return sja1105_xfer_u32(priv, SPI_WRITE, SJA1110_SPI_ADDR(reg), &tmp,
+ NULL);
+}
+
+static struct regmap_bus sja1105_regmap_bus = {
+ .reg_read = sja1105_regmap_bus_reg_read,
+ .reg_write = sja1105_regmap_bus_reg_write,
+ .reg_format_endian_default = REGMAP_ENDIAN_NATIVE,
+ .val_format_endian_default = REGMAP_ENDIAN_NATIVE,
+};
+
+/* The primary purpose of this is to pass it to child devices,
+ * not to abstract SPI access for the main driver.
+ */
+int sja1105_create_regmap(struct sja1105_private *priv)
+{
+ struct device *dev = &priv->spidev->dev;
+ struct regmap_config regmap_config = {
+ .name = "switch",
+ .reg_bits = 32,
+ .val_bits = 32,
+ .reg_stride = 4,
+ };
+ struct regmap *regmap;
+
+ regmap = devm_regmap_init(dev, &sja1105_regmap_bus, priv,
+ ®map_config);
+ if (IS_ERR(regmap))
+ return PTR_ERR(regmap);
+
+ priv->regmap = regmap;
+
+ return 0;
+}
+
static const struct sja1105_regs sja1105et_regs = {
.device_id = 0x0,
.prod_id = 0x100BC3,
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread* [PATCH net-next 06/15] net: dsa: sja1105: include spi.h from sja1105.h
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
` (4 preceding siblings ...)
2025-11-18 19:05 ` [PATCH net-next 05/15] net: dsa: sja1105: prepare regmap for passing to child devices Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
2025-11-18 19:05 ` [PATCH net-next 07/15] mfd: core: add ability for cells to probe on a custom parent OF node Vladimir Oltean
` (8 subsequent siblings)
14 siblings, 0 replies; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel
We have a reference to struct spi_device, but users of sja1105.h cannot
dereference it if they need to. One such example will come in the next
change, where sja1105_mdio.c does not include <linux/spi.h>, so it
cannot dereference priv->spidev->dev.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
drivers/net/dsa/sja1105/sja1105.h | 1 +
1 file changed, 1 insertion(+)
diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h
index e952917b67b6..4fd6121bd07f 100644
--- a/drivers/net/dsa/sja1105/sja1105.h
+++ b/drivers/net/dsa/sja1105/sja1105.h
@@ -9,6 +9,7 @@
#include <linux/timecounter.h>
#include <linux/dsa/sja1105.h>
#include <linux/dsa/8021q.h>
+#include <linux/spi/spi.h>
#include <net/dsa.h>
#include <linux/mutex.h>
#include <linux/regmap.h>
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread* [PATCH net-next 07/15] mfd: core: add ability for cells to probe on a custom parent OF node
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
` (5 preceding siblings ...)
2025-11-18 19:05 ` [PATCH net-next 06/15] net: dsa: sja1105: include spi.h from sja1105.h Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
2025-11-20 14:41 ` Lee Jones
2025-11-18 19:05 ` [PATCH net-next 08/15] net: dsa: sja1105: transition OF-based MDIO drivers to standalone Vladimir Oltean
` (7 subsequent siblings)
14 siblings, 1 reply; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel,
Lee Jones
I would like the "nxp,sja1110a" driver, in the configuration below, to
be able to probe the drivers for "nxp,sja1110-base-t1-mdio" and for
"nxp,sja1110-base-tx-mdio" via mfd_add_devices():
ethernet-switch@0 {
compatible = "nxp,sja1110a";
mdios {
mdio@0 {
compatible = "nxp,sja1110-base-t1-mdio";
};
mdio@1 {
compatible = "nxp,sja1110-base-tx-mdio";
};
};
};
This isn't currently possible, because mfd assumes that the parent
OF node ("mdios") == OF node of the parent ("ethernet-switch@0"), which
in this case isn't true, and as it searches through the children of
"ethernet-switch@0", it finds no MDIO bus to probe.
Cc: Lee Jones <lee@kernel.org>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
drivers/mfd/mfd-core.c | 11 +++++++++--
include/linux/mfd/core.h | 7 +++++++
2 files changed, 16 insertions(+), 2 deletions(-)
diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
index 7d14a1e7631e..e0b7f93a2654 100644
--- a/drivers/mfd/mfd-core.c
+++ b/drivers/mfd/mfd-core.c
@@ -181,8 +181,14 @@ static int mfd_add_device(struct device *parent, int id,
if (ret < 0)
goto fail_res;
- if (IS_ENABLED(CONFIG_OF) && parent->of_node && cell->of_compatible) {
- for_each_child_of_node(parent->of_node, np) {
+ if (IS_ENABLED(CONFIG_OF)) {
+ const struct device_node *parent_of_node;
+
+ parent_of_node = cell->parent_of_node ?: parent->of_node;
+ if (!parent_of_node || !cell->of_compatible)
+ goto skip_of;
+
+ for_each_child_of_node(parent_of_node, np) {
if (of_device_is_compatible(np, cell->of_compatible)) {
/* Skip 'disabled' devices */
if (!of_device_is_available(np)) {
@@ -213,6 +219,7 @@ static int mfd_add_device(struct device *parent, int id,
cell->name, platform_id);
}
+skip_of:
mfd_acpi_add_device(cell, pdev);
if (cell->pdata_size) {
diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
index faeea7abd688..2e94ea376125 100644
--- a/include/linux/mfd/core.h
+++ b/include/linux/mfd/core.h
@@ -81,6 +81,13 @@ struct mfd_cell {
/* Software node for the device. */
const struct software_node *swnode;
+ /*
+ * Parent OF node of the device, if different from the OF node
+ * of the MFD parent (e.g. there is at least one more hierarchical
+ * level between them)
+ */
+ const struct device_node *parent_of_node;
+
/*
* Device Tree compatible string
* See: Documentation/devicetree/usage-model.rst Chapter 2.2 for details
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread* Re: [PATCH net-next 07/15] mfd: core: add ability for cells to probe on a custom parent OF node
2025-11-18 19:05 ` [PATCH net-next 07/15] mfd: core: add ability for cells to probe on a custom parent OF node Vladimir Oltean
@ 2025-11-20 14:41 ` Lee Jones
2025-11-20 15:36 ` Vladimir Oltean
0 siblings, 1 reply; 54+ messages in thread
From: Lee Jones @ 2025-11-20 14:41 UTC (permalink / raw)
To: Vladimir Oltean
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
On Tue, 18 Nov 2025, Vladimir Oltean wrote:
> I would like the "nxp,sja1110a" driver, in the configuration below, to
> be able to probe the drivers for "nxp,sja1110-base-t1-mdio" and for
> "nxp,sja1110-base-tx-mdio" via mfd_add_devices():
>
> ethernet-switch@0 {
> compatible = "nxp,sja1110a";
>
> mdios {
> mdio@0 {
> compatible = "nxp,sja1110-base-t1-mdio";
> };
>
> mdio@1 {
> compatible = "nxp,sja1110-base-tx-mdio";
> };
> };
> };
This device is not an MFD.
Please find a different way to instantiate these network drivers.
> This isn't currently possible, because mfd assumes that the parent
> OF node ("mdios") == OF node of the parent ("ethernet-switch@0"), which
> in this case isn't true, and as it searches through the children of
> "ethernet-switch@0", it finds no MDIO bus to probe.
>
> Cc: Lee Jones <lee@kernel.org>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
> drivers/mfd/mfd-core.c | 11 +++++++++--
> include/linux/mfd/core.h | 7 +++++++
> 2 files changed, 16 insertions(+), 2 deletions(-)
>
> diff --git a/drivers/mfd/mfd-core.c b/drivers/mfd/mfd-core.c
> index 7d14a1e7631e..e0b7f93a2654 100644
> --- a/drivers/mfd/mfd-core.c
> +++ b/drivers/mfd/mfd-core.c
> @@ -181,8 +181,14 @@ static int mfd_add_device(struct device *parent, int id,
> if (ret < 0)
> goto fail_res;
>
> - if (IS_ENABLED(CONFIG_OF) && parent->of_node && cell->of_compatible) {
> - for_each_child_of_node(parent->of_node, np) {
> + if (IS_ENABLED(CONFIG_OF)) {
> + const struct device_node *parent_of_node;
> +
> + parent_of_node = cell->parent_of_node ?: parent->of_node;
> + if (!parent_of_node || !cell->of_compatible)
> + goto skip_of;
> +
> + for_each_child_of_node(parent_of_node, np) {
> if (of_device_is_compatible(np, cell->of_compatible)) {
> /* Skip 'disabled' devices */
> if (!of_device_is_available(np)) {
> @@ -213,6 +219,7 @@ static int mfd_add_device(struct device *parent, int id,
> cell->name, platform_id);
> }
>
> +skip_of:
> mfd_acpi_add_device(cell, pdev);
>
> if (cell->pdata_size) {
> diff --git a/include/linux/mfd/core.h b/include/linux/mfd/core.h
> index faeea7abd688..2e94ea376125 100644
> --- a/include/linux/mfd/core.h
> +++ b/include/linux/mfd/core.h
> @@ -81,6 +81,13 @@ struct mfd_cell {
> /* Software node for the device. */
> const struct software_node *swnode;
>
> + /*
> + * Parent OF node of the device, if different from the OF node
> + * of the MFD parent (e.g. there is at least one more hierarchical
> + * level between them)
> + */
> + const struct device_node *parent_of_node;
> +
> /*
> * Device Tree compatible string
> * See: Documentation/devicetree/usage-model.rst Chapter 2.2 for details
> --
> 2.34.1
>
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 07/15] mfd: core: add ability for cells to probe on a custom parent OF node
2025-11-20 14:41 ` Lee Jones
@ 2025-11-20 15:36 ` Vladimir Oltean
2025-11-21 12:06 ` Lee Jones
0 siblings, 1 reply; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-20 15:36 UTC (permalink / raw)
To: Lee Jones
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
On Thu, Nov 20, 2025 at 02:41:36PM +0000, Lee Jones wrote:
> On Tue, 18 Nov 2025, Vladimir Oltean wrote:
>
> > I would like the "nxp,sja1110a" driver, in the configuration below, to
> > be able to probe the drivers for "nxp,sja1110-base-t1-mdio" and for
> > "nxp,sja1110-base-tx-mdio" via mfd_add_devices():
> >
> > ethernet-switch@0 {
> > compatible = "nxp,sja1110a";
> >
> > mdios {
> > mdio@0 {
> > compatible = "nxp,sja1110-base-t1-mdio";
> > };
> >
> > mdio@1 {
> > compatible = "nxp,sja1110-base-tx-mdio";
> > };
> > };
> > };
>
> This device is not an MFD.
>
> Please find a different way to instantiate these network drivers.
Ok.. but what is an MFD? I'm seriously interested in a definition.
One data point: the VSC7512 (driver in drivers/mfd/ocelot-spi.c,
bindings in Documentation/devicetree/bindings/mfd/mscc,ocelot.yaml) is
almost the same class of hardware (except the embedded Cortex-M7 in
SJA1110 can't run Linux, and the CPU in VSC7512 can). It instantiates
MDIO bus children, like this patch proposes too, except it works with a
different device tree hierarchy which I need to adapt to, without breaking.
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 07/15] mfd: core: add ability for cells to probe on a custom parent OF node
2025-11-20 15:36 ` Vladimir Oltean
@ 2025-11-21 12:06 ` Lee Jones
2025-11-21 17:03 ` Vladimir Oltean
0 siblings, 1 reply; 54+ messages in thread
From: Lee Jones @ 2025-11-21 12:06 UTC (permalink / raw)
To: Vladimir Oltean
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
On Thu, 20 Nov 2025, Vladimir Oltean wrote:
> On Thu, Nov 20, 2025 at 02:41:36PM +0000, Lee Jones wrote:
> > On Tue, 18 Nov 2025, Vladimir Oltean wrote:
> >
> > > I would like the "nxp,sja1110a" driver, in the configuration below, to
> > > be able to probe the drivers for "nxp,sja1110-base-t1-mdio" and for
> > > "nxp,sja1110-base-tx-mdio" via mfd_add_devices():
> > >
> > > ethernet-switch@0 {
> > > compatible = "nxp,sja1110a";
> > >
> > > mdios {
> > > mdio@0 {
> > > compatible = "nxp,sja1110-base-t1-mdio";
> > > };
> > >
> > > mdio@1 {
> > > compatible = "nxp,sja1110-base-tx-mdio";
> > > };
> > > };
> > > };
> >
> > This device is not an MFD.
> >
> > Please find a different way to instantiate these network drivers.
>
> Ok.. but what is an MFD? I'm seriously interested in a definition.
>
> One data point: the VSC7512 (driver in drivers/mfd/ocelot-spi.c,
> bindings in Documentation/devicetree/bindings/mfd/mscc,ocelot.yaml) is
> almost the same class of hardware (except the embedded Cortex-M7 in
> SJA1110 can't run Linux, and the CPU in VSC7512 can). It instantiates
> MDIO bus children, like this patch proposes too, except it works with a
> different device tree hierarchy which I need to adapt to, without breaking.
The devices should be different types i.e. be located in different
subsystems. If you're simply instantiating Watchdog timers, the code
should live solely in drivers/watchdog. If the devices all pertain to
Networking, the code should live in the Networking subsystem, etc.
MFD is Linuxisum, simply used to split devices up such that each
component can be located it their own applicable subsystem and be
reviewed and maintained by the subject matter experts of those domains.
TL;DR: if your device only deals with Networking, that's where it should
live. And from there, it should handle its own device registration and
instantiation without reaching into other, non-related subsystems.
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 07/15] mfd: core: add ability for cells to probe on a custom parent OF node
2025-11-21 12:06 ` Lee Jones
@ 2025-11-21 17:03 ` Vladimir Oltean
2025-11-26 10:20 ` Lee Jones
2025-12-15 15:50 ` Lee Jones
0 siblings, 2 replies; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-21 17:03 UTC (permalink / raw)
To: Lee Jones
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
On Fri, Nov 21, 2025 at 12:06:46PM +0000, Lee Jones wrote:
> MFD is Linuxisum, simply used to split devices up such that each
> component can be located it their own applicable subsystem and be
> reviewed and maintained by the subject matter experts of those domains.
Perfect, so the SJA1110 fits the MFD bill perfectly.
I'm getting the impression that the more I write to explain, the fewer
chances I have for you to read. I'll try to keep things as concise as I
can, but please remember that:
- We've had the exact same discussions with Colin Foster's VSC7512
work, which you ended up accepting
- This email sent to you in 2022 and again in the other reply on patch 8:
https://lore.kernel.org/lkml/20221222134844.lbzyx5hz7z5n763n@skbuf/
already explains what is the kind of hardware I'm dealing with
> TL;DR: if your device only deals with Networking, that's where it should
> live. And from there, it should handle its own device registration and
> instantiation without reaching into other, non-related subsystems.
Ok, you make a vague reference which I think I understand the point of.
I need to merge the discussion with the one from patch 8:
https://lore.kernel.org/netdev/20251121120037.GA1117685@google.com/
where you say:
| Another more recent avenue you may explore is the Auxiliary Bus.
Excerpt from documentation here:
https://docs.kernel.org/driver-api/auxiliary_bus.html
When Should the Auxiliary Bus Be Used
(...)
The emphasis here is on a common generic interface that keeps subsystem
customization out of the bus infrastructure.
(...)
A key requirement for utilizing the auxiliary bus is that there is no
dependency on a physical bus, device, register accesses or regmap
support. These individual devices split from the core cannot live on the
platform bus as they are not physical devices that are controlled by
DT/ACPI. The same argument applies for not using MFD in this scenario as
MFD relies on individual function devices being physical devices.
The thesis I need to defend is that the SJA1110 usage is 100% fit for
MFD and 0% auxiliary bus. In order to explain it I have to give a bit of
history on DSA.
DSA is a Linuxism for managing Ethernet switches. Key thing is they are
a hardware IP with registers to configure them. There are many ways
to integrate an Ethernet switch hardware IP in a chip that you sell.
You can (a) sell the IP itself for SoC vendors to put in their address
space and access using MMIO, or you can (b) sell them an entire chip
with the switch IP in it, that they access over a bus like PCIe, SPI,
I2C, MDIO, whatever, and integrate with their existing Linux SoC.
DSA has started from a place where it didn't really understand that its
core domain of expertise was the Ethernet switching IP itself. The first
devices it supported were all of the (b) kind, discrete chips on buses.
Thus, many drivers were written where DSA takes charge of the struct
spi_device, mdio_device, i2c_client etc.
These early drivers are simplistic, they configure the switch to pass
traffic, and the PHYs through the internal MDIO bus to establish a link,
and voila! They pass traffic, they're good to go.
Then you start to want to develop these further. You want to avoid
polling PHYs for link status every second.. well, you find there's an
interrupt controller in that chip too, that you should be using with
irqchip. You want to read the chip's temperature to prevent it from
overheating - you find temperature sensors too, for which you register
with hwmon. You find reset blocks, clock generation blocks, power
management blocks, GPIO controllers, what have you.
See, the more you look at the datasheet, the more you start to notice
an entire universe of hardware IPs, and then.. you notice a microcontroller!
Those hardware IPs are all also memory-mapped in the address space of
that microcontroller, and when you from Linux are accessing them, you're
just going through a SPI-to-AHB bridge.
Things become really shitty when the DSA chip that you want to drive
from drivers/net/dsa has a full-blown microprocessor capable of running
Linux instead of that microcontroller! Then you have to support driving
the same switch from the small Linux, using MMIO, or from the big Linux,
over SPI.
Out of a lack of expressivity that we as engineers have, we call both
the SoC at large "a switch", and the switching IP "a switch". Hell,
we even call the rack-mounted pizza box computer with many ports "a switch",
no wonder nobody understands anything! We just name things after the
most important thing that's in them.
So unwind 100 steps from the rabbit hole and ask: what does DSA concern
itself with?
Ideally, the answer is "the Ethernet switch IP". This is always mapped
in somebody's address space from address X to Y.
Practically, legacy makes it that DSA concerns itself with the entire
address space of SPI devices, MDIO devices, I2C devices etc. If you
imagine a microprocessor in these discrete chips (which is architecturally
almost always possible), the device tree of that would only describe a
single region with the Ethernet switching IP, and Linux would probe a
platform device for that. The rest is.. other stuff (of various degrees
of functional relatedness, but nonetheless, other stuff) with *other*
platform devices.
So, DSA is in a process of trying to define a conversion model that is
coherent, compatible with the past, minimal in its description,
applicable to other devices, and not a pain in the butt.
Fact of the matter is, we will always clash with the MFD maintainer in
this process, and it simply doesn't scale for us to keep repeating the
same stuff over and over. It is just too much friction. We went through
this once, with Colin Foster who added the Microchip VSC7512 as MFD
through your tree, and that marked the first time when a DSA driver over
a SPI device concerned itself with just the switching IP, using MFD as
the abstraction layer.
The NXP SJA1110 is just another step in that journey, but this one is
harder because it has legacy device tree bindings to maintain. However,
if we are to accept that Colin Foster's work was not an architectural
mistake, then the SJA1110 is not the end of the road either, and you
have to be prepared for more devices to come and do the same thing.
So practically speaking, the fact that DSA has these particular needs
is just a fact. Treat the above description as a "global prompt", if you
will :)
So why not the auxiliary bus? That creates auxiliary_device structures,
which are fake things that some core device wants to keep out to make
things leaner. But what we want is a platform_device, because that is
the common denominator between what kind of drivers the "small Linux"
and the "big Linux" would use for the same hardware IPs. MFD gives us
exactly that, and regmap provides the abstraction between MMIO and SPI.
================================================================
The above was the "global prompt" that you need to have in your context,
now let's return to the patch at hand.
SJA1110 is *not* capable of running Linux inside. This allows us to get
away with partial conversions, where the DSA driver still remains in
charge of the entire SPI device, but delegates the other stuff to MFD.
The existing bindings cannot be broken. Hindsight is 20/20, but whatever
stupid decisions I made in the past with this "mdios" container node are
there to stay.
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 07/15] mfd: core: add ability for cells to probe on a custom parent OF node
2025-11-21 17:03 ` Vladimir Oltean
@ 2025-11-26 10:20 ` Lee Jones
2025-12-15 15:50 ` Lee Jones
1 sibling, 0 replies; 54+ messages in thread
From: Lee Jones @ 2025-11-26 10:20 UTC (permalink / raw)
To: Vladimir Oltean
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
I acknowledge receipt of your mail, but I need to get my list of reviews
down to a sensible number before fully processing it. Please stand-by.
/ Lee
> On Fri, Nov 21, 2025 at 12:06:46PM +0000, Lee Jones wrote:
> > MFD is Linuxisum, simply used to split devices up such that each
> > component can be located it their own applicable subsystem and be
> > reviewed and maintained by the subject matter experts of those domains.
>
> Perfect, so the SJA1110 fits the MFD bill perfectly.
>
> I'm getting the impression that the more I write to explain, the fewer
> chances I have for you to read. I'll try to keep things as concise as I
> can, but please remember that:
> - We've had the exact same discussions with Colin Foster's VSC7512
> work, which you ended up accepting
> - This email sent to you in 2022 and again in the other reply on patch 8:
> https://lore.kernel.org/lkml/20221222134844.lbzyx5hz7z5n763n@skbuf/
> already explains what is the kind of hardware I'm dealing with
>
> > TL;DR: if your device only deals with Networking, that's where it should
> > live. And from there, it should handle its own device registration and
> > instantiation without reaching into other, non-related subsystems.
>
> Ok, you make a vague reference which I think I understand the point of.
>
> I need to merge the discussion with the one from patch 8:
> https://lore.kernel.org/netdev/20251121120037.GA1117685@google.com/
> where you say:
>
> | Another more recent avenue you may explore is the Auxiliary Bus.
>
> Excerpt from documentation here:
> https://docs.kernel.org/driver-api/auxiliary_bus.html
>
> When Should the Auxiliary Bus Be Used
>
> (...)
> The emphasis here is on a common generic interface that keeps subsystem
> customization out of the bus infrastructure.
> (...)
> A key requirement for utilizing the auxiliary bus is that there is no
> dependency on a physical bus, device, register accesses or regmap
> support. These individual devices split from the core cannot live on the
> platform bus as they are not physical devices that are controlled by
> DT/ACPI. The same argument applies for not using MFD in this scenario as
> MFD relies on individual function devices being physical devices.
>
> The thesis I need to defend is that the SJA1110 usage is 100% fit for
> MFD and 0% auxiliary bus. In order to explain it I have to give a bit of
> history on DSA.
>
> DSA is a Linuxism for managing Ethernet switches. Key thing is they are
> a hardware IP with registers to configure them. There are many ways
> to integrate an Ethernet switch hardware IP in a chip that you sell.
> You can (a) sell the IP itself for SoC vendors to put in their address
> space and access using MMIO, or you can (b) sell them an entire chip
> with the switch IP in it, that they access over a bus like PCIe, SPI,
> I2C, MDIO, whatever, and integrate with their existing Linux SoC.
>
> DSA has started from a place where it didn't really understand that its
> core domain of expertise was the Ethernet switching IP itself. The first
> devices it supported were all of the (b) kind, discrete chips on buses.
> Thus, many drivers were written where DSA takes charge of the struct
> spi_device, mdio_device, i2c_client etc.
>
> These early drivers are simplistic, they configure the switch to pass
> traffic, and the PHYs through the internal MDIO bus to establish a link,
> and voila! They pass traffic, they're good to go.
>
> Then you start to want to develop these further. You want to avoid
> polling PHYs for link status every second.. well, you find there's an
> interrupt controller in that chip too, that you should be using with
> irqchip. You want to read the chip's temperature to prevent it from
> overheating - you find temperature sensors too, for which you register
> with hwmon. You find reset blocks, clock generation blocks, power
> management blocks, GPIO controllers, what have you.
>
> See, the more you look at the datasheet, the more you start to notice
> an entire universe of hardware IPs, and then.. you notice a microcontroller!
> Those hardware IPs are all also memory-mapped in the address space of
> that microcontroller, and when you from Linux are accessing them, you're
> just going through a SPI-to-AHB bridge.
>
> Things become really shitty when the DSA chip that you want to drive
> from drivers/net/dsa has a full-blown microprocessor capable of running
> Linux instead of that microcontroller! Then you have to support driving
> the same switch from the small Linux, using MMIO, or from the big Linux,
> over SPI.
>
> Out of a lack of expressivity that we as engineers have, we call both
> the SoC at large "a switch", and the switching IP "a switch". Hell,
> we even call the rack-mounted pizza box computer with many ports "a switch",
> no wonder nobody understands anything! We just name things after the
> most important thing that's in them.
>
> So unwind 100 steps from the rabbit hole and ask: what does DSA concern
> itself with?
>
> Ideally, the answer is "the Ethernet switch IP". This is always mapped
> in somebody's address space from address X to Y.
>
> Practically, legacy makes it that DSA concerns itself with the entire
> address space of SPI devices, MDIO devices, I2C devices etc. If you
> imagine a microprocessor in these discrete chips (which is architecturally
> almost always possible), the device tree of that would only describe a
> single region with the Ethernet switching IP, and Linux would probe a
> platform device for that. The rest is.. other stuff (of various degrees
> of functional relatedness, but nonetheless, other stuff) with *other*
> platform devices.
>
> So, DSA is in a process of trying to define a conversion model that is
> coherent, compatible with the past, minimal in its description,
> applicable to other devices, and not a pain in the butt.
>
> Fact of the matter is, we will always clash with the MFD maintainer in
> this process, and it simply doesn't scale for us to keep repeating the
> same stuff over and over. It is just too much friction. We went through
> this once, with Colin Foster who added the Microchip VSC7512 as MFD
> through your tree, and that marked the first time when a DSA driver over
> a SPI device concerned itself with just the switching IP, using MFD as
> the abstraction layer.
>
> The NXP SJA1110 is just another step in that journey, but this one is
> harder because it has legacy device tree bindings to maintain. However,
> if we are to accept that Colin Foster's work was not an architectural
> mistake, then the SJA1110 is not the end of the road either, and you
> have to be prepared for more devices to come and do the same thing.
>
> So practically speaking, the fact that DSA has these particular needs
> is just a fact. Treat the above description as a "global prompt", if you
> will :)
>
> So why not the auxiliary bus? That creates auxiliary_device structures,
> which are fake things that some core device wants to keep out to make
> things leaner. But what we want is a platform_device, because that is
> the common denominator between what kind of drivers the "small Linux"
> and the "big Linux" would use for the same hardware IPs. MFD gives us
> exactly that, and regmap provides the abstraction between MMIO and SPI.
>
> ================================================================
>
> The above was the "global prompt" that you need to have in your context,
> now let's return to the patch at hand.
>
> SJA1110 is *not* capable of running Linux inside. This allows us to get
> away with partial conversions, where the DSA driver still remains in
> charge of the entire SPI device, but delegates the other stuff to MFD.
>
> The existing bindings cannot be broken. Hindsight is 20/20, but whatever
> stupid decisions I made in the past with this "mdios" container node are
> there to stay.
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 07/15] mfd: core: add ability for cells to probe on a custom parent OF node
2025-11-21 17:03 ` Vladimir Oltean
2025-11-26 10:20 ` Lee Jones
@ 2025-12-15 15:50 ` Lee Jones
2025-12-16 0:29 ` Vladimir Oltean
1 sibling, 1 reply; 54+ messages in thread
From: Lee Jones @ 2025-12-15 15:50 UTC (permalink / raw)
To: Vladimir Oltean
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
Sorry for the delay.
Just getting around to some task items en-route back from Plumbers.
> On Fri, Nov 21, 2025 at 12:06:46PM +0000, Lee Jones wrote:
> > MFD is Linuxisum, simply used to split devices up such that each
> > component can be located it their own applicable subsystem and be
> > reviewed and maintained by the subject matter experts of those domains.
>
> Perfect, so the SJA1110 fits the MFD bill perfectly.
>
> I'm getting the impression that the more I write to explain, the fewer
> chances I have for you to read. I'll try to keep things as concise as I
> can, but please remember that:
> - We've had the exact same discussions with Colin Foster's VSC7512
> work, which you ended up accepting
> - This email sent to you in 2022 and again in the other reply on patch 8:
> https://lore.kernel.org/lkml/20221222134844.lbzyx5hz7z5n763n@skbuf/
> already explains what is the kind of hardware I'm dealing with
>
> > TL;DR: if your device only deals with Networking, that's where it should
> > live. And from there, it should handle its own device registration and
> > instantiation without reaching into other, non-related subsystems.
>
> Ok, you make a vague reference which I think I understand the point of.
>
> I need to merge the discussion with the one from patch 8:
> https://lore.kernel.org/netdev/20251121120037.GA1117685@google.com/
> where you say:
>
> | Another more recent avenue you may explore is the Auxiliary Bus.
>
> Excerpt from documentation here:
> https://docs.kernel.org/driver-api/auxiliary_bus.html
>
> When Should the Auxiliary Bus Be Used
>
> (...)
> The emphasis here is on a common generic interface that keeps subsystem
> customization out of the bus infrastructure.
> (...)
> A key requirement for utilizing the auxiliary bus is that there is no
> dependency on a physical bus, device, register accesses or regmap
> support. These individual devices split from the core cannot live on the
> platform bus as they are not physical devices that are controlled by
> DT/ACPI. The same argument applies for not using MFD in this scenario as
> MFD relies on individual function devices being physical devices.
>
> The thesis I need to defend is that the SJA1110 usage is 100% fit for
> MFD and 0% auxiliary bus. In order to explain it I have to give a bit of
> history on DSA.
>
> DSA is a Linuxism for managing Ethernet switches. Key thing is they are
> a hardware IP with registers to configure them. There are many ways
> to integrate an Ethernet switch hardware IP in a chip that you sell.
> You can (a) sell the IP itself for SoC vendors to put in their address
> space and access using MMIO, or you can (b) sell them an entire chip
> with the switch IP in it, that they access over a bus like PCIe, SPI,
> I2C, MDIO, whatever, and integrate with their existing Linux SoC.
>
> DSA has started from a place where it didn't really understand that its
> core domain of expertise was the Ethernet switching IP itself. The first
> devices it supported were all of the (b) kind, discrete chips on buses.
> Thus, many drivers were written where DSA takes charge of the struct
> spi_device, mdio_device, i2c_client etc.
>
> These early drivers are simplistic, they configure the switch to pass
> traffic, and the PHYs through the internal MDIO bus to establish a link,
> and voila! They pass traffic, they're good to go.
>
> Then you start to want to develop these further. You want to avoid
> polling PHYs for link status every second.. well, you find there's an
> interrupt controller in that chip too, that you should be using with
> irqchip. You want to read the chip's temperature to prevent it from
> overheating - you find temperature sensors too, for which you register
> with hwmon. You find reset blocks, clock generation blocks, power
> management blocks, GPIO controllers, what have you.
>
> See, the more you look at the datasheet, the more you start to notice
> an entire universe of hardware IPs, and then.. you notice a microcontroller!
> Those hardware IPs are all also memory-mapped in the address space of
> that microcontroller, and when you from Linux are accessing them, you're
> just going through a SPI-to-AHB bridge.
>
> Things become really shitty when the DSA chip that you want to drive
> from drivers/net/dsa has a full-blown microprocessor capable of running
> Linux instead of that microcontroller! Then you have to support driving
> the same switch from the small Linux, using MMIO, or from the big Linux,
> over SPI.
>
> Out of a lack of expressivity that we as engineers have, we call both
> the SoC at large "a switch", and the switching IP "a switch". Hell,
> we even call the rack-mounted pizza box computer with many ports "a switch",
> no wonder nobody understands anything! We just name things after the
> most important thing that's in them.
>
> So unwind 100 steps from the rabbit hole and ask: what does DSA concern
> itself with?
>
> Ideally, the answer is "the Ethernet switch IP". This is always mapped
> in somebody's address space from address X to Y.
>
> Practically, legacy makes it that DSA concerns itself with the entire
> address space of SPI devices, MDIO devices, I2C devices etc. If you
> imagine a microprocessor in these discrete chips (which is architecturally
> almost always possible), the device tree of that would only describe a
> single region with the Ethernet switching IP, and Linux would probe a
> platform device for that. The rest is.. other stuff (of various degrees
> of functional relatedness, but nonetheless, other stuff) with *other*
> platform devices.
>
> So, DSA is in a process of trying to define a conversion model that is
> coherent, compatible with the past, minimal in its description,
> applicable to other devices, and not a pain in the butt.
>
> Fact of the matter is, we will always clash with the MFD maintainer in
> this process, and it simply doesn't scale for us to keep repeating the
> same stuff over and over. It is just too much friction. We went through
> this once, with Colin Foster who added the Microchip VSC7512 as MFD
> through your tree, and that marked the first time when a DSA driver over
> a SPI device concerned itself with just the switching IP, using MFD as
> the abstraction layer.
>
> The NXP SJA1110 is just another step in that journey, but this one is
> harder because it has legacy device tree bindings to maintain. However,
> if we are to accept that Colin Foster's work was not an architectural
> mistake, then the SJA1110 is not the end of the road either, and you
> have to be prepared for more devices to come and do the same thing.
>
> So practically speaking, the fact that DSA has these particular needs
> is just a fact. Treat the above description as a "global prompt", if you
> will :)
>
> So why not the auxiliary bus? That creates auxiliary_device structures,
> which are fake things that some core device wants to keep out to make
> things leaner. But what we want is a platform_device, because that is
> the common denominator between what kind of drivers the "small Linux"
> and the "big Linux" would use for the same hardware IPs. MFD gives us
> exactly that, and regmap provides the abstraction between MMIO and SPI.
>
> ================================================================
>
> The above was the "global prompt" that you need to have in your context,
> now let's return to the patch at hand.
>
> SJA1110 is *not* capable of running Linux inside. This allows us to get
> away with partial conversions, where the DSA driver still remains in
> charge of the entire SPI device, but delegates the other stuff to MFD.
>
> The existing bindings cannot be broken. Hindsight is 20/20, but whatever
> stupid decisions I made in the past with this "mdios" container node are
> there to stay.
Thanks for drafting all of this. It's not an ideal level of verboseness
for a busy maintainer with 50+ of reviews to do, but I appreciate your
depth of knowledge and the eloquence of the writing.
There does appear to be at least some level of misunderstanding between
us. I'm not for one moment suggesting that a switch can't be an MFD. If
it contains probe-able components that need to be split-up across
multiple different subsystems, then by all means, move the core driver
into drivers/mfd/ and register child devices 'till your heart's content.
What I am saying, however, is that from what I can see in front of me,
there doesn't appear to be any evidence that this device belongs there.
Unless there's something I'm missing, it looks awfully like you're
simply trying to register a couple of platform deices devices and you've
chosen to use the MFD API as a convenient way to do so. That is not
what MFD is for.
Side note: The implementation is also janky.
> Fact of the matter is, we will always clash with the MFD maintainer in
> this process, and it simply doesn't scale for us to keep repeating the
> same stuff over and over. It is just too much friction. We went through
> this once, with Colin Foster who added the Microchip VSC7512 as MFD
> through your tree, and that marked the first time when a DSA driver over
> a SPI device concerned itself with just the switching IP, using MFD as
> the abstraction layer.
I don't recall those discussions from 3 years ago, but the Ocelot
platform, whatever it may be, seems to have quite a lot more
cross-subsystem device support requirements going on than I see here:
drivers/i2c/busses/i2c-designware-platdrv.c
drivers/irqchip/irq-mscc-ocelot.c
drivers/mfd/ocelot-*
drivers/net/dsa/ocelot/*
drivers/net/ethernet/mscc/ocelot*
drivers/net/mdio/mdio-mscc-miim.c
drivers/phy/mscc/phy-ocelot-serdes.c
drivers/pinctrl/pinctrl-microchip-sgpio.c
drivers/pinctrl/pinctrl-ocelot.c
drivers/power/reset/ocelot-reset.c
drivers/spi/spi-dw-mmio.c
net/dsa/tag_ocelot_8021q.c
> - We've had the exact same discussions with Colin Foster's VSC7512
> work, which you ended up accepting
Quick update: After doing a little searching for Colin's original
patch-set, I've managed to find as far back as v5 (v16 was merged),
which I believe was the first version that proposed using MFD. There
were lots of review comments and an insistence to add more than one
device (rather than adding them subsequently) to make it a true MFD,
however, I don't see any suggestion that MFD wasn't the right place for
it.
> Then you start to want to develop these further. You want to avoid
> polling PHYs for link status every second.. well, you find there's an
> interrupt controller in that chip too, that you should be using with
> irqchip. You want to read the chip's temperature to prevent it from
> overheating - you find temperature sensors too, for which you register
> with hwmon. You find reset blocks, clock generation blocks, power
> management blocks, GPIO controllers, what have you.
Absolutely! MFD would be perfect for that.
My point is, you don't seem to have have any of that here.
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 07/15] mfd: core: add ability for cells to probe on a custom parent OF node
2025-12-15 15:50 ` Lee Jones
@ 2025-12-16 0:29 ` Vladimir Oltean
2025-12-16 9:18 ` Lee Jones
0 siblings, 1 reply; 54+ messages in thread
From: Vladimir Oltean @ 2025-12-16 0:29 UTC (permalink / raw)
To: Lee Jones
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
Hello Lee,
On Mon, Dec 15, 2025 at 03:50:28PM +0000, Lee Jones wrote:
> Thanks for drafting all of this. It's not an ideal level of verboseness
> for a busy maintainer with 50+ of reviews to do, but I appreciate your
> depth of knowledge and the eloquence of the writing.
Thanks for coming back and I hope your time at LPC was spent usefully.
I will try to reorder your messages to group the replies in the way that
is most efficient.
> Side note: The implementation is also janky.
Yes, this is why it's up for review, so I can learn why it's janky and
fix it.
> There does appear to be at least some level of misunderstanding between
> us. I'm not for one moment suggesting that a switch can't be an MFD. If
> it contains probe-able components that need to be split-up across
> multiple different subsystems, then by all means, move the core driver
> into drivers/mfd/ and register child devices 'till your heart's content.
Are you still speaking generically here, or have you actually looked at
any "nxp,sja1105q" or "nxp,sja1110a" device trees to see what it would
mean for these compatible strings to be probed by a driver in drivers/mfd?
What OF node would remain for the DSA switch (child) device driver? The same?
Or are you suggesting that the entire drivers/net/dsa/sja1105/ would
move to drivers/mfd/? Or?
> What I am saying, however, is that from what I can see in front of me,
> there doesn't appear to be any evidence that this device belongs there.
>
> Unless there's something I'm missing, it looks awfully like you're
> simply trying to register a couple of platform deices devices and you've
> chosen to use the MFD API as a convenient way to do so. That is not
> what MFD is for.
I may be just uneducated here, but I'm genuinely perplexed. Isn't the
MFD API a convenient way to instantiate resources of a device into
platform sub-devices for _everyone_ who uses it? Is it more than that?
I don't know how to defend this.
> > Fact of the matter is, we will always clash with the MFD maintainer in
> > this process, and it simply doesn't scale for us to keep repeating the
> > same stuff over and over. It is just too much friction. We went through
> > this once, with Colin Foster who added the Microchip VSC7512 as MFD
> > through your tree, and that marked the first time when a DSA driver over
> > a SPI device concerned itself with just the switching IP, using MFD as
> > the abstraction layer.
>
> I don't recall those discussions from 3 years ago, but the Ocelot
> platform, whatever it may be, seems to have quite a lot more
> cross-subsystem device support requirements going on than I see here:
>
> drivers/i2c/busses/i2c-designware-platdrv.c
> drivers/irqchip/irq-mscc-ocelot.c
> drivers/mfd/ocelot-*
> drivers/net/dsa/ocelot/*
> drivers/net/ethernet/mscc/ocelot*
> drivers/net/mdio/mdio-mscc-miim.c
> drivers/phy/mscc/phy-ocelot-serdes.c
> drivers/pinctrl/pinctrl-microchip-sgpio.c
> drivers/pinctrl/pinctrl-ocelot.c
> drivers/power/reset/ocelot-reset.c
> drivers/spi/spi-dw-mmio.c
> net/dsa/tag_ocelot_8021q.c
This is a natural effect of Ocelot being "whatever it may be". It is a
family of networking SoCs, of which VSC7514 has a MIPS CPU and Linux
port, where the above drivers are used. The VSC7512 is then a simplified
variant with the MIPS CPU removed, and the internal components controlled
externally over SPI. Hence MFD to reuse the same drivers as Linux on
MIPS (using MMIO) did. This is all that matters, not the quantity.
> > - We've had the exact same discussions with Colin Foster's VSC7512
> > work, which you ended up accepting
>
> Quick update: After doing a little searching for Colin's original
> patch-set, I've managed to find as far back as v5 (v16 was merged),
> which I believe was the first version that proposed using MFD. There
> were lots of review comments and an insistence to add more than one
> device (rather than adding them subsequently) to make it a true MFD,
> however, I don't see any suggestion that MFD wasn't the right place for
> it.
>
> > Then you start to want to develop these further. You want to avoid
> > polling PHYs for link status every second.. well, you find there's an
> > interrupt controller in that chip too, that you should be using with
> > irqchip. You want to read the chip's temperature to prevent it from
> > overheating - you find temperature sensors too, for which you register
> > with hwmon. You find reset blocks, clock generation blocks, power
> > management blocks, GPIO controllers, what have you.
>
> Absolutely! MFD would be perfect for that.
>
> My point is, you don't seem to have have any of that here.
What do you want to see exactly which is not here?
I have converted three classes of sub-devices on the NXP SJA1110 to MFD
children in this patch set. Two MDIO buses and an Ethernet PCS for SGMII.
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
I need to remind you that my purpose here is not to add drivers in
breadth for all SJA1110 sub-devices now.
But rather, a concrete use case (SGMII polarity inversion) has appeared
which requires the SGMII1..SGMII4 blocks to appear in the device tree
(so far, the SJA1110 driver has happily programmed these blocks based on
hardcoded SPI addresses in the driver, and there hasn't existed a reason
to describe them in the DT).
The SGMII blocks are highly reusable IPs licensed from Synopsys, and
Linux already has DT bindings and a corresponding platform driver for
the case where their registers are viewed using MMIO.
So my proposal in patch 14/15 is to create the following DT sub-nodes of
the DSA switch:
- regs/ethernet-pcs@705000 for SGMII1
- regs/ethernet-pcs@706000 for SGMII2
- regs/ethernet-pcs@707000 for SGMII3
- regs/ethernet-pcs@708000 for SGMII4
and to use MFD so that the xpcs-plat driver currently used for the MMIO
case "just works" for the "register view over SPI" case, and the SPI DT
node inherits the same bindings. In this sense, it is exactly the same
problem and solution as Colin Foster's ocelot set, at a smaller scale
(just one sub-device of this switch already had an established MMIO driver).
https://lore.kernel.org/netdev/20251118190530.580267-15-vladimir.oltean@nxp.com/
Furthermore, I also finalized the split of region handling that started
with the aforementioned SGMII blocks, by making the DSA driver stop
accessing the 100BASE-T1 and 100BASE-TX regions directly, and use MFD to
probe separate drivers for these resources.
I did not _have_ to do this for 100BASE-T1 and 100BASE-TX, but the
intention behind doing it was to solidify the argument that this device
has multiple regions for which the MFD model is suitable, rather than
impair it.
In the upstream DT bindings of the switch, the 100BASE-T1 region has a
corresponding mdios/mdio@0 child node, and the resource is hardcoded in
the driver. Similarly, the 100BASE-TX region is described as the
mdios/mdio@1 child. This is what I need this patch (07/15) for.
The intention is for all future sub-devices of the switch to live under
the "regs" sub-node, with the exception of "mdios/mdio@0" and "mdios/mdio@1"
which are already established somewhere else via a stable ABI. This
makes the SJA1110 a hybrid DSA+MFD driver, due to the impossibility of
getting rid of current DT bindings (this, plus the fact that I don't
necessarily see a problem with them).
In my opinion I do not need to add handling for any other sub-device,
for the support to be more "cross-system" like for Ocelot. What is here
is enough for you to decide if this is adequate for MFD or not.
The driver for SJA1110 needs a path forward from point A (where it
handles some resources internally which are outside the SWITCH region)
to point B (where those resources are handled by their correct reusable
drivers with specific DT bindings which we need). At the very least, I
expect you to clarify what are the problems you perceive in MFD being
part of this transition. I'd rather not speculate, and your previous
response is not sufficiently applied to the problem at hand.
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 07/15] mfd: core: add ability for cells to probe on a custom parent OF node
2025-12-16 0:29 ` Vladimir Oltean
@ 2025-12-16 9:18 ` Lee Jones
2025-12-16 16:24 ` Vladimir Oltean
2025-12-17 9:31 ` Andrew Lunn
0 siblings, 2 replies; 54+ messages in thread
From: Lee Jones @ 2025-12-16 9:18 UTC (permalink / raw)
To: Vladimir Oltean
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
> > Side note: The implementation is also janky.
>
> Yes, this is why it's up for review, so I can learn why it's janky and
> fix it.
I'd be happy to discuss this in great detail if we finally conclude that
this device is suitable for MFD.
Spoiler alert: Unless you add/convert more child devices that are
outside of net/ and drivers/net AND move the core MFD usage to
drivers/mfd/, then we can't conclude that.
> > There does appear to be at least some level of misunderstanding between
> > us. I'm not for one moment suggesting that a switch can't be an MFD. If
> > it contains probe-able components that need to be split-up across
> > multiple different subsystems, then by all means, move the core driver
> > into drivers/mfd/ and register child devices 'till your heart's content.
>
> Are you still speaking generically here, or have you actually looked at
> any "nxp,sja1105q" or "nxp,sja1110a" device trees to see what it would
> mean for these compatible strings to be probed by a driver in drivers/mfd?
It's not my role to go digging into existing implementations and
previous submissions to prove whether a particular submission is
suitable for inclusion into MFD.
Please put in front of me, in a concise way (please), why you think this
is fit for inclusion. I've explained what is usually required, but I'll
(over-)simplify again for clarity:
- The mfd_* API call-sites must only exist in drivers/mfd/
- Consumers usually spit out non-system specific logic into a 'core'
- MFDs need to have more than one child
- This is where the 'Multi' comes in
- Children should straddle different sub-systems
- drivers/net is not enough [0]
- If all of your sub-devices are in 'net' use the platform_* API
- <other stipulations less relevant to this stipulation> ...
There will always be exceptions, but previous mistakes are not good
justifications for future ones.
[0]
.../bindings/net/dsa/nxp,sja1105.yaml | 28 +
.../bindings/net/pcs/snps,dw-xpcs.yaml | 8 +
MAINTAINERS | 2 +
drivers/mfd/mfd-core.c | 11 +-
drivers/net/dsa/sja1105/Kconfig | 2 +
drivers/net/dsa/sja1105/Makefile | 2 +-
drivers/net/dsa/sja1105/sja1105.h | 42 +-
drivers/net/dsa/sja1105/sja1105_main.c | 169 +++---
drivers/net/dsa/sja1105/sja1105_mdio.c | 507 ------------------
drivers/net/dsa/sja1105/sja1105_mfd.c | 293 ++++++++++
drivers/net/dsa/sja1105/sja1105_mfd.h | 11 +
drivers/net/dsa/sja1105/sja1105_spi.c | 113 +++-
drivers/net/mdio/Kconfig | 21 +-
drivers/net/mdio/Makefile | 2 +
drivers/net/mdio/mdio-regmap-simple.c | 77 +++
drivers/net/mdio/mdio-regmap.c | 7 +-
drivers/net/mdio/mdio-sja1110-cbt1.c | 173 ++++++
drivers/net/pcs/pcs-xpcs-plat.c | 146 +++--
drivers/net/pcs/pcs-xpcs.c | 12 +
drivers/net/phy/phylink.c | 75 ++-
include/linux/mdio/mdio-regmap.h | 2 +
include/linux/mfd/core.h | 7 +
include/linux/pcs/pcs-xpcs.h | 1 +
include/linux/phylink.h | 5 +
24 files changed, 1033 insertions(+), 683 deletions(-)
delete mode 100644 drivers/net/dsa/sja1105/sja1105_mdio.c
create mode 100644 drivers/net/dsa/sja1105/sja1105_mfd.c
create mode 100644 drivers/net/dsa/sja1105/sja1105_mfd.h
create mode 100644 drivers/net/mdio/mdio-regmap-simple.c
create mode 100644 drivers/net/mdio/mdio-sja1110-cbt1.c
> What OF node would remain for the DSA switch (child) device driver? The same?
> Or are you suggesting that the entire drivers/net/dsa/sja1105/ would
> move to drivers/mfd/? Or?
See bullet 1.1 above.
[...]
> > I don't recall those discussions from 3 years ago, but the Ocelot
> > platform, whatever it may be, seems to have quite a lot more
> > cross-subsystem device support requirements going on than I see here:
> >
> > drivers/i2c/busses/i2c-designware-platdrv.c
> > drivers/irqchip/irq-mscc-ocelot.c
> > drivers/mfd/ocelot-*
> > drivers/net/dsa/ocelot/*
> > drivers/net/ethernet/mscc/ocelot*
> > drivers/net/mdio/mdio-mscc-miim.c
> > drivers/phy/mscc/phy-ocelot-serdes.c
> > drivers/pinctrl/pinctrl-microchip-sgpio.c
> > drivers/pinctrl/pinctrl-ocelot.c
> > drivers/power/reset/ocelot-reset.c
> > drivers/spi/spi-dw-mmio.c
> > net/dsa/tag_ocelot_8021q.c
>
> This is a natural effect of Ocelot being "whatever it may be". It is a
> family of networking SoCs, of which VSC7514 has a MIPS CPU and Linux
> port, where the above drivers are used. The VSC7512 is then a simplified
> variant with the MIPS CPU removed, and the internal components controlled
> externally over SPI. Hence MFD to reuse the same drivers as Linux on
> MIPS (using MMIO) did. This is all that matters, not the quantity.
From what I can see, Ocelot ticks all of the boxes for MFD API usage,
whereas this submission does not. The fact that the overarching device
provides a similar function is neither here nor there.
These are the results from my searches of your device:
git grep -i SJA1110 | grep -v 'net\|arch\|include'
<no results>
[...]
> > My point is, you don't seem to have have any of that here.
>
> What do you want to see exactly which is not here?
>
> I have converted three classes of sub-devices on the NXP SJA1110 to MFD
> children in this patch set. Two MDIO buses and an Ethernet PCS for SGMII.
>
> 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
All in drivers/net.
> ACU Auxiliary Control Unit 0x711000 0x711ffc
> GPIO General Purpose Input/Output 0x712000 0x712ffc
Where are these drivers?
> I need to remind you that my purpose here is not to add drivers in
> breadth for all SJA1110 sub-devices now.
You'll see from my discussions with Colin, sub-drivers (if they are to
be used for MFD justification (point 3 above), then they must be added
as part of the first submission. Perhaps this isn't an MFD, "yet"?
[...]
> The SGMII blocks are highly reusable IPs licensed from Synopsys, and
> Linux already has DT bindings and a corresponding platform driver for
> the case where their registers are viewed using MMIO.
This is a good reason for dividing them up into subordinate platform
devices. However, it is not a good use-case of MFD. In it's current
guise, your best bet is to use the platform_* API directly.
This is a well trodden path and it not challenging:
% git grep platform_device_add -- arch drivers sound | wc -l
398
[...]
> In my opinion I do not need to add handling for any other sub-device,
> for the support to be more "cross-system" like for Ocelot. What is here
> is enough for you to decide if this is adequate for MFD or not.
Currently ... it's not.
[...]
Hopefully that helps to clarify my expectations a little.
TL;DR, this looks like a good candidate for direct platform_* usage.
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 07/15] mfd: core: add ability for cells to probe on a custom parent OF node
2025-12-16 9:18 ` Lee Jones
@ 2025-12-16 16:24 ` Vladimir Oltean
2025-12-17 9:31 ` Andrew Lunn
1 sibling, 0 replies; 54+ messages in thread
From: Vladimir Oltean @ 2025-12-16 16:24 UTC (permalink / raw)
To: Lee Jones
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
On Tue, Dec 16, 2025 at 09:18:31AM +0000, Lee Jones wrote:
> Unless you add/convert more child devices that are outside of net/ and
> drivers/net AND move the core MFD usage to drivers/mfd/, then we can't
> conclude that [ this device is suitable for MFD ].
To me, the argument that child devices can't all be under drivers/net/
is superficial. An mii_bus is very different in purpose from a phylink_pcs
and from a net_device, yet all 3 live in drivers/net/.
Furthermore, I am looking at schemas such as /devicetree/bindings/mfd/adi,max77541.yaml:
"MAX77540 is a Power Management IC with 2 buck regulators."
and I don't understand how it possibly passed this criterion. It is one
chip with two devices of the same kind, and nothing else.
If moving the core MFD usage to drivers/mfd/ is another hard requirement,
this is also attacking form rather than substance. You as the MFD
maintainer can make an appeal to authority and NACK aesthetics you don't
like, but I just want everyone to be on the same page about this.
> > > There does appear to be at least some level of misunderstanding between
> > > us. I'm not for one moment suggesting that a switch can't be an MFD. If
> > > it contains probe-able components that need to be split-up across
> > > multiple different subsystems, then by all means, move the core driver
> > > into drivers/mfd/ and register child devices 'till your heart's content.
> >
> > Are you still speaking generically here, or have you actually looked at
> > any "nxp,sja1105q" or "nxp,sja1110a" device trees to see what it would
> > mean for these compatible strings to be probed by a driver in drivers/mfd?
>
> It's not my role to go digging into existing implementations and
> previous submissions to prove whether a particular submission is
> suitable for inclusion into MFD.
>
> Please put in front of me, in a concise way (please), why you think this
> is fit for inclusion.
No new information, I think the devices are fit for MFD because of their
memory map which was shown in the previous reply.
> I've explained what is usually required, but I'll (over-)simplify
> again for clarity:
>
> - The mfd_* API call-sites must only exist in drivers/mfd/
> - Consumers usually spit out non-system specific logic into a 'core'
> - MFDs need to have more than one child
> - This is where the 'Multi' comes in
> - Children should straddle different sub-systems
> - drivers/net is not enough [0]
> - If all of your sub-devices are in 'net' use the platform_* API
> - <other stipulations less relevant to this stipulation> ...
>
> There will always be exceptions, but previous mistakes are not good
> justifications for future ones.
>
> [0]
>
> .../bindings/net/dsa/nxp,sja1105.yaml | 28 +
> .../bindings/net/pcs/snps,dw-xpcs.yaml | 8 +
> MAINTAINERS | 2 +
> drivers/mfd/mfd-core.c | 11 +-
> drivers/net/dsa/sja1105/Kconfig | 2 +
> drivers/net/dsa/sja1105/Makefile | 2 +-
> drivers/net/dsa/sja1105/sja1105.h | 42 +-
> drivers/net/dsa/sja1105/sja1105_main.c | 169 +++---
> drivers/net/dsa/sja1105/sja1105_mdio.c | 507 ------------------
> drivers/net/dsa/sja1105/sja1105_mfd.c | 293 ++++++++++
> drivers/net/dsa/sja1105/sja1105_mfd.h | 11 +
> drivers/net/dsa/sja1105/sja1105_spi.c | 113 +++-
> drivers/net/mdio/Kconfig | 21 +-
> drivers/net/mdio/Makefile | 2 +
> drivers/net/mdio/mdio-regmap-simple.c | 77 +++
> drivers/net/mdio/mdio-regmap.c | 7 +-
> drivers/net/mdio/mdio-sja1110-cbt1.c | 173 ++++++
> drivers/net/pcs/pcs-xpcs-plat.c | 146 +++--
> drivers/net/pcs/pcs-xpcs.c | 12 +
> drivers/net/phy/phylink.c | 75 ++-
> include/linux/mdio/mdio-regmap.h | 2 +
> include/linux/mfd/core.h | 7 +
> include/linux/pcs/pcs-xpcs.h | 1 +
> include/linux/phylink.h | 5 +
> 24 files changed, 1033 insertions(+), 683 deletions(-)
> delete mode 100644 drivers/net/dsa/sja1105/sja1105_mdio.c
> create mode 100644 drivers/net/dsa/sja1105/sja1105_mfd.c
> create mode 100644 drivers/net/dsa/sja1105/sja1105_mfd.h
> create mode 100644 drivers/net/mdio/mdio-regmap-simple.c
> create mode 100644 drivers/net/mdio/mdio-sja1110-cbt1.c
>
> > What OF node would remain for the DSA switch (child) device driver? The same?
> > Or are you suggesting that the entire drivers/net/dsa/sja1105/ would
> > move to drivers/mfd/? Or?
>
> See bullet 1.1 above.
>
> [...]
>
> > > I don't recall those discussions from 3 years ago, but the Ocelot
> > > platform, whatever it may be, seems to have quite a lot more
> > > cross-subsystem device support requirements going on than I see here:
> > >
> > > drivers/i2c/busses/i2c-designware-platdrv.c
> > > drivers/irqchip/irq-mscc-ocelot.c
> > > drivers/mfd/ocelot-*
> > > drivers/net/dsa/ocelot/*
> > > drivers/net/ethernet/mscc/ocelot*
> > > drivers/net/mdio/mdio-mscc-miim.c
> > > drivers/phy/mscc/phy-ocelot-serdes.c
> > > drivers/pinctrl/pinctrl-microchip-sgpio.c
> > > drivers/pinctrl/pinctrl-ocelot.c
> > > drivers/power/reset/ocelot-reset.c
> > > drivers/spi/spi-dw-mmio.c
> > > net/dsa/tag_ocelot_8021q.c
> >
> > This is a natural effect of Ocelot being "whatever it may be". It is a
> > family of networking SoCs, of which VSC7514 has a MIPS CPU and Linux
> > port, where the above drivers are used. The VSC7512 is then a simplified
> > variant with the MIPS CPU removed, and the internal components controlled
> > externally over SPI. Hence MFD to reuse the same drivers as Linux on
> > MIPS (using MMIO) did. This is all that matters, not the quantity.
>
> From what I can see, Ocelot ticks all of the boxes for MFD API usage,
> whereas this submission does not. The fact that the overarching device
> provides a similar function is neither here nor there.
>
> These are the results from my searches of your device:
>
> git grep -i SJA1110 | grep -v 'net\|arch\|include'
> <no results>
>
> [...]
>
> > > My point is, you don't seem to have have any of that here.
> >
> > What do you want to see exactly which is not here?
> >
> > I have converted three classes of sub-devices on the NXP SJA1110 to MFD
> > children in this patch set. Two MDIO buses and an Ethernet PCS for SGMII.
> >
> > 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
>
> All in drivers/net.
>
> > ACU Auxiliary Control Unit 0x711000 0x711ffc
> > GPIO General Purpose Input/Output 0x712000 0x712ffc
>
> Where are these drivers?
For the GPIO I have no driver yet.
For the ACU, there is a reusable group of 4 registers for which I wrote
a cascaded interrupt controller driver in 2022. This register group is
instantiated multiple times in the SJA1110, which justified a reusable
driver.
Upstreaming it was blocked by the inability to instantiate it from the
main DSA driver using backwards-compatible DT bindings.
In any case, on the older generation SJA1105 (common driver with SJA1110),
the GPIO and interrupt controller blocks are missing. There is an ACU
block, but it handles just pinmux and pad configuration, and the DSA
driver programs it directly rather than going through the pinmux subsystem.
This highlights a key requirement I have from the API for instantiating
sub-devices: that it is sufficiently flexible to split them out of the
main device when that starts making sense (we identify a reusable block,
or we need to configure it in the device tree, etc). Otherwise, chopping
up the switch address space upfront is a huge overhead that may have no
practical gains.
>
> > I need to remind you that my purpose here is not to add drivers in
> > breadth for all SJA1110 sub-devices now.
>
> You'll see from my discussions with Colin, sub-drivers (if they are to
> be used for MFD justification (point 3 above), then they must be added
> as part of the first submission. Perhaps this isn't an MFD, "yet"?
>
> [...]
IMHO, the concept of being or not being MFD "yet" is silly. Based on the
register map, you are, or are not.
> > The SGMII blocks are highly reusable IPs licensed from Synopsys, and
> > Linux already has DT bindings and a corresponding platform driver for
> > the case where their registers are viewed using MMIO.
>
> This is a good reason for dividing them up into subordinate platform
> devices. However, it is not a good use-case of MFD. In it's current
> guise, your best bet is to use the platform_* API directly.
>
> This is a well trodden path and it not challenging:
>
> % git grep platform_device_add -- arch drivers sound | wc -l
> 398
>
> [...]
>
> > In my opinion I do not need to add handling for any other sub-device,
> > for the support to be more "cross-system" like for Ocelot. What is here
> > is enough for you to decide if this is adequate for MFD or not.
>
> Currently ... it's not.
>
> [...]
>
> Hopefully that helps to clarify my expectations a little.
>
> TL;DR, this looks like a good candidate for direct platform_* usage.
I do have a local branch with platform devices created manually, and yet,
I considered the mfd_add_devices() form looked cleaner when submitting.
I expect the desire to split up reusable register regions into platform
sub-devices to pop up again, so the logic should be available as library
code at some level (possibly DSA).
Unless you have something against the idea, I'm thinking a good name for
this library code would be "nmfd", for "Not MFD". It is like MFD, except:
- the parent can simultaneously handle the main function of the device
while delegating other regions to sub-devices
- the sub-devices can all have drivers in the same subsystem (debatable
whether MFD follows this - just to avoid discussions)
- their OF nodes don't have to be direct children of the parent.
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 07/15] mfd: core: add ability for cells to probe on a custom parent OF node
2025-12-16 9:18 ` Lee Jones
2025-12-16 16:24 ` Vladimir Oltean
@ 2025-12-17 9:31 ` Andrew Lunn
1 sibling, 0 replies; 54+ messages in thread
From: Andrew Lunn @ 2025-12-17 9:31 UTC (permalink / raw)
To: Lee Jones
Cc: Vladimir Oltean, netdev, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
> > 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
>
> All in drivers/net.
I've not been following this conversation too much, but i would like
to point out that what you find in drivers/net is not a uniform set of
drivers, but a collection of different driver types.
SWITCH might belong on drivers/net/dsa
100BASE-T1 might belong on drivers/net/mdio
SGMIIX might belong in drivers/net/pcs
100BASE-TX might belong in drivers/net/mdio
I also expect those T1 and TX PHYs have drivers in drivers/net/phy,
but they are not memory mapped, so not on your list.
Each driver can probe independently, registering with different parts
of the net core. And then the switch driver will link all the parts
together using phandles.
Saying that all the sub drivers are in drivers/net seems an odd
argument it is not an MFD.
Andrew
^ permalink raw reply [flat|nested] 54+ messages in thread
* [PATCH net-next 08/15] net: dsa: sja1105: transition OF-based MDIO drivers to standalone
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
` (6 preceding siblings ...)
2025-11-18 19:05 ` [PATCH net-next 07/15] mfd: core: add ability for cells to probe on a custom parent OF node Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
2025-11-20 14:40 ` Lee Jones
2025-11-18 19:05 ` [PATCH net-next 09/15] net: dsa: sja1105: remove sja1105_mdio_private Vladimir Oltean
` (6 subsequent siblings)
14 siblings, 1 reply; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel,
Lee Jones
Delete the duplicated drivers for 100base-T1 and 100base-TX from the DSA
driver, and use devm_mfd_add_devices() to platform devices which probe
on the dedicated drivers from drivers/net/mdio/. This makes the switch
act as a sort of bus driver for devices in the "mdios" subnode.
We can use mfd because the switch driver interacts with the PHYs from
these MDIO buses exclusively using phylink, which follows "phy-handle"
fwnode references to them.
Cc: Lee Jones <lee@kernel.org>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
drivers/net/dsa/sja1105/Kconfig | 1 +
drivers/net/dsa/sja1105/Makefile | 1 +
drivers/net/dsa/sja1105/sja1105.h | 4 -
drivers/net/dsa/sja1105/sja1105_main.c | 13 ++
drivers/net/dsa/sja1105/sja1105_mdio.c | 270 +------------------------
drivers/net/dsa/sja1105/sja1105_mfd.c | 69 +++++++
drivers/net/dsa/sja1105/sja1105_mfd.h | 9 +
drivers/net/dsa/sja1105/sja1105_spi.c | 6 -
8 files changed, 94 insertions(+), 279 deletions(-)
create mode 100644 drivers/net/dsa/sja1105/sja1105_mfd.c
create mode 100644 drivers/net/dsa/sja1105/sja1105_mfd.h
diff --git a/drivers/net/dsa/sja1105/Kconfig b/drivers/net/dsa/sja1105/Kconfig
index 1291bba3f3b6..932bca545d69 100644
--- a/drivers/net/dsa/sja1105/Kconfig
+++ b/drivers/net/dsa/sja1105/Kconfig
@@ -7,6 +7,7 @@ tristate "NXP SJA1105 Ethernet switch family support"
select PCS_XPCS
select PACKING
select CRC32
+ select MFD_CORE
help
This is the driver for the NXP SJA1105 (5-port) and SJA1110 (10-port)
automotive Ethernet switch family. These are managed over an SPI
diff --git a/drivers/net/dsa/sja1105/Makefile b/drivers/net/dsa/sja1105/Makefile
index 40d69e6c0bae..3ac2d77dbe6c 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_mfd.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 4fd6121bd07f..ff6b69663851 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];
};
@@ -279,8 +277,6 @@ struct sja1105_private {
struct regmap *regmap;
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 622264c13fdb..6da5c655dae7 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_mfd.h"
#include "sja1105_tas.h"
#define SJA1105_UNKNOWN_MULTICAST 0x010000000000ull
@@ -3316,6 +3317,11 @@ static int sja1105_probe(struct spi_device *spi)
if (priv->max_xfer_len > max_msg - SJA1105_SIZE_SPI_MSG_HEADER)
priv->max_xfer_len = max_msg - SJA1105_SIZE_SPI_MSG_HEADER;
+ /* Explicitly advertise "no DMA" support, to suppress
+ * "DMA mask not set" warning in MFD children
+ */
+ dev->dma_mask = &dev->coherent_dma_mask;
+
priv->info = of_device_get_match_data(dev);
rc = sja1105_create_regmap(priv);
@@ -3356,6 +3362,13 @@ static int sja1105_probe(struct spi_device *spi)
return rc;
}
+ rc = sja1105_mfd_add_devices(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_mfd.c b/drivers/net/dsa/sja1105/sja1105_mfd.c
new file mode 100644
index 000000000000..9e60cd3b5d01
--- /dev/null
+++ b/drivers/net/dsa/sja1105/sja1105_mfd.c
@@ -0,0 +1,69 @@
+// SPDX-License-Identifier: GPL-2.0
+/* Copyright 2025 NXP
+ */
+#include <linux/ioport.h>
+#include <linux/mfd/core.h>
+
+#include "sja1105.h"
+#include "sja1105_mfd.h"
+
+static const struct resource sja1110_mdio_cbtx_res =
+ DEFINE_RES_REG_NAMED(0x709000, 0x1000, "mdio_cbtx");
+
+static const struct resource sja1110_mdio_cbt1_res =
+ DEFINE_RES_REG_NAMED(0x704000, 0x4000, "mdio_cbt1");
+
+static void sja1105_mfd_add_mdio_cells(struct sja1105_private *priv,
+ struct device_node *mdio_node,
+ struct mfd_cell *cells,
+ int *num_cells)
+{
+ struct device_node *np;
+
+ np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-tx-mdio");
+ if (np && of_device_is_available(np)) {
+ cells[(*num_cells)++] = (struct mfd_cell) {
+ .name = "sja1110-base-tx-mdio",
+ .of_compatible = "nxp,sja1110-base-tx-mdio",
+ .resources = &sja1110_mdio_cbtx_res,
+ .num_resources = 1,
+ .parent_of_node = mdio_node,
+ };
+ }
+ if (np)
+ of_node_put(np);
+
+ np = of_get_compatible_child(mdio_node, "nxp,sja1110-base-t1-mdio");
+ if (np && of_device_is_available(np)) {
+ cells[(*num_cells)++] = (struct mfd_cell) {
+ .name = "sja1110-base-t1-mdio",
+ .of_compatible = "nxp,sja1110-base-t1-mdio",
+ .resources = &sja1110_mdio_cbt1_res,
+ .num_resources = 1,
+ .parent_of_node = mdio_node,
+ };
+ }
+ if (np)
+ of_node_put(np);
+}
+
+int sja1105_mfd_add_devices(struct dsa_switch *ds)
+{
+ struct device_node *switch_node = dev_of_node(ds->dev);
+ struct sja1105_private *priv = ds->priv;
+ struct device_node *mdio_node;
+ struct mfd_cell cells[2] = {};
+ int num_cells = 0;
+ int rc = 0;
+
+ mdio_node = of_get_available_child_by_name(switch_node, "mdios");
+ if (mdio_node)
+ sja1105_mfd_add_mdio_cells(priv, mdio_node, cells, &num_cells);
+
+ if (num_cells > 0)
+ rc = devm_mfd_add_devices(ds->dev, PLATFORM_DEVID_AUTO, cells,
+ num_cells, NULL, 0, NULL);
+
+ of_node_put(mdio_node);
+ return rc;
+}
diff --git a/drivers/net/dsa/sja1105/sja1105_mfd.h b/drivers/net/dsa/sja1105/sja1105_mfd.h
new file mode 100644
index 000000000000..c33c8ff24e25
--- /dev/null
+++ b/drivers/net/dsa/sja1105/sja1105_mfd.h
@@ -0,0 +1,9 @@
+/* SPDX-License-Identifier: GPL-2.0 */
+/* Copyright 2025 NXP
+ */
+#ifndef _SJA1105_MFD_H
+#define _SJA1105_MFD_H
+
+int sja1105_mfd_add_devices(struct dsa_switch *ds);
+
+#endif
diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c
index cfc76af8a65b..087acded7827 100644
--- a/drivers/net/dsa/sja1105/sja1105_spi.c
+++ b/drivers/net/dsa/sja1105/sja1105_spi.c
@@ -498,8 +498,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 = {
@@ -537,8 +535,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 = {
@@ -621,8 +617,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},
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread* Re: [PATCH net-next 08/15] net: dsa: sja1105: transition OF-based MDIO drivers to standalone
2025-11-18 19:05 ` [PATCH net-next 08/15] net: dsa: sja1105: transition OF-based MDIO drivers to standalone Vladimir Oltean
@ 2025-11-20 14:40 ` Lee Jones
2025-11-20 15:14 ` Vladimir Oltean
0 siblings, 1 reply; 54+ messages in thread
From: Lee Jones @ 2025-11-20 14:40 UTC (permalink / raw)
To: Vladimir Oltean
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
On Tue, 18 Nov 2025, Vladimir Oltean wrote:
> Delete the duplicated drivers for 100base-T1 and 100base-TX from the DSA
> driver, and use devm_mfd_add_devices() to platform devices which probe
> on the dedicated drivers from drivers/net/mdio/. This makes the switch
> act as a sort of bus driver for devices in the "mdios" subnode.
>
> We can use mfd because the switch driver interacts with the PHYs from
> these MDIO buses exclusively using phylink, which follows "phy-handle"
> fwnode references to them.
>
> Cc: Lee Jones <lee@kernel.org>
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
> drivers/net/dsa/sja1105/Kconfig | 1 +
> drivers/net/dsa/sja1105/Makefile | 1 +
> drivers/net/dsa/sja1105/sja1105.h | 4 -
> drivers/net/dsa/sja1105/sja1105_main.c | 13 ++
> drivers/net/dsa/sja1105/sja1105_mdio.c | 270 +------------------------
> drivers/net/dsa/sja1105/sja1105_mfd.c | 69 +++++++
> drivers/net/dsa/sja1105/sja1105_mfd.h | 9 +
> drivers/net/dsa/sja1105/sja1105_spi.c | 6 -
> 8 files changed, 94 insertions(+), 279 deletions(-)
> create mode 100644 drivers/net/dsa/sja1105/sja1105_mfd.c
> create mode 100644 drivers/net/dsa/sja1105/sja1105_mfd.h
>
> diff --git a/drivers/net/dsa/sja1105/Kconfig b/drivers/net/dsa/sja1105/Kconfig
> index 1291bba3f3b6..932bca545d69 100644
> --- a/drivers/net/dsa/sja1105/Kconfig
> +++ b/drivers/net/dsa/sja1105/Kconfig
> @@ -7,6 +7,7 @@ tristate "NXP SJA1105 Ethernet switch family support"
> select PCS_XPCS
> select PACKING
> select CRC32
> + select MFD_CORE
> help
> This is the driver for the NXP SJA1105 (5-port) and SJA1110 (10-port)
> automotive Ethernet switch family. These are managed over an SPI
> diff --git a/drivers/net/dsa/sja1105/Makefile b/drivers/net/dsa/sja1105/Makefile
> index 40d69e6c0bae..3ac2d77dbe6c 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_mfd.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 4fd6121bd07f..ff6b69663851 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];
> };
>
> @@ -279,8 +277,6 @@ struct sja1105_private {
> struct regmap *regmap;
> 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 622264c13fdb..6da5c655dae7 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_mfd.h"
> #include "sja1105_tas.h"
>
> #define SJA1105_UNKNOWN_MULTICAST 0x010000000000ull
> @@ -3316,6 +3317,11 @@ static int sja1105_probe(struct spi_device *spi)
> if (priv->max_xfer_len > max_msg - SJA1105_SIZE_SPI_MSG_HEADER)
> priv->max_xfer_len = max_msg - SJA1105_SIZE_SPI_MSG_HEADER;
>
> + /* Explicitly advertise "no DMA" support, to suppress
> + * "DMA mask not set" warning in MFD children
> + */
> + dev->dma_mask = &dev->coherent_dma_mask;
> +
> priv->info = of_device_get_match_data(dev);
>
> rc = sja1105_create_regmap(priv);
> @@ -3356,6 +3362,13 @@ static int sja1105_probe(struct spi_device *spi)
> return rc;
> }
>
> + rc = sja1105_mfd_add_devices(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);
[...]
> diff --git a/drivers/net/dsa/sja1105/sja1105_mfd.c b/drivers/net/dsa/sja1105/sja1105_mfd.c
> new file mode 100644
> index 000000000000..9e60cd3b5d01
> --- /dev/null
> +++ b/drivers/net/dsa/sja1105/sja1105_mfd.c
> @@ -0,0 +1,69 @@
> +// SPDX-License-Identifier: GPL-2.0
> +/* Copyright 2025 NXP
> + */
> +#include <linux/ioport.h>
> +#include <linux/mfd/core.h>
The MFD API is not to be {ab}used out side of drivers/mfd.
Maybe of_platform_populate() will scratch your itch instead.
[...]
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 08/15] net: dsa: sja1105: transition OF-based MDIO drivers to standalone
2025-11-20 14:40 ` Lee Jones
@ 2025-11-20 15:14 ` Vladimir Oltean
2025-11-20 16:36 ` Lee Jones
0 siblings, 1 reply; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-20 15:14 UTC (permalink / raw)
To: Lee Jones
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
Hi Lee,
Thank you for commenting on the patch!
On Thu, Nov 20, 2025 at 02:40:46PM +0000, Lee Jones wrote:
> The MFD API is not to be {ab}used out side of drivers/mfd.
If mfd_add_devices() is not to be used outside of drivers/mfd, why
export it to the global include/linux/mfd/core.h in the first place,
rather than make the header available just to drivers/mfd?
> Maybe of_platform_populate() will scratch your itch instead.
I did already explore of_platform_populate() on this thread which asked
for advice (to which you were also copied):
https://lore.kernel.org/lkml/20221222134844.lbzyx5hz7z5n763n@skbuf/
It looks like of_platform_populate() would be an alternative option for
this task, but that doesn't live up to the task either. It will assume
that the addresses of the SoC children are in the CPU's address space
(IORESOURCE_MEM), and attempt to translate them. It simply doesn't have
the concept of IORESOURCE_REG. The MFD drivers which call
of_platform_populate() (simple-mfd-i2c.c) simply don't have unit
addresses for their children, and this is why address translation isn't
a problem for them.
I'm not trying to start an argument, but as you can see, I've been stuck
on this problem for years, and I'm between a rock and a hard place.
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 08/15] net: dsa: sja1105: transition OF-based MDIO drivers to standalone
2025-11-20 15:14 ` Vladimir Oltean
@ 2025-11-20 16:36 ` Lee Jones
2025-11-20 19:59 ` Vladimir Oltean
0 siblings, 1 reply; 54+ messages in thread
From: Lee Jones @ 2025-11-20 16:36 UTC (permalink / raw)
To: Vladimir Oltean
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
On Thu, 20 Nov 2025, Vladimir Oltean wrote:
> Hi Lee,
>
> Thank you for commenting on the patch!
>
> On Thu, Nov 20, 2025 at 02:40:46PM +0000, Lee Jones wrote:
> > The MFD API is not to be {ab}used out side of drivers/mfd.
>
> If mfd_add_devices() is not to be used outside of drivers/mfd, why
> export it to the global include/linux/mfd/core.h in the first place,
> rather than make the header available just to drivers/mfd?
That's a good question.
mfd_add_devices() has been exported since its inception nearly 20 years
ago. But it wasn't {ab}used outside of the subsystem until 2011 when it
somehow found its way into the NVEC Staging driver and then into some
IIO driver in 2015, etc. Since then other 8 instances have slipped
through the gaps without me noticing. I'd love to remove the global
export, but something would need to be done about those 10 occurrences
before hand and I just don't have the time to invest in that right now.
> > Maybe of_platform_populate() will scratch your itch instead.
>
> I did already explore of_platform_populate() on this thread which asked
> for advice (to which you were also copied):
> https://lore.kernel.org/lkml/20221222134844.lbzyx5hz7z5n763n@skbuf/
>
> It looks like of_platform_populate() would be an alternative option for
> this task, but that doesn't live up to the task either. It will assume
> that the addresses of the SoC children are in the CPU's address space
> (IORESOURCE_MEM), and attempt to translate them. It simply doesn't have
> the concept of IORESOURCE_REG. The MFD drivers which call
> of_platform_populate() (simple-mfd-i2c.c) simply don't have unit
> addresses for their children, and this is why address translation isn't
> a problem for them.
>
> I'm not trying to start an argument, but as you can see, I've been stuck
> on this problem for years, and I'm between a rock and a hard place.
I get that. Equally, I'm not trying to be suborn, but those are the
rule's I've been attempting to stick to for the last decade and a bit to
prevent (minor) chaos.
The canonical answer goes 3 ways: If you want to use the MFD API, move
the handling to drivers/mfd. If it's possible, use one of the
predetermined helpers like of_platform_populate() (and I think we
authored another one that worked around some of its issues, but I forget
where we put it!). Or if all else fails, you have to register the
device the old fashioned way with the platform_device_*() API.
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 08/15] net: dsa: sja1105: transition OF-based MDIO drivers to standalone
2025-11-20 16:36 ` Lee Jones
@ 2025-11-20 19:59 ` Vladimir Oltean
2025-11-21 12:00 ` Lee Jones
0 siblings, 1 reply; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-20 19:59 UTC (permalink / raw)
To: Lee Jones
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
On Thu, Nov 20, 2025 at 04:36:03PM +0000, Lee Jones wrote:
> The canonical answer goes 3 ways: If you want to use the MFD API, move
> the handling to drivers/mfd.
Wait, so now it's negotiable? What about "this device is not an MFD"
from the other patch? Move it to another folder and suddenly it's an MFD?
https://lore.kernel.org/netdev/20251120153622.p6sy77coa3de6srw@skbuf/
> If it's possible, use one of the predetermined helpers like
> of_platform_populate() (and I think we authored another one that
> worked around some of its issues, but I forget where we put it!).
yay...
I don't need the code necessarily, just the overall idea if you remember it.
> Or if all else fails, you have to register the device the old
> fashioned way with the platform_device_*() API.
Do you realize that by this, you are inviting me to waste time until the
next reviewer rightfully asks, why didn't you use MFD, then I'll point
them towards this discussion, but you didn't really answer?
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 08/15] net: dsa: sja1105: transition OF-based MDIO drivers to standalone
2025-11-20 19:59 ` Vladimir Oltean
@ 2025-11-21 12:00 ` Lee Jones
0 siblings, 0 replies; 54+ messages in thread
From: Lee Jones @ 2025-11-21 12:00 UTC (permalink / raw)
To: Vladimir Oltean
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel
On Thu, 20 Nov 2025, Vladimir Oltean wrote:
> On Thu, Nov 20, 2025 at 04:36:03PM +0000, Lee Jones wrote:
> > The canonical answer goes 3 ways: If you want to use the MFD API, move
> > the handling to drivers/mfd.
>
> Wait, so now it's negotiable? What about "this device is not an MFD"
> from the other patch? Move it to another folder and suddenly it's an MFD?
> https://lore.kernel.org/netdev/20251120153622.p6sy77coa3de6srw@skbuf/
The "canonical answer" is the general answer, the one that applies to
everyone, not just your use-case. I'm not (yet?) convinced that this is
an MFD, so at the moment, option one is not on the table for you.
> > If it's possible, use one of the predetermined helpers like
> > of_platform_populate() (and I think we authored another one that
> > worked around some of its issues, but I forget where we put it!).
>
> yay...
>
> I don't need the code necessarily, just the overall idea if you remember it.
It was an extension to "simple-bus". Perhaps "simple-mfd"?
Again, it might not work for you, but it's an avenue worth exploring.
> > Or if all else fails, you have to register the device the old
> > fashioned way with the platform_device_*() API.
>
> Do you realize that by this, you are inviting me to waste time until the
> next reviewer rightfully asks, why didn't you use MFD, then I'll point
> them towards this discussion, but you didn't really answer?
This is still an abuse of the MFD API. Used outside of the subsystem
for something that isn't an MFD. I like the idea of not duplicating
code, but the fact remains that this is a hack.
Another more recent avenue you may explore is the Auxiliary Bus.
--
Lee Jones [李琼斯]
^ permalink raw reply [flat|nested] 54+ messages in thread
* [PATCH net-next 09/15] net: dsa: sja1105: remove sja1105_mdio_private
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
` (7 preceding siblings ...)
2025-11-18 19:05 ` [PATCH net-next 08/15] net: dsa: sja1105: transition OF-based MDIO drivers to standalone Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
2025-11-18 19:05 ` [PATCH net-next 10/15] net: pcs: xpcs: introduce xpcs_create_pcs_fwnode() Vladimir Oltean
` (5 subsequent siblings)
14 siblings, 0 replies; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel
This structure is no longer used for anything. We can just set the
bus->priv of the PCS MDIO bus to be struct sja1105_private.
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
drivers/net/dsa/sja1105/sja1105.h | 4 ----
drivers/net/dsa/sja1105/sja1105_mdio.c | 18 ++++++------------
2 files changed, 6 insertions(+), 16 deletions(-)
diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h
index ff6b69663851..22fce143cb76 100644
--- a/drivers/net/dsa/sja1105/sja1105.h
+++ b/drivers/net/dsa/sja1105/sja1105.h
@@ -94,10 +94,6 @@ struct sja1105_regs {
u64 pcs_base[SJA1105_MAX_NUM_PORTS];
};
-struct sja1105_mdio_private {
- struct sja1105_private *priv;
-};
-
enum {
SJA1105_SPEED_AUTO,
SJA1105_SPEED_10MBPS,
diff --git a/drivers/net/dsa/sja1105/sja1105_mdio.c b/drivers/net/dsa/sja1105/sja1105_mdio.c
index b803ce71f5cc..d5577c702902 100644
--- a/drivers/net/dsa/sja1105/sja1105_mdio.c
+++ b/drivers/net/dsa/sja1105/sja1105_mdio.c
@@ -9,8 +9,7 @@
int sja1105_pcs_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;
+ struct sja1105_private *priv = bus->priv;
u64 addr;
u32 tmp;
int rc;
@@ -35,8 +34,7 @@ int sja1105_pcs_mdio_read_c45(struct mii_bus *bus, int phy, int mmd, int reg)
int sja1105_pcs_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;
+ struct sja1105_private *priv = bus->priv;
u64 addr;
u32 tmp;
@@ -51,8 +49,7 @@ int sja1105_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int mmd,
int sja1110_pcs_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;
+ struct sja1105_private *priv = bus->priv;
const struct sja1105_regs *regs = priv->info->regs;
int offset, bank;
u64 addr;
@@ -97,8 +94,7 @@ int sja1110_pcs_mdio_read_c45(struct mii_bus *bus, int phy, int mmd, int reg)
int sja1110_pcs_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;
+ struct sja1105_private *priv = bus->priv;
const struct sja1105_regs *regs = priv->info->regs;
int offset, bank;
u64 addr;
@@ -135,7 +131,6 @@ int sja1110_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int mmd, int reg,
static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
{
- struct sja1105_mdio_private *mdio_priv;
struct dsa_switch *ds = priv->ds;
struct mii_bus *bus;
int rc = 0;
@@ -144,7 +139,7 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
if (!priv->info->pcs_mdio_read_c45 || !priv->info->pcs_mdio_write_c45)
return 0;
- bus = mdiobus_alloc_size(sizeof(*mdio_priv));
+ bus = mdiobus_alloc_size(0);
if (!bus)
return -ENOMEM;
@@ -158,8 +153,7 @@ static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
* from auto probing.
*/
bus->phy_mask = ~0;
- mdio_priv = bus->priv;
- mdio_priv->priv = priv;
+ bus->priv = priv;
rc = mdiobus_register(bus);
if (rc) {
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread* [PATCH net-next 10/15] net: pcs: xpcs: introduce xpcs_create_pcs_fwnode()
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
` (8 preceding siblings ...)
2025-11-18 19:05 ` [PATCH net-next 09/15] net: dsa: sja1105: remove sja1105_mdio_private Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
2025-11-18 19:05 ` [PATCH net-next 11/15] net: pcs: xpcs-plat: convert to regmap Vladimir Oltean
` (4 subsequent siblings)
14 siblings, 0 replies; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel
Introduce a wrapper over xpcs_create_fwnode() that doesn't return the
specific dw_xpcs pointer type, but the generic phylink_pcs pointer type.
For example, the NXP SJA1105 driver might use this if it has a
pcs-handle - it is already a user of xpcs_create_pcs_mdiodev().
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
drivers/net/pcs/pcs-xpcs.c | 12 ++++++++++++
include/linux/pcs/pcs-xpcs.h | 1 +
2 files changed, 13 insertions(+)
diff --git a/drivers/net/pcs/pcs-xpcs.c b/drivers/net/pcs/pcs-xpcs.c
index 3d1bd5aac093..8f7c43a066c8 100644
--- a/drivers/net/pcs/pcs-xpcs.c
+++ b/drivers/net/pcs/pcs-xpcs.c
@@ -1591,6 +1591,18 @@ struct dw_xpcs *xpcs_create_fwnode(struct fwnode_handle *fwnode)
}
EXPORT_SYMBOL_GPL(xpcs_create_fwnode);
+struct phylink_pcs *xpcs_create_pcs_fwnode(struct fwnode_handle *fwnode)
+{
+ struct dw_xpcs *xpcs;
+
+ xpcs = xpcs_create_fwnode(fwnode);
+ if (IS_ERR(xpcs))
+ return ERR_CAST(xpcs);
+
+ return &xpcs->pcs;
+}
+EXPORT_SYMBOL_GPL(xpcs_create_pcs_fwnode);
+
void xpcs_destroy(struct dw_xpcs *xpcs)
{
if (!xpcs)
diff --git a/include/linux/pcs/pcs-xpcs.h b/include/linux/pcs/pcs-xpcs.h
index e40f554ff717..1fcbcd419ede 100644
--- a/include/linux/pcs/pcs-xpcs.h
+++ b/include/linux/pcs/pcs-xpcs.h
@@ -56,6 +56,7 @@ struct dw_xpcs *xpcs_create_fwnode(struct fwnode_handle *fwnode);
void xpcs_destroy(struct dw_xpcs *xpcs);
struct phylink_pcs *xpcs_create_pcs_mdiodev(struct mii_bus *bus, int addr);
+struct phylink_pcs *xpcs_create_pcs_fwnode(struct fwnode_handle *fwnode);
void xpcs_destroy_pcs(struct phylink_pcs *pcs);
#endif /* __LINUX_PCS_XPCS_H */
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread* [PATCH net-next 11/15] net: pcs: xpcs-plat: convert to regmap
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
` (9 preceding siblings ...)
2025-11-18 19:05 ` [PATCH net-next 10/15] net: pcs: xpcs: introduce xpcs_create_pcs_fwnode() Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
2025-11-18 19:05 ` [PATCH net-next 12/15] dt-bindings: net: dsa: sja1105: document the PCS nodes Vladimir Oltean
` (3 subsequent siblings)
14 siblings, 0 replies; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel,
Serge Semin
Generalize the MDIO buses for accessing memory-mapped XPCS devices
(through direct or indirect I/O) to also cover the case where the CSR is
behind an SPI bus. This is the case when accessing the embedded XPCS
from the NXP SJA1105/SJA1110 DSA switches.
Cc: Serge Semin <fancer.lancer@gmail.com>
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
drivers/net/pcs/pcs-xpcs-plat.c | 142 +++++++++++++++++++++-----------
1 file changed, 95 insertions(+), 47 deletions(-)
diff --git a/drivers/net/pcs/pcs-xpcs-plat.c b/drivers/net/pcs/pcs-xpcs-plat.c
index c422e8d8b89f..ea6482aa8431 100644
--- a/drivers/net/pcs/pcs-xpcs-plat.c
+++ b/drivers/net/pcs/pcs-xpcs-plat.c
@@ -17,6 +17,7 @@
#include <linux/platform_device.h>
#include <linux/pm_runtime.h>
#include <linux/property.h>
+#include <linux/regmap.h>
#include <linux/sizes.h>
#include "pcs-xpcs.h"
@@ -29,7 +30,8 @@ struct dw_xpcs_plat {
struct mii_bus *bus;
bool reg_indir;
int reg_width;
- void __iomem *reg_base;
+ unsigned int base;
+ struct regmap *regmap;
struct clk *cclk;
};
@@ -52,7 +54,9 @@ static int xpcs_mmio_read_reg_indirect(struct dw_xpcs_plat *pxpcs,
int dev, int reg)
{
ptrdiff_t csr, ofs;
+ unsigned int addr;
u16 page;
+ u32 val;
int ret;
csr = xpcs_mmio_addr_format(dev, reg);
@@ -63,19 +67,21 @@ static int xpcs_mmio_read_reg_indirect(struct dw_xpcs_plat *pxpcs,
if (ret)
return ret;
- switch (pxpcs->reg_width) {
- case 4:
- writel(page, pxpcs->reg_base + (DW_VR_CSR_VIEWPORT << 2));
- ret = readl(pxpcs->reg_base + (ofs << 2)) & 0xffff;
- break;
- default:
- writew(page, pxpcs->reg_base + (DW_VR_CSR_VIEWPORT << 1));
- ret = readw(pxpcs->reg_base + (ofs << 1));
- break;
- }
+ addr = pxpcs->base + (DW_VR_CSR_VIEWPORT * pxpcs->reg_width);
+ ret = regmap_write(pxpcs->regmap, addr, page);
+ if (ret)
+ goto err_put;
+
+ addr = pxpcs->base + (ofs * pxpcs->reg_width);
+ ret = regmap_read(pxpcs->regmap, addr, &val);
+ if (ret)
+ goto err_put;
pm_runtime_put(&pxpcs->pdev->dev);
+ return val & 0xffff;
+err_put:
+ pm_runtime_put(&pxpcs->pdev->dev);
return ret;
}
@@ -83,6 +89,7 @@ static int xpcs_mmio_write_reg_indirect(struct dw_xpcs_plat *pxpcs,
int dev, int reg, u16 val)
{
ptrdiff_t csr, ofs;
+ unsigned int addr;
u16 page;
int ret;
@@ -94,26 +101,25 @@ static int xpcs_mmio_write_reg_indirect(struct dw_xpcs_plat *pxpcs,
if (ret)
return ret;
- switch (pxpcs->reg_width) {
- case 4:
- writel(page, pxpcs->reg_base + (DW_VR_CSR_VIEWPORT << 2));
- writel(val, pxpcs->reg_base + (ofs << 2));
- break;
- default:
- writew(page, pxpcs->reg_base + (DW_VR_CSR_VIEWPORT << 1));
- writew(val, pxpcs->reg_base + (ofs << 1));
- break;
- }
+ addr = pxpcs->base + (DW_VR_CSR_VIEWPORT * pxpcs->reg_width);
+ ret = regmap_write(pxpcs->regmap, addr, page);
+ if (ret)
+ goto err_put;
- pm_runtime_put(&pxpcs->pdev->dev);
+ addr = pxpcs->base + (ofs * pxpcs->reg_width);
+ ret = regmap_write(pxpcs->regmap, addr, val);
- return 0;
+err_put:
+ pm_runtime_put(&pxpcs->pdev->dev);
+ return ret;
}
static int xpcs_mmio_read_reg_direct(struct dw_xpcs_plat *pxpcs,
int dev, int reg)
{
+ unsigned int addr;
ptrdiff_t csr;
+ u32 val;
int ret;
csr = xpcs_mmio_addr_format(dev, reg);
@@ -122,23 +128,23 @@ static int xpcs_mmio_read_reg_direct(struct dw_xpcs_plat *pxpcs,
if (ret)
return ret;
- switch (pxpcs->reg_width) {
- case 4:
- ret = readl(pxpcs->reg_base + (csr << 2)) & 0xffff;
- break;
- default:
- ret = readw(pxpcs->reg_base + (csr << 1));
- break;
- }
+ addr = pxpcs->base + (csr * pxpcs->reg_width);
+ ret = regmap_read(pxpcs->regmap, addr, &val);
+ if (ret)
+ goto err_put;
pm_runtime_put(&pxpcs->pdev->dev);
+ return val & 0xffff;
+err_put:
+ pm_runtime_put(&pxpcs->pdev->dev);
return ret;
}
static int xpcs_mmio_write_reg_direct(struct dw_xpcs_plat *pxpcs,
int dev, int reg, u16 val)
{
+ unsigned int addr;
ptrdiff_t csr;
int ret;
@@ -148,18 +154,11 @@ static int xpcs_mmio_write_reg_direct(struct dw_xpcs_plat *pxpcs,
if (ret)
return ret;
- switch (pxpcs->reg_width) {
- case 4:
- writel(val, pxpcs->reg_base + (csr << 2));
- break;
- default:
- writew(val, pxpcs->reg_base + (csr << 1));
- break;
- }
+ addr = pxpcs->base + (csr * pxpcs->reg_width);
+ ret = regmap_write(pxpcs->regmap, addr, val);
pm_runtime_put(&pxpcs->pdev->dev);
-
- return 0;
+ return ret;
}
static int xpcs_mmio_read_c22(struct mii_bus *bus, int addr, int reg)
@@ -230,11 +229,48 @@ static struct dw_xpcs_plat *xpcs_plat_create_data(struct platform_device *pdev)
return pxpcs;
}
+static struct regmap *xpcs_plat_create_regmap(struct dw_xpcs_plat *pxpcs,
+ const struct resource *res)
+{
+ struct platform_device *pdev = pxpcs->pdev;
+ struct regmap_config config = {};
+ struct device *dev = &pdev->dev;
+ void __iomem *reg_base;
+
+ reg_base = devm_ioremap_resource(dev, res);
+ if (IS_ERR(reg_base)) {
+ dev_err(dev, "Failed to map reg-space\n");
+ return ERR_CAST(reg_base);
+ }
+
+ if (pxpcs->reg_width == 2) {
+ config.reg_bits = 16;
+ config.val_bits = 16;
+ config.reg_stride = 2;
+ } else {
+ config.reg_bits = 32;
+ config.val_bits = 32;
+ config.reg_stride = 4;
+ }
+
+ if (pxpcs->reg_indir)
+ config.max_register = 0xff * pxpcs->reg_width;
+ else
+ config.max_register = 0x1fffff * pxpcs->reg_width;
+
+ config.reg_format_endian = REGMAP_ENDIAN_NATIVE;
+ config.val_format_endian = REGMAP_ENDIAN_NATIVE;
+
+ return devm_regmap_init_mmio(dev, reg_base, &config);
+}
+
static int xpcs_plat_init_res(struct dw_xpcs_plat *pxpcs)
{
struct platform_device *pdev = pxpcs->pdev;
struct device *dev = &pdev->dev;
+ bool have_reg_resource = false;
resource_size_t spc_size;
+ struct regmap *regmap;
struct resource *res;
if (!device_property_read_u32(dev, "reg-io-width", &pxpcs->reg_width)) {
@@ -246,8 +282,14 @@ static int xpcs_plat_init_res(struct dw_xpcs_plat *pxpcs)
pxpcs->reg_width = 2;
}
- res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "direct") ?:
- platform_get_resource_byname(pdev, IORESOURCE_MEM, "indirect");
+ res = platform_get_resource_byname(pdev, IORESOURCE_REG, "direct") ?:
+ platform_get_resource_byname(pdev, IORESOURCE_REG, "indirect");
+ if (res) {
+ have_reg_resource = true;
+ } else {
+ res = platform_get_resource_byname(pdev, IORESOURCE_MEM, "direct") ?:
+ platform_get_resource_byname(pdev, IORESOURCE_MEM, "indirect");
+ }
if (!res) {
dev_err(dev, "No reg-space found\n");
return -EINVAL;
@@ -266,10 +308,16 @@ static int xpcs_plat_init_res(struct dw_xpcs_plat *pxpcs)
return -EINVAL;
}
- pxpcs->reg_base = devm_ioremap_resource(dev, res);
- if (IS_ERR(pxpcs->reg_base)) {
- dev_err(dev, "Failed to map reg-space\n");
- return PTR_ERR(pxpcs->reg_base);
+ if (have_reg_resource) {
+ regmap = dev_get_regmap(dev->parent, NULL);
+ pxpcs->base = res->start;
+ } else {
+ regmap = xpcs_plat_create_regmap(pxpcs, res);
+ }
+ pxpcs->regmap = regmap;
+ if (!pxpcs->regmap) {
+ dev_err(dev, "No regmap available\n");
+ return -ENODEV;
}
return 0;
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread* [PATCH net-next 12/15] dt-bindings: net: dsa: sja1105: document the PCS nodes
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
` (10 preceding siblings ...)
2025-11-18 19:05 ` [PATCH net-next 11/15] net: pcs: xpcs-plat: convert to regmap Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
2025-11-20 17:30 ` Rob Herring
2025-11-18 19:05 ` [PATCH net-next 13/15] net: pcs: xpcs-plat: add NXP SJA1105/SJA1110 support Vladimir Oltean
` (2 subsequent siblings)
14 siblings, 1 reply; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree
The XPCS blocks in NXP SJA1105 and SJA1110 may be described in the
device tree, and they follow the same bindings as the other instances
which are memory-mapped using an APB3 or MCI interface.
Document their compatible string, positioning in the switch's "regs"
subnode, and the pcs-handle to them.
The "type: object" addition in the ethernet-port node is to suppress
a dt_binding_check warning that states "node schemas must have a type
or $ref". This is fine, but I don't completely understand why it started
being required just now (apparently, the presence of "properties" under
the port node affects this).
Cc: Rob Herring <robh@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
.../bindings/net/dsa/nxp,sja1105.yaml | 28 +++++++++++++++++++
.../bindings/net/pcs/snps,dw-xpcs.yaml | 8 ++++++
2 files changed, 36 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml b/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml
index 607b7fe8d28e..ee1a95d6b032 100644
--- a/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml
+++ b/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml
@@ -85,11 +85,31 @@ properties:
- compatible
- reg
+ regs:
+ type: object
+ description:
+ Optional container node for peripherals in the switch address space other
+ than the switching IP itself. This node and its children only need to be
+ described if board-specific properties need to be specified, like SerDes
+ lane polarity inversion. If absent, default descriptions are used.
+ additionalProperties: false
+
+ properties:
+ '#address-cells':
+ const: 1
+ '#size-cells':
+ const: 1
+
+ patternProperties:
+ "^ethernet-pcs@[0-9a-f]+$":
+ $ref: /schemas/net/pcs/snps,dw-xpcs.yaml#
+
patternProperties:
"^(ethernet-)?ports$":
additionalProperties: true
patternProperties:
"^(ethernet-)?port@[0-9]$":
+ type: object
allOf:
- if:
properties:
@@ -107,6 +127,14 @@ patternProperties:
tx-internal-delay-ps:
$ref: "#/$defs/internal-delay-ps"
+ properties:
+ pcs-handle:
+ $ref: /schemas/types.yaml#/definitions/phandle
+ description:
+ Phandle to a PCS device node from the "regs" container.
+ Can be skipped if the PCS description is missing - in that case,
+ the connection is implicit.
+
required:
- compatible
- reg
diff --git a/Documentation/devicetree/bindings/net/pcs/snps,dw-xpcs.yaml b/Documentation/devicetree/bindings/net/pcs/snps,dw-xpcs.yaml
index e77eec9ac9ee..46e4f611f714 100644
--- a/Documentation/devicetree/bindings/net/pcs/snps,dw-xpcs.yaml
+++ b/Documentation/devicetree/bindings/net/pcs/snps,dw-xpcs.yaml
@@ -25,6 +25,14 @@ description:
properties:
compatible:
oneOf:
+ - description:
+ Synopsys DesignWare XPCS in NXP SJA1105 switch (direct APB3 access
+ via SPI) with custom PMA
+ const: nxp,sja1105-pcs
+ - description:
+ Synopsys DesignWare XPCS in NXP SJA1110 switch (indirect APB3 access
+ via SPI) with custom PMA
+ const: nxp,sja1110-pcs
- description: Synopsys DesignWare XPCS with none or unknown PMA
const: snps,dw-xpcs
- description: Synopsys DesignWare XPCS with Consumer Gen1 3G PMA
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread* Re: [PATCH net-next 12/15] dt-bindings: net: dsa: sja1105: document the PCS nodes
2025-11-18 19:05 ` [PATCH net-next 12/15] dt-bindings: net: dsa: sja1105: document the PCS nodes Vladimir Oltean
@ 2025-11-20 17:30 ` Rob Herring
0 siblings, 0 replies; 54+ messages in thread
From: Rob Herring @ 2025-11-20 17:30 UTC (permalink / raw)
To: Vladimir Oltean
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel, Krzysztof Kozlowski, Conor Dooley, devicetree
On Tue, Nov 18, 2025 at 09:05:27PM +0200, Vladimir Oltean wrote:
> The XPCS blocks in NXP SJA1105 and SJA1110 may be described in the
> device tree, and they follow the same bindings as the other instances
> which are memory-mapped using an APB3 or MCI interface.
>
> Document their compatible string, positioning in the switch's "regs"
> subnode, and the pcs-handle to them.
>
> The "type: object" addition in the ethernet-port node is to suppress
> a dt_binding_check warning that states "node schemas must have a type
> or $ref". This is fine, but I don't completely understand why it started
> being required just now (apparently, the presence of "properties" under
> the port node affects this).
Yes. It's related to quirks in how json-schema works. You would think
'properties' would require the instance to be an object, but no, such a
schema defining properties would pass even for a boolean property. So
requiring 'type: object' is necessary. In this case, we already do that
elsewhere so it's not strictly needed here, but figuring that out is
complicated.
> Cc: Rob Herring <robh@kernel.org>
> Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
> Cc: Conor Dooley <conor+dt@kernel.org>
> Cc: devicetree@vger.kernel.org
> Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
> ---
> .../bindings/net/dsa/nxp,sja1105.yaml | 28 +++++++++++++++++++
> .../bindings/net/pcs/snps,dw-xpcs.yaml | 8 ++++++
> 2 files changed, 36 insertions(+)
>
> diff --git a/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml b/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml
> index 607b7fe8d28e..ee1a95d6b032 100644
> --- a/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml
> +++ b/Documentation/devicetree/bindings/net/dsa/nxp,sja1105.yaml
> @@ -85,11 +85,31 @@ properties:
> - compatible
> - reg
>
> + regs:
> + type: object
> + description:
> + Optional container node for peripherals in the switch address space other
> + than the switching IP itself. This node and its children only need to be
> + described if board-specific properties need to be specified, like SerDes
> + lane polarity inversion. If absent, default descriptions are used.
> + additionalProperties: false
> +
> + properties:
> + '#address-cells':
> + const: 1
> + '#size-cells':
> + const: 1
> +
> + patternProperties:
> + "^ethernet-pcs@[0-9a-f]+$":
> + $ref: /schemas/net/pcs/snps,dw-xpcs.yaml#
> +
> patternProperties:
> "^(ethernet-)?ports$":
> additionalProperties: true
> patternProperties:
> "^(ethernet-)?port@[0-9]$":
> + type: object
> allOf:
> - if:
> properties:
> @@ -107,6 +127,14 @@ patternProperties:
> tx-internal-delay-ps:
> $ref: "#/$defs/internal-delay-ps"
>
> + properties:
> + pcs-handle:
> + $ref: /schemas/types.yaml#/definitions/phandle
This already has a type, so drop the $ref.
> + description:
> + Phandle to a PCS device node from the "regs" container.
> + Can be skipped if the PCS description is missing - in that case,
> + the connection is implicit.
> +
> required:
> - compatible
> - reg
> diff --git a/Documentation/devicetree/bindings/net/pcs/snps,dw-xpcs.yaml b/Documentation/devicetree/bindings/net/pcs/snps,dw-xpcs.yaml
> index e77eec9ac9ee..46e4f611f714 100644
> --- a/Documentation/devicetree/bindings/net/pcs/snps,dw-xpcs.yaml
> +++ b/Documentation/devicetree/bindings/net/pcs/snps,dw-xpcs.yaml
> @@ -25,6 +25,14 @@ description:
> properties:
> compatible:
> oneOf:
> + - description:
> + Synopsys DesignWare XPCS in NXP SJA1105 switch (direct APB3 access
> + via SPI) with custom PMA
> + const: nxp,sja1105-pcs
> + - description:
> + Synopsys DesignWare XPCS in NXP SJA1110 switch (indirect APB3 access
> + via SPI) with custom PMA
> + const: nxp,sja1110-pcs
> - description: Synopsys DesignWare XPCS with none or unknown PMA
> const: snps,dw-xpcs
> - description: Synopsys DesignWare XPCS with Consumer Gen1 3G PMA
> --
> 2.34.1
>
^ permalink raw reply [flat|nested] 54+ messages in thread
* [PATCH net-next 13/15] net: pcs: xpcs-plat: add NXP SJA1105/SJA1110 support
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
` (11 preceding siblings ...)
2025-11-18 19:05 ` [PATCH net-next 12/15] dt-bindings: net: dsa: sja1105: document the PCS nodes Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
2025-11-18 19:05 ` [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver Vladimir Oltean
2025-11-18 19:05 ` [PATCH net-next 15/15] net: dsa: sja1105: permit finding the XPCS via pcs-handle Vladimir Oltean
14 siblings, 0 replies; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel,
Serge Semin, Rob Herring, Krzysztof Kozlowski, Conor Dooley,
devicetree
The XPCS in these NXP switches returns 0 when reading the ID registers,
and is integrated with a custom PMA.
The current way to support it is with hijacked PHYID register reads
in sja1105_pcs_mdio_read_c45(), to fake that it returns
NXP_SJA1105_XPCS_ID.
The new way to support it is with a specific compatible string. This
makes the platform XPCS driver use a specific struct dw_xpcs_info which
it assigns to mdiodev->dev.platform_data, and from there, xpcs_init_id()
picks it up and uses it. Later, xpcs_identify() doesn't overwrite the
xpcs->info.pcs and xpcs->info.pma unless they are set to
DW_XPCS_ID_NATIVE and DW_XPCS_PMA_ID_NATIVE, aka zeroes.
Since what is custom is the PMA and not the PCS, a later patch will
probably have to move the NXP constants around. But that should be done
only after this becomes strictly XPCS internal business.
Cc: Serge Semin <fancer.lancer@gmail.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
drivers/net/pcs/pcs-xpcs-plat.c | 4 ++++
1 file changed, 4 insertions(+)
diff --git a/drivers/net/pcs/pcs-xpcs-plat.c b/drivers/net/pcs/pcs-xpcs-plat.c
index ea6482aa8431..f96eaafb6376 100644
--- a/drivers/net/pcs/pcs-xpcs-plat.c
+++ b/drivers/net/pcs/pcs-xpcs-plat.c
@@ -479,6 +479,8 @@ DW_XPCS_INFO_DECLARE(xpcs_pma_gen4_3g, DW_XPCS_ID_NATIVE, DW_XPCS_PMA_GEN4_3G_ID
DW_XPCS_INFO_DECLARE(xpcs_pma_gen4_6g, DW_XPCS_ID_NATIVE, DW_XPCS_PMA_GEN4_6G_ID);
DW_XPCS_INFO_DECLARE(xpcs_pma_gen5_10g, DW_XPCS_ID_NATIVE, DW_XPCS_PMA_GEN5_10G_ID);
DW_XPCS_INFO_DECLARE(xpcs_pma_gen5_12g, DW_XPCS_ID_NATIVE, DW_XPCS_PMA_GEN5_12G_ID);
+DW_XPCS_INFO_DECLARE(xpcs_sja1105, NXP_SJA1105_XPCS_ID, DW_XPCS_PMA_ID_NATIVE);
+DW_XPCS_INFO_DECLARE(xpcs_sja1110, NXP_SJA1110_XPCS_ID, DW_XPCS_PMA_ID_NATIVE);
static const struct of_device_id xpcs_of_ids[] = {
{ .compatible = "snps,dw-xpcs", .data = &xpcs_generic },
@@ -489,6 +491,8 @@ static const struct of_device_id xpcs_of_ids[] = {
{ .compatible = "snps,dw-xpcs-gen4-6g", .data = &xpcs_pma_gen4_6g },
{ .compatible = "snps,dw-xpcs-gen5-10g", .data = &xpcs_pma_gen5_10g },
{ .compatible = "snps,dw-xpcs-gen5-12g", .data = &xpcs_pma_gen5_12g },
+ { .compatible = "nxp,sja1105-pcs", .data = &xpcs_sja1105 },
+ { .compatible = "nxp,sja1110-pcs", .data = &xpcs_sja1110 },
{ /* sentinel */ },
};
MODULE_DEVICE_TABLE(of, xpcs_of_ids);
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread* [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
` (12 preceding siblings ...)
2025-11-18 19:05 ` [PATCH net-next 13/15] net: pcs: xpcs-plat: add NXP SJA1105/SJA1110 support Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
2025-11-19 0:41 ` Jakub Kicinski
` (3 more replies)
2025-11-18 19:05 ` [PATCH net-next 15/15] net: dsa: sja1105: permit finding the XPCS via pcs-handle Vladimir Oltean
14 siblings, 4 replies; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel,
Serge Semin, Andy Shevchenko, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
The code in sja1105_mdio.c does the same thing as the one added by Serge
Semin in drivers/net/pcs/pcs-xpcs-plat.c (implements a virtual MDIO bus,
backed by either a direct or an indirect register access method), except
the latter is generic after the conversion to regmap.
Except for just one problem: pcs-xpcs-plat.c expects to probe on a
device tree node, and the SJA1105 and SJA1110 doesn't describe its XPCS
on the SGMII ports in the device tree.
This is both a problem and a design intention. I've long held the view
that for SPI devices which don't have a common .dtsi but whose bindings
have to be written many times by many people for many boards, less is
more, and all the details like internal subdevices can probably stay
hidden even if those devices are being configured by the kernel.
I've also held the view that DSA should delegate its responsibility for
configuring non-essential subdevices to other drivers in their
respective subsystems, and that the switching IP core (the one with the
DSA driver) should merely be one of the MFD children of a MFD parent
that is in charge of the spi_device.
This would mean something like the "mscc,vsc7512" example from
Documentation/devicetree/bindings/mfd/mscc,ocelot.yaml, but:
- retrofitting that model onto the SJA1105 bindings (and any other
switch on a non-MMIO bus, where the ethernet-switch node coincides
with the SPI/I2C bus device node) is a huge pain for backwards and
especially forward compatibility, as it implies that the switch can be
either a spi_device or a platform_device after the conversion
- if it sounds like it is conflicting with the first requirement of
"less is more", yes it is
I've tried various ways of using the xpcs-plat driver while
avoiding major DT bindings changes for this switch, like
fwnode_create_software_node() and custom platform data.
Platform data was ugly and software nodes didn't work at all, for
reasons explained here:
https://lore.kernel.org/lkml/20230223203713.hcse3mkbq3m6sogb@skbuf/
I have to give huge credits to Andy Shevchenko, who after more than one
year remembered the discussion and referenced Hervé Codina's work on PCI
DT overlays, as well as a presentation from Lizhi Hou and Rob Herring.
I think I found the compromise solution that allows me to make progress,
which is to create a dynamic OF changeset that attaches the PCS node to
the live device tree, if it wasn't described already in the DTS, or use
the one from the DTS if it's already there. With a proper OF node, the
xpcs-plat driver probes just fine.
As for where to attach the XPCS node? Memory-mapped devices (in the
SPI address space, mind you) don't naturally sit well in the
"ethernet-switch" node, because that has #address-cells = <0>
and #size-cells = <0>.
We can't modify #address-cells and #size-cells, because "ethernet-switch"
has a reg-less "ethernet-ports" child node as per dsa.yaml, and the PCS
would sit on the same hierarchical level as that. Essentially this is
another angle of the argument that the DSA OF node shouldn't coincide
with the SPI bus device node, as this implies it is in control of the
entire address space.
The compromise, retrofit-ready solution here is to create a "regs"
container node which is a child of the ethernet-switch and
has #address-cells = <1> and #size-cells = <1>, then attach the XPCS to
that.
There also exists a use case where the XPCS is manually described
in the device tree, and that is when we need to describe SGMII lane
polarity inversion (not yet supported, TBD). In that case,
sja1105_fill_device_tree() simply backs off for the already present PCS
nodes, and sja1105_mfd_add_pcs_cells() works all the same.
A small implementation note in sja1105_create_pcs():
xpcs_create_fwnode() is NULL-tolerant via fwnode_device_is_available(),
so we don't need to explicitly handle the case where
priv->pcs_fwnode[port] wasn't assigned by sja1105_create_pcs_nodes()
(because the OF node exists in the DTS). This case currently returns
-ENODEV and will be handled by the next change.
Cc: Serge Semin <fancer.lancer@gmail.com>
Cc: Andy Shevchenko <andriy.shevchenko@linux.intel.com>
Cc: Herve Codina <herve.codina@bootlin.com>
Cc: Rob Herring <robh@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
drivers/net/dsa/sja1105/Kconfig | 1 +
drivers/net/dsa/sja1105/Makefile | 1 -
drivers/net/dsa/sja1105/sja1105.h | 29 ++-
drivers/net/dsa/sja1105/sja1105_main.c | 82 +++++++--
drivers/net/dsa/sja1105/sja1105_mdio.c | 233 -------------------------
drivers/net/dsa/sja1105/sja1105_mfd.c | 228 +++++++++++++++++++++++-
drivers/net/dsa/sja1105/sja1105_mfd.h | 2 +
drivers/net/dsa/sja1105/sja1105_spi.c | 49 ++++--
8 files changed, 342 insertions(+), 283 deletions(-)
delete mode 100644 drivers/net/dsa/sja1105/sja1105_mdio.c
diff --git a/drivers/net/dsa/sja1105/Kconfig b/drivers/net/dsa/sja1105/Kconfig
index 932bca545d69..eef06e419559 100644
--- a/drivers/net/dsa/sja1105/Kconfig
+++ b/drivers/net/dsa/sja1105/Kconfig
@@ -8,6 +8,7 @@ tristate "NXP SJA1105 Ethernet switch family support"
select PACKING
select CRC32
select MFD_CORE
+ select OF_DYNAMIC
help
This is the driver for the NXP SJA1105 (5-port) and SJA1110 (10-port)
automotive Ethernet switch family. These are managed over an SPI
diff --git a/drivers/net/dsa/sja1105/Makefile b/drivers/net/dsa/sja1105/Makefile
index 3ac2d77dbe6c..94907116c1cc 100644
--- a/drivers/net/dsa/sja1105/Makefile
+++ b/drivers/net/dsa/sja1105/Makefile
@@ -4,7 +4,6 @@ obj-$(CONFIG_NET_DSA_SJA1105) += sja1105.o
sja1105-objs := \
sja1105_spi.o \
sja1105_main.o \
- sja1105_mdio.o \
sja1105_mfd.o \
sja1105_flower.o \
sja1105_ethtool.o \
diff --git a/drivers/net/dsa/sja1105/sja1105.h b/drivers/net/dsa/sja1105/sja1105.h
index 22fce143cb76..96954f1f5bcf 100644
--- a/drivers/net/dsa/sja1105/sja1105.h
+++ b/drivers/net/dsa/sja1105/sja1105.h
@@ -44,6 +44,8 @@
#define SJA1105_RGMII_DELAY_MAX_PS \
SJA1105_RGMII_DELAY_PHASE_TO_PS(1017)
+#define SJA1105_SGMII_PORT 4
+
typedef enum {
SPI_READ = 0,
SPI_WRITE = 1,
@@ -91,7 +93,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 pcs_base[SJA1105_MAX_NUM_PORTS];
};
enum {
@@ -109,6 +110,13 @@ enum sja1105_internal_phy_t {
SJA1105_PHY_BASE_T1,
};
+struct sja1105_pcs_resource {
+ struct resource res;
+ int port;
+ const char *cell_name;
+ const char *compatible;
+};
+
struct sja1105_info {
u64 device_id;
/* Needed for distinction between P and R, and between Q and S
@@ -148,10 +156,6 @@ struct sja1105_info {
bool (*rxtstamp)(struct dsa_switch *ds, int port, struct sk_buff *skb);
void (*txtstamp)(struct dsa_switch *ds, int port, struct sk_buff *skb);
int (*clocking_setup)(struct sja1105_private *priv);
- int (*pcs_mdio_read_c45)(struct mii_bus *bus, int phy, int mmd,
- int reg);
- int (*pcs_mdio_write_c45)(struct mii_bus *bus, int phy, int mmd,
- int reg, u16 val);
int (*disable_microcontroller)(struct sja1105_private *priv);
const char *name;
bool supports_mii[SJA1105_MAX_NUM_PORTS];
@@ -161,6 +165,8 @@ struct sja1105_info {
bool supports_2500basex[SJA1105_MAX_NUM_PORTS];
enum sja1105_internal_phy_t internal_phy[SJA1105_MAX_NUM_PORTS];
const u64 port_speed[SJA1105_SPEED_MAX];
+ const struct sja1105_pcs_resource *pcs_resources;
+ size_t num_pcs_resources;
};
enum sja1105_key_type {
@@ -273,8 +279,9 @@ struct sja1105_private {
struct regmap *regmap;
struct devlink_region **regions;
struct sja1105_cbs_entry *cbs;
- struct mii_bus *mdio_pcs;
struct phylink_pcs *pcs[SJA1105_MAX_NUM_PORTS];
+ struct fwnode_handle *pcs_fwnode[SJA1105_MAX_NUM_PORTS];
+ struct of_changeset of_cs;
struct sja1105_ptp_data ptp_data;
struct sja1105_tas_data tas_data;
};
@@ -302,16 +309,6 @@ int sja1105_vlan_filtering(struct dsa_switch *ds, int port, bool enabled,
struct netlink_ext_ack *extack);
void sja1105_frame_memory_partitioning(struct sja1105_private *priv);
-/* From sja1105_mdio.c */
-int sja1105_mdiobus_register(struct dsa_switch *ds);
-void sja1105_mdiobus_unregister(struct dsa_switch *ds);
-int sja1105_pcs_mdio_read_c45(struct mii_bus *bus, int phy, int mmd, int reg);
-int sja1105_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int mmd, int reg,
- u16 val);
-int sja1110_pcs_mdio_read_c45(struct mii_bus *bus, int phy, int mmd, int reg);
-int sja1110_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int mmd, int reg,
- u16 val);
-
/* From sja1105_devlink.c */
int sja1105_devlink_setup(struct dsa_switch *ds);
void sja1105_devlink_teardown(struct dsa_switch *ds);
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 6da5c655dae7..70aecdf9fd0e 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -15,6 +15,7 @@
#include <linux/of.h>
#include <linux/of_net.h>
#include <linux/of_mdio.h>
+#include <linux/pcs/pcs-xpcs.h>
#include <linux/netdev_features.h>
#include <linux/netdevice.h>
#include <linux/if_bridge.h>
@@ -3032,6 +3033,44 @@ static int sja1105_port_bridge_flags(struct dsa_switch *ds, int port,
return 0;
}
+static int sja1105_create_pcs(struct dsa_switch *ds, int port)
+{
+ struct sja1105_private *priv = ds->priv;
+ struct phylink_pcs *pcs;
+
+ if (priv->phy_mode[port] != PHY_INTERFACE_MODE_SGMII &&
+ priv->phy_mode[port] != PHY_INTERFACE_MODE_2500BASEX)
+ return 0;
+
+ pcs = xpcs_create_pcs_fwnode(priv->pcs_fwnode[port]);
+ if (IS_ERR(pcs))
+ return PTR_ERR(pcs);
+
+ priv->pcs[port] = pcs;
+
+ return 0;
+}
+
+static void sja1105_destroy_pcs(struct dsa_switch *ds, int port)
+{
+ struct sja1105_private *priv = ds->priv;
+
+ if (priv->pcs[port]) {
+ xpcs_destroy_pcs(priv->pcs[port]);
+ priv->pcs[port] = NULL;
+ }
+}
+
+static int sja1105_port_setup(struct dsa_switch *ds, int port)
+{
+ return sja1105_create_pcs(ds, port);
+}
+
+static void sja1105_port_teardown(struct dsa_switch *ds, int port)
+{
+ sja1105_destroy_pcs(ds, port);
+}
+
/* The programming model for the SJA1105 switch is "all-at-once" via static
* configuration tables. Some of these can be dynamically modified at runtime,
* but not the xMII mode parameters table.
@@ -3086,16 +3125,9 @@ static int sja1105_setup(struct dsa_switch *ds)
goto out_flower_teardown;
}
- rc = sja1105_mdiobus_register(ds);
- if (rc < 0) {
- dev_err(ds->dev, "Failed to register MDIO bus: %pe\n",
- ERR_PTR(rc));
- goto out_ptp_clock_unregister;
- }
-
rc = sja1105_devlink_setup(ds);
if (rc < 0)
- goto out_mdiobus_unregister;
+ goto out_ptp_clock_unregister;
rtnl_lock();
rc = dsa_tag_8021q_register(ds, htons(ETH_P_8021Q));
@@ -3125,8 +3157,6 @@ static int sja1105_setup(struct dsa_switch *ds)
out_devlink_teardown:
sja1105_devlink_teardown(ds);
-out_mdiobus_unregister:
- sja1105_mdiobus_unregister(ds);
out_ptp_clock_unregister:
sja1105_ptp_clock_unregister(ds);
out_flower_teardown:
@@ -3147,7 +3177,6 @@ static void sja1105_teardown(struct dsa_switch *ds)
rtnl_unlock();
sja1105_devlink_teardown(ds);
- sja1105_mdiobus_unregister(ds);
sja1105_ptp_clock_unregister(ds);
sja1105_flower_teardown(ds);
sja1105_tas_teardown(ds);
@@ -3166,6 +3195,8 @@ static const struct dsa_switch_ops sja1105_switch_ops = {
.connect_tag_protocol = sja1105_connect_tag_protocol,
.setup = sja1105_setup,
.teardown = sja1105_teardown,
+ .port_setup = sja1105_port_setup,
+ .port_teardown = sja1105_port_teardown,
.set_ageing_time = sja1105_set_ageing_time,
.port_change_mtu = sja1105_change_mtu,
.port_max_mtu = sja1105_get_max_mtu,
@@ -3362,32 +3393,51 @@ static int sja1105_probe(struct spi_device *spi)
return rc;
}
+ rc = sja1105_fill_device_tree(ds);
+ if (rc) {
+ dev_err(ds->dev, "Failed to fill device tree: %pe\n",
+ ERR_PTR(rc));
+ return rc;
+ }
+
rc = sja1105_mfd_add_devices(ds);
if (rc) {
dev_err(ds->dev, "Failed to create child devices: %pe\n",
ERR_PTR(rc));
- return rc;
+ goto restore_device_tree;
}
if (IS_ENABLED(CONFIG_NET_SCH_CBS)) {
priv->cbs = devm_kcalloc(dev, priv->info->num_cbs_shapers,
sizeof(struct sja1105_cbs_entry),
GFP_KERNEL);
- if (!priv->cbs)
- return -ENOMEM;
+ if (!priv->cbs) {
+ rc = -ENOMEM;
+ goto restore_device_tree;
+ }
}
- return dsa_register_switch(priv->ds);
+ rc = dsa_register_switch(priv->ds);
+ if (rc)
+ goto restore_device_tree;
+
+ return 0;
+
+restore_device_tree:
+ sja1105_restore_device_tree(ds);
+ return rc;
}
static void sja1105_remove(struct spi_device *spi)
{
struct sja1105_private *priv = spi_get_drvdata(spi);
+ struct dsa_switch *ds = priv->ds;
if (!priv)
return;
- dsa_unregister_switch(priv->ds);
+ dsa_unregister_switch(ds);
+ sja1105_restore_device_tree(ds);
}
static void sja1105_shutdown(struct spi_device *spi)
diff --git a/drivers/net/dsa/sja1105/sja1105_mdio.c b/drivers/net/dsa/sja1105/sja1105_mdio.c
deleted file mode 100644
index d5577c702902..000000000000
--- a/drivers/net/dsa/sja1105/sja1105_mdio.c
+++ /dev/null
@@ -1,233 +0,0 @@
-// SPDX-License-Identifier: GPL-2.0
-/* Copyright 2021 NXP
- */
-#include <linux/pcs/pcs-xpcs.h>
-#include <linux/of_mdio.h>
-#include "sja1105.h"
-
-#define SJA1110_PCS_BANK_REG SJA1110_SPI_ADDR(0x3fc)
-
-int sja1105_pcs_mdio_read_c45(struct mii_bus *bus, int phy, int mmd, int reg)
-{
- struct sja1105_private *priv = bus->priv;
- u64 addr;
- u32 tmp;
- int rc;
-
- addr = (mmd << 16) | reg;
-
- if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
- return 0xffff;
-
- if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID1)
- return NXP_SJA1105_XPCS_ID >> 16;
- if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID2)
- return NXP_SJA1105_XPCS_ID & GENMASK(15, 0);
-
- rc = sja1105_xfer_u32(priv, SPI_READ, addr, &tmp, NULL);
- if (rc < 0)
- return rc;
-
- return tmp & 0xffff;
-}
-
-int sja1105_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int mmd,
- int reg, u16 val)
-{
- struct sja1105_private *priv = bus->priv;
- u64 addr;
- u32 tmp;
-
- addr = (mmd << 16) | reg;
- tmp = val;
-
- if (mmd != MDIO_MMD_VEND1 && mmd != MDIO_MMD_VEND2)
- return -EINVAL;
-
- return sja1105_xfer_u32(priv, SPI_WRITE, addr, &tmp, NULL);
-}
-
-int sja1110_pcs_mdio_read_c45(struct mii_bus *bus, int phy, int mmd, int reg)
-{
- struct sja1105_private *priv = bus->priv;
- const struct sja1105_regs *regs = priv->info->regs;
- int offset, bank;
- u64 addr;
- u32 tmp;
- int rc;
-
- if (regs->pcs_base[phy] == SJA1105_RSV_ADDR)
- return -ENODEV;
-
- addr = (mmd << 16) | reg;
-
- if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID1)
- return NXP_SJA1110_XPCS_ID >> 16;
- if (mmd == MDIO_MMD_VEND2 && (reg & GENMASK(15, 0)) == MII_PHYSID2)
- return NXP_SJA1110_XPCS_ID & GENMASK(15, 0);
-
- bank = addr >> 8;
- offset = addr & GENMASK(7, 0);
-
- /* This addressing scheme reserves register 0xff for the bank address
- * register, so that can never be addressed.
- */
- if (WARN_ON(offset == 0xff))
- return -ENODEV;
-
- tmp = bank;
-
- rc = sja1105_xfer_u32(priv, SPI_WRITE,
- regs->pcs_base[phy] + SJA1110_PCS_BANK_REG,
- &tmp, NULL);
- if (rc < 0)
- return rc;
-
- rc = sja1105_xfer_u32(priv, SPI_READ, regs->pcs_base[phy] + offset,
- &tmp, NULL);
- if (rc < 0)
- return rc;
-
- return tmp & 0xffff;
-}
-
-int sja1110_pcs_mdio_write_c45(struct mii_bus *bus, int phy, int mmd, int reg,
- u16 val)
-{
- struct sja1105_private *priv = bus->priv;
- const struct sja1105_regs *regs = priv->info->regs;
- int offset, bank;
- u64 addr;
- u32 tmp;
- int rc;
-
- if (regs->pcs_base[phy] == SJA1105_RSV_ADDR)
- return -ENODEV;
-
- addr = (mmd << 16) | reg;
-
- bank = addr >> 8;
- offset = addr & GENMASK(7, 0);
-
- /* This addressing scheme reserves register 0xff for the bank address
- * register, so that can never be addressed.
- */
- if (WARN_ON(offset == 0xff))
- return -ENODEV;
-
- tmp = bank;
-
- rc = sja1105_xfer_u32(priv, SPI_WRITE,
- regs->pcs_base[phy] + SJA1110_PCS_BANK_REG,
- &tmp, NULL);
- if (rc < 0)
- return rc;
-
- tmp = val;
-
- return sja1105_xfer_u32(priv, SPI_WRITE, regs->pcs_base[phy] + offset,
- &tmp, NULL);
-}
-
-static int sja1105_mdiobus_pcs_register(struct sja1105_private *priv)
-{
- struct dsa_switch *ds = priv->ds;
- struct mii_bus *bus;
- int rc = 0;
- int port;
-
- if (!priv->info->pcs_mdio_read_c45 || !priv->info->pcs_mdio_write_c45)
- return 0;
-
- bus = mdiobus_alloc_size(0);
- if (!bus)
- return -ENOMEM;
-
- bus->name = "SJA1105 PCS MDIO bus";
- snprintf(bus->id, MII_BUS_ID_SIZE, "%s-pcs",
- dev_name(ds->dev));
- bus->read_c45 = priv->info->pcs_mdio_read_c45;
- bus->write_c45 = priv->info->pcs_mdio_write_c45;
- bus->parent = ds->dev;
- /* There is no PHY on this MDIO bus => mask out all PHY addresses
- * from auto probing.
- */
- bus->phy_mask = ~0;
- bus->priv = priv;
-
- rc = mdiobus_register(bus);
- if (rc) {
- mdiobus_free(bus);
- return rc;
- }
-
- for (port = 0; port < ds->num_ports; port++) {
- struct phylink_pcs *pcs;
-
- if (dsa_is_unused_port(ds, port))
- continue;
-
- if (priv->phy_mode[port] != PHY_INTERFACE_MODE_SGMII &&
- priv->phy_mode[port] != PHY_INTERFACE_MODE_2500BASEX)
- continue;
-
- pcs = xpcs_create_pcs_mdiodev(bus, port);
- if (IS_ERR(pcs)) {
- rc = PTR_ERR(pcs);
- goto out_pcs_free;
- }
-
- priv->pcs[port] = pcs;
- }
-
- priv->mdio_pcs = bus;
-
- return 0;
-
-out_pcs_free:
- for (port = 0; port < ds->num_ports; port++) {
- if (priv->pcs[port]) {
- xpcs_destroy_pcs(priv->pcs[port]);
- priv->pcs[port] = NULL;
- }
- }
-
- mdiobus_unregister(bus);
- mdiobus_free(bus);
-
- return rc;
-}
-
-static void sja1105_mdiobus_pcs_unregister(struct sja1105_private *priv)
-{
- struct dsa_switch *ds = priv->ds;
- int port;
-
- if (!priv->mdio_pcs)
- return;
-
- for (port = 0; port < ds->num_ports; port++) {
- if (priv->pcs[port]) {
- xpcs_destroy_pcs(priv->pcs[port]);
- priv->pcs[port] = NULL;
- }
- }
-
- mdiobus_unregister(priv->mdio_pcs);
- mdiobus_free(priv->mdio_pcs);
- priv->mdio_pcs = NULL;
-}
-
-int sja1105_mdiobus_register(struct dsa_switch *ds)
-{
- struct sja1105_private *priv = ds->priv;
-
- return sja1105_mdiobus_pcs_register(priv);
-}
-
-void sja1105_mdiobus_unregister(struct dsa_switch *ds)
-{
- struct sja1105_private *priv = ds->priv;
-
- sja1105_mdiobus_pcs_unregister(priv);
-}
diff --git a/drivers/net/dsa/sja1105/sja1105_mfd.c b/drivers/net/dsa/sja1105/sja1105_mfd.c
index 9e60cd3b5d01..7785e7d33c3d 100644
--- a/drivers/net/dsa/sja1105/sja1105_mfd.c
+++ b/drivers/net/dsa/sja1105/sja1105_mfd.c
@@ -7,12 +7,40 @@
#include "sja1105.h"
#include "sja1105_mfd.h"
+#define SJA1105_MAX_NUM_MDIOS 2
+#define SJA1105_MAX_NUM_PCS 4
+#define SJA1105_MAX_NUM_CELLS (SJA1105_MAX_NUM_MDIOS + \
+ SJA1105_MAX_NUM_PCS + \
+ 1) /* sentinel */
+
static const struct resource sja1110_mdio_cbtx_res =
DEFINE_RES_REG_NAMED(0x709000, 0x1000, "mdio_cbtx");
static const struct resource sja1110_mdio_cbt1_res =
DEFINE_RES_REG_NAMED(0x704000, 0x4000, "mdio_cbt1");
+static void sja1105_mfd_add_pcs_cells(struct sja1105_private *priv,
+ struct device_node *regs_node,
+ struct mfd_cell *cells,
+ int *num_cells)
+{
+ for (int i = 0; i < priv->info->num_pcs_resources; i++) {
+ const struct sja1105_pcs_resource *pcs_res;
+
+ pcs_res = &priv->info->pcs_resources[i];
+
+ cells[(*num_cells)++] = (struct mfd_cell) {
+ .name = pcs_res->cell_name,
+ .of_compatible = pcs_res->compatible,
+ .of_reg = pcs_res->res.start,
+ .use_of_reg = true,
+ .resources = &pcs_res->res,
+ .num_resources = 1,
+ .parent_of_node = regs_node,
+ };
+ }
+}
+
static void sja1105_mfd_add_mdio_cells(struct sja1105_private *priv,
struct device_node *mdio_node,
struct mfd_cell *cells,
@@ -50,12 +78,16 @@ static void sja1105_mfd_add_mdio_cells(struct sja1105_private *priv,
int sja1105_mfd_add_devices(struct dsa_switch *ds)
{
struct device_node *switch_node = dev_of_node(ds->dev);
+ struct mfd_cell cells[SJA1105_MAX_NUM_CELLS] = {};
+ struct device_node *regs_node, *mdio_node;
struct sja1105_private *priv = ds->priv;
- struct device_node *mdio_node;
- struct mfd_cell cells[2] = {};
int num_cells = 0;
int rc = 0;
+ regs_node = of_get_available_child_by_name(switch_node, "regs");
+ if (regs_node)
+ sja1105_mfd_add_pcs_cells(priv, regs_node, cells, &num_cells);
+
mdio_node = of_get_available_child_by_name(switch_node, "mdios");
if (mdio_node)
sja1105_mfd_add_mdio_cells(priv, mdio_node, cells, &num_cells);
@@ -64,6 +96,198 @@ int sja1105_mfd_add_devices(struct dsa_switch *ds)
rc = devm_mfd_add_devices(ds->dev, PLATFORM_DEVID_AUTO, cells,
num_cells, NULL, 0, NULL);
+ of_node_put(regs_node);
of_node_put(mdio_node);
return rc;
}
+
+static bool sja1105_child_node_exists(struct device_node *node,
+ const char *name,
+ const struct resource *res)
+{
+ struct device_node *child = of_get_child_by_name(node, name);
+ u32 reg[2];
+
+ for_each_child_of_node(node, child) {
+ if (!of_node_name_eq(child, name))
+ continue;
+
+ if (of_property_read_u32_array(child, "reg", reg, ARRAY_SIZE(reg)))
+ continue;
+
+ if (reg[0] == res->start && reg[1] == resource_size(res))
+ return true;
+ }
+
+ return false;
+}
+
+static int sja1105_create_pcs_nodes(struct sja1105_private *priv,
+ struct device_node *regs_node)
+{
+ struct dsa_switch *ds = priv->ds;
+ struct device *dev = ds->dev;
+ struct device_node *pcs_node;
+ const u32 reg_io_width = 4;
+ char node_name[32];
+ u32 reg_props[2];
+ int rc;
+
+ for (int i = 0; i < priv->info->num_pcs_resources; i++) {
+ const struct sja1105_pcs_resource *pcs_res;
+
+ pcs_res = &priv->info->pcs_resources[i];
+
+ if (sja1105_child_node_exists(regs_node, "ethernet-pcs",
+ &pcs_res->res))
+ continue;
+
+ snprintf(node_name, sizeof(node_name), "ethernet-pcs@%llx",
+ pcs_res->res.start);
+
+ pcs_node = of_changeset_create_node(&priv->of_cs, regs_node,
+ node_name);
+ if (!pcs_node) {
+ dev_err(dev, "Failed to create PCS node %s\n", node_name);
+ return -ENOMEM;
+ }
+
+ rc = of_changeset_add_prop_string(&priv->of_cs, pcs_node,
+ "compatible",
+ pcs_res->compatible);
+ if (rc) {
+ dev_err(dev, "Failed to add compatible property to %s: %pe\n",
+ node_name, ERR_PTR(rc));
+ return rc;
+ }
+
+ reg_props[0] = pcs_res->res.start;
+ reg_props[1] = resource_size(&pcs_res->res);
+ rc = of_changeset_add_prop_u32_array(&priv->of_cs, pcs_node,
+ "reg", reg_props, 2);
+ if (rc) {
+ dev_err(dev, "Failed to add reg property to %s: %pe\n",
+ node_name, ERR_PTR(rc));
+ return rc;
+ }
+
+ rc = of_changeset_add_prop_string(&priv->of_cs, pcs_node,
+ "reg-names",
+ pcs_res->res.name);
+ if (rc) {
+ dev_err(dev, "Failed to add reg-names property to %s: %pe\n",
+ node_name, ERR_PTR(rc));
+ return rc;
+ }
+
+ rc = of_changeset_add_prop_u32_array(&priv->of_cs, pcs_node,
+ "reg-io-width",
+ ®_io_width, 1);
+ if (rc) {
+ dev_err(dev, "Failed to add reg-io-width property to %s: %pe\n",
+ node_name, ERR_PTR(rc));
+ return rc;
+ }
+
+ dev_dbg(dev, "Created OF node %pOF\n", pcs_node);
+ priv->pcs_fwnode[pcs_res->port] = of_fwnode_handle(pcs_node);
+ }
+
+ return 0;
+}
+
+static struct device_node *sja1105_create_regs_node(struct sja1105_private *priv,
+ struct device_node *switch_node)
+{
+ struct device *dev = priv->ds->dev;
+ struct device_node *regs_node;
+ const u32 addr_size_cells = 1;
+ int rc;
+
+ regs_node = of_changeset_create_node(&priv->of_cs, switch_node, "regs");
+ if (!regs_node) {
+ dev_err(dev, "Failed to create 'regs' device tree node\n");
+ return ERR_PTR(-ENOMEM);
+ }
+
+ rc = of_changeset_add_prop_u32_array(&priv->of_cs, regs_node,
+ "#address-cells",
+ &addr_size_cells, 1);
+ if (rc) {
+ dev_err(dev, "Failed to add #address-cells property: %pe\n",
+ ERR_PTR(rc));
+ return ERR_PTR(rc);
+ }
+
+ rc = of_changeset_add_prop_u32_array(&priv->of_cs, regs_node,
+ "#size-cells",
+ &addr_size_cells, 1);
+ if (rc) {
+ dev_err(dev, "Failed to add #size-cells property: %pe\n",
+ ERR_PTR(rc));
+ return ERR_PTR(rc);
+ }
+
+ return regs_node;
+}
+
+int sja1105_fill_device_tree(struct dsa_switch *ds)
+{
+ struct device_node *switch_node, *regs_node;
+ struct sja1105_private *priv = ds->priv;
+ bool regs_node_created = false;
+ struct device *dev = ds->dev;
+ int rc;
+
+ switch_node = dev_of_node(dev);
+ of_changeset_init(&priv->of_cs);
+
+ regs_node = of_get_child_by_name(switch_node, "regs");
+ if (!regs_node) {
+ regs_node = sja1105_create_regs_node(priv, switch_node);
+ if (IS_ERR(regs_node)) {
+ rc = PTR_ERR(regs_node);
+ goto out_destroy_changeset;
+ }
+
+ regs_node_created = true;
+ dev_dbg(dev, "Created OF node %pOF\n", regs_node);
+ }
+
+ rc = sja1105_create_pcs_nodes(priv, regs_node);
+ if (rc)
+ goto out_destroy_changeset;
+
+ rc = of_changeset_apply(&priv->of_cs);
+ if (rc) {
+ dev_err(dev, "Failed to apply device tree changeset: %pe\n",
+ ERR_PTR(rc));
+ goto out_destroy_changeset;
+ }
+
+ /* Don't destroy the changeset - we need it for reverting later */
+ goto out_put_regs_node;
+
+out_destroy_changeset:
+ of_changeset_destroy(&priv->of_cs);
+out_put_regs_node:
+ if (!regs_node_created)
+ of_node_put(regs_node);
+
+ return rc;
+}
+
+void sja1105_restore_device_tree(struct dsa_switch *ds)
+{
+ struct sja1105_private *priv = ds->priv;
+ struct device *dev = ds->dev;
+ int rc;
+
+ rc = of_changeset_revert(&priv->of_cs);
+ if (rc) {
+ dev_err(dev, "Failed to revert device tree changeset: %pe\n",
+ ERR_PTR(rc));
+ }
+
+ of_changeset_destroy(&priv->of_cs);
+}
diff --git a/drivers/net/dsa/sja1105/sja1105_mfd.h b/drivers/net/dsa/sja1105/sja1105_mfd.h
index c33c8ff24e25..7195c3aa1437 100644
--- a/drivers/net/dsa/sja1105/sja1105_mfd.h
+++ b/drivers/net/dsa/sja1105/sja1105_mfd.h
@@ -5,5 +5,7 @@
#define _SJA1105_MFD_H
int sja1105_mfd_add_devices(struct dsa_switch *ds);
+int sja1105_fill_device_tree(struct dsa_switch *ds);
+void sja1105_restore_device_tree(struct dsa_switch *ds);
#endif
diff --git a/drivers/net/dsa/sja1105/sja1105_spi.c b/drivers/net/dsa/sja1105/sja1105_spi.c
index 087acded7827..8af3d01d0f5c 100644
--- a/drivers/net/dsa/sja1105/sja1105_spi.c
+++ b/drivers/net/dsa/sja1105/sja1105_spi.c
@@ -617,9 +617,28 @@ static const struct sja1105_regs sja1110_regs = {
.ptpclkrate = SJA1110_SPI_ADDR(0x74),
.ptpclkcorp = SJA1110_SPI_ADDR(0x80),
.ptpsyncts = SJA1110_SPI_ADDR(0x84),
- .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},
+};
+
+/* See port compatibility matrix in Documentation/networking/dsa/sja1105.rst */
+static const struct sja1105_pcs_resource sja1105rs_pcs_resources[] = {
+ { DEFINE_RES_REG_NAMED(0x0, 0x800000, "direct"),
+ SJA1105_SGMII_PORT, "sja1105-pcs", "nxp,sja1105-pcs"
+ },
+};
+
+static const struct sja1105_pcs_resource sja1110_pcs_resources[] = {
+ { DEFINE_RES_REG_NAMED(0x705000, 0x1000, "indirect"),
+ 1, "sja1110-pcs", "nxp,sja1110-pcs"
+ },
+ { DEFINE_RES_REG_NAMED(0x706000, 0x1000, "indirect"),
+ 2, "sja1110-pcs", "nxp,sja1110-pcs"
+ },
+ { DEFINE_RES_REG_NAMED(0x707000, 0x1000, "indirect"),
+ 3, "sja1110-pcs", "nxp,sja1110-pcs"
+ },
+ { DEFINE_RES_REG_NAMED(0x708000, 0x1000, "indirect"),
+ 4, "sja1110-pcs", "nxp,sja1110-pcs"
+ },
};
const struct sja1105_info sja1105e_info = {
@@ -771,8 +790,6 @@ const struct sja1105_info sja1105r_info = {
.ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing,
.rxtstamp = sja1105_rxtstamp,
.clocking_setup = sja1105_clocking_setup,
- .pcs_mdio_read_c45 = sja1105_pcs_mdio_read_c45,
- .pcs_mdio_write_c45 = sja1105_pcs_mdio_write_c45,
.regs = &sja1105pqrs_regs,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
@@ -785,6 +802,8 @@ const struct sja1105_info sja1105r_info = {
.supports_rmii = {true, true, true, true, true},
.supports_rgmii = {true, true, true, true, true},
.supports_sgmii = {false, false, false, false, true},
+ .pcs_resources = sja1105rs_pcs_resources,
+ .num_pcs_resources = ARRAY_SIZE(sja1105rs_pcs_resources),
.name = "SJA1105R",
};
@@ -808,8 +827,6 @@ const struct sja1105_info sja1105s_info = {
.ptp_cmd_packing = sja1105pqrs_ptp_cmd_packing,
.rxtstamp = sja1105_rxtstamp,
.clocking_setup = sja1105_clocking_setup,
- .pcs_mdio_read_c45 = sja1105_pcs_mdio_read_c45,
- .pcs_mdio_write_c45 = sja1105_pcs_mdio_write_c45,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 3,
@@ -821,6 +838,8 @@ const struct sja1105_info sja1105s_info = {
.supports_rmii = {true, true, true, true, true},
.supports_rgmii = {true, true, true, true, true},
.supports_sgmii = {false, false, false, false, true},
+ .pcs_resources = sja1105rs_pcs_resources,
+ .num_pcs_resources = ARRAY_SIZE(sja1105rs_pcs_resources),
.name = "SJA1105S",
};
@@ -847,8 +866,6 @@ const struct sja1105_info sja1110a_info = {
.rxtstamp = sja1110_rxtstamp,
.txtstamp = sja1110_txtstamp,
.disable_microcontroller = sja1110_disable_microcontroller,
- .pcs_mdio_read_c45 = sja1110_pcs_mdio_read_c45,
- .pcs_mdio_write_c45 = sja1110_pcs_mdio_write_c45,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 4,
@@ -872,6 +889,8 @@ const struct sja1105_info sja1110a_info = {
SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1,
SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1,
SJA1105_PHY_BASE_T1},
+ .pcs_resources = sja1110_pcs_resources,
+ .num_pcs_resources = ARRAY_SIZE(sja1110_pcs_resources),
.name = "SJA1110A",
};
@@ -898,8 +917,6 @@ const struct sja1105_info sja1110b_info = {
.rxtstamp = sja1110_rxtstamp,
.txtstamp = sja1110_txtstamp,
.disable_microcontroller = sja1110_disable_microcontroller,
- .pcs_mdio_read_c45 = sja1110_pcs_mdio_read_c45,
- .pcs_mdio_write_c45 = sja1110_pcs_mdio_write_c45,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 4,
@@ -923,6 +940,8 @@ const struct sja1105_info sja1110b_info = {
SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1,
SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1,
SJA1105_NO_PHY},
+ .pcs_resources = &sja1110_pcs_resources[2], /* ports 3 and 4 */
+ .num_pcs_resources = ARRAY_SIZE(sja1110_pcs_resources) - 2,
.name = "SJA1110B",
};
@@ -949,8 +968,6 @@ const struct sja1105_info sja1110c_info = {
.rxtstamp = sja1110_rxtstamp,
.txtstamp = sja1110_txtstamp,
.disable_microcontroller = sja1110_disable_microcontroller,
- .pcs_mdio_read_c45 = sja1110_pcs_mdio_read_c45,
- .pcs_mdio_write_c45 = sja1110_pcs_mdio_write_c45,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 4,
@@ -974,6 +991,8 @@ const struct sja1105_info sja1110c_info = {
SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1,
SJA1105_NO_PHY, SJA1105_NO_PHY,
SJA1105_NO_PHY},
+ .pcs_resources = &sja1110_pcs_resources[3], /* port 4 */
+ .num_pcs_resources = ARRAY_SIZE(sja1110_pcs_resources) - 3,
.name = "SJA1110C",
};
@@ -1000,8 +1019,6 @@ const struct sja1105_info sja1110d_info = {
.rxtstamp = sja1110_rxtstamp,
.txtstamp = sja1110_txtstamp,
.disable_microcontroller = sja1110_disable_microcontroller,
- .pcs_mdio_read_c45 = sja1110_pcs_mdio_read_c45,
- .pcs_mdio_write_c45 = sja1110_pcs_mdio_write_c45,
.port_speed = {
[SJA1105_SPEED_AUTO] = 0,
[SJA1105_SPEED_10MBPS] = 4,
@@ -1025,5 +1042,7 @@ const struct sja1105_info sja1110d_info = {
SJA1105_PHY_BASE_T1, SJA1105_PHY_BASE_T1,
SJA1105_NO_PHY, SJA1105_NO_PHY,
SJA1105_NO_PHY},
+ .pcs_resources = sja1110_pcs_resources,
+ .num_pcs_resources = ARRAY_SIZE(sja1110_pcs_resources),
.name = "SJA1110D",
};
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-18 19:05 ` [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver Vladimir Oltean
@ 2025-11-19 0:41 ` Jakub Kicinski
2025-11-19 9:59 ` Vladimir Oltean
2025-11-19 11:19 ` kernel test robot
` (2 subsequent siblings)
3 siblings, 1 reply; 54+ messages in thread
From: Jakub Kicinski @ 2025-11-19 0:41 UTC (permalink / raw)
To: Vladimir Oltean
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Paolo Abeni, linux-kernel,
Serge Semin, Andy Shevchenko, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
On Tue, 18 Nov 2025 21:05:29 +0200 Vladimir Oltean wrote:
> +static bool sja1105_child_node_exists(struct device_node *node,
> + const char *name,
> + const struct resource *res)
> +{
> + struct device_node *child = of_get_child_by_name(node, name);
> + u32 reg[2];
> +
> + for_each_child_of_node(node, child) {
> + if (!of_node_name_eq(child, name))
> + continue;
> +
> + if (of_property_read_u32_array(child, "reg", reg, ARRAY_SIZE(reg)))
> + continue;
> +
> + if (reg[0] == res->start && reg[1] == resource_size(res))
> + return true;
coccicheck says you're likely leaking the reference on the child here
> + }
> +
> + return false;
> +}
--
pw-bot: cr
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-19 0:41 ` Jakub Kicinski
@ 2025-11-19 9:59 ` Vladimir Oltean
2025-11-19 10:31 ` Andy Shevchenko
0 siblings, 1 reply; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-19 9:59 UTC (permalink / raw)
To: Jakub Kicinski
Cc: netdev, Andrew Lunn, Heiner Kallweit, Russell King,
David S. Miller, Eric Dumazet, Paolo Abeni, linux-kernel,
Serge Semin, Andy Shevchenko, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
On Tue, Nov 18, 2025 at 04:41:30PM -0800, Jakub Kicinski wrote:
> On Tue, 18 Nov 2025 21:05:29 +0200 Vladimir Oltean wrote:
> > +static bool sja1105_child_node_exists(struct device_node *node,
> > + const char *name,
> > + const struct resource *res)
> > +{
> > + struct device_node *child = of_get_child_by_name(node, name);
> > + u32 reg[2];
> > +
> > + for_each_child_of_node(node, child) {
> > + if (!of_node_name_eq(child, name))
> > + continue;
> > +
> > + if (of_property_read_u32_array(child, "reg", reg, ARRAY_SIZE(reg)))
> > + continue;
> > +
> > + if (reg[0] == res->start && reg[1] == resource_size(res))
> > + return true;
>
> coccicheck says you're likely leaking the reference on the child here
Ok, one item added to the change list for v2.
Why is cocci-check.sh part of the "contest" test suite that runs on
remote executors? This test didn't run when I tested this series locally
with ingest_mdir.py.
> > + }
> > +
> > + return false;
> > +}
> --
> pw-bot: cr
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-19 9:59 ` Vladimir Oltean
@ 2025-11-19 10:31 ` Andy Shevchenko
2025-11-19 11:25 ` Vladimir Oltean
0 siblings, 1 reply; 54+ messages in thread
From: Andy Shevchenko @ 2025-11-19 10:31 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Jakub Kicinski, netdev, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Paolo Abeni,
linux-kernel, Serge Semin, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
On Wed, Nov 19, 2025 at 11:59:42AM +0200, Vladimir Oltean wrote:
> On Tue, Nov 18, 2025 at 04:41:30PM -0800, Jakub Kicinski wrote:
> > On Tue, 18 Nov 2025 21:05:29 +0200 Vladimir Oltean wrote:
...
> > > + for_each_child_of_node(node, child) {
> > > + if (!of_node_name_eq(child, name))
> > > + continue;
> > > +
> > > + if (of_property_read_u32_array(child, "reg", reg, ARRAY_SIZE(reg)))
> > > + continue;
> > > +
> > > + if (reg[0] == res->start && reg[1] == resource_size(res))
> > > + return true;
> >
> > coccicheck says you're likely leaking the reference on the child here
>
> Ok, one item added to the change list for v2.
Note, we have __free() and _scoped() variants of the respective APIs to make it
easier to not forget.
> Why is cocci-check.sh part of the "contest" test suite that runs on
> remote executors? This test didn't run when I tested this series locally
> with ingest_mdir.py.
I believe it's due to heavy load it makes. Running it on a (whole) kernel make
take hours.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-19 10:31 ` Andy Shevchenko
@ 2025-11-19 11:25 ` Vladimir Oltean
2025-11-19 16:11 ` Jakub Kicinski
0 siblings, 1 reply; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-19 11:25 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Jakub Kicinski, netdev, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Paolo Abeni,
linux-kernel, Serge Semin, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
On Wed, Nov 19, 2025 at 12:31:27PM +0200, Andy Shevchenko wrote:
> On Wed, Nov 19, 2025 at 11:59:42AM +0200, Vladimir Oltean wrote:
> > On Tue, Nov 18, 2025 at 04:41:30PM -0800, Jakub Kicinski wrote:
> > > On Tue, 18 Nov 2025 21:05:29 +0200 Vladimir Oltean wrote:
>
> ...
>
> > > > + for_each_child_of_node(node, child) {
> > > > + if (!of_node_name_eq(child, name))
> > > > + continue;
> > > > +
> > > > + if (of_property_read_u32_array(child, "reg", reg, ARRAY_SIZE(reg)))
> > > > + continue;
> > > > +
> > > > + if (reg[0] == res->start && reg[1] == resource_size(res))
> > > > + return true;
> > >
> > > coccicheck says you're likely leaking the reference on the child here
> >
> > Ok, one item added to the change list for v2.
>
> Note, we have __free() and _scoped() variants of the respective APIs to make it
> easier to not forget.
Ok, I'll use for_each_child_of_node_scoped(), as it's a good fit, thanks.
> > Why is cocci-check.sh part of the "contest" test suite that runs on
> > remote executors? This test didn't run when I tested this series locally
> > with ingest_mdir.py.
>
> I believe it's due to heavy load it makes. Running it on a (whole) kernel make
> take hours.
For context, the "local" NIPA tests for this set took me 3 hours and 34 minutes
to run on 32 AMD EPYC 9R14 CPU cores. So if cocci-check.sh increases that time
by a few additional hours, yeah, it's bad, but it was bad before too, so
the "heavy load" argument doesn't satisfactorily explain things.
Plus, looking deeper at the NIPA code, it only submits the patch set
under test to a "contest" branch if it already passed the slow
gate_checks=build_clang,build_32bit,build_allmodconfig_warn. So it's not
like the "local" build tests run in parallel with the remote worker, and
we're not saving any time for a single build.
I think it's due to the fact that the "contest" checks are fundamentally
so slow, that they can't be run on individual patch sets, and are run on
batches of patch sets merged into a single branch (of which there seem
to be 8 per day). I didn't get this from NIPA documentation, though.
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-19 11:25 ` Vladimir Oltean
@ 2025-11-19 16:11 ` Jakub Kicinski
2025-11-19 16:17 ` Andy Shevchenko
2025-11-20 12:32 ` Russell King (Oracle)
0 siblings, 2 replies; 54+ messages in thread
From: Jakub Kicinski @ 2025-11-19 16:11 UTC (permalink / raw)
To: Vladimir Oltean
Cc: Andy Shevchenko, netdev, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Paolo Abeni,
linux-kernel, Serge Semin, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
On Wed, 19 Nov 2025 13:25:22 +0200 Vladimir Oltean wrote:
> I think it's due to the fact that the "contest" checks are fundamentally
> so slow, that they can't be run on individual patch sets, and are run on
> batches of patch sets merged into a single branch (of which there seem
> to be 8 per day).
Correct, looking at the logs AFAICT coccicheck takes 25min on a
relatively beefy machine, and we only run it on path that were actually
modified by pending changes. We get 100+ patches a day, and 40+ series,
and coccicheck fails relatively rarely. So on the NIPA side it's not
worth it.
But, we can certainly integrate it into ingest_mdir.
FTR make htmldocs and of course selftests are also not executed by
ingest_mdir.
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-19 16:11 ` Jakub Kicinski
@ 2025-11-19 16:17 ` Andy Shevchenko
2025-11-19 17:23 ` Russell King (Oracle)
2025-11-20 12:32 ` Russell King (Oracle)
1 sibling, 1 reply; 54+ messages in thread
From: Andy Shevchenko @ 2025-11-19 16:17 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Vladimir Oltean, netdev, Andrew Lunn, Heiner Kallweit,
Russell King, David S. Miller, Eric Dumazet, Paolo Abeni,
linux-kernel, Serge Semin, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
On Wed, Nov 19, 2025 at 08:11:12AM -0800, Jakub Kicinski wrote:
> On Wed, 19 Nov 2025 13:25:22 +0200 Vladimir Oltean wrote:
> > I think it's due to the fact that the "contest" checks are fundamentally
> > so slow, that they can't be run on individual patch sets, and are run on
> > batches of patch sets merged into a single branch (of which there seem
> > to be 8 per day).
>
> Correct, looking at the logs AFAICT coccicheck takes 25min on a
> relatively beefy machine, and we only run it on path that were actually
> modified by pending changes. We get 100+ patches a day, and 40+ series,
> and coccicheck fails relatively rarely. So on the NIPA side it's not
> worth it.
>
> But, we can certainly integrate it into ingest_mdir.
>
> FTR make htmldocs and of course selftests are also not executed by
> ingest_mdir.
Btw, do you do `make W=1` while having CONFIG_WERROR=y?
And if so, do you also compile with clang?
Sorry if it's documented / answered already, please point me to that discussion
/ documentation.
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-19 16:17 ` Andy Shevchenko
@ 2025-11-19 17:23 ` Russell King (Oracle)
2025-11-19 17:39 ` Andy Shevchenko
0 siblings, 1 reply; 54+ messages in thread
From: Russell King (Oracle) @ 2025-11-19 17:23 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Jakub Kicinski, Vladimir Oltean, netdev, Andrew Lunn,
Heiner Kallweit, David S. Miller, Eric Dumazet, Paolo Abeni,
linux-kernel, Serge Semin, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
On Wed, Nov 19, 2025 at 06:17:48PM +0200, Andy Shevchenko wrote:
> On Wed, Nov 19, 2025 at 08:11:12AM -0800, Jakub Kicinski wrote:
> > On Wed, 19 Nov 2025 13:25:22 +0200 Vladimir Oltean wrote:
> > > I think it's due to the fact that the "contest" checks are fundamentally
> > > so slow, that they can't be run on individual patch sets, and are run on
> > > batches of patch sets merged into a single branch (of which there seem
> > > to be 8 per day).
> >
> > Correct, looking at the logs AFAICT coccicheck takes 25min on a
> > relatively beefy machine, and we only run it on path that were actually
> > modified by pending changes. We get 100+ patches a day, and 40+ series,
> > and coccicheck fails relatively rarely. So on the NIPA side it's not
> > worth it.
> >
> > But, we can certainly integrate it into ingest_mdir.
> >
> > FTR make htmldocs and of course selftests are also not executed by
> > ingest_mdir.
>
> Btw, do you do `make W=1` while having CONFIG_WERROR=y?
> And if so, do you also compile with clang?
If you look at any patch in patchwork, e.g.
https://patchwork.kernel.org/project/netdevbpf/patch/E1vLgSZ-0000000FMrW-0cEu@rmk-PC.armlinux.org.uk/
it gives a list of the tests performed. In answer to your questions:
netdev/build_clang success Errors and warnings before: 1 this patch: 1
So yes, building with clang is tested.
I can say that stuff such as unused const variables gets found by
nipa, via -Wunused-const-variable, which as I understand it is a
W=1 thing.
I suspect CONFIG_WERROR=y isn't used (I don't know) as that would
stop the build on warnings, whereas what is done instead is that
the output of the build is analysed, and the number of warnings
counted and reported in patchwork. Note that the "build" stuff
reports number of errors/warnings before and after the patch.
Hope this answers your question.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-19 17:23 ` Russell King (Oracle)
@ 2025-11-19 17:39 ` Andy Shevchenko
2025-11-19 18:35 ` Jakub Kicinski
0 siblings, 1 reply; 54+ messages in thread
From: Andy Shevchenko @ 2025-11-19 17:39 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: Jakub Kicinski, Vladimir Oltean, netdev, Andrew Lunn,
Heiner Kallweit, David S. Miller, Eric Dumazet, Paolo Abeni,
linux-kernel, Serge Semin, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
On Wed, Nov 19, 2025 at 05:23:48PM +0000, Russell King (Oracle) wrote:
> On Wed, Nov 19, 2025 at 06:17:48PM +0200, Andy Shevchenko wrote:
> > On Wed, Nov 19, 2025 at 08:11:12AM -0800, Jakub Kicinski wrote:
> > > On Wed, 19 Nov 2025 13:25:22 +0200 Vladimir Oltean wrote:
> > > > I think it's due to the fact that the "contest" checks are fundamentally
> > > > so slow, that they can't be run on individual patch sets, and are run on
> > > > batches of patch sets merged into a single branch (of which there seem
> > > > to be 8 per day).
> > >
> > > Correct, looking at the logs AFAICT coccicheck takes 25min on a
> > > relatively beefy machine, and we only run it on path that were actually
> > > modified by pending changes. We get 100+ patches a day, and 40+ series,
> > > and coccicheck fails relatively rarely. So on the NIPA side it's not
> > > worth it.
> > >
> > > But, we can certainly integrate it into ingest_mdir.
> > >
> > > FTR make htmldocs and of course selftests are also not executed by
> > > ingest_mdir.
> >
> > Btw, do you do `make W=1` while having CONFIG_WERROR=y?
> > And if so, do you also compile with clang?
>
> If you look at any patch in patchwork, e.g.
>
> https://patchwork.kernel.org/project/netdevbpf/patch/E1vLgSZ-0000000FMrW-0cEu@rmk-PC.armlinux.org.uk/
>
> it gives a list of the tests performed. In answer to your questions:
>
> netdev/build_clang success Errors and warnings before: 1 this patch: 1
>
> So yes, building with clang is tested.
>
> I can say that stuff such as unused const variables gets found by
> nipa, via -Wunused-const-variable, which as I understand it is a
> W=1 thing.
>
> I suspect CONFIG_WERROR=y isn't used (I don't know) as that would
> stop the build on warnings, whereas what is done instead is that
> the output of the build is analysed, and the number of warnings
> counted and reported in patchwork. Note that the "build" stuff
> reports number of errors/warnings before and after the patch.
>
> Hope this answers your question.
Pretty much, thanks!
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-19 17:39 ` Andy Shevchenko
@ 2025-11-19 18:35 ` Jakub Kicinski
2025-11-19 19:33 ` Andy Shevchenko
0 siblings, 1 reply; 54+ messages in thread
From: Jakub Kicinski @ 2025-11-19 18:35 UTC (permalink / raw)
To: Andy Shevchenko
Cc: Russell King (Oracle), Vladimir Oltean, netdev, Andrew Lunn,
Heiner Kallweit, David S. Miller, Eric Dumazet, Paolo Abeni,
linux-kernel, Serge Semin, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
On Wed, 19 Nov 2025 19:39:32 +0200 Andy Shevchenko wrote:
> On Wed, Nov 19, 2025 at 05:23:48PM +0000, Russell King (Oracle) wrote:
> > On Wed, Nov 19, 2025 at 06:17:48PM +0200, Andy Shevchenko wrote:
> > > On Wed, Nov 19, 2025 at 08:11:12AM -0800, Jakub Kicinski wrote:
> > I can say that stuff such as unused const variables gets found by
> > nipa, via -Wunused-const-variable, which as I understand it is a
> > W=1 thing.
> >
> > I suspect CONFIG_WERROR=y isn't used (I don't know) as that would
> > stop the build on warnings, whereas what is done instead is that
> > the output of the build is analysed, and the number of warnings
> > counted and reported in patchwork. Note that the "build" stuff
> > reports number of errors/warnings before and after the patch.
> >
> > Hope this answers your question.
>
> Pretty much, thanks!
We do:
prep_config() {
make LLVM=1 O=$output_dir allmodconfig
./scripts/config --file $output_dir/.config -d werror
./scripts/config --file $output_dir/.config -d drm_werror
./scripts/config --file $output_dir/.config -d kvm_werror
}
I have strong feelings about people who think Werror is an acceptable
practice in 2025, but let me not violate the CoC here..
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-19 18:35 ` Jakub Kicinski
@ 2025-11-19 19:33 ` Andy Shevchenko
0 siblings, 0 replies; 54+ messages in thread
From: Andy Shevchenko @ 2025-11-19 19:33 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Russell King (Oracle), Vladimir Oltean, netdev, Andrew Lunn,
Heiner Kallweit, David S. Miller, Eric Dumazet, Paolo Abeni,
linux-kernel, Serge Semin, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
On Wed, Nov 19, 2025 at 10:35:45AM -0800, Jakub Kicinski wrote:
> On Wed, 19 Nov 2025 19:39:32 +0200 Andy Shevchenko wrote:
> > On Wed, Nov 19, 2025 at 05:23:48PM +0000, Russell King (Oracle) wrote:
> > > On Wed, Nov 19, 2025 at 06:17:48PM +0200, Andy Shevchenko wrote:
> > > > On Wed, Nov 19, 2025 at 08:11:12AM -0800, Jakub Kicinski wrote:
> > > I can say that stuff such as unused const variables gets found by
> > > nipa, via -Wunused-const-variable, which as I understand it is a
> > > W=1 thing.
> > >
> > > I suspect CONFIG_WERROR=y isn't used (I don't know) as that would
> > > stop the build on warnings, whereas what is done instead is that
> > > the output of the build is analysed, and the number of warnings
> > > counted and reported in patchwork. Note that the "build" stuff
> > > reports number of errors/warnings before and after the patch.
> > >
> > > Hope this answers your question.
> >
> > Pretty much, thanks!
>
> We do:
A-ha, thanks!
> prep_config() {
> make LLVM=1 O=$output_dir allmodconfig
> ./scripts/config --file $output_dir/.config -d werror
> ./scripts/config --file $output_dir/.config -d drm_werror
> ./scripts/config --file $output_dir/.config -d kvm_werror
> }
>
> I have strong feelings about people who think Werror is an acceptable
> practice in 2025, but let me not violate the CoC here..
WERROR=y by default was introduced you-know-by-whom :-)
--
With Best Regards,
Andy Shevchenko
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-19 16:11 ` Jakub Kicinski
2025-11-19 16:17 ` Andy Shevchenko
@ 2025-11-20 12:32 ` Russell King (Oracle)
2025-11-20 15:00 ` Jakub Kicinski
1 sibling, 1 reply; 54+ messages in thread
From: Russell King (Oracle) @ 2025-11-20 12:32 UTC (permalink / raw)
To: Jakub Kicinski
Cc: Vladimir Oltean, Andy Shevchenko, netdev, Andrew Lunn,
Heiner Kallweit, David S. Miller, Eric Dumazet, Paolo Abeni,
linux-kernel, Serge Semin, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
On Wed, Nov 19, 2025 at 08:11:12AM -0800, Jakub Kicinski wrote:
> On Wed, 19 Nov 2025 13:25:22 +0200 Vladimir Oltean wrote:
> > I think it's due to the fact that the "contest" checks are fundamentally
> > so slow, that they can't be run on individual patch sets, and are run on
> > batches of patch sets merged into a single branch (of which there seem
> > to be 8 per day).
>
> Correct, looking at the logs AFAICT coccicheck takes 25min on a
> relatively beefy machine, and we only run it on path that were actually
> modified by pending changes. We get 100+ patches a day, and 40+ series,
> and coccicheck fails relatively rarely. So on the NIPA side it's not
> worth it.
On "contest" I find when looking at patchwork, it's just best to ignore
the result that NIPA posts for that, because more often than not it
reports "fail" when there's nothing wrong.
For example, the qcom-ethqos patches - v1 passed contest, and this
morning I submitted v2. The only change was removing the double space
in patch 2. What I see in v2 is that _all_ the patches failed contest,
even those that are unchanged and previously passed. This makes
contest unreliable and IMHO misleading - and as such I hate it.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-20 12:32 ` Russell King (Oracle)
@ 2025-11-20 15:00 ` Jakub Kicinski
0 siblings, 0 replies; 54+ messages in thread
From: Jakub Kicinski @ 2025-11-20 15:00 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: Vladimir Oltean, Andy Shevchenko, netdev, Andrew Lunn,
Heiner Kallweit, David S. Miller, Eric Dumazet, Paolo Abeni,
linux-kernel, Serge Semin, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
On Thu, 20 Nov 2025 12:32:37 +0000 Russell King (Oracle) wrote:
> On Wed, Nov 19, 2025 at 08:11:12AM -0800, Jakub Kicinski wrote:
> > On Wed, 19 Nov 2025 13:25:22 +0200 Vladimir Oltean wrote:
> > > I think it's due to the fact that the "contest" checks are fundamentally
> > > so slow, that they can't be run on individual patch sets, and are run on
> > > batches of patch sets merged into a single branch (of which there seem
> > > to be 8 per day).
> >
> > Correct, looking at the logs AFAICT coccicheck takes 25min on a
> > relatively beefy machine, and we only run it on path that were actually
> > modified by pending changes. We get 100+ patches a day, and 40+ series,
> > and coccicheck fails relatively rarely. So on the NIPA side it's not
> > worth it.
>
> On "contest" I find when looking at patchwork, it's just best to ignore
> the result that NIPA posts for that, because more often than not it
> reports "fail" when there's nothing wrong.
>
> For example, the qcom-ethqos patches - v1 passed contest, and this
> morning I submitted v2. The only change was removing the double space
> in patch 2. What I see in v2 is that _all_ the patches failed contest,
> even those that are unchanged and previously passed. This makes
> contest unreliable and IMHO misleading - and as such I hate it.
Fair, I'll fix it over the weekend. tl;dr it shows up as failing until
we get a clean run because of patchwork UI shortcomings.
Long version is that unfortunately patchwork UI does not show "pending"
tests on the main page. So when we eyeball the queue to get a sense
of patches which are fully validated its hard to tell "done" from
"in progress". I believe BPF's KPD system also uses "fail until
finished", I'm guessing for the same reason.
That said I stopped using the patchwork UI completely now, and switch
to my own UIs within NIPA. So patchwork shortcomings are no longer
a concern.
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-18 19:05 ` [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver Vladimir Oltean
2025-11-19 0:41 ` Jakub Kicinski
@ 2025-11-19 11:19 ` kernel test robot
2025-11-19 12:01 ` Vladimir Oltean
2025-11-19 12:01 ` kernel test robot
2025-11-20 0:01 ` kernel test robot
3 siblings, 1 reply; 54+ messages in thread
From: kernel test robot @ 2025-11-19 11:19 UTC (permalink / raw)
To: Vladimir Oltean, netdev
Cc: oe-kbuild-all, Andrew Lunn, Heiner Kallweit, Russell King,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel,
Serge Semin, Andy Shevchenko, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
Hi Vladimir,
kernel test robot noticed the following build warnings:
[auto build test WARNING on net-next/main]
url: https://github.com/intel-lab-lkp/linux/commits/Vladimir-Oltean/net-dsa-sja1105-let-phylink-help-with-the-replay-of-link-callbacks/20251119-031300
base: net-next/main
patch link: https://lore.kernel.org/r/20251118190530.580267-15-vladimir.oltean%40nxp.com
patch subject: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20251119/202511191835.rwfD48SW-lkp@intel.com/config)
compiler: m68k-linux-gcc (GCC) 15.1.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251119/202511191835.rwfD48SW-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511191835.rwfD48SW-lkp@intel.com/
All warnings (new ones prefixed by >>):
drivers/net/dsa/sja1105/sja1105_mfd.c: In function 'sja1105_create_pcs_nodes':
>> drivers/net/dsa/sja1105/sja1105_mfd.c:145:73: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 4 has type 'resource_size_t' {aka 'unsigned int'} [-Wformat=]
145 | snprintf(node_name, sizeof(node_name), "ethernet-pcs@%llx",
| ~~~^
| |
| long long unsigned int
| %x
146 | pcs_res->res.start);
| ~~~~~~~~~~~~~~~~~~
| |
| resource_size_t {aka unsigned int}
vim +145 drivers/net/dsa/sja1105/sja1105_mfd.c
124
125 static int sja1105_create_pcs_nodes(struct sja1105_private *priv,
126 struct device_node *regs_node)
127 {
128 struct dsa_switch *ds = priv->ds;
129 struct device *dev = ds->dev;
130 struct device_node *pcs_node;
131 const u32 reg_io_width = 4;
132 char node_name[32];
133 u32 reg_props[2];
134 int rc;
135
136 for (int i = 0; i < priv->info->num_pcs_resources; i++) {
137 const struct sja1105_pcs_resource *pcs_res;
138
139 pcs_res = &priv->info->pcs_resources[i];
140
141 if (sja1105_child_node_exists(regs_node, "ethernet-pcs",
142 &pcs_res->res))
143 continue;
144
> 145 snprintf(node_name, sizeof(node_name), "ethernet-pcs@%llx",
146 pcs_res->res.start);
147
148 pcs_node = of_changeset_create_node(&priv->of_cs, regs_node,
149 node_name);
150 if (!pcs_node) {
151 dev_err(dev, "Failed to create PCS node %s\n", node_name);
152 return -ENOMEM;
153 }
154
155 rc = of_changeset_add_prop_string(&priv->of_cs, pcs_node,
156 "compatible",
157 pcs_res->compatible);
158 if (rc) {
159 dev_err(dev, "Failed to add compatible property to %s: %pe\n",
160 node_name, ERR_PTR(rc));
161 return rc;
162 }
163
164 reg_props[0] = pcs_res->res.start;
165 reg_props[1] = resource_size(&pcs_res->res);
166 rc = of_changeset_add_prop_u32_array(&priv->of_cs, pcs_node,
167 "reg", reg_props, 2);
168 if (rc) {
169 dev_err(dev, "Failed to add reg property to %s: %pe\n",
170 node_name, ERR_PTR(rc));
171 return rc;
172 }
173
174 rc = of_changeset_add_prop_string(&priv->of_cs, pcs_node,
175 "reg-names",
176 pcs_res->res.name);
177 if (rc) {
178 dev_err(dev, "Failed to add reg-names property to %s: %pe\n",
179 node_name, ERR_PTR(rc));
180 return rc;
181 }
182
183 rc = of_changeset_add_prop_u32_array(&priv->of_cs, pcs_node,
184 "reg-io-width",
185 ®_io_width, 1);
186 if (rc) {
187 dev_err(dev, "Failed to add reg-io-width property to %s: %pe\n",
188 node_name, ERR_PTR(rc));
189 return rc;
190 }
191
192 dev_dbg(dev, "Created OF node %pOF\n", pcs_node);
193 priv->pcs_fwnode[pcs_res->port] = of_fwnode_handle(pcs_node);
194 }
195
196 return 0;
197 }
198
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-19 11:19 ` kernel test robot
@ 2025-11-19 12:01 ` Vladimir Oltean
2025-11-19 12:03 ` Russell King (Oracle)
0 siblings, 1 reply; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-19 12:01 UTC (permalink / raw)
To: kernel test robot
Cc: netdev, oe-kbuild-all, Andrew Lunn, Heiner Kallweit, Russell King,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel,
Serge Semin, Andy Shevchenko, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
On Wed, Nov 19, 2025 at 07:19:59PM +0800, kernel test robot wrote:
> Hi Vladimir,
>
> kernel test robot noticed the following build warnings:
>
> [auto build test WARNING on net-next/main]
>
> url: https://github.com/intel-lab-lkp/linux/commits/Vladimir-Oltean/net-dsa-sja1105-let-phylink-help-with-the-replay-of-link-callbacks/20251119-031300
> base: net-next/main
> patch link: https://lore.kernel.org/r/20251118190530.580267-15-vladimir.oltean%40nxp.com
> patch subject: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
> config: m68k-allyesconfig (https://download.01.org/0day-ci/archive/20251119/202511191835.rwfD48SW-lkp@intel.com/config)
> compiler: m68k-linux-gcc (GCC) 15.1.0
> reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251119/202511191835.rwfD48SW-lkp@intel.com/reproduce)
>
> If you fix the issue in a separate patch/commit (i.e. not just a new version of
> the same patch/commit), kindly add following tags
> | Reported-by: kernel test robot <lkp@intel.com>
> | Closes: https://lore.kernel.org/oe-kbuild-all/202511191835.rwfD48SW-lkp@intel.com/
>
> All warnings (new ones prefixed by >>):
>
> drivers/net/dsa/sja1105/sja1105_mfd.c: In function 'sja1105_create_pcs_nodes':
> >> drivers/net/dsa/sja1105/sja1105_mfd.c:145:73: warning: format '%llx' expects argument of type 'long long unsigned int', but argument 4 has type 'resource_size_t' {aka 'unsigned int'} [-Wformat=]
> 145 | snprintf(node_name, sizeof(node_name), "ethernet-pcs@%llx",
> | ~~~^
> | |
> | long long unsigned int
> | %x
> 146 | pcs_res->res.start);
> | ~~~~~~~~~~~~~~~~~~
> | |
> | resource_size_t {aka unsigned int}
I do wonder how to print resource_size_t (typedef to phys_addr_t, which
is typedeffed to u64 or u32 depending on CONFIG_PHYS_ADDR_T_64BIT).
Using %pa should be fine, like drivers/irqchip/irq-gic-v3-its.c does?
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-19 12:01 ` Vladimir Oltean
@ 2025-11-19 12:03 ` Russell King (Oracle)
2025-11-19 12:05 ` Russell King (Oracle)
0 siblings, 1 reply; 54+ messages in thread
From: Russell King (Oracle) @ 2025-11-19 12:03 UTC (permalink / raw)
To: Vladimir Oltean
Cc: kernel test robot, netdev, oe-kbuild-all, Andrew Lunn,
Heiner Kallweit, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel, Serge Semin, Andy Shevchenko, Herve Codina,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree
On Wed, Nov 19, 2025 at 02:01:11PM +0200, Vladimir Oltean wrote:
> I do wonder how to print resource_size_t (typedef to phys_addr_t, which
> is typedeffed to u64 or u32 depending on CONFIG_PHYS_ADDR_T_64BIT).
From the now hard to find Documentation/core-api/printk-formats.rst:
Physical address types phys_addr_t
----------------------------------
::
%pa[p] 0x01234567 or 0x0123456789abcdef
For printing a phys_addr_t type (and its derivatives, such as
resource_size_t) which can vary based on build options, regardless of the
width of the CPU data path.
Passed by reference.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-19 12:03 ` Russell King (Oracle)
@ 2025-11-19 12:05 ` Russell King (Oracle)
2025-11-19 13:28 ` Vladimir Oltean
0 siblings, 1 reply; 54+ messages in thread
From: Russell King (Oracle) @ 2025-11-19 12:05 UTC (permalink / raw)
To: Vladimir Oltean
Cc: kernel test robot, netdev, oe-kbuild-all, Andrew Lunn,
Heiner Kallweit, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel, Serge Semin, Andy Shevchenko, Herve Codina,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree
On Wed, Nov 19, 2025 at 12:03:29PM +0000, Russell King (Oracle) wrote:
> On Wed, Nov 19, 2025 at 02:01:11PM +0200, Vladimir Oltean wrote:
> > I do wonder how to print resource_size_t (typedef to phys_addr_t, which
> > is typedeffed to u64 or u32 depending on CONFIG_PHYS_ADDR_T_64BIT).
>
> From the now hard to find Documentation/core-api/printk-formats.rst:
>
> Physical address types phys_addr_t
> ----------------------------------
>
> ::
>
> %pa[p] 0x01234567 or 0x0123456789abcdef
>
> For printing a phys_addr_t type (and its derivatives, such as
> resource_size_t) which can vary based on build options, regardless of the
> width of the CPU data path.
>
> Passed by reference.
Hmm, but I guess you don't want the 0x prefix. Maybe print it to a
separate buffer and then lop off the first two characters?
Another solution would be to always cast it to a u64 and use %llx as
suggested in the "Integer types" section.
--
RMK's Patch system: https://www.armlinux.org.uk/developer/patches/
FTTP is here! 80Mbps down 10Mbps up. Decent connectivity at last!
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-19 12:05 ` Russell King (Oracle)
@ 2025-11-19 13:28 ` Vladimir Oltean
0 siblings, 0 replies; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-19 13:28 UTC (permalink / raw)
To: Russell King (Oracle)
Cc: kernel test robot, netdev, oe-kbuild-all, Andrew Lunn,
Heiner Kallweit, Eric Dumazet, Jakub Kicinski, Paolo Abeni,
linux-kernel, Serge Semin, Andy Shevchenko, Herve Codina,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree
On Wed, Nov 19, 2025 at 12:05:43PM +0000, Russell King (Oracle) wrote:
> On Wed, Nov 19, 2025 at 12:03:29PM +0000, Russell King (Oracle) wrote:
> > On Wed, Nov 19, 2025 at 02:01:11PM +0200, Vladimir Oltean wrote:
> > > I do wonder how to print resource_size_t (typedef to phys_addr_t, which
> > > is typedeffed to u64 or u32 depending on CONFIG_PHYS_ADDR_T_64BIT).
> >
> > From the now hard to find Documentation/core-api/printk-formats.rst:
I really wasn't aware of this, and I was reading the inline docs from
lib/vsprintf.c all this time... Thanks!
> > Physical address types phys_addr_t
> > ----------------------------------
> >
> > ::
> >
> > %pa[p] 0x01234567 or 0x0123456789abcdef
> >
> > For printing a phys_addr_t type (and its derivatives, such as
> > resource_size_t) which can vary based on build options, regardless of the
> > width of the CPU data path.
> >
> > Passed by reference.
>
> Hmm, but I guess you don't want the 0x prefix. Maybe print it to a
> separate buffer and then lop off the first two characters?
>
> Another solution would be to always cast it to a u64 and use %llx as
> suggested in the "Integer types" section.
Yeah, although I see the ePAPR section on node names doesn't disallow
the 0x prefix for the unit-address, it is just that the established
convention is without it.
By far the most unassuming option seems to be to do explicit type
casting to unsigned long long. I've started a new test build with the
changes made so far.
^ permalink raw reply [flat|nested] 54+ messages in thread
* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-18 19:05 ` [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver Vladimir Oltean
2025-11-19 0:41 ` Jakub Kicinski
2025-11-19 11:19 ` kernel test robot
@ 2025-11-19 12:01 ` kernel test robot
2025-11-20 0:01 ` kernel test robot
3 siblings, 0 replies; 54+ messages in thread
From: kernel test robot @ 2025-11-19 12:01 UTC (permalink / raw)
To: Vladimir Oltean, netdev
Cc: llvm, oe-kbuild-all, Andrew Lunn, Heiner Kallweit, Russell King,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel,
Serge Semin, Andy Shevchenko, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
Hi Vladimir,
kernel test robot noticed the following build warnings:
[auto build test WARNING on net-next/main]
url: https://github.com/intel-lab-lkp/linux/commits/Vladimir-Oltean/net-dsa-sja1105-let-phylink-help-with-the-replay-of-link-callbacks/20251119-031300
base: net-next/main
patch link: https://lore.kernel.org/r/20251118190530.580267-15-vladimir.oltean%40nxp.com
patch subject: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
config: hexagon-randconfig-002-20251119 (https://download.01.org/0day-ci/archive/20251119/202511191946.DzxNhLVl-lkp@intel.com/config)
compiler: clang version 22.0.0git (https://github.com/llvm/llvm-project 0bba1e76581bad04e7d7f09f5115ae5e2989e0d9)
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251119/202511191946.DzxNhLVl-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511191946.DzxNhLVl-lkp@intel.com/
All warnings (new ones prefixed by >>):
>> drivers/net/dsa/sja1105/sja1105_mfd.c:146:5: warning: format specifies type 'unsigned long long' but the argument has type 'resource_size_t' (aka 'unsigned int') [-Wformat]
145 | snprintf(node_name, sizeof(node_name), "ethernet-pcs@%llx",
| ~~~~
| %x
146 | pcs_res->res.start);
| ^~~~~~~~~~~~~~~~~~
1 warning generated.
vim +146 drivers/net/dsa/sja1105/sja1105_mfd.c
124
125 static int sja1105_create_pcs_nodes(struct sja1105_private *priv,
126 struct device_node *regs_node)
127 {
128 struct dsa_switch *ds = priv->ds;
129 struct device *dev = ds->dev;
130 struct device_node *pcs_node;
131 const u32 reg_io_width = 4;
132 char node_name[32];
133 u32 reg_props[2];
134 int rc;
135
136 for (int i = 0; i < priv->info->num_pcs_resources; i++) {
137 const struct sja1105_pcs_resource *pcs_res;
138
139 pcs_res = &priv->info->pcs_resources[i];
140
141 if (sja1105_child_node_exists(regs_node, "ethernet-pcs",
142 &pcs_res->res))
143 continue;
144
145 snprintf(node_name, sizeof(node_name), "ethernet-pcs@%llx",
> 146 pcs_res->res.start);
147
148 pcs_node = of_changeset_create_node(&priv->of_cs, regs_node,
149 node_name);
150 if (!pcs_node) {
151 dev_err(dev, "Failed to create PCS node %s\n", node_name);
152 return -ENOMEM;
153 }
154
155 rc = of_changeset_add_prop_string(&priv->of_cs, pcs_node,
156 "compatible",
157 pcs_res->compatible);
158 if (rc) {
159 dev_err(dev, "Failed to add compatible property to %s: %pe\n",
160 node_name, ERR_PTR(rc));
161 return rc;
162 }
163
164 reg_props[0] = pcs_res->res.start;
165 reg_props[1] = resource_size(&pcs_res->res);
166 rc = of_changeset_add_prop_u32_array(&priv->of_cs, pcs_node,
167 "reg", reg_props, 2);
168 if (rc) {
169 dev_err(dev, "Failed to add reg property to %s: %pe\n",
170 node_name, ERR_PTR(rc));
171 return rc;
172 }
173
174 rc = of_changeset_add_prop_string(&priv->of_cs, pcs_node,
175 "reg-names",
176 pcs_res->res.name);
177 if (rc) {
178 dev_err(dev, "Failed to add reg-names property to %s: %pe\n",
179 node_name, ERR_PTR(rc));
180 return rc;
181 }
182
183 rc = of_changeset_add_prop_u32_array(&priv->of_cs, pcs_node,
184 "reg-io-width",
185 ®_io_width, 1);
186 if (rc) {
187 dev_err(dev, "Failed to add reg-io-width property to %s: %pe\n",
188 node_name, ERR_PTR(rc));
189 return rc;
190 }
191
192 dev_dbg(dev, "Created OF node %pOF\n", pcs_node);
193 priv->pcs_fwnode[pcs_res->port] = of_fwnode_handle(pcs_node);
194 }
195
196 return 0;
197 }
198
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 54+ messages in thread* Re: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
2025-11-18 19:05 ` [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver Vladimir Oltean
` (2 preceding siblings ...)
2025-11-19 12:01 ` kernel test robot
@ 2025-11-20 0:01 ` kernel test robot
3 siblings, 0 replies; 54+ messages in thread
From: kernel test robot @ 2025-11-20 0:01 UTC (permalink / raw)
To: Vladimir Oltean, netdev
Cc: oe-kbuild-all, Andrew Lunn, Heiner Kallweit, Russell King,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel,
Serge Semin, Andy Shevchenko, Herve Codina, Rob Herring,
Krzysztof Kozlowski, Conor Dooley, devicetree
Hi Vladimir,
kernel test robot noticed the following build errors:
[auto build test ERROR on net-next/main]
url: https://github.com/intel-lab-lkp/linux/commits/Vladimir-Oltean/net-dsa-sja1105-let-phylink-help-with-the-replay-of-link-callbacks/20251119-031300
base: net-next/main
patch link: https://lore.kernel.org/r/20251118190530.580267-15-vladimir.oltean%40nxp.com
patch subject: [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver
config: s390-randconfig-002-20251120 (https://download.01.org/0day-ci/archive/20251120/202511200752.hGkPwqbU-lkp@intel.com/config)
compiler: s390-linux-gcc (GCC) 8.5.0
reproduce (this is a W=1 build): (https://download.01.org/0day-ci/archive/20251120/202511200752.hGkPwqbU-lkp@intel.com/reproduce)
If you fix the issue in a separate patch/commit (i.e. not just a new version of
the same patch/commit), kindly add following tags
| Reported-by: kernel test robot <lkp@intel.com>
| Closes: https://lore.kernel.org/oe-kbuild-all/202511200752.hGkPwqbU-lkp@intel.com/
All errors (new ones prefixed by >>):
In file included from include/linux/cpufreq.h:17,
from kernel/sched/sched.h:31,
from kernel/sched/rq-offsets.c:5:
include/linux/of.h: In function 'of_changeset_attach_node':
>> include/linux/of.h:1623:34: error: 'OF_RECONFIG_ATTACH_NODE' undeclared (first use in this function); did you mean 'OF_RECONFIG_NO_CHANGE'?
return of_changeset_action(ocs, OF_RECONFIG_ATTACH_NODE, np, NULL);
^~~~~~~~~~~~~~~~~~~~~~~
OF_RECONFIG_NO_CHANGE
include/linux/of.h:1623:34: note: each undeclared identifier is reported only once for each function it appears in
include/linux/of.h: In function 'of_changeset_detach_node':
>> include/linux/of.h:1629:34: error: 'OF_RECONFIG_DETACH_NODE' undeclared (first use in this function); did you mean 'OF_RECONFIG_NO_CHANGE'?
return of_changeset_action(ocs, OF_RECONFIG_DETACH_NODE, np, NULL);
^~~~~~~~~~~~~~~~~~~~~~~
OF_RECONFIG_NO_CHANGE
include/linux/of.h: In function 'of_changeset_add_property':
>> include/linux/of.h:1635:34: error: 'OF_RECONFIG_ADD_PROPERTY' undeclared (first use in this function); did you mean 'OF_RECONFIG_NO_CHANGE'?
return of_changeset_action(ocs, OF_RECONFIG_ADD_PROPERTY, np, prop);
^~~~~~~~~~~~~~~~~~~~~~~~
OF_RECONFIG_NO_CHANGE
include/linux/of.h: In function 'of_changeset_remove_property':
>> include/linux/of.h:1641:34: error: 'OF_RECONFIG_REMOVE_PROPERTY' undeclared (first use in this function); did you mean 'OF_RECONFIG_CHANGE_REMOVE'?
return of_changeset_action(ocs, OF_RECONFIG_REMOVE_PROPERTY, np, prop);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
OF_RECONFIG_CHANGE_REMOVE
include/linux/of.h: In function 'of_changeset_update_property':
>> include/linux/of.h:1647:34: error: 'OF_RECONFIG_UPDATE_PROPERTY' undeclared (first use in this function); did you mean 'OF_RECONFIG_CHANGE_REMOVE'?
return of_changeset_action(ocs, OF_RECONFIG_UPDATE_PROPERTY, np, prop);
^~~~~~~~~~~~~~~~~~~~~~~~~~~
OF_RECONFIG_CHANGE_REMOVE
make[3]: *** [scripts/Makefile.build:182: kernel/sched/rq-offsets.s] Error 1 shuffle=1571759522
make[3]: Target 'prepare' not remade because of errors.
make[2]: *** [Makefile:1280: prepare0] Error 2 shuffle=1571759522
make[2]: Target 'prepare' not remade because of errors.
make[1]: *** [Makefile:248: __sub-make] Error 2 shuffle=1571759522
make[1]: Target 'prepare' not remade because of errors.
make: *** [Makefile:248: __sub-make] Error 2 shuffle=1571759522
make: Target 'prepare' not remade because of errors.
Kconfig warnings: (for reference only)
WARNING: unmet direct dependencies detected for OF_DYNAMIC
Depends on [n]: OF [=n]
Selected by [m]:
- NET_DSA_SJA1105 [=m] && NETDEVICES [=y] && NET_DSA [=m] && SPI [=y] && PTP_1588_CLOCK_OPTIONAL [=m]
vim +1623 include/linux/of.h
2e8fff668dc14e Rob Herring 2023-03-29 1604
201c910bd6898d Pantelis Antoniou 2014-07-04 1605 #ifdef CONFIG_OF_DYNAMIC
f6892d193fb9d6 Grant Likely 2014-11-21 1606 extern int of_reconfig_notifier_register(struct notifier_block *);
f6892d193fb9d6 Grant Likely 2014-11-21 1607 extern int of_reconfig_notifier_unregister(struct notifier_block *);
f5242e5a883bf1 Grant Likely 2014-11-24 1608 extern int of_reconfig_notify(unsigned long, struct of_reconfig_data *rd);
f5242e5a883bf1 Grant Likely 2014-11-24 1609 extern int of_reconfig_get_state_change(unsigned long action,
f5242e5a883bf1 Grant Likely 2014-11-24 1610 struct of_reconfig_data *arg);
f6892d193fb9d6 Grant Likely 2014-11-21 1611
201c910bd6898d Pantelis Antoniou 2014-07-04 1612 extern void of_changeset_init(struct of_changeset *ocs);
201c910bd6898d Pantelis Antoniou 2014-07-04 1613 extern void of_changeset_destroy(struct of_changeset *ocs);
201c910bd6898d Pantelis Antoniou 2014-07-04 1614 extern int of_changeset_apply(struct of_changeset *ocs);
201c910bd6898d Pantelis Antoniou 2014-07-04 1615 extern int of_changeset_revert(struct of_changeset *ocs);
201c910bd6898d Pantelis Antoniou 2014-07-04 1616 extern int of_changeset_action(struct of_changeset *ocs,
201c910bd6898d Pantelis Antoniou 2014-07-04 1617 unsigned long action, struct device_node *np,
201c910bd6898d Pantelis Antoniou 2014-07-04 1618 struct property *prop);
201c910bd6898d Pantelis Antoniou 2014-07-04 1619
201c910bd6898d Pantelis Antoniou 2014-07-04 1620 static inline int of_changeset_attach_node(struct of_changeset *ocs,
201c910bd6898d Pantelis Antoniou 2014-07-04 1621 struct device_node *np)
201c910bd6898d Pantelis Antoniou 2014-07-04 1622 {
201c910bd6898d Pantelis Antoniou 2014-07-04 @1623 return of_changeset_action(ocs, OF_RECONFIG_ATTACH_NODE, np, NULL);
201c910bd6898d Pantelis Antoniou 2014-07-04 1624 }
201c910bd6898d Pantelis Antoniou 2014-07-04 1625
201c910bd6898d Pantelis Antoniou 2014-07-04 1626 static inline int of_changeset_detach_node(struct of_changeset *ocs,
201c910bd6898d Pantelis Antoniou 2014-07-04 1627 struct device_node *np)
201c910bd6898d Pantelis Antoniou 2014-07-04 1628 {
201c910bd6898d Pantelis Antoniou 2014-07-04 @1629 return of_changeset_action(ocs, OF_RECONFIG_DETACH_NODE, np, NULL);
201c910bd6898d Pantelis Antoniou 2014-07-04 1630 }
201c910bd6898d Pantelis Antoniou 2014-07-04 1631
201c910bd6898d Pantelis Antoniou 2014-07-04 1632 static inline int of_changeset_add_property(struct of_changeset *ocs,
201c910bd6898d Pantelis Antoniou 2014-07-04 1633 struct device_node *np, struct property *prop)
201c910bd6898d Pantelis Antoniou 2014-07-04 1634 {
201c910bd6898d Pantelis Antoniou 2014-07-04 @1635 return of_changeset_action(ocs, OF_RECONFIG_ADD_PROPERTY, np, prop);
201c910bd6898d Pantelis Antoniou 2014-07-04 1636 }
201c910bd6898d Pantelis Antoniou 2014-07-04 1637
201c910bd6898d Pantelis Antoniou 2014-07-04 1638 static inline int of_changeset_remove_property(struct of_changeset *ocs,
201c910bd6898d Pantelis Antoniou 2014-07-04 1639 struct device_node *np, struct property *prop)
201c910bd6898d Pantelis Antoniou 2014-07-04 1640 {
201c910bd6898d Pantelis Antoniou 2014-07-04 @1641 return of_changeset_action(ocs, OF_RECONFIG_REMOVE_PROPERTY, np, prop);
201c910bd6898d Pantelis Antoniou 2014-07-04 1642 }
201c910bd6898d Pantelis Antoniou 2014-07-04 1643
201c910bd6898d Pantelis Antoniou 2014-07-04 1644 static inline int of_changeset_update_property(struct of_changeset *ocs,
201c910bd6898d Pantelis Antoniou 2014-07-04 1645 struct device_node *np, struct property *prop)
201c910bd6898d Pantelis Antoniou 2014-07-04 1646 {
201c910bd6898d Pantelis Antoniou 2014-07-04 @1647 return of_changeset_action(ocs, OF_RECONFIG_UPDATE_PROPERTY, np, prop);
201c910bd6898d Pantelis Antoniou 2014-07-04 1648 }
b544fc2b8606d7 Lizhi Hou 2023-08-15 1649
--
0-DAY CI Kernel Test Service
https://github.com/intel/lkp-tests/wiki
^ permalink raw reply [flat|nested] 54+ messages in thread
* [PATCH net-next 15/15] net: dsa: sja1105: permit finding the XPCS via pcs-handle
2025-11-18 19:05 [PATCH net-next 00/15] Probe SJA1105 DSA children using MFD and dynamic OF nodes Vladimir Oltean
` (13 preceding siblings ...)
2025-11-18 19:05 ` [PATCH net-next 14/15] net: dsa: sja1105: replace mdiobus-pcs with xpcs-plat driver Vladimir Oltean
@ 2025-11-18 19:05 ` Vladimir Oltean
14 siblings, 0 replies; 54+ messages in thread
From: Vladimir Oltean @ 2025-11-18 19:05 UTC (permalink / raw)
To: netdev
Cc: Andrew Lunn, Heiner Kallweit, Russell King, David S. Miller,
Eric Dumazet, Jakub Kicinski, Paolo Abeni, linux-kernel,
Rob Herring, Krzysztof Kozlowski, Conor Dooley, devicetree
This completes support for describing the XPCS in the device tree,
rather than just the case where sja1105_fill_device_tree() populates it.
Having it in the device tree is necessary when configuring lane polarity.
Cc: Rob Herring <robh@kernel.org>
Cc: Krzysztof Kozlowski <krzk+dt@kernel.org>
Cc: Conor Dooley <conor+dt@kernel.org>
Cc: devicetree@vger.kernel.org
Signed-off-by: Vladimir Oltean <vladimir.oltean@nxp.com>
---
drivers/net/dsa/sja1105/sja1105_main.c | 14 +++++++++++++-
1 file changed, 13 insertions(+), 1 deletion(-)
diff --git a/drivers/net/dsa/sja1105/sja1105_main.c b/drivers/net/dsa/sja1105/sja1105_main.c
index 70aecdf9fd0e..e62b2facc1be 100644
--- a/drivers/net/dsa/sja1105/sja1105_main.c
+++ b/drivers/net/dsa/sja1105/sja1105_main.c
@@ -3035,14 +3035,26 @@ static int sja1105_port_bridge_flags(struct dsa_switch *ds, int port,
static int sja1105_create_pcs(struct dsa_switch *ds, int port)
{
+ struct dsa_port *dp = dsa_to_port(ds, port);
struct sja1105_private *priv = ds->priv;
+ struct fwnode_handle *pcs_fwnode;
struct phylink_pcs *pcs;
if (priv->phy_mode[port] != PHY_INTERFACE_MODE_SGMII &&
priv->phy_mode[port] != PHY_INTERFACE_MODE_2500BASEX)
return 0;
- pcs = xpcs_create_pcs_fwnode(priv->pcs_fwnode[port]);
+ pcs_fwnode = fwnode_handle_get(priv->pcs_fwnode[port]);
+ /* priv->pcs_fwnode[port] is only set if the PCS is absent
+ * from the device tree source. If present, there needs to
+ * be a pcs-handle to it.
+ */
+ if (!pcs_fwnode)
+ pcs_fwnode = fwnode_find_reference(of_fwnode_handle(dp->dn),
+ "pcs-handle", 0);
+
+ pcs = xpcs_create_pcs_fwnode(pcs_fwnode);
+ fwnode_handle_put(pcs_fwnode);
if (IS_ERR(pcs))
return PTR_ERR(pcs);
--
2.34.1
^ permalink raw reply related [flat|nested] 54+ messages in thread