static int mii_probe(struct net_device *dev, int phy_mode) { struct bfin_mac_local *lp = netdev_priv(dev); struct phy_device *phydev; unsigned short sysctl; u32 sclk, mdc_div; /* Enable PHY output early */ if (!(bfin_read_VR_CTL() & CLKBUFOE)) bfin_write_VR_CTL(bfin_read_VR_CTL() | CLKBUFOE); sclk = get_sclk(); mdc_div = ((sclk / MDC_CLK) / 2) - 1; sysctl = bfin_read_EMAC_SYSCTL(); sysctl = (sysctl & ~MDCDIV) | SET_MDCDIV(mdc_div); bfin_write_EMAC_SYSCTL(sysctl); phydev = phy_find_first(lp->mii_bus); if (!phydev) { netdev_err(dev, "no phy device found\n"); return -ENODEV; } if (phy_mode != PHY_INTERFACE_MODE_RMII && phy_mode != PHY_INTERFACE_MODE_MII) { netdev_err(dev, "invalid phy interface mode\n"); return -EINVAL; } phydev = phy_connect(dev, phydev_name(phydev), &bfin_mac_adjust_link, phy_mode); if (IS_ERR(phydev)) { netdev_err(dev, "could not attach PHY\n"); return PTR_ERR(phydev); } /* mask with MAC supported features */ phydev->supported &= (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_Autoneg | SUPPORTED_Pause | SUPPORTED_Asym_Pause | SUPPORTED_MII | SUPPORTED_TP); phydev->advertising = phydev->supported; lp->old_link = 0; lp->old_speed = 0; lp->old_duplex = -1; lp->phydev = phydev; phy_attached_print(phydev, "mdc_clk=%dHz(mdc_div=%d)@sclk=%dMHz)\n", MDC_CLK, mdc_div, sclk / 1000000); return 0; }
static int tc_mii_probe(struct net_device *dev) { struct tc35815_local *lp = netdev_priv(dev); struct phy_device *phydev; u32 dropmask; phydev = phy_find_first(lp->mii_bus); if (!phydev) { printk(KERN_ERR "%s: no PHY found\n", dev->name); return -ENODEV; } /* attach the mac to the phy */ phydev = phy_connect(dev, phydev_name(phydev), &tc_handle_link_change, lp->chiptype == TC35815_TX4939 ? PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII); if (IS_ERR(phydev)) { printk(KERN_ERR "%s: Could not attach to PHY\n", dev->name); return PTR_ERR(phydev); } phy_attached_info(phydev); /* mask with MAC supported features */ phydev->supported &= PHY_BASIC_FEATURES; dropmask = 0; if (options.speed == 10) dropmask |= SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full; else if (options.speed == 100) dropmask |= SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full; if (options.duplex == 1) dropmask |= SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Full; else if (options.duplex == 2) dropmask |= SUPPORTED_10baseT_Half | SUPPORTED_100baseT_Half; phydev->supported &= ~dropmask; phydev->advertising = phydev->supported; lp->link = 0; lp->speed = 0; lp->duplex = -1; return 0; }
static int lpc_mii_probe(struct net_device *ndev) { struct netdata_local *pldat = netdev_priv(ndev); struct phy_device *phydev = phy_find_first(pldat->mii_bus); if (!phydev) { netdev_err(ndev, "no PHY found\n"); return -ENODEV; } /* Attach to the PHY */ if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII) netdev_info(ndev, "using MII interface\n"); else netdev_info(ndev, "using RMII interface\n"); phydev = phy_connect(ndev, dev_name(&phydev->dev), &lpc_handle_link_change, lpc_phy_interface_mode(&pldat->pdev->dev)); if (IS_ERR(phydev)) { netdev_err(ndev, "Could not attach to PHY\n"); return PTR_ERR(phydev); } /* mask with MAC supported features */ phydev->supported &= PHY_BASIC_FEATURES; phydev->advertising = phydev->supported; pldat->link = 0; pldat->speed = 0; pldat->duplex = -1; pldat->phy_dev = phydev; netdev_info(ndev, "attached PHY driver [%s] (mii_bus:phy_addr=%s, irq=%d)\n", phydev->drv->name, dev_name(&phydev->dev), phydev->irq); return 0; }
static int pci_eth_mii_probe(struct net_device *dev) { struct pci_eth_private *priv = netdev_priv(dev); struct phy_device *phydev = NULL; phydev = phy_find_first(priv->mii_bus); if (!phydev) { dev_err(&priv->pdev->dev, "no PHY found\n"); return -ENODEV; } phydev = phy_connect(dev, phydev_name(phydev), &pci_eth_adjust_link, PHY_INTERFACE_MODE_MII); if (IS_ERR(phydev)) { dev_err(&priv->pdev->dev, "could not attach to PHY\n"); return PTR_ERR(phydev); } /* mask with MAC supported features */ phydev->supported &= (SUPPORTED_10baseT_Half | SUPPORTED_10baseT_Full | SUPPORTED_100baseT_Half | SUPPORTED_100baseT_Full | SUPPORTED_Autoneg | SUPPORTED_MII | SUPPORTED_TP); phydev->advertising = phydev->supported; priv->phydev = phydev; priv->old_link = 0; priv->old_duplex = -1; phy_attached_info(phydev); return 0; }
static int bcmgenet_mii_pd_init(struct bcmgenet_priv *priv) { struct device *kdev = &priv->pdev->dev; struct bcmgenet_platform_data *pd = kdev->platform_data; struct mii_bus *mdio = priv->mii_bus; struct phy_device *phydev; int ret; if (pd->phy_interface != PHY_INTERFACE_MODE_MOCA && pd->mdio_enabled) { /* * Internal or external PHY with MDIO access */ if (pd->phy_address >= 0 && pd->phy_address < PHY_MAX_ADDR) mdio->phy_mask = ~(1 << pd->phy_address); else mdio->phy_mask = 0; ret = mdiobus_register(mdio); if (ret) { dev_err(kdev, "failed to register MDIO bus\n"); return ret; } if (pd->phy_address >= 0 && pd->phy_address < PHY_MAX_ADDR) phydev = mdio->phy_map[pd->phy_address]; else phydev = phy_find_first(mdio); if (!phydev) { dev_err(kdev, "failed to register PHY device\n"); mdiobus_unregister(mdio); return -ENODEV; } } else { /* * MoCA port or no MDIO access. * Use fixed PHY to represent the link layer. */ struct fixed_phy_status fphy_status = { .link = 1, .speed = pd->phy_speed, .duplex = pd->phy_duplex, .pause = 0, .asym_pause = 0, }; phydev = fixed_phy_register(PHY_POLL, &fphy_status, NULL); if (!phydev || IS_ERR(phydev)) { dev_err(kdev, "failed to register fixed PHY device\n"); return -ENODEV; } } priv->phydev = phydev; priv->phy_interface = pd->phy_interface; return 0; } static int bcmgenet_mii_bus_init(struct bcmgenet_priv *priv) { struct device_node *dn = priv->pdev->dev.of_node; if (dn) return bcmgenet_mii_of_init(priv); else return bcmgenet_mii_pd_init(priv); } int bcmgenet_mii_init(struct net_device *dev) { struct bcmgenet_priv *priv = netdev_priv(dev); int ret; ret = bcmgenet_mii_alloc(priv); if (ret) return ret; ret = bcmgenet_mii_bus_init(priv); if (ret) goto out_free; ret = bcmgenet_mii_probe(dev); if (ret) goto out; return 0; out: of_node_put(priv->phy_dn); mdiobus_unregister(priv->mii_bus); out_free: kfree(priv->mii_bus->irq); mdiobus_free(priv->mii_bus); return ret; } void bcmgenet_mii_exit(struct net_device *dev) { struct bcmgenet_priv *priv = netdev_priv(dev); of_node_put(priv->phy_dn); mdiobus_unregister(priv->mii_bus); kfree(priv->mii_bus->irq); mdiobus_free(priv->mii_bus); }
/* Configure the MDIO bus and connect the external PHY */ int emac_phy_config(struct platform_device *pdev, struct emac_adapter *adpt) { struct device_node *np = pdev->dev.of_node; struct mii_bus *mii_bus; int ret; /* Create the mii_bus object for talking to the MDIO bus */ adpt->mii_bus = mii_bus = devm_mdiobus_alloc(&pdev->dev); if (!mii_bus) return -ENOMEM; mii_bus->name = "emac-mdio"; snprintf(mii_bus->id, MII_BUS_ID_SIZE, "%s", pdev->name); mii_bus->read = emac_mdio_read; mii_bus->write = emac_mdio_write; mii_bus->parent = &pdev->dev; mii_bus->priv = adpt; if (has_acpi_companion(&pdev->dev)) { u32 phy_addr; ret = mdiobus_register(mii_bus); if (ret) { dev_err(&pdev->dev, "could not register mdio bus\n"); return ret; } ret = device_property_read_u32(&pdev->dev, "phy-channel", &phy_addr); if (ret) /* If we can't read a valid phy address, then assume * that there is only one phy on this mdio bus. */ adpt->phydev = phy_find_first(mii_bus); else adpt->phydev = mdiobus_get_phy(mii_bus, phy_addr); /* of_phy_find_device() claims a reference to the phydev, * so we do that here manually as well. When the driver * later unloads, it can unilaterally drop the reference * without worrying about ACPI vs DT. */ if (adpt->phydev) get_device(&adpt->phydev->mdio.dev); } else { struct device_node *phy_np; ret = of_mdiobus_register(mii_bus, np); if (ret) { dev_err(&pdev->dev, "could not register mdio bus\n"); return ret; } phy_np = of_parse_phandle(np, "phy-handle", 0); adpt->phydev = of_phy_find_device(phy_np); of_node_put(phy_np); } if (!adpt->phydev) { dev_err(&pdev->dev, "could not find external phy\n"); mdiobus_unregister(mii_bus); return -ENODEV; } return 0; }