/* Initialise the interrupts to polling and 64-bit seqcounts */ for (i = 0; i < PHY_MAX_ADDR; i++) {
bus->irq[i] = PHY_POLL;
u64_stats_init(&bus->stats[i].syncp);
}
return bus;
}
EXPORT_SYMBOL(mdiobus_alloc_size);
#if IS_ENABLED(CONFIG_OF_MDIO) /* Walk the list of subnodes of a mdio bus and look for a node that *matchesthemdiodevice'saddresswithits'reg'property.If *found,settheof_nodepointerforthemdiodevice.Thisallows *auto-probedphydevicestobesuppliedwithinformationpassedin *viaDT. *IfaPHYpackageisfound,PHYissearchedalsothere.
*/ staticint of_mdiobus_find_phy(struct device *dev, struct mdio_device *mdiodev, struct device_node *np)
{ struct device_node *child;
for_each_available_child_of_node(np, child) { int addr;
if (of_node_name_eq(child, "ethernet-phy-package")) { /* Validate PHY package reg presence */ if (!of_property_present(child, "reg")) {
of_node_put(child); return -EINVAL;
}
if (!of_mdiobus_find_phy(dev, mdiodev, child)) { /* The refcount for the PHY package will be *incrementedlaterwhenPHYjointhePackage.
*/
of_node_put(child); return0;
}
continue;
}
addr = of_mdio_parse_addr(dev, child); if (addr < 0) continue;
if (addr == mdiodev->addr) {
device_set_node(dev, of_fwnode_handle(child)); /* The refcount on "child" is passed to the mdio *device.Do_not_useof_node_put(child)here.
*/ return0;
}
}
phydev = get_phy_device(bus, addr, c45); if (IS_ERR(phydev)) return phydev;
#if IS_ENABLED(CONFIG_OF_MDIO) /* For DT, see if the auto-probed phy has a corresponding child *inthebusnode,andsettheof_nodepointerinthiscase.
*/
of_mdiobus_link_mdiodev(bus, &phydev->mdio); #endif
/* Search for a swnode for the phy in the swnode hierarchy of the bus. *Ifthereisnoswnodeforthephyprovided,justignoreit.
*/ if (dev_fwnode(&bus->dev) && !dev_fwnode(&phydev->mdio.dev)) {
snprintf(node_name, sizeof(node_name), "ethernet-phy@%d",
addr);
fwnode = fwnode_get_named_child_node(dev_fwnode(&bus->dev),
node_name); if (fwnode)
device_set_node(&phydev->mdio.dev, fwnode);
}
err = phy_device_register(phydev); if (err) {
phy_device_free(phydev); return ERR_PTR(-ENODEV);
}
/* There are some C22 PHYs which do bad things when where is a C45 *transactiononthebus,likeacceptingareadthemselves,and *stompingoverthetruedevicesreply,toperformingawriteto *themselveswhichwasintendedforanotherdevice.NowthatC22 *deviceshavebeenfound,seeifanyofthemarebadforC45,andifwe *shouldskiptheC45scan.
*/ staticbool mdiobus_prevent_c45_scan(struct mii_bus *bus)
{ int i;
for (i = 0; i < PHY_MAX_ADDR; i++) { struct phy_device *phydev;
u32 oui;
/* If the bus state is allocated, we're registering a fresh bus *thatmayhaveafwnodeassociatedwithit.Grabareference *tothefwnode.Thiswillbedroppedwhenthebusisreleased. *Ifthebuswassettounregistered,itmeansthatthebuswas *previouslyregistered,andwe'vealreadygrabbedareference.
*/ if (bus->state == MDIOBUS_ALLOCATED)
fwnode_handle_get(dev_fwnode(&bus->dev));
/* We need to set state to MDIOBUS_UNREGISTERED to correctly release *thedeviceinmdiobus_free() * *Statewillbeupdatedlaterinthisfunctionincaseofsuccess
*/
bus->state = MDIOBUS_UNREGISTERED;
err = device_register(&bus->dev); if (err) {
pr_err("mii_bus %s failed to register\n", bus->id); return -EINVAL;
}
error: for (i = 0; i < PHY_MAX_ADDR; i++) {
mdiodev = bus->mdio_map[i]; if (!mdiodev) continue;
mdiodev->device_remove(mdiodev);
mdiodev->device_free(mdiodev);
}
error_reset_gpiod: /* Put PHYs in RESET to save power */ if (bus->reset_gpiod)
gpiod_set_value_cansleep(bus->reset_gpiod, 1);
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.