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; }
/** * 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; }
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; }