* [PATCH net-next v2 0/3] net: mdio: realtek-rtl9300: add bus frequency handling
@ 2026-09-06 8:19 Markus Stockhausen
2026-09-06 8:19 ` [PATCH net-next v2 1/3] dt-bindings: net: realtek,rtl9301-mdio: Add clock-frequency Markus Stockhausen
` (2 more replies)
0 siblings, 3 replies; 10+ messages in thread
From: Markus Stockhausen @ 2026-09-06 8:19 UTC (permalink / raw)
To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
chris.packham, robh, krzk+dt, conor+dt, devicetree
Cc: Markus Stockhausen
The Realtek Otto switch platform consists of four different series
- RTL838x aka maple : 28 port 1G Switches
- RTL839x aka cypress : 52 port 1G Switches
- RTL930x aka longan : 28 port 1G/2.5G/10G Switches
- RTL931x aka mango : 56 port 1G/2.5G/10G Switches
All of them support changing the bus frequency of their one to four
Ethernet MDIO buses, although the available settings differ between
the series. Extend the driver to support this feature.
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
v1 -> v2:
- Describe per-device frequencies in devicetree. (Andrew)
- Add proper per-device frequency checks. (Andrew)
- Use the initialized parent device for dev_warn(). (Sashiko)
- Make clear that otto_emdio_probe_one() currently has an
indentation issue that will be fixed by this series. (Andrew)
- Throw error if RTL839x devicetree has different speeds set
for first and second bus.
v1: https://lore.kernel.org/netdev/20260903122119.2638354-1-markus.stockhausen@gmx.de/
v1 Sashiko: https://sashiko.dev/#/patchset/20260903122119.2638354-1-markus.stockhausen%40gmx.de
Markus Stockhausen (3):
dt-bindings: net: realtek,rtl9301-mdio: Add clock-frequency
net: mdio: realtek-rtl9300: Convert "fwnode" left-overs to "of"
net: mdio: realtek-rtl9300: Support non-default clock frequency
.../bindings/net/realtek,rtl9301-mdio.yaml | 40 +++++++++
drivers/net/mdio/mdio-realtek-rtl9300.c | 89 +++++++++++++++++--
2 files changed, 124 insertions(+), 5 deletions(-)
--
2.55.0
^ permalink raw reply [flat|nested] 10+ messages in thread
* [PATCH net-next v2 1/3] dt-bindings: net: realtek,rtl9301-mdio: Add clock-frequency
2026-09-06 8:19 [PATCH net-next v2 0/3] net: mdio: realtek-rtl9300: add bus frequency handling Markus Stockhausen
@ 2026-09-06 8:19 ` Markus Stockhausen
2026-09-07 17:30 ` Conor Dooley
2026-09-09 3:20 ` netdev-bot+sashiko
2026-09-06 8:19 ` [PATCH net-next v2 2/3] net: mdio: realtek-rtl9300: Convert "fwnode" left-overs to "of" Markus Stockhausen
2026-09-06 8:19 ` [PATCH net-next v2 3/3] net: mdio: realtek-rtl9300: Support non-default clock frequency Markus Stockhausen
2 siblings, 2 replies; 10+ messages in thread
From: Markus Stockhausen @ 2026-09-06 8:19 UTC (permalink / raw)
To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
chris.packham, robh, krzk+dt, conor+dt, devicetree
Cc: Markus Stockhausen
The Realtek Otto Switch ethernet MDIO controller supports different MDC
speeds ranging from 1.25MHz to 10MHz. Document the clock-frequency
attribute for the device tree.
There is neither an official documentation nor any obvious registers that
indicate a dependency to one of the hardware clocks. The usable setup bits
are more like hardcoded values than dividers. Without further details do
not add a clock reference.
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
.../bindings/net/realtek,rtl9301-mdio.yaml | 40 +++++++++++++++++++
1 file changed, 40 insertions(+)
diff --git a/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml b/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml
index 67e0b23a8470..88502d017eed 100644
--- a/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml
+++ b/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml
@@ -56,6 +56,9 @@ patternProperties:
reg:
maxItems: 1
+ clock-frequency:
+ default: 2500000
+
required:
- reg
@@ -71,6 +74,43 @@ required:
- compatible
- reg
+allOf:
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - realtek,rtl8380-mdio
+ - realtek,rtl8381-mdio
+ - realtek,rtl8382-mdio
+ then:
+ patternProperties:
+ '^mdio-bus@[0-3]$':
+ properties:
+ clock-frequency:
+ enum: [2500000, 10000000]
+ - if:
+ properties:
+ compatible:
+ contains:
+ enum:
+ - realtek,rtl8391-mdio
+ - realtek,rtl8392-mdio
+ - realtek,rtl8393-mdio
+ - realtek,rtl9301-mdio
+ - realtek,rtl9302b-mdio
+ - realtek,rtl9302c-mdio
+ - realtek,rtl9303-mdio
+ - realtek,rtl9311-mdio
+ - realtek,rtl9312-mdio
+ - realtek,rtl9313-mdio
+ then:
+ patternProperties:
+ '^mdio-bus@[0-3]$':
+ properties:
+ clock-frequency:
+ enum: [1250000, 2500000, 5000000]
+
unevaluatedProperties: false
examples:
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next v2 2/3] net: mdio: realtek-rtl9300: Convert "fwnode" left-overs to "of"
2026-09-06 8:19 [PATCH net-next v2 0/3] net: mdio: realtek-rtl9300: add bus frequency handling Markus Stockhausen
2026-09-06 8:19 ` [PATCH net-next v2 1/3] dt-bindings: net: realtek,rtl9301-mdio: Add clock-frequency Markus Stockhausen
@ 2026-09-06 8:19 ` Markus Stockhausen
2026-09-08 0:39 ` Andrew Lunn
2026-09-09 3:20 ` netdev-bot+sashiko
2026-09-06 8:19 ` [PATCH net-next v2 3/3] net: mdio: realtek-rtl9300: Support non-default clock frequency Markus Stockhausen
2 siblings, 2 replies; 10+ messages in thread
From: Markus Stockhausen @ 2026-09-06 8:19 UTC (permalink / raw)
To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
chris.packham, robh, krzk+dt, conor+dt, devicetree
Cc: Markus Stockhausen
The latest developments of the MDIO driver consistently used the
"of" API. Convert the remaining "fwnode" left-overs too. With this
align the continued parameter of otto_emdio_probe_one() with the
opening parenthesis to follow the kernel coding style.
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
drivers/net/mdio/mdio-realtek-rtl9300.c | 8 ++++----
1 file changed, 4 insertions(+), 4 deletions(-)
diff --git a/drivers/net/mdio/mdio-realtek-rtl9300.c b/drivers/net/mdio/mdio-realtek-rtl9300.c
index 11d078ef941c..429321e9114f 100644
--- a/drivers/net/mdio/mdio-realtek-rtl9300.c
+++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
@@ -831,14 +831,14 @@ static void otto_emdio_notify_phy_detach(struct phy_device *phydev)
}
static int otto_emdio_probe_one(struct device *dev, struct otto_emdio_priv *priv,
- struct fwnode_handle *node)
+ struct device_node *node)
{
struct otto_emdio_chan *chan;
struct mii_bus *bus;
u32 mdio_bus;
int err;
- err = fwnode_property_read_u32(node, "reg", &mdio_bus);
+ err = of_property_read_u32(node, "reg", &mdio_bus);
if (err)
return dev_err_probe(dev, err, "undefined smi bus number\n");
@@ -865,7 +865,7 @@ static int otto_emdio_probe_one(struct device *dev, struct otto_emdio_priv *priv
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", dev_name(dev), mdio_bus);
- err = devm_of_mdiobus_register(dev, bus, to_of_node(node));
+ err = devm_of_mdiobus_register(dev, bus, node);
if (err)
return dev_err_probe(dev, err, "cannot register MDIO bus\n");
@@ -1027,7 +1027,7 @@ static int otto_emdio_probe(struct platform_device *pdev)
return dev_err_probe(dev, err, "failed to setup MDIO bus controller\n");
}
- device_for_each_child_node_scoped(dev, child) {
+ for_each_child_of_node_scoped(dev->of_node, child) {
err = otto_emdio_probe_one(dev, priv, child);
if (err)
return err;
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* [PATCH net-next v2 3/3] net: mdio: realtek-rtl9300: Support non-default clock frequency
2026-09-06 8:19 [PATCH net-next v2 0/3] net: mdio: realtek-rtl9300: add bus frequency handling Markus Stockhausen
2026-09-06 8:19 ` [PATCH net-next v2 1/3] dt-bindings: net: realtek,rtl9301-mdio: Add clock-frequency Markus Stockhausen
2026-09-06 8:19 ` [PATCH net-next v2 2/3] net: mdio: realtek-rtl9300: Convert "fwnode" left-overs to "of" Markus Stockhausen
@ 2026-09-06 8:19 ` Markus Stockhausen
2026-09-08 0:41 ` Andrew Lunn
2026-09-09 3:20 ` netdev-bot+sashiko
2 siblings, 2 replies; 10+ messages in thread
From: Markus Stockhausen @ 2026-09-06 8:19 UTC (permalink / raw)
To: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
chris.packham, robh, krzk+dt, conor+dt, devicetree
Cc: Markus Stockhausen
The ethernet MDIO controller of the Realtek Otto switches has a default
MDC clock frequency of 2.5MHz. Via configuration bits one can adapt this.
Depending on the series the following can be set
- RTL838x: 2.5 Mhz, 10 MHz
- RTL839x, RTL930x, RTL931x: 1.25 MHz, 2.5 MHz, 5 Mhz
Enhance the driver so it allows to set the clock frequency via device
tree. This helps to
- simplify protocol analysis with a logic analyzer (lower speeds)
- reduce MDIO access times during normal operation (higher speeds)
Note: While the devices normally support a per-bus frequency selection,
the RTL839x is an exception from that. It can only select the speed for
both buses globally. To avoid device tree special treatment for this,
use the per-bus speeds for this series too. Return an error if the
RTL839x Devicetree specifies different frequencies for the first and
second bus.
Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
---
drivers/net/mdio/mdio-realtek-rtl9300.c | 81 ++++++++++++++++++++++++-
1 file changed, 80 insertions(+), 1 deletion(-)
diff --git a/drivers/net/mdio/mdio-realtek-rtl9300.c b/drivers/net/mdio/mdio-realtek-rtl9300.c
index 429321e9114f..8edb0ba0bcdd 100644
--- a/drivers/net/mdio/mdio-realtek-rtl9300.c
+++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
@@ -130,6 +130,7 @@
#define RTL8380_NUM_PAGES 4096
#define RTL8380_NUM_PORTS 28
#define RTL8380_SMI_GLB_CTRL 0xa100
+#define RTL8380_SMI_FREQ_SEL BIT(1)
#define RTL8380_SMI_PHY_PATCH_DONE BIT(15)
#define RTL8380_SMI_ACCESS_PHY_CTRL_0 0xa1b8
#define RTL8380_SMI_ACCESS_PHY_CTRL_1 0xa1bc
@@ -169,12 +170,15 @@
#define RTL8390_PHYREG_PORT_CTRL_LOW 0x03e4
#define RTL8390_PHYREG_PORT_CTRL_HIGH 0x03e8
#define RTL8390_SMI_PORT_POLLING_CTRL 0x03fc
+#define RTL8390_SMI_GLB_CTRL 0x03f8
+#define RTL8390_SMI_FREQ_SEL GENMASK(6, 5)
#define RTL9300_NUM_BUSES 4
#define RTL9300_NUM_PAGES 4096
#define RTL9300_NUM_PORTS 28
#define RTL9300_SMI_GLB_CTRL 0xca00
#define RTL9300_GLB_CTRL_INTF_SEL(intf) BIT(16 + (intf))
+#define RTL9300_SMI_FREQ_SEL(intf) GENMASK((intf) * 2 + 9, (intf) * 2 + 8)
#define RTL9300_SMI_PORT0_15_POLLING_SEL 0xca08
#define RTL9300_SMI_ACCESS_PHY_CTRL_0 0xcb70
#define RTL9300_SMI_ACCESS_PHY_CTRL_1 0xcb74
@@ -196,6 +200,8 @@
#define RTL9310_NUM_BUSES 4
#define RTL9310_NUM_PAGES 8192
#define RTL9310_NUM_PORTS 56
+#define RTL9310_SMI_GLB_CTRL0 0x0cc0
+#define RTL9310_SMI_FREQ_SEL(intf) GENMASK((intf) * 2 + 5, (intf) * 2 + 4)
#define RTL9310_SMI_GLB_CTRL1 0x0cbc
#define RTL9310_SMI_GLB_FMT_SEL_C45(intf) BIT((intf) * 2 + 1)
#define RTL9310_SMI_INDRT_ACCESS_CTRL_0 0x0c00
@@ -251,6 +257,7 @@ struct otto_emdio_priv {
struct regmap *regmap;
struct mutex lock; /* protect HW access */
DECLARE_BITMAP(valid_ports, MAX_PORTS);
+ u32 global_freq;
u16 page[MAX_PORTS];
u8 smi_bus[MAX_PORTS];
u8 smi_addr[MAX_PORTS];
@@ -269,6 +276,7 @@ struct otto_emdio_info {
u8 num_ports;
u16 num_pages;
u32 poll_ctrl;
+ int (*set_bus_frequency)(struct mii_bus *bus, u32 freq);
int (*setup_controller)(struct otto_emdio_priv *priv);
int (*read_c22)(struct mii_bus *bus, int port, int regnum, u32 *value);
int (*read_c45)(struct mii_bus *bus, int port, int dev_addr, int regnum, u32 *value);
@@ -740,6 +748,17 @@ static int otto_emdio_setup_topology(struct otto_emdio_priv *priv)
return 0;
}
+static int otto_emdio_8380_set_bus_frequency(struct mii_bus *bus, u32 freq)
+{
+ struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
+
+ if (freq != 2500000 && freq != 10000000)
+ return -EINVAL;
+
+ return regmap_assign_bits(priv->regmap, RTL8380_SMI_GLB_CTRL,
+ RTL8380_SMI_FREQ_SEL, freq == 10000000);
+}
+
static int otto_emdio_8380_setup_controller(struct otto_emdio_priv *priv)
{
/*
@@ -749,6 +768,40 @@ static int otto_emdio_8380_setup_controller(struct otto_emdio_priv *priv)
return regmap_set_bits(priv->regmap, RTL8380_SMI_GLB_CTRL, RTL8380_SMI_PHY_PATCH_DONE);
}
+static int otto_emdio_8390_set_bus_frequency(struct mii_bus *bus, u32 freq)
+{
+ struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
+ u32 val;
+ int err;
+
+ if (freq != 1250000 && freq != 2500000 && freq != 5000000)
+ return -EINVAL;
+ if (priv->global_freq)
+ return freq == priv->global_freq ? 0 : -EINVAL;
+
+ val = FIELD_PREP(RTL8390_SMI_FREQ_SEL, freq / 2500000);
+ err = regmap_update_bits(priv->regmap, RTL8390_SMI_GLB_CTRL, RTL8390_SMI_FREQ_SEL, val);
+ if (!err)
+ priv->global_freq = freq;
+
+ return err;
+}
+
+static int otto_emdio_9300_set_bus_frequency(struct mii_bus *bus, u32 freq)
+{
+ struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
+ struct otto_emdio_chan *chan = bus->priv;
+ u32 mask, val;
+
+ if (freq != 1250000 && freq != 2500000 && freq != 5000000)
+ return -EINVAL;
+
+ mask = RTL9300_SMI_FREQ_SEL(chan->mdio_bus);
+ val = field_prep(mask, freq / 2500000);
+
+ return regmap_update_bits(priv->regmap, RTL9300_SMI_GLB_CTRL, mask, val);
+}
+
static int otto_emdio_9300_setup_controller(struct otto_emdio_priv *priv)
{
u32 glb_ctrl_mask = 0, glb_ctrl_val = 0;
@@ -769,6 +822,21 @@ static int otto_emdio_9300_setup_controller(struct otto_emdio_priv *priv)
return 0;
}
+static int otto_emdio_9310_set_bus_frequency(struct mii_bus *bus, u32 freq)
+{
+ struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
+ struct otto_emdio_chan *chan = bus->priv;
+ u32 mask, val;
+
+ if (freq != 1250000 && freq != 2500000 && freq != 5000000)
+ return -EINVAL;
+
+ mask = RTL9310_SMI_FREQ_SEL(chan->mdio_bus);
+ val = field_prep(mask, freq / 2500000);
+
+ return regmap_update_bits(priv->regmap, RTL9310_SMI_GLB_CTRL0, mask, val);
+}
+
static int otto_emdio_9310_setup_controller(struct otto_emdio_priv *priv)
{
int i, err;
@@ -835,7 +903,7 @@ static int otto_emdio_probe_one(struct device *dev, struct otto_emdio_priv *priv
{
struct otto_emdio_chan *chan;
struct mii_bus *bus;
- u32 mdio_bus;
+ u32 mdio_bus, freq;
int err;
err = of_property_read_u32(node, "reg", &mdio_bus);
@@ -865,6 +933,13 @@ static int otto_emdio_probe_one(struct device *dev, struct otto_emdio_priv *priv
snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", dev_name(dev), mdio_bus);
+ if (of_property_read_u32(node, "clock-frequency", &freq))
+ freq = 2500000;
+ err = priv->info->set_bus_frequency(bus, freq);
+ if (err)
+ return dev_err_probe(dev, err, "cannot set frequency %u for MDIO bus %d\n",
+ freq, mdio_bus);
+
err = devm_of_mdiobus_register(dev, bus, node);
if (err)
return dev_err_probe(dev, err, "cannot register MDIO bus\n");
@@ -1051,6 +1126,7 @@ static const struct otto_emdio_info otto_emdio_8380_info = {
.num_pages = RTL8380_NUM_PAGES,
.num_ports = RTL8380_NUM_PORTS,
.poll_ctrl = RTL8380_SMI_POLL_CTRL,
+ .set_bus_frequency = otto_emdio_8380_set_bus_frequency,
.setup_controller = otto_emdio_8380_setup_controller,
.read_c22 = otto_emdio_8380_read_c22,
.read_c45 = otto_emdio_8380_read_c45,
@@ -1075,6 +1151,7 @@ static const struct otto_emdio_info otto_emdio_8390_info = {
.num_pages = RTL8390_NUM_PAGES,
.num_ports = RTL8390_NUM_PORTS,
.poll_ctrl = RTL8390_SMI_PORT_POLLING_CTRL,
+ .set_bus_frequency = otto_emdio_8390_set_bus_frequency,
.read_c22 = otto_emdio_8390_read_c22,
.read_c45 = otto_emdio_8390_read_c45,
.write_c22 = otto_emdio_8390_write_c22,
@@ -1097,6 +1174,7 @@ static const struct otto_emdio_info otto_emdio_9300_info = {
.num_ports = RTL9300_NUM_PORTS,
.num_pages = RTL9300_NUM_PAGES,
.poll_ctrl = RTL9300_SMI_POLL_CTRL,
+ .set_bus_frequency = otto_emdio_9300_set_bus_frequency,
.setup_controller = otto_emdio_9300_setup_controller,
.read_c22 = otto_emdio_9300_read_c22,
.read_c45 = otto_emdio_9300_read_c45,
@@ -1123,6 +1201,7 @@ static const struct otto_emdio_info otto_emdio_9310_info = {
.num_pages = RTL9310_NUM_PAGES,
.num_ports = RTL9310_NUM_PORTS,
.poll_ctrl = RTL9310_SMI_PORT_POLLING_CTRL,
+ .set_bus_frequency = otto_emdio_9310_set_bus_frequency,
.setup_controller = otto_emdio_9310_setup_controller,
.read_c22 = otto_emdio_9310_read_c22,
.read_c45 = otto_emdio_9310_read_c45,
--
2.55.0
^ permalink raw reply related [flat|nested] 10+ messages in thread
* Re: [PATCH net-next v2 1/3] dt-bindings: net: realtek,rtl9301-mdio: Add clock-frequency
2026-09-06 8:19 ` [PATCH net-next v2 1/3] dt-bindings: net: realtek,rtl9301-mdio: Add clock-frequency Markus Stockhausen
@ 2026-09-07 17:30 ` Conor Dooley
2026-09-09 3:20 ` netdev-bot+sashiko
1 sibling, 0 replies; 10+ messages in thread
From: Conor Dooley @ 2026-09-07 17:30 UTC (permalink / raw)
To: Markus Stockhausen
Cc: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
chris.packham, robh, krzk+dt, conor+dt, devicetree
[-- Attachment #1: Type: text/plain, Size: 52 bytes --]
Acked-by: Conor Dooley <conor.dooley@microchip.com>
[-- Attachment #2: signature.asc --]
[-- Type: application/pgp-signature, Size: 228 bytes --]
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net-next v2 2/3] net: mdio: realtek-rtl9300: Convert "fwnode" left-overs to "of"
2026-09-06 8:19 ` [PATCH net-next v2 2/3] net: mdio: realtek-rtl9300: Convert "fwnode" left-overs to "of" Markus Stockhausen
@ 2026-09-08 0:39 ` Andrew Lunn
2026-09-09 3:20 ` netdev-bot+sashiko
1 sibling, 0 replies; 10+ messages in thread
From: Andrew Lunn @ 2026-09-08 0:39 UTC (permalink / raw)
To: Markus Stockhausen
Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
chris.packham, robh, krzk+dt, conor+dt, devicetree
On Sun, Sep 06, 2026 at 10:19:45AM +0200, Markus Stockhausen wrote:
> The latest developments of the MDIO driver consistently used the
> "of" API. Convert the remaining "fwnode" left-overs too. With this
> align the continued parameter of otto_emdio_probe_one() with the
> opening parenthesis to follow the kernel coding style.
>
> Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net-next v2 3/3] net: mdio: realtek-rtl9300: Support non-default clock frequency
2026-09-06 8:19 ` [PATCH net-next v2 3/3] net: mdio: realtek-rtl9300: Support non-default clock frequency Markus Stockhausen
@ 2026-09-08 0:41 ` Andrew Lunn
2026-09-09 3:20 ` netdev-bot+sashiko
1 sibling, 0 replies; 10+ messages in thread
From: Andrew Lunn @ 2026-09-08 0:41 UTC (permalink / raw)
To: Markus Stockhausen
Cc: hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
chris.packham, robh, krzk+dt, conor+dt, devicetree
On Sun, Sep 06, 2026 at 10:19:46AM +0200, Markus Stockhausen wrote:
> The ethernet MDIO controller of the Realtek Otto switches has a default
> MDC clock frequency of 2.5MHz. Via configuration bits one can adapt this.
> Depending on the series the following can be set
>
> - RTL838x: 2.5 Mhz, 10 MHz
> - RTL839x, RTL930x, RTL931x: 1.25 MHz, 2.5 MHz, 5 Mhz
>
> Enhance the driver so it allows to set the clock frequency via device
> tree. This helps to
>
> - simplify protocol analysis with a logic analyzer (lower speeds)
> - reduce MDIO access times during normal operation (higher speeds)
>
> Note: While the devices normally support a per-bus frequency selection,
> the RTL839x is an exception from that. It can only select the speed for
> both buses globally. To avoid device tree special treatment for this,
> use the per-bus speeds for this series too. Return an error if the
> RTL839x Devicetree specifies different frequencies for the first and
> second bus.
>
> Signed-off-by: Markus Stockhausen <markus.stockhausen@gmx.de>
Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Andrew
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net-next v2 1/3] dt-bindings: net: realtek,rtl9301-mdio: Add clock-frequency
2026-09-06 8:19 ` [PATCH net-next v2 1/3] dt-bindings: net: realtek,rtl9301-mdio: Add clock-frequency Markus Stockhausen
2026-09-07 17:30 ` Conor Dooley
@ 2026-09-09 3:20 ` netdev-bot+sashiko
1 sibling, 0 replies; 10+ messages in thread
From: netdev-bot+sashiko @ 2026-09-09 3:20 UTC (permalink / raw)
To: markus.stockhausen
Cc: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
chris.packham, robh, krzk+dt, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:
Critical: 0 · High: 0 · Medium: 0 · Low: 1
- [Low] Concern (validated as a FALSE POSITIVE, retained only because
requires_validation=true): the claim is that the new `clock-frequency`…
--
dt-bindings: net: realtek,rtl9301-mdio: Add clock-frequency
This documents a per-bus clock-frequency property for the Realtek Otto
switch MDIO controller, with a default of 2.5MHz and per-family enums of
the supported MDC rates. No clock reference is added because the setup
bits do not look like dividers of a known hardware clock.
> diff --git a/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml b/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml
> index 67e0b23a8470e..88502d017eedb 100644
> --- a/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml
> +++ b/Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml
> @@ -56,6 +56,9 @@ patternProperties:
> reg:
> maxItems: 1
>
> + clock-frequency:
> + default: 2500000
> +
[Severity: Low]
This isn't a bug, just a note on ordering for anyone reading this patch
standalone: at this commit nothing in tree reads clock-frequency for this
binding, so on its own the property and the documented 2.5MHz default are
not yet implemented.
The consumer arrives later in the same series, in
drivers/net/mdio/mdio-realtek-rtl9300.c:otto_emdio_probe_one():
if (of_property_read_u32(node, "clock-frequency", &freq))
freq = 2500000;
err = priv->info->set_bus_frequency(bus, freq);
if (err)
return dev_err_probe(dev, err, "cannot set frequency %u for MDIO bus %d\n",
freq, mdio_bus);
with per-family .set_bus_frequency callbacks whose accepted values match
the enums added below, so the schema and the driver agree once the whole
series is applied. Nothing to change here.
> required:
> - reg
>
> @@ -71,6 +74,43 @@ required:
> - compatible
> - reg
>
> +allOf:
> + - if:
> + properties:
> + compatible:
> + contains:
> + enum:
> + - realtek,rtl8380-mdio
> + - realtek,rtl8381-mdio
> + - realtek,rtl8382-mdio
> + then:
> + patternProperties:
> + '^mdio-bus@[0-3]$':
> + properties:
> + clock-frequency:
> + enum: [2500000, 10000000]
[ ... ]
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260906081946.3499898-1-markus.stockhausen%40gmx.de
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net-next v2 2/3] net: mdio: realtek-rtl9300: Convert "fwnode" left-overs to "of"
2026-09-06 8:19 ` [PATCH net-next v2 2/3] net: mdio: realtek-rtl9300: Convert "fwnode" left-overs to "of" Markus Stockhausen
2026-09-08 0:39 ` Andrew Lunn
@ 2026-09-09 3:20 ` netdev-bot+sashiko
1 sibling, 0 replies; 10+ messages in thread
From: netdev-bot+sashiko @ 2026-09-09 3:20 UTC (permalink / raw)
To: markus.stockhausen
Cc: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
chris.packham, robh, krzk+dt, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:
Critical: 0 · High: 1 · Medium: 0 · Low: 0
- [High] Non-equivalent API conversion in otto_emdio_probe(): replacing
`device_for_each_child_node_scoped(dev, child)` with…
--
net: mdio: realtek-rtl9300: Convert "fwnode" left-overs to "of"
This converts the remaining fwnode based property/child-node accesses in
the rtl9300 MDIO driver over to the OF API, and re-indents the
continuation line of otto_emdio_probe_one().
> diff --git a/drivers/net/mdio/mdio-realtek-rtl9300.c b/drivers/net/mdio/mdio-realtek-rtl9300.c
> index 11d078ef941cd..429321e9114fd 100644
> --- a/drivers/net/mdio/mdio-realtek-rtl9300.c
> +++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
> @@ -831,14 +831,14 @@ static void otto_emdio_notify_phy_detach(struct phy_device *phydev)
> }
>
> static int otto_emdio_probe_one(struct device *dev, struct otto_emdio_priv *priv,
> - struct fwnode_handle *node)
> + struct device_node *node)
> {
> struct otto_emdio_chan *chan;
> struct mii_bus *bus;
> u32 mdio_bus;
> int err;
>
> - err = fwnode_property_read_u32(node, "reg", &mdio_bus);
> + err = of_property_read_u32(node, "reg", &mdio_bus);
> if (err)
> return dev_err_probe(dev, err, "undefined smi bus number\n");
>
> @@ -865,7 +865,7 @@ static int otto_emdio_probe_one(struct device *dev, struct otto_emdio_priv *priv
>
> snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", dev_name(dev), mdio_bus);
>
> - err = devm_of_mdiobus_register(dev, bus, to_of_node(node));
> + err = devm_of_mdiobus_register(dev, bus, node);
> if (err)
> return dev_err_probe(dev, err, "cannot register MDIO bus\n");
>
> @@ -1027,7 +1027,7 @@ static int otto_emdio_probe(struct platform_device *pdev)
> return dev_err_probe(dev, err, "failed to setup MDIO bus controller\n");
> }
>
> - device_for_each_child_node_scoped(dev, child) {
> + for_each_child_of_node_scoped(dev->of_node, child) {
[Severity: High]
Is this iterator swap intended to be behaviour preserving? The two
iterators differ in whether they honour the DT status property.
The old one dispatched into the OF fwnode ops:
drivers/of/property.c:of_fwnode_get_next_child_node() {
return of_fwnode_handle(of_get_next_available_child(to_of_node(fwnode),
to_of_node(child)));
}
The new one does not filter:
include/linux/of.h
#define for_each_child_of_node_scoped(parent, child) \
for (struct device_node *child __free(device_node) = \
of_get_next_child(parent, NULL); \
child != NULL; \
child = of_get_next_child(parent, child))
So nodes with status = "disabled" now reach otto_emdio_probe_one().
Does that turn a disabled bus child into a probe failure for the whole
controller? A disabled mdio-bus@N node still has a valid reg, so it
passes the reg and num_buses checks and ends up in:
err = devm_of_mdiobus_register(dev, bus, node);
if (err)
return dev_err_probe(dev, err, "cannot register MDIO bus\n");
which reaches:
drivers/net/mdio/of_mdio.c:__of_mdiobus_register() {
/* Do not continue if the node is disabled */
if (!of_device_is_available(np))
return -ENODEV;
and otto_emdio_probe() propagates that error immediately:
for_each_child_of_node_scoped(dev->of_node, child) {
err = otto_emdio_probe_one(dev, priv, child);
if (err)
return err;
}
Previously the disabled child was skipped and the enabled buses still
came up.
This looks reachable with in-tree DT: arch/mips/boot/dts/realtek/rtl930x.dtsi
ships all four mdio-bus@0..3 children with status = "disabled", so boards
that enable the controller plus only the buses they use would now fail
probe entirely.
There is also a CONFIG_OF_MDIO=n variant of the same concern: the stub
devm_of_mdiobus_register() in include/linux/of_mdio.h forwards to
devm_mdiobus_register() with no availability check, so a DT-disabled bus
would be registered and address-scanned instead.
Finally, the sibling OF walk in the same driver still filters on
availability:
for_each_available_child_of_node_scoped(ports_dn, port_dn) {
so otto_emdio_map_ports() and the bus enumeration would no longer agree on
which nodes are usable. Would for_each_available_child_of_node_scoped(dev->of_node, child)
be the equivalent conversion here?
Note this is still present at the end of the series, in otto_emdio_probe()
at e4ad7bb3a35d ("net: mdio: realtek-rtl9300: Support non-default clock
frequency").
> err = otto_emdio_probe_one(dev, priv, child);
> if (err)
> return err;
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260906081946.3499898-1-markus.stockhausen%40gmx.de
^ permalink raw reply [flat|nested] 10+ messages in thread
* Re: [PATCH net-next v2 3/3] net: mdio: realtek-rtl9300: Support non-default clock frequency
2026-09-06 8:19 ` [PATCH net-next v2 3/3] net: mdio: realtek-rtl9300: Support non-default clock frequency Markus Stockhausen
2026-09-08 0:41 ` Andrew Lunn
@ 2026-09-09 3:20 ` netdev-bot+sashiko
1 sibling, 0 replies; 10+ messages in thread
From: netdev-bot+sashiko @ 2026-09-09 3:20 UTC (permalink / raw)
To: markus.stockhausen
Cc: andrew, hkallweit1, linux, davem, edumazet, kuba, pabeni, netdev,
chris.packham, robh, krzk+dt, conor+dt, devicetree
Thank you for your contribution! Sashiko AI review found 1 potential
issue(s) to consider:
Critical: 0 · High: 1 · Medium: 0 · Low: 0
- [High] RTL839x: a device tree that is fully valid against
realtek,rtl9301-mdio.yaml can make the entire MDIO controller fail to…
--
net: mdio: realtek-rtl9300: Support non-default clock frequency
This adds a per-family set_bus_frequency() callback so the MDC clock of
the Realtek Otto MDIO controllers can be selected from the device tree
via clock-frequency, defaulting to 2.5 MHz. RTL839x only has a single
global frequency field, so the driver caches the first programmed value
and rejects a second bus asking for something else.
> diff --git a/drivers/net/mdio/mdio-realtek-rtl9300.c b/drivers/net/mdio/mdio-realtek-rtl9300.c
> index 429321e9114fd..8edb0ba0bcdd1 100644
> --- a/drivers/net/mdio/mdio-realtek-rtl9300.c
> +++ b/drivers/net/mdio/mdio-realtek-rtl9300.c
[ ... ]
> @@ -749,6 +768,40 @@ static int otto_emdio_8380_setup_controller(struct otto_emdio_priv *priv)
> return regmap_set_bits(priv->regmap, RTL8380_SMI_GLB_CTRL, RTL8380_SMI_PHY_PATCH_DONE);
> }
>
> +static int otto_emdio_8390_set_bus_frequency(struct mii_bus *bus, u32 freq)
> +{
> + struct otto_emdio_priv *priv = otto_emdio_bus_to_priv(bus);
> + u32 val;
> + int err;
> +
> + if (freq != 1250000 && freq != 2500000 && freq != 5000000)
> + return -EINVAL;
> + if (priv->global_freq)
> + return freq == priv->global_freq ? 0 : -EINVAL;
> +
> + val = FIELD_PREP(RTL8390_SMI_FREQ_SEL, freq / 2500000);
> + err = regmap_update_bits(priv->regmap, RTL8390_SMI_GLB_CTRL, RTL8390_SMI_FREQ_SEL, val);
> + if (!err)
> + priv->global_freq = freq;
> +
> + return err;
> +}
[Severity: High]
Can a device tree that is valid against realtek,rtl9301-mdio.yaml make the
whole RTL839x controller fail to probe here?
The binding describes clock-frequency as an independent per-bus property of
each mdio-bus@N child, with an implicit default:
Documentation/devicetree/bindings/net/realtek,rtl9301-mdio.yaml
clock-frequency:
default: 2500000
and the realtek,rtl8391-mdio / rtl8392-mdio / rtl8393-mdio conditional only
restricts the allowed values per child bus:
clock-frequency:
enum: [1250000, 2500000, 5000000]
There is nothing in the schema requiring the two RTL839x child buses to name
the same frequency, so the natural way to express "set the shared field to
5 MHz" is:
mdio-bus@0 {
reg = <0>;
clock-frequency = <5000000>;
...
};
mdio-bus@1 {
reg = <1>;
...
};
Because otto_emdio_probe_one() substitutes the default before calling the
callback:
if (of_property_read_u32(node, "clock-frequency", &freq))
freq = 2500000;
an absent property is indistinguishable from an explicit 2.5 MHz request.
Doesn't that mean the second bus reaches
otto_emdio_8390_set_bus_frequency() with freq = 2500000 while
priv->global_freq is already 5000000, and
if (priv->global_freq)
return freq == priv->global_freq ? 0 : -EINVAL;
returns -EINVAL for a device tree that never asked for two different
frequencies? The reverse node ordering fails the same way.
otto_emdio_probe() aborts on the first failing child:
for_each_child_of_node_scoped(dev->of_node, child) {
err = otto_emdio_probe_one(dev, priv, child);
if (err)
return err;
}
so no MDIO bus is registered at all and none of the PHYs behind the switch
are reachable. The message "cannot set frequency 2500000 for MDIO bus 1"
also does not point at anything the device tree actually contains.
Would it make sense to either express the RTL839x restriction in the binding
(a controller level property or a dedicated conditional/schema), or to treat
an absent per-bus clock-frequency as "no constraint" instead of an explicit
2.5 MHz request, so that a schema legal device tree keeps probing?
> +
> static int otto_emdio_9300_set_bus_frequency(struct mii_bus *bus, u32 freq)
[ ... ]
> @@ -865,6 +933,13 @@ static int otto_emdio_probe_one(struct device *dev, struct otto_emdio_priv *priv
>
> snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", dev_name(dev), mdio_bus);
>
> + if (of_property_read_u32(node, "clock-frequency", &freq))
> + freq = 2500000;
> + err = priv->info->set_bus_frequency(bus, freq);
> + if (err)
> + return dev_err_probe(dev, err, "cannot set frequency %u for MDIO bus %d\n",
> + freq, mdio_bus);
> +
> err = devm_of_mdiobus_register(dev, bus, node);
> if (err)
> return dev_err_probe(dev, err, "cannot register MDIO bus\n");
[ ... ]
--
Sashiko AI review · https://netdev-ai.bots.linux.dev/sashiko/#/patchset/20260906081946.3499898-1-markus.stockhausen%40gmx.de
^ permalink raw reply [flat|nested] 10+ messages in thread
end of thread, other threads:[~2026-09-09 3:20 UTC | newest]
Thread overview: 10+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2026-09-06 8:19 [PATCH net-next v2 0/3] net: mdio: realtek-rtl9300: add bus frequency handling Markus Stockhausen
2026-09-06 8:19 ` [PATCH net-next v2 1/3] dt-bindings: net: realtek,rtl9301-mdio: Add clock-frequency Markus Stockhausen
2026-09-07 17:30 ` Conor Dooley
2026-09-09 3:20 ` netdev-bot+sashiko
2026-09-06 8:19 ` [PATCH net-next v2 2/3] net: mdio: realtek-rtl9300: Convert "fwnode" left-overs to "of" Markus Stockhausen
2026-09-08 0:39 ` Andrew Lunn
2026-09-09 3:20 ` netdev-bot+sashiko
2026-09-06 8:19 ` [PATCH net-next v2 3/3] net: mdio: realtek-rtl9300: Support non-default clock frequency Markus Stockhausen
2026-09-08 0:41 ` Andrew Lunn
2026-09-09 3:20 ` netdev-bot+sashiko
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox