static void sfp_sm_probe_phy(struct sfp *sfp) { struct phy_device *phy; int err; msleep(T_PHY_RESET_MS); phy = mdiobus_scan(sfp->i2c_mii, SFP_PHY_ADDR); if (IS_ERR(phy)) { dev_err(sfp->dev, "mdiobus scan returned %ld\n", PTR_ERR(phy)); return; } if (!phy) { dev_info(sfp->dev, "no PHY detected\n"); return; } err = sfp_add_phy(sfp->sfp_bus, phy); if (err) { phy_device_remove(phy); phy_device_free(phy); dev_err(sfp->dev, "sfp_add_phy failed: %d\n", err); return; } sfp->mod_phy = phy; phy_start(phy); }
static void sfp_sm_phy_detach(struct sfp *sfp) { phy_stop(sfp->mod_phy); sfp_remove_phy(sfp->sfp_bus); phy_device_remove(sfp->mod_phy); phy_device_free(sfp->mod_phy); sfp->mod_phy = NULL; }
struct phy_device *xgene_enet_phy_register(struct mii_bus *bus, int phy_addr) { struct phy_device *phy_dev; phy_dev = get_phy_device(bus, phy_addr, false); if (!phy_dev || IS_ERR(phy_dev)) return NULL; if (phy_device_register(phy_dev)) phy_device_free(phy_dev); return phy_dev; }
int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) { struct phy_device *phy; struct device_node *child; int rc, i; mdio->phy_mask = ~0; if (mdio->irq) for (i=0; i<PHY_MAX_ADDR; i++) mdio->irq[i] = PHY_POLL; rc = mdiobus_register(mdio); if (rc) return rc; for_each_child_of_node(np, child) { const __be32 *paddr; u32 addr; int len; paddr = of_get_property(child, "reg", &len); if (!paddr || len < sizeof(*paddr)) { dev_err(&mdio->dev, "%s has invalid PHY address\n", child->full_name); continue; } addr = be32_to_cpup(paddr); if (addr >= 32) { dev_err(&mdio->dev, "%s PHY address %i is too large\n", child->full_name, addr); continue; } if (mdio->irq) { mdio->irq[addr] = irq_of_parse_and_map(child, 0); if (!mdio->irq[addr]) mdio->irq[addr] = PHY_POLL; } phy = get_phy_device(mdio, addr); if (!phy || IS_ERR(phy)) { dev_err(&mdio->dev, "error probing PHY at address %i\n", addr); continue; } of_node_get(child); phy->dev.of_node = child; rc = phy_device_register(phy); if (rc) { phy_device_free(phy); of_node_put(child); continue; } dev_dbg(&mdio->dev, "registered phy %s at address %i\n", child->name, addr); } return 0; }
/** * mdiobus_register - bring up all the PHYs on a given bus and attach them to bus * @bus: target mii_bus * * Description: Called by a bus driver to bring up all the PHYs * on a given bus, and attach them to the bus. * * Returns 0 on success or < 0 on error. */ int mdiobus_register(struct mii_bus *bus) { int i; int err = 0; if (NULL == bus || NULL == bus->name || NULL == bus->read || NULL == bus->write) return -EINVAL; mutex_init(&bus->mdio_lock); if (bus->reset) bus->reset(bus); for (i = 0; i < PHY_MAX_ADDR; i++) { struct phy_device *phydev; if (bus->phy_mask & (1 << i)) { bus->phy_map[i] = NULL; continue; } phydev = get_phy_device(bus, i); if (IS_ERR(phydev)) return PTR_ERR(phydev); /* There's a PHY at this address * We need to set: * 1) IRQ * 2) bus_id * 3) parent * 4) bus * 5) mii_bus * And, we need to register it */ if (phydev) { phydev->irq = bus->irq[i]; phydev->dev.parent = bus->dev; phydev->dev.bus = &mdio_bus_type; snprintf(phydev->dev.bus_id, BUS_ID_SIZE, PHY_ID_FMT, bus->id, i); phydev->bus = bus; /* Run all of the fixups for this PHY */ phy_scan_fixups(phydev); err = device_register(&phydev->dev); if (err) { printk(KERN_ERR "phy %d failed to register\n", i); phy_device_free(phydev); phydev = NULL; } } bus->phy_map[i] = phydev; } pr_info("%s: probed\n", bus->name); return err; }
/** * of_mdiobus_register - Register mii_bus and create PHYs from the device tree * @mdio: pointer to mii_bus structure * @np: pointer to device_node of MDIO bus. * * This function registers the mii_bus structure and registers a phy_device * for each child node of @np. */ int of_mdiobus_register(struct mii_bus *mdio, struct device_node *np) { struct phy_device *phy; struct device_node *child; int rc, i; /* Mask out all PHYs from auto probing. Instead the PHYs listed in * the device tree are populated after the bus has been registered */ mdio->phy_mask = ~0; /* Clear all the IRQ properties */ if (mdio->irq) for (i=0; i<PHY_MAX_ADDR; i++) mdio->irq[i] = PHY_POLL; mdio->dev.of_node = np; /* Register the MDIO bus */ rc = mdiobus_register(mdio); if (rc) return rc; /* Loop over the child nodes and register a phy_device for each one */ for_each_available_child_of_node(np, child) { const __be32 *paddr; u32 addr; int len; bool is_c45; /* A PHY must have a reg property in the range [0-31] */ paddr = of_get_property(child, "reg", &len); if (!paddr || len < sizeof(*paddr)) { dev_err(&mdio->dev, "%s has invalid PHY address\n", child->full_name); continue; } addr = be32_to_cpup(paddr); if (addr >= 32) { dev_err(&mdio->dev, "%s PHY address %i is too large\n", child->full_name, addr); continue; } if (mdio->irq) { mdio->irq[addr] = irq_of_parse_and_map(child, 0); if (!mdio->irq[addr]) mdio->irq[addr] = PHY_POLL; } is_c45 = of_device_is_compatible(child, "ethernet-phy-ieee802.3-c45"); phy = get_phy_device(mdio, addr, is_c45); if (!phy || IS_ERR(phy)) { phy = phy_device_create(mdio, addr, 0, false, NULL); if (!phy || IS_ERR(phy)) { dev_err(&mdio->dev, "error creating PHY at address %i\n", addr); continue; } } /* Associate the OF node with the device structure so it * can be looked up later */ of_node_get(child); phy->dev.of_node = child; /* All data is now stored in the phy struct; register it */ rc = phy_device_register(phy); if (rc) { phy_device_free(phy); of_node_put(child); continue; } dev_dbg(&mdio->dev, "registered phy %s at address %i\n", child->name, addr); } return 0; }
static void phy_device_release(struct device *dev) { phy_device_free(to_phy_device(dev)); }
int xgbe_mdio_register(struct xgbe_prv_data *pdata) { struct device_node *phy_node; struct mii_bus *mii; struct phy_device *phydev; int ret = 0; DBGPR("-->xgbe_mdio_register\n"); /* Retrieve the phy-handle */ phy_node = of_parse_phandle(pdata->dev->of_node, "phy-handle", 0); if (!phy_node) { dev_err(pdata->dev, "unable to parse phy-handle\n"); return -EINVAL; } mii = mdiobus_alloc(); if (mii == NULL) { dev_err(pdata->dev, "mdiobus_alloc failed\n"); ret = -ENOMEM; goto err_node_get; } /* Register on the MDIO bus (don't probe any PHYs) */ mii->name = XGBE_PHY_NAME; mii->read = xgbe_mdio_read; mii->write = xgbe_mdio_write; snprintf(mii->id, sizeof(mii->id), "%s", pdata->mii_bus_id); mii->priv = pdata; mii->phy_mask = ~0; mii->parent = pdata->dev; ret = mdiobus_register(mii); if (ret) { dev_err(pdata->dev, "mdiobus_register failed\n"); goto err_mdiobus_alloc; } DBGPR(" mdiobus_register succeeded for %s\n", pdata->mii_bus_id); /* Probe the PCS using Clause 45 */ phydev = get_phy_device(mii, XGBE_PRTAD, true); if (IS_ERR(phydev) || !phydev || !phydev->c45_ids.device_ids[MDIO_MMD_PCS]) { dev_err(pdata->dev, "get_phy_device failed\n"); ret = phydev ? PTR_ERR(phydev) : -ENOLINK; goto err_mdiobus_register; } request_module(MDIO_MODULE_PREFIX MDIO_ID_FMT, MDIO_ID_ARGS(phydev->c45_ids.device_ids[MDIO_MMD_PCS])); of_node_get(phy_node); phydev->dev.of_node = phy_node; ret = phy_device_register(phydev); if (ret) { dev_err(pdata->dev, "phy_device_register failed\n"); of_node_put(phy_node); goto err_phy_device; } /* Add a reference to the PHY driver so it can't be unloaded */ pdata->phy_module = phydev->dev.driver ? phydev->dev.driver->owner : NULL; if (!try_module_get(pdata->phy_module)) { dev_err(pdata->dev, "try_module_get failed\n"); ret = -EIO; goto err_phy_device; } pdata->mii = mii; pdata->mdio_mmd = MDIO_MMD_PCS; phydev->autoneg = pdata->default_autoneg; if (phydev->autoneg == AUTONEG_DISABLE) { phydev->speed = pdata->default_speed; phydev->duplex = DUPLEX_FULL; phydev->advertising &= ~ADVERTISED_Autoneg; } pdata->phydev = phydev; of_node_put(phy_node); DBGPHY_REGS(pdata); DBGPR("<--xgbe_mdio_register\n"); return 0; err_phy_device: phy_device_free(phydev); err_mdiobus_register: mdiobus_unregister(mii); err_mdiobus_alloc: mdiobus_free(mii); err_node_get: of_node_put(phy_node); return ret; }