示例#1
0
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;
}
示例#2
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;
}
示例#3
0
文件: lpc_eth.c 项目: guanhe0/kernel
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;
}
示例#4
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;
}
示例#5
0
文件: bcmmii.c 项目: 383530895/linux
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);
}
示例#6
0
/* 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;
}