Exemplo n.º 1
0
Arquivo: mdio.c Projeto: Lyude/linux
static int mtk_phy_connect(struct mtk_mac *mac)
{
	struct mtk_eth *eth = mac->hw;
	int i;

	for (i = 0; i < 8; i++) {
		if (eth->phy->phy_node[i]) {
			if (!mac->phy_dev) {
				mac->phy_dev = eth->phy->phy[i];
				mac->phy_flags = MTK_PHY_FLAG_PORT;
			}
		} else if (eth->mii_bus) {
			struct phy_device *phy;

			phy = mdiobus_get_phy(eth->mii_bus, i);
			if (phy) {
				phy_init(eth, mac, phy);
				if (!mac->phy_dev) {
					mac->phy_dev = phy;
					mac->phy_flags = MTK_PHY_FLAG_ATTACH;
				}
			}
		}
	}

	return 0;
}
Exemplo n.º 2
0
static int mt7621_gsw_config(struct fe_priv *priv)
{
	if (priv->mii_bus &&  mdiobus_get_phy(priv->mii_bus, 0x1f))
		mt7530_probe(priv->device, NULL, priv->mii_bus, 1);

	return 0;
}
Exemplo n.º 3
0
/**
 * stmmac_mdio_register
 * @ndev: net device structure
 * Description: it registers the MII bus
 */
int stmmac_mdio_register(struct net_device *ndev)
{
	int err = 0;
	struct mii_bus *new_bus;
	struct stmmac_priv *priv = netdev_priv(ndev);
	int addr, found;

	new_bus = mdiobus_alloc();
	if (new_bus == NULL)
		return -ENOMEM;

	/* Assign IRQ to phy at address phy_addr */
	if (priv->phy_addr != -1)
		new_bus->irq[priv->phy_addr] = priv->phy_irq;

	new_bus->name = "STMMAC MII Bus";
	new_bus->read = &stmmac_mdio_read;
	new_bus->write = &stmmac_mdio_write;
	new_bus->reset = &stmmac_mdio_reset;
	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", priv->plat->bus_id);
	new_bus->priv = ndev;
	new_bus->phy_mask = priv->phy_mask;
	new_bus->parent = priv->device;
	err = mdiobus_register(new_bus);
	if (err != 0) {
		pr_err("%s: Cannot register as MDIO bus\n", new_bus->name);
		goto bus_register_fail;
	}

	priv->mii = new_bus;

	found = 0;
	for (addr = 0; addr < 32; addr++) {
		struct phy_device *phydev = mdiobus_get_phy(new_bus, addr);
		if (phydev) {
			if (priv->phy_addr == -1) {
				priv->phy_addr = addr;
				phydev->irq = priv->phy_irq;
				new_bus->irq[addr] = priv->phy_irq;
			}
			if (addr == priv->phy_addr) {
				pr_info("%s: PHY ID %08x at %d IRQ %d (%s)%s\n",
					   ndev->name, phydev->phy_id, addr,
				       phydev->irq, phydev_name(phydev),
				       (addr == priv->phy_addr) ? " active" : "");
			}
			found = 1;
		}
	}

	if (!found)
		pr_warning("%s: No PHY found\n", ndev->name);

	return 0;
bus_register_fail:
	kfree(new_bus);
	return err;
}
Exemplo n.º 4
0
/* slave device setup *******************************************************/
static int dsa_slave_phy_connect(struct dsa_slave_priv *p,
				 struct net_device *slave_dev,
				 int addr)
{
	struct dsa_switch *ds = p->parent;

	p->phy = mdiobus_get_phy(ds->slave_mii_bus, addr);
	if (!p->phy) {
		netdev_err(slave_dev, "no phy at %d\n", addr);
		return -ENODEV;
	}

	/* Use already configured phy mode */
	if (p->phy_interface == PHY_INTERFACE_MODE_NA)
		p->phy_interface = p->phy->interface;
	phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link,
			   p->phy_interface);

	return 0;
}
Exemplo n.º 5
0
Arquivo: mdio.c Projeto: Lyude/linux
static void mtk_phy_disconnect(struct mtk_mac *mac)
{
	struct mtk_eth *eth = mac->hw;
	unsigned long flags;
	int i;

	for (i = 0; i < 8; i++)
		if (eth->phy->phy_fixed[i]) {
			spin_lock_irqsave(&eth->phy->lock, flags);
			eth->link[i] = 0;
			if (eth->soc->mdio_adjust_link)
				eth->soc->mdio_adjust_link(eth, i);
			spin_unlock_irqrestore(&eth->phy->lock, flags);
		} else if (eth->phy->phy[i]) {
			phy_disconnect(eth->phy->phy[i]);
		} else if (eth->mii_bus) {
			struct phy_device *phy =
				mdiobus_get_phy(eth->mii_bus, i);

			if (phy)
				phy_detach(phy);
		}
}
Exemplo n.º 6
0
static int ag71xx_phy_connect_multi(struct ag71xx *ag)
{
	struct device *dev = &ag->pdev->dev;
	struct ag71xx_platform_data *pdata = ag71xx_get_pdata(ag);
	struct phy_device *phydev = NULL;
	int phy_addr;
	int ret = 0;

	for (phy_addr = 0; phy_addr < PHY_MAX_ADDR; phy_addr++) {
		if (!(pdata->phy_mask & (1 << phy_addr)))
			continue;

#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0)
		if (ag->mii_bus->phy_map[phy_addr] == NULL)
			continue;

		DBG("%s: PHY found at %s, uid=%08x\n",
			dev_name(dev),
			dev_name(&ag->mii_bus->phy_map[phy_addr]->dev),
			&ag->mii_bus->phy_map[phy_addr]->phy_id),
			&ag->mii_bus->phy_map[phy_addr]->phy_id : 0);

		if (phydev == NULL)
			phydev = ag->mii_bus->phy_map[phy_addr];
#else
		if (ag->mii_bus->mdio_map[phy_addr] == NULL)
			continue;

		DBG("%s: PHY found at %s, uid=%08x\n",
			dev_name(dev),
			dev_name(&ag->mii_bus->mdio_map[phy_addr]->dev),
			mdiobus_get_phy(ag->mii_bus, phy_addr) ?
			mdiobus_get_phy(ag->mii_bus, phy_addr)->phy_id : 0);

		if (phydev == NULL)
			phydev = mdiobus_get_phy(ag->mii_bus, phy_addr);
#endif
	}

	if (!phydev) {
		dev_err(dev, "no PHY found with phy_mask=%08x\n",
			   pdata->phy_mask);
		return -ENODEV;
	}

#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0)
	ag->phy_dev = phy_connect(ag->dev, dev_name(&phydev->dev),
#else
	ag->phy_dev = phy_connect(ag->dev, phydev_name(phydev),
#endif
				  &ag71xx_phy_link_adjust,
				  pdata->phy_if_mode);

	if (IS_ERR(ag->phy_dev)) {
		dev_err(dev, "could not connect to PHY at %s\n",
#if LINUX_VERSION_CODE < KERNEL_VERSION(4,5,0)
			   dev_name(&phydev->dev));
#else
			   phydev_name(phydev));
#endif
		return PTR_ERR(ag->phy_dev);
	}
Exemplo n.º 7
0
/**
 * stmmac_mdio_register
 * @ndev: net device structure
 * Description: it registers the MII bus
 */
int stmmac_mdio_register(struct net_device *ndev)
{
    int err = 0;
    struct mii_bus *new_bus;
    struct stmmac_priv *priv = netdev_priv(ndev);
    struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
    struct device_node *mdio_node = priv->plat->mdio_node;
    int addr, found;

    if (!mdio_bus_data)
        return 0;

    new_bus = mdiobus_alloc();
    if (new_bus == NULL)
        return -ENOMEM;

    if (mdio_bus_data->irqs)
        memcpy(new_bus->irq, mdio_bus_data, sizeof(new_bus->irq));

#ifdef CONFIG_OF
    if (priv->device->of_node)
        mdio_bus_data->reset_gpio = -1;
#endif

    new_bus->name = "stmmac";
    new_bus->read = &stmmac_mdio_read;
    new_bus->write = &stmmac_mdio_write;
    new_bus->reset = &stmmac_mdio_reset;
    snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
             new_bus->name, priv->plat->bus_id);
    new_bus->priv = ndev;
    new_bus->phy_mask = mdio_bus_data->phy_mask;
    new_bus->parent = priv->device;

    if (mdio_node)
        err = of_mdiobus_register(new_bus, mdio_node);
    else
        err = mdiobus_register(new_bus);
    if (err != 0) {
        pr_err("%s: Cannot register as MDIO bus\n", new_bus->name);
        goto bus_register_fail;
    }

    if (priv->plat->phy_node || mdio_node)
        goto bus_register_done;

    found = 0;
    for (addr = 0; addr < PHY_MAX_ADDR; addr++) {
        struct phy_device *phydev = mdiobus_get_phy(new_bus, addr);
        if (phydev) {
            int act = 0;
            char irq_num[4];
            char *irq_str;

            /*
             * If an IRQ was provided to be assigned after
             * the bus probe, do it here.
             */
            if ((mdio_bus_data->irqs == NULL) &&
                    (mdio_bus_data->probed_phy_irq > 0)) {
                new_bus->irq[addr] =
                    mdio_bus_data->probed_phy_irq;
                phydev->irq = mdio_bus_data->probed_phy_irq;
            }

            /*
             * If we're going to bind the MAC to this PHY bus,
             * and no PHY number was provided to the MAC,
             * use the one probed here.
             */
            if (priv->plat->phy_addr == -1)
                priv->plat->phy_addr = addr;

            act = (priv->plat->phy_addr == addr);
            switch (phydev->irq) {
            case PHY_POLL:
                irq_str = "POLL";
                break;
            case PHY_IGNORE_INTERRUPT:
                irq_str = "IGNORE";
                break;
            default:
                sprintf(irq_num, "%d", phydev->irq);
                irq_str = irq_num;
                break;
            }
            pr_info("%s: PHY ID %08x at %d IRQ %s (%s)%s\n",
                    ndev->name, phydev->phy_id, addr,
                    irq_str, phydev_name(phydev),
                    act ? " active" : "");
            found = 1;
        }
    }

    if (!found && !mdio_node) {
        pr_warn("%s: No PHY found\n", ndev->name);
        mdiobus_unregister(new_bus);
        mdiobus_free(new_bus);
        return -ENODEV;
    }

bus_register_done:
    priv->mii = new_bus;

    return 0;

bus_register_fail:
    mdiobus_free(new_bus);
    return err;
}
Exemplo n.º 8
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;
}
Exemplo n.º 9
0
/**
 * stmmac_mdio_register
 * @ndev: net device structure
 * Description: it registers the MII bus
 */
int stmmac_mdio_register(struct net_device *ndev)
{
	int err = 0;
	struct mii_bus *new_bus;
	struct stmmac_priv *priv = netdev_priv(ndev);
	struct stmmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
	struct device_node *mdio_node = priv->plat->mdio_node;
	struct device *dev = ndev->dev.parent;
	int addr, found, max_addr;

	if (!mdio_bus_data)
		return 0;

	new_bus = mdiobus_alloc();
	if (!new_bus)
		return -ENOMEM;

	if (mdio_bus_data->irqs)
		memcpy(new_bus->irq, mdio_bus_data->irqs, sizeof(new_bus->irq));

#ifdef CONFIG_OF
	if (priv->device->of_node)
		mdio_bus_data->reset_gpio = -1;
#endif

	new_bus->name = "stmmac";

	if (priv->plat->has_xgmac) {
		new_bus->read = &stmmac_xgmac2_mdio_read;
		new_bus->write = &stmmac_xgmac2_mdio_write;

		/* Right now only C22 phys are supported */
		max_addr = MII_XGMAC_MAX_C22ADDR + 1;

		/* Check if DT specified an unsupported phy addr */
		if (priv->plat->phy_addr > MII_XGMAC_MAX_C22ADDR)
			dev_err(dev, "Unsupported phy_addr (max=%d)\n",
					MII_XGMAC_MAX_C22ADDR);
	} else {
		new_bus->read = &stmmac_mdio_read;
		new_bus->write = &stmmac_mdio_write;
		max_addr = PHY_MAX_ADDR;
	}

	new_bus->reset = &stmmac_mdio_reset;
	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
		 new_bus->name, priv->plat->bus_id);
	new_bus->priv = ndev;
	new_bus->phy_mask = mdio_bus_data->phy_mask;
	new_bus->parent = priv->device;

	err = of_mdiobus_register(new_bus, mdio_node);
	if (err != 0) {
		dev_err(dev, "Cannot register the MDIO bus\n");
		goto bus_register_fail;
	}

	if (priv->plat->phy_node || mdio_node)
		goto bus_register_done;

	found = 0;
	for (addr = 0; addr < max_addr; addr++) {
		struct phy_device *phydev = mdiobus_get_phy(new_bus, addr);

		if (!phydev)
			continue;

		/*
		 * If an IRQ was provided to be assigned after
		 * the bus probe, do it here.
		 */
		if (!mdio_bus_data->irqs &&
		    (mdio_bus_data->probed_phy_irq > 0)) {
			new_bus->irq[addr] = mdio_bus_data->probed_phy_irq;
			phydev->irq = mdio_bus_data->probed_phy_irq;
		}

		/*
		 * If we're going to bind the MAC to this PHY bus,
		 * and no PHY number was provided to the MAC,
		 * use the one probed here.
		 */
		if (priv->plat->phy_addr == -1)
			priv->plat->phy_addr = addr;

		phy_attached_info(phydev);
		found = 1;
	}

	if (!found && !mdio_node) {
		dev_warn(dev, "No PHY found\n");
		mdiobus_unregister(new_bus);
		mdiobus_free(new_bus);
		return -ENODEV;
	}

bus_register_done:
	priv->mii = new_bus;

	return 0;

bus_register_fail:
	mdiobus_free(new_bus);
	return err;
}
Exemplo n.º 10
0
/* http://bcm-v4.sipsolutions.net/mac-gbit/gmac/chipattach */
static int bgmac_probe(struct bcma_device *core)
{
	struct bcma_chipinfo *ci = &core->bus->chipinfo;
	struct ssb_sprom *sprom = &core->bus->sprom;
	struct mii_bus *mii_bus;
	struct bgmac *bgmac;
	const u8 *mac = NULL;
	int err;

	bgmac = bgmac_alloc(&core->dev);
	if (!bgmac)
		return -ENOMEM;

	bgmac->bcma.core = core;
	bgmac->dma_dev = core->dma_dev;
	bgmac->irq = core->irq;

	bcma_set_drvdata(core, bgmac);

	if (bgmac->dev->of_node)
		mac = of_get_mac_address(bgmac->dev->of_node);

	/* If no MAC address assigned via device tree, check SPROM */
	if (IS_ERR_OR_NULL(mac)) {
		switch (core->core_unit) {
		case 0:
			mac = sprom->et0mac;
			break;
		case 1:
			mac = sprom->et1mac;
			break;
		case 2:
			mac = sprom->et2mac;
			break;
		default:
			dev_err(bgmac->dev, "Unsupported core_unit %d\n",
				core->core_unit);
			err = -ENOTSUPP;
			goto err;
		}
	}

	ether_addr_copy(bgmac->net_dev->dev_addr, mac);

	/* On BCM4706 we need common core to access PHY */
	if (core->id.id == BCMA_CORE_4706_MAC_GBIT &&
	    !core->bus->drv_gmac_cmn.core) {
		dev_err(bgmac->dev, "GMAC CMN core not found (required for BCM4706)\n");
		err = -ENODEV;
		goto err;
	}
	bgmac->bcma.cmn = core->bus->drv_gmac_cmn.core;

	switch (core->core_unit) {
	case 0:
		bgmac->phyaddr = sprom->et0phyaddr;
		break;
	case 1:
		bgmac->phyaddr = sprom->et1phyaddr;
		break;
	case 2:
		bgmac->phyaddr = sprom->et2phyaddr;
		break;
	}
	bgmac->phyaddr &= BGMAC_PHY_MASK;
	if (bgmac->phyaddr == BGMAC_PHY_MASK) {
		dev_err(bgmac->dev, "No PHY found\n");
		err = -ENODEV;
		goto err;
	}
	dev_info(bgmac->dev, "Found PHY addr: %d%s\n", bgmac->phyaddr,
		 bgmac->phyaddr == BGMAC_PHY_NOREGS ? " (NOREGS)" : "");

	if (!bgmac_is_bcm4707_family(core) &&
	    !(ci->id == BCMA_CHIP_ID_BCM53573 && core->core_unit == 1)) {
		struct phy_device *phydev;

		mii_bus = bcma_mdio_mii_register(bgmac);
		if (IS_ERR(mii_bus)) {
			err = PTR_ERR(mii_bus);
			goto err;
		}
		bgmac->mii_bus = mii_bus;

		phydev = mdiobus_get_phy(bgmac->mii_bus, bgmac->phyaddr);
		if (ci->id == BCMA_CHIP_ID_BCM53573 && phydev &&
		    (phydev->drv->phy_id & phydev->drv->phy_id_mask) == PHY_ID_BCM54210E)
			phydev->dev_flags |= PHY_BRCM_EN_MASTER_MODE;
	}

	if (core->bus->hosttype == BCMA_HOSTTYPE_PCI) {
		dev_err(bgmac->dev, "PCI setup not implemented\n");
		err = -ENOTSUPP;
		goto err1;
	}

	bgmac->has_robosw = !!(sprom->boardflags_lo & BGMAC_BFL_ENETROBO);
	if (bgmac->has_robosw)
		dev_warn(bgmac->dev, "Support for Roboswitch not implemented\n");

	if (sprom->boardflags_lo & BGMAC_BFL_ENETADM)
		dev_warn(bgmac->dev, "Support for ADMtek ethernet switch not implemented\n");

	/* Feature Flags */
	switch (ci->id) {
	/* BCM 471X/535X family */
	case BCMA_CHIP_ID_BCM4716:
		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
		/* fallthrough */
	case BCMA_CHIP_ID_BCM47162:
		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL2;
		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
		break;
	case BCMA_CHIP_ID_BCM5357:
	case BCMA_CHIP_ID_BCM53572:
		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
		bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
		if (ci->pkg == BCMA_PKG_ID_BCM47188 ||
		    ci->pkg == BCMA_PKG_ID_BCM47186) {
			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
			bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
		}
		if (ci->pkg == BCMA_PKG_ID_BCM5358)
			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_EPHYRMII;
		break;
	case BCMA_CHIP_ID_BCM53573:
		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
		if (ci->pkg == BCMA_PKG_ID_BCM47189)
			bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
		if (core->core_unit == 0) {
			bgmac->feature_flags |= BGMAC_FEAT_CC4_IF_SW_TYPE;
			if (ci->pkg == BCMA_PKG_ID_BCM47189)
				bgmac->feature_flags |=
					BGMAC_FEAT_CC4_IF_SW_TYPE_RGMII;
		} else if (core->core_unit == 1) {
			bgmac->feature_flags |= BGMAC_FEAT_IRQ_ID_OOB_6;
			bgmac->feature_flags |= BGMAC_FEAT_CC7_IF_TYPE_RGMII;
		}
		break;
	case BCMA_CHIP_ID_BCM4749:
		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
		bgmac->feature_flags |= BGMAC_FEAT_FLW_CTRL1;
		bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_PHY;
		if (ci->pkg == 10) {
			bgmac->feature_flags |= BGMAC_FEAT_SW_TYPE_RGMII;
			bgmac->feature_flags |= BGMAC_FEAT_IOST_ATTACHED;
		}
		break;
	/* bcm4707_family */
	case BCMA_CHIP_ID_BCM4707:
	case BCMA_CHIP_ID_BCM47094:
	case BCMA_CHIP_ID_BCM53018:
		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
		bgmac->feature_flags |= BGMAC_FEAT_NO_RESET;
		bgmac->feature_flags |= BGMAC_FEAT_FORCE_SPEED_2500;
		break;
	default:
		bgmac->feature_flags |= BGMAC_FEAT_CLKCTLST;
		bgmac->feature_flags |= BGMAC_FEAT_SET_RXQ_CLK;
	}

	if (!bgmac_is_bcm4707_family(core) && core->id.rev > 2)
		bgmac->feature_flags |= BGMAC_FEAT_MISC_PLL_REQ;

	if (core->id.id == BCMA_CORE_4706_MAC_GBIT) {
		bgmac->feature_flags |= BGMAC_FEAT_CMN_PHY_CTL;
		bgmac->feature_flags |= BGMAC_FEAT_NO_CLR_MIB;
	}

	if (core->id.rev >= 4) {
		bgmac->feature_flags |= BGMAC_FEAT_CMDCFG_SR_REV4;
		bgmac->feature_flags |= BGMAC_FEAT_TX_MASK_SETUP;
		bgmac->feature_flags |= BGMAC_FEAT_RX_MASK_SETUP;
	}

	bgmac->read = bcma_bgmac_read;
	bgmac->write = bcma_bgmac_write;
	bgmac->idm_read = bcma_bgmac_idm_read;
	bgmac->idm_write = bcma_bgmac_idm_write;
	bgmac->clk_enabled = bcma_bgmac_clk_enabled;
	bgmac->clk_enable = bcma_bgmac_clk_enable;
	bgmac->cco_ctl_maskset = bcma_bgmac_cco_ctl_maskset;
	bgmac->get_bus_clock = bcma_bgmac_get_bus_clock;
	bgmac->cmn_maskset32 = bcma_bgmac_cmn_maskset32;
	if (bgmac->mii_bus)
		bgmac->phy_connect = bcma_phy_connect;
	else
		bgmac->phy_connect = bgmac_phy_connect_direct;

	err = bgmac_enet_probe(bgmac);
	if (err)
		goto err1;

	return 0;

err1:
	bcma_mdio_mii_unregister(bgmac->mii_bus);
err:
	bcma_set_drvdata(core, NULL);

	return err;
}