* [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
* 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 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
* [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
* 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 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
* [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 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 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