Skip to content

Commit 771089c

Browse files
ffainellikuba-moo
authored andcommitted
net: dsa: bcm_sf2: Ensure that MDIO diversion is used
Registering our slave MDIO bus outside of the OF infrastructure is necessary in order to avoid creating double references of the same Device Tree nodes, however it is not sufficient to guarantee that the MDIO bus diversion is used because of_phy_connect() will still resolve to a valid PHY phandle and it will connect to the PHY using its parent MDIO bus which is still the SF2 master MDIO bus. The reason for that is because BCM7445 systems were already shipped with a Device Tree blob looking like this (irrelevant parts omitted for simplicity): ports { #address-cells = <1>; #size-cells = <0>; port@1 { phy-mode = "rgmii-txid"; phy-handle = <&phy0>; reg = <1>; label = "rgmii_1"; }; ... mdio@403c0 { ... phy0: ethernet-phy@0 { broken-turn-around; device_type = "ethernet-phy"; max-speed = <0x3e8>; reg = <0>; compatible = "brcm,bcm53125", "ethernet-phy-ieee802.3-c22"; }; }; There is a hardware issue with chip revisions (Dx) that lead to the development of the following commits: 461cd1b ("net: dsa: bcm_sf2: Register our slave MDIO bus") 536fab5 ("net: dsa: bcm_sf2: Do not register slave MDIO bus with OF") b8c6cd1 ("net: dsa: bcm_sf2: do not use indirect reads and writes for 7445E0") There should have been an internal MDIO bus node created for the chip revision (Dx) that suffers from this problem, but it did not happen back then. Had that happen, that we should have correctly parented phy@0 (bcm53125 below) as child node of the internal MDIO bus, but the production Device Tree blob that was shipped with the firmware targeted the fixed version of the chip, despite both the affected and corrected chips being shipped into production. The problem is that of_phy_connect() for port@1 will happily resolve the 'phy-handle' from the mdio@403c0 node, which bypasses the diversion completely. This results in this double programming that the diversion refers to and aims to avoid. In order to force of_phy_connect() to fail, and have DSA call to dsa_slave_phy_connect(), we must deactivate ethernet-phy@0 from mdio@403c0, and the best way to do that is by removing the phandle property completely. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Reviewed-by: Andrew Lunn <andrew@lunn.ch> Signed-off-by: Jakub Kicinski <kuba@kernel.org>
1 parent 0f7c531 commit 771089c

File tree

1 file changed

+29
-2
lines changed

1 file changed

+29
-2
lines changed

drivers/net/dsa/bcm_sf2.c

Lines changed: 29 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -489,9 +489,11 @@ static void bcm_sf2_identify_ports(struct bcm_sf2_priv *priv,
489489
static int bcm_sf2_mdio_register(struct dsa_switch *ds)
490490
{
491491
struct bcm_sf2_priv *priv = bcm_sf2_to_priv(ds);
492-
struct device_node *dn;
492+
struct device_node *dn, *child;
493+
struct phy_device *phydev;
494+
struct property *prop;
493495
static int index;
494-
int err;
496+
int err, reg;
495497

496498
/* Find our integrated MDIO bus node */
497499
dn = of_find_compatible_node(NULL, NULL, "brcm,unimac-mdio");
@@ -534,6 +536,31 @@ static int bcm_sf2_mdio_register(struct dsa_switch *ds)
534536
priv->slave_mii_bus->parent = ds->dev->parent;
535537
priv->slave_mii_bus->phy_mask = ~priv->indir_phy_mask;
536538

539+
/* We need to make sure that of_phy_connect() will not work by
540+
* removing the 'phandle' and 'linux,phandle' properties and
541+
* unregister the existing PHY device that was already registered.
542+
*/
543+
for_each_available_child_of_node(dn, child) {
544+
if (of_property_read_u32(child, "reg", &reg) ||
545+
reg >= PHY_MAX_ADDR)
546+
continue;
547+
548+
if (!(priv->indir_phy_mask & BIT(reg)))
549+
continue;
550+
551+
prop = of_find_property(child, "phandle", NULL);
552+
if (prop)
553+
of_remove_property(child, prop);
554+
555+
prop = of_find_property(child, "linux,phandle", NULL);
556+
if (prop)
557+
of_remove_property(child, prop);
558+
559+
phydev = of_phy_find_device(child);
560+
if (phydev)
561+
phy_device_remove(phydev);
562+
}
563+
537564
err = mdiobus_register(priv->slave_mii_bus);
538565
if (err && dn)
539566
of_node_put(dn);

0 commit comments

Comments
 (0)