示例#1
0
static struct net_device * au1000_probe(int port_num)
{
    static unsigned version_printed = 0;
    struct au1000_private *aup = NULL;
    struct net_device *dev = NULL;
    db_dest_t *pDB, *pDBfree;
    char ethaddr[6];
    int irq, i, err;
    u32 base, macen;

    if (port_num >= NUM_ETH_INTERFACES)
        return NULL;

    base  = CPHYSADDR(iflist[port_num].base_addr );
    macen = CPHYSADDR(iflist[port_num].macen_addr);
    irq = iflist[port_num].irq;

    if (!request_mem_region( base, MAC_IOSIZE, "Au1x00 ENET") ||
            !request_mem_region(macen, 4, "Au1x00 ENET"))
        return NULL;

    if (version_printed++ == 0)
        printk("%s version %s %s\n", DRV_NAME, DRV_VERSION, DRV_AUTHOR);

    dev = alloc_etherdev(sizeof(struct au1000_private));
    if (!dev) {
        printk(KERN_ERR "%s: alloc_etherdev failed\n", DRV_NAME);
        return NULL;
    }

    dev->base_addr = base;
    dev->irq = irq;
    dev->netdev_ops = &au1000_netdev_ops;
    SET_ETHTOOL_OPS(dev, &au1000_ethtool_ops);
    dev->watchdog_timeo = ETH_TX_TIMEOUT;

    err = register_netdev(dev);
    if (err != 0) {
        printk(KERN_ERR "%s: Cannot register net device, error %d\n",
               DRV_NAME, err);
        free_netdev(dev);
        return NULL;
    }

    printk("%s: Au1xx0 Ethernet found at 0x%x, irq %d\n",
           dev->name, base, irq);

    aup = netdev_priv(dev);

    spin_lock_init(&aup->lock);

    /* Allocate the data buffers */
    /* Snooping works fine with eth on all au1xxx */
    aup->vaddr = (u32)dma_alloc_noncoherent(NULL, MAX_BUF_SIZE *
                                            (NUM_TX_BUFFS + NUM_RX_BUFFS),
                                            &aup->dma_addr,	0);
    if (!aup->vaddr) {
        free_netdev(dev);
        release_mem_region( base, MAC_IOSIZE);
        release_mem_region(macen, 4);
        return NULL;
    }

    /* aup->mac is the base address of the MAC's registers */
    aup->mac = (volatile mac_reg_t *)iflist[port_num].base_addr;

    /* Setup some variables for quick register address access */
    aup->enable = (volatile u32 *)iflist[port_num].macen_addr;
    aup->mac_id = port_num;
    au_macs[port_num] = aup;

    if (port_num == 0) {
        if (prom_get_ethernet_addr(ethaddr) == 0)
            memcpy(au1000_mac_addr, ethaddr, sizeof(au1000_mac_addr));
        else {
            printk(KERN_INFO "%s: No MAC address found\n",
                   dev->name);
            /* Use the hard coded MAC addresses */
        }

        setup_hw_rings(aup, MAC0_RX_DMA_ADDR, MAC0_TX_DMA_ADDR);
    } else if (port_num == 1)
        setup_hw_rings(aup, MAC1_RX_DMA_ADDR, MAC1_TX_DMA_ADDR);

    /*
     * Assign to the Ethernet ports two consecutive MAC addresses
     * to match those that are printed on their stickers
     */
    memcpy(dev->dev_addr, au1000_mac_addr, sizeof(au1000_mac_addr));
    dev->dev_addr[5] += port_num;

    *aup->enable = 0;
    aup->mac_enabled = 0;

    aup->mii_bus = mdiobus_alloc();
    if (aup->mii_bus == NULL)
        goto err_out;

    aup->mii_bus->priv = dev;
    aup->mii_bus->read = au1000_mdiobus_read;
    aup->mii_bus->write = au1000_mdiobus_write;
    aup->mii_bus->reset = au1000_mdiobus_reset;
    aup->mii_bus->name = "au1000_eth_mii";
    snprintf(aup->mii_bus->id, MII_BUS_ID_SIZE, "%x", aup->mac_id);
    aup->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
    for(i = 0; i < PHY_MAX_ADDR; ++i)
        aup->mii_bus->irq[i] = PHY_POLL;

    /* if known, set corresponding PHY IRQs */
#if defined(AU1XXX_PHY_STATIC_CONFIG)
# if defined(AU1XXX_PHY0_IRQ)
    if (AU1XXX_PHY0_BUSID == aup->mac_id)
        aup->mii_bus->irq[AU1XXX_PHY0_ADDR] = AU1XXX_PHY0_IRQ;
# endif
# if defined(AU1XXX_PHY1_IRQ)
    if (AU1XXX_PHY1_BUSID == aup->mac_id)
        aup->mii_bus->irq[AU1XXX_PHY1_ADDR] = AU1XXX_PHY1_IRQ;
# endif
#endif
    mdiobus_register(aup->mii_bus);

    if (mii_probe(dev) != 0) {
        goto err_out;
    }

    pDBfree = NULL;
    /* setup the data buffer descriptors and attach a buffer to each one */
    pDB = aup->db;
    for (i = 0; i < (NUM_TX_BUFFS+NUM_RX_BUFFS); i++) {
        pDB->pnext = pDBfree;
        pDBfree = pDB;
        pDB->vaddr = (u32 *)((unsigned)aup->vaddr + MAX_BUF_SIZE*i);
        pDB->dma_addr = (dma_addr_t)virt_to_bus(pDB->vaddr);
        pDB++;
    }
    aup->pDBfree = pDBfree;

    for (i = 0; i < NUM_RX_DMA; i++) {
        pDB = GetFreeDB(aup);
        if (!pDB) {
            goto err_out;
        }
        aup->rx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
        aup->rx_db_inuse[i] = pDB;
    }
    for (i = 0; i < NUM_TX_DMA; i++) {
        pDB = GetFreeDB(aup);
        if (!pDB) {
            goto err_out;
        }
        aup->tx_dma_ring[i]->buff_stat = (unsigned)pDB->dma_addr;
        aup->tx_dma_ring[i]->len = 0;
        aup->tx_db_inuse[i] = pDB;
    }

    /*
     * The boot code uses the ethernet controller, so reset it to start
     * fresh.  au1000_init() expects that the device is in reset state.
     */
    reset_mac(dev);

    return dev;

err_out:
    if (aup->mii_bus != NULL) {
        mdiobus_unregister(aup->mii_bus);
        mdiobus_free(aup->mii_bus);
    }

    /* here we should have a valid dev plus aup-> register addresses
     * so we can reset the mac properly.*/
    reset_mac(dev);

    for (i = 0; i < NUM_RX_DMA; i++) {
        if (aup->rx_db_inuse[i])
            ReleaseDB(aup, aup->rx_db_inuse[i]);
    }
    for (i = 0; i < NUM_TX_DMA; i++) {
        if (aup->tx_db_inuse[i])
            ReleaseDB(aup, aup->tx_db_inuse[i]);
    }
    dma_free_noncoherent(NULL, MAX_BUF_SIZE * (NUM_TX_BUFFS + NUM_RX_BUFFS),
                         (void *)aup->vaddr, aup->dma_addr);
    unregister_netdev(dev);
    free_netdev(dev);
    release_mem_region( base, MAC_IOSIZE);
    release_mem_region(macen, 4);
    return NULL;
}
示例#2
0
/**
 * axienet_mdio_teardown - MDIO remove function
 * @lp:		Pointer to axienet local data structure.
 *
 * Unregisters the MDIO and frees any associate memory for mii bus.
 */
void axienet_mdio_teardown(struct axienet_local *lp)
{
	mdiobus_unregister(lp->mii_bus);
	mdiobus_free(lp->mii_bus);
	lp->mii_bus = NULL;
}
示例#3
0
static int bgmac_fixed_phy_register(struct bgmac *bgmac)
{
	struct fixed_phy_status fphy_status = {
		.link = 1,
		.speed = SPEED_1000,
		.duplex = DUPLEX_FULL,
	};
	struct phy_device *phy_dev;
	int err;

	phy_dev = fixed_phy_register(PHY_POLL, &fphy_status, -1, NULL);
	if (!phy_dev || IS_ERR(phy_dev)) {
		bgmac_err(bgmac, "Failed to register fixed PHY device\n");
		return -ENODEV;
	}

	err = phy_connect_direct(bgmac->net_dev, phy_dev, bgmac_adjust_link,
				 PHY_INTERFACE_MODE_MII);
	if (err) {
		bgmac_err(bgmac, "Connecting PHY failed\n");
		return err;
	}

	bgmac->phy_dev = phy_dev;

	return err;
}

static int bgmac_mii_register(struct bgmac *bgmac)
{
	struct bcma_chipinfo *ci = &bgmac->core->bus->chipinfo;
	struct mii_bus *mii_bus;
	struct phy_device *phy_dev;
	char bus_id[MII_BUS_ID_SIZE + 3];
	int i, err = 0;

	if (ci->id == BCMA_CHIP_ID_BCM4707 ||
	    ci->id == BCMA_CHIP_ID_BCM53018)
		return bgmac_fixed_phy_register(bgmac);

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

	mii_bus->name = "bgmac mii bus";
	sprintf(mii_bus->id, "%s-%d-%d", "bgmac", bgmac->core->bus->num,
		bgmac->core->core_unit);
	mii_bus->priv = bgmac;
	mii_bus->read = bgmac_mii_read;
	mii_bus->write = bgmac_mii_write;
	mii_bus->parent = &bgmac->core->dev;
	mii_bus->phy_mask = ~(1 << bgmac->phyaddr);

	mii_bus->irq = kmalloc_array(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
	if (!mii_bus->irq) {
		err = -ENOMEM;
		goto err_free_bus;
	}
	for (i = 0; i < PHY_MAX_ADDR; i++)
		mii_bus->irq[i] = PHY_POLL;

	err = mdiobus_register(mii_bus);
	if (err) {
		bgmac_err(bgmac, "Registration of mii bus failed\n");
		goto err_free_irq;
	}

	bgmac->mii_bus = mii_bus;

	/* Connect to the PHY */
	snprintf(bus_id, sizeof(bus_id), PHY_ID_FMT, mii_bus->id,
		 bgmac->phyaddr);
	phy_dev = phy_connect(bgmac->net_dev, bus_id, &bgmac_adjust_link,
			      PHY_INTERFACE_MODE_MII);
	if (IS_ERR(phy_dev)) {
		bgmac_err(bgmac, "PHY connecton failed\n");
		err = PTR_ERR(phy_dev);
		goto err_unregister_bus;
	}
	bgmac->phy_dev = phy_dev;

	return err;

err_unregister_bus:
	mdiobus_unregister(mii_bus);
err_free_irq:
	kfree(mii_bus->irq);
err_free_bus:
	mdiobus_free(mii_bus);
	return err;
}

static void bgmac_mii_unregister(struct bgmac *bgmac)
{
	struct mii_bus *mii_bus = bgmac->mii_bus;

	mdiobus_unregister(mii_bus);
	kfree(mii_bus->irq);
	mdiobus_free(mii_bus);
}

/**************************************************
 * BCMA bus ops
 **************************************************/

/* 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 net_device *net_dev;
	struct bgmac *bgmac;
	struct ssb_sprom *sprom = &core->bus->sprom;
	u8 *mac;
	int err;

	switch (core->core_unit) {
	case 0:
		mac = sprom->et0mac;
		break;
	case 1:
		mac = sprom->et1mac;
		break;
	case 2:
		mac = sprom->et2mac;
		break;
	default:
		pr_err("Unsupported core_unit %d\n", core->core_unit);
		return -ENOTSUPP;
	}

	if (!is_valid_ether_addr(mac)) {
		dev_err(&core->dev, "Invalid MAC addr: %pM\n", mac);
		eth_random_addr(mac);
		dev_warn(&core->dev, "Using random MAC: %pM\n", mac);
	}

	/* Allocation and references */
	net_dev = alloc_etherdev(sizeof(*bgmac));
	if (!net_dev)
		return -ENOMEM;
	net_dev->netdev_ops = &bgmac_netdev_ops;
	net_dev->irq = core->irq;
	net_dev->ethtool_ops = &bgmac_ethtool_ops;
	bgmac = netdev_priv(net_dev);
	bgmac->net_dev = net_dev;
	bgmac->core = core;
	bcma_set_drvdata(core, bgmac);

	/* Defaults */
	memcpy(bgmac->net_dev->dev_addr, mac, ETH_ALEN);

	/* On BCM4706 we need common core to access PHY */
	if (core->id.id == BCMA_CORE_4706_MAC_GBIT &&
	    !core->bus->drv_gmac_cmn.core) {
		bgmac_err(bgmac, "GMAC CMN core not found (required for BCM4706)\n");
		err = -ENODEV;
		goto err_netdev_free;
	}
	bgmac->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) {
		bgmac_err(bgmac, "No PHY found\n");
		err = -ENODEV;
		goto err_netdev_free;
	}
	bgmac_info(bgmac, "Found PHY addr: %d%s\n", bgmac->phyaddr,
		   bgmac->phyaddr == BGMAC_PHY_NOREGS ? " (NOREGS)" : "");

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

	bgmac_chip_reset(bgmac);

	/* For Northstar, we have to take all GMAC core out of reset */
	if (ci->id == BCMA_CHIP_ID_BCM4707 ||
	    ci->id == BCMA_CHIP_ID_BCM53018) {
		struct bcma_device *ns_core;
		int ns_gmac;

		/* Northstar has 4 GMAC cores */
		for (ns_gmac = 0; ns_gmac < 4; ns_gmac++) {
			/* As Northstar requirement, we have to reset all GMACs
			 * before accessing one. bgmac_chip_reset() call
			 * bcma_core_enable() for this core. Then the other
			 * three GMACs didn't reset.  We do it here.
			 */
			ns_core = bcma_find_core_unit(core->bus,
						      BCMA_CORE_MAC_GBIT,
						      ns_gmac);
			if (ns_core && !bcma_core_is_enabled(ns_core))
				bcma_core_enable(ns_core, 0);
		}
	}

	err = bgmac_dma_alloc(bgmac);
	if (err) {
		bgmac_err(bgmac, "Unable to alloc memory for DMA\n");
		goto err_netdev_free;
	}

	bgmac->int_mask = BGMAC_IS_ERRMASK | BGMAC_IS_RX | BGMAC_IS_TX_MASK;
	if (bcm47xx_nvram_getenv("et0_no_txint", NULL, 0) == 0)
		bgmac->int_mask &= ~BGMAC_IS_TX_MASK;

	/* TODO: reset the external phy. Specs are needed */
	bgmac_phy_reset(bgmac);

	bgmac->has_robosw = !!(core->bus->sprom.boardflags_lo &
			       BGMAC_BFL_ENETROBO);
	if (bgmac->has_robosw)
		bgmac_warn(bgmac, "Support for Roboswitch not implemented\n");

	if (core->bus->sprom.boardflags_lo & BGMAC_BFL_ENETADM)
		bgmac_warn(bgmac, "Support for ADMtek ethernet switch not implemented\n");

	netif_napi_add(net_dev, &bgmac->napi, bgmac_poll, BGMAC_WEIGHT);

	err = bgmac_mii_register(bgmac);
	if (err) {
		bgmac_err(bgmac, "Cannot register MDIO\n");
		goto err_dma_free;
	}

	net_dev->features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM;
	net_dev->hw_features = net_dev->features;
	net_dev->vlan_features = net_dev->features;

	err = register_netdev(bgmac->net_dev);
	if (err) {
		bgmac_err(bgmac, "Cannot register net device\n");
		goto err_mii_unregister;
	}

	netif_carrier_off(net_dev);

	return 0;

err_mii_unregister:
	bgmac_mii_unregister(bgmac);
err_dma_free:
	bgmac_dma_free(bgmac);

err_netdev_free:
	bcma_set_drvdata(core, NULL);
	free_netdev(net_dev);

	return err;
}

static void bgmac_remove(struct bcma_device *core)
{
	struct bgmac *bgmac = bcma_get_drvdata(core);

	unregister_netdev(bgmac->net_dev);
	bgmac_mii_unregister(bgmac);
	netif_napi_del(&bgmac->napi);
	bgmac_dma_free(bgmac);
	bcma_set_drvdata(core, NULL);
	free_netdev(bgmac->net_dev);
}

static struct bcma_driver bgmac_bcma_driver = {
	.name		= KBUILD_MODNAME,
	.id_table	= bgmac_bcma_tbl,
	.probe		= bgmac_probe,
	.remove		= bgmac_remove,
};

static int __init bgmac_init(void)
{
	int err;

	err = bcma_driver_register(&bgmac_bcma_driver);
	if (err)
		return err;
	pr_info("Broadcom 47xx GBit MAC driver loaded\n");

	return 0;
}
示例#4
0
static void ixp4xx_mdio_remove(void)
{
	mdiobus_unregister(mdio_bus);
	mdiobus_free(mdio_bus);
}
示例#5
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;
}
示例#6
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;
}
示例#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;
	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;
}
示例#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;
}
示例#9
0
static int pci_eth_probe(struct pci_dev *pdev, const struct pci_device_id *ent)
{
	struct net_device *dev;
	struct pci_eth_private *priv;
	void __iomem *ioaddr;
	int err;
	static int card_idx = -1;
	int bar = 0; /* Base Adderess Register 0 */
	u16 *adrp;
	unsigned long iomem_size;

	pr_info("%s\n", version);

	/* Wake up PCI device */
	err = pci_enable_device(pdev);
	if (err)
		goto err_out;

	/* Does the device support 32-bit DMA address? */
	err = pci_set_dma_mask(pdev, DMA_BIT_MASK(32));
	if (err) {
		dev_err(&pdev->dev, "32-bit PCI DMA addresses"
				"not supported by the card\n");
		goto err_out_disable_dev;
	}

	err = pci_set_consistent_dma_mask(pdev, DMA_BIT_MASK(32));
	if (err) {
		dev_err(&pdev->dev, "32-bit PCI DMA addresses"
				"not supported by the card\n");
		goto err_out_disable_dev;
	}

	/* Get IO Size */
	iomem_size = pci_resource_len(pdev, bar);
	pr_info("iomem_size = 0x%lx\n", iomem_size);

	/* Enable PCI bus mastering */
	pci_set_master(pdev);

	/* Reserve PCI I/O and memory resources */
	err = pci_request_regions(pdev, DRV_NAME);
	if (err) {
		dev_err(&pdev->dev, "Failed to request PCI regions\n");
		goto err_out_free_dev;
	}

	/* Map iomem_size bytes. After that ioaddr can be used via ioread*
	 * and iwrite* functions.
	 */
	ioaddr = pci_iomap(pdev, bar, iomem_size);
	if (!ioaddr) {
		dev_err(&pdev->dev, "ioremap failed for device\n");
		err = -EIO;
		goto err_out_free_res;
	}

	dev = alloc_etherdev(sizeof(struct pci_eth_private));
	if (!dev) {
		err = -ENOMEM;
		goto err_out_disable_dev;
	}
	SET_NETDEV_DEV(dev, &pdev->dev);
	priv = netdev_priv(dev);

	/* TODO: here we need to set PHY if it was not set by bootloader.
	 * (HW specific code)
	 */

	/* Set IRQ in struct net_device */
	dev->irq = pdev->irq;
	/* Set base address in struct net_device */
	dev->base_addr = ioaddr;

	/* Initialize spin lock */
	spin_lock_init(&priv->lock);

	/* Save struct net_device in the PCI private data */
	pci_set_drvdata(pdev, dev);

	/* TODO: Set MAC address (HW specific code) */

	/* Link new device into pci_eth_root_dev */
	priv->pdev = pdev;
	priv->dev = dev;

	/* TODO: Enable transmit and receive (HW specific code) */

	/* Fill struct net_device. */
	dev->netdev_ops = &pci_eth_netdev_ops;
	dev->watchdog_timeo = TX_TIMEOUT;

	netif_napi_add(dev, &priv->napi, pci_eth_poll, 64);

	priv->mii_bus = mdiobus_alloc();
	if (!priv->mii_bus) {
		dev_err(&pdev->dev, "mdiobus_alloc() failed\n");
		err = -ENOMEM;
		goto err_out_unmap;
	}

	/* Initialize MII if supported. */
	priv->mii_bus->priv = dev;
	priv->mii_bus->read = pci_eth_mdiobus_read;
	priv->mii_bus->write = pci_eth_mdiobus_write;
	priv->mii_bus->name = "pci_eth_mii";
	snprintf(priv->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
		dev_name(&pdev->dev), card_idx);

	err = mdiobus_register(priv->mii_bus);
	if (err) {
		dev_err(&pdev->dev, "failed to register MII bus\n");
		goto err_out_mdio;
	}

	err = pci_eth_mii_probe(dev);
	if (err) {
		dev_err(&pdev->dev, "failed to probe MII bus\n");
		goto err_out_mdio_unregister;
	}

	/* Register net device. After this dev->name assign */
	err = register_netdev(dev);
	if (err) {
		dev_err(&pdev->dev, "Failed to register net device\n");
		goto err_out_mdio_unregister;
	}
	return 0;

err_out_mdio_unregister:
	mdiobus_unregister(priv->mii_bus);
err_out_mdio:
	mdiobus_free(priv->mii_bus);
err_out_unmap:
	netif_napi_del(&priv->napi);
	pci_iounmap(pdev, ioaddr);
err_out_free_res:
	pci_release_regions(pdev);
err_out_free_dev:
	free_netdev(dev);
err_out_disable_dev:
	pci_disable_device(pdev);
err_out:
	return err;
}
示例#10
0
static void bcm_sf2_mdio_unregister(struct bcm_sf2_priv *priv)
{
	mdiobus_unregister(priv->slave_mii_bus);
	of_node_put(priv->master_mii_dn);
}
示例#11
0
static int __devinit bfin_mac_probe(struct platform_device *pdev)
{
	struct net_device *ndev;
	struct bfin_mac_local *lp;
	struct platform_device *pd;
	int rc;

	ndev = alloc_etherdev(sizeof(struct bfin_mac_local));
	if (!ndev) {
		dev_err(&pdev->dev, "Cannot allocate net device!\n");
		return -ENOMEM;
	}

	SET_NETDEV_DEV(ndev, &pdev->dev);
	platform_set_drvdata(pdev, ndev);
	lp = netdev_priv(ndev);

	/* Grab the MAC address in the MAC */
	*(__le32 *) (&(ndev->dev_addr[0])) = cpu_to_le32(bfin_read_EMAC_ADDRLO());
	*(__le16 *) (&(ndev->dev_addr[4])) = cpu_to_le16((u16) bfin_read_EMAC_ADDRHI());

	/* probe mac */
	/*todo: how to proble? which is revision_register */
	bfin_write_EMAC_ADDRLO(0x12345678);
	if (bfin_read_EMAC_ADDRLO() != 0x12345678) {
		dev_err(&pdev->dev, "Cannot detect Blackfin on-chip ethernet MAC controller!\n");
		rc = -ENODEV;
		goto out_err_probe_mac;
	}


	/*
	 * Is it valid? (Did bootloader initialize it?)
	 * Grab the MAC from the board somehow
	 * this is done in the arch/blackfin/mach-bfxxx/boards/eth_mac.c
	 */
	if (!is_valid_ether_addr(ndev->dev_addr))
		bfin_get_ether_addr(ndev->dev_addr);

	/* If still not valid, get a random one */
	if (!is_valid_ether_addr(ndev->dev_addr))
		random_ether_addr(ndev->dev_addr);

	setup_mac_addr(ndev->dev_addr);

	if (!pdev->dev.platform_data) {
		dev_err(&pdev->dev, "Cannot get platform device bfin_mii_bus!\n");
		rc = -ENODEV;
		goto out_err_probe_mac;
	}
	pd = pdev->dev.platform_data;
	lp->mii_bus = platform_get_drvdata(pd);
	lp->mii_bus->priv = ndev;

	rc = mii_probe(ndev);
	if (rc) {
		dev_err(&pdev->dev, "MII Probe failed!\n");
		goto out_err_mii_probe;
	}

	/* Fill in the fields of the device structure with ethernet values. */
	ether_setup(ndev);

	ndev->netdev_ops = &bfin_mac_netdev_ops;
	ndev->ethtool_ops = &bfin_mac_ethtool_ops;

	spin_lock_init(&lp->lock);

	/* now, enable interrupts */
	/* register irq handler */
	rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt,
			IRQF_DISABLED, "EMAC_RX", ndev);
	if (rc) {
		dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n");
		rc = -EBUSY;
		goto out_err_request_irq;
	}

	rc = register_netdev(ndev);
	if (rc) {
		dev_err(&pdev->dev, "Cannot register net device!\n");
		goto out_err_reg_ndev;
	}

	/* now, print out the card info, in a short format.. */
	dev_info(&pdev->dev, "%s, Version %s\n", DRV_DESC, DRV_VERSION);

	return 0;

out_err_reg_ndev:
	free_irq(IRQ_MAC_RX, ndev);
out_err_request_irq:
out_err_mii_probe:
	mdiobus_unregister(lp->mii_bus);
	mdiobus_free(lp->mii_bus);
	peripheral_free_list(pin_req);
out_err_probe_mac:
	platform_set_drvdata(pdev, NULL);
	free_netdev(ndev);

	return rc;
}
示例#12
0
static int __devinit bfin_mac_probe(struct platform_device *pdev)
{
	struct net_device *ndev;
	struct bfin_mac_local *lp;
	int rc, i;

	ndev = alloc_etherdev(sizeof(struct bfin_mac_local));
	if (!ndev) {
		dev_err(&pdev->dev, "Cannot allocate net device!\n");
		return -ENOMEM;
	}

	SET_NETDEV_DEV(ndev, &pdev->dev);
	platform_set_drvdata(pdev, ndev);
	lp = netdev_priv(ndev);

	/* Grab the MAC address in the MAC */
	*(__le32 *) (&(ndev->dev_addr[0])) = cpu_to_le32(bfin_read_EMAC_ADDRLO());
	*(__le16 *) (&(ndev->dev_addr[4])) = cpu_to_le16((u16) bfin_read_EMAC_ADDRHI());

	/* probe mac */
	/*todo: how to proble? which is revision_register */
	bfin_write_EMAC_ADDRLO(0x12345678);
	if (bfin_read_EMAC_ADDRLO() != 0x12345678) {
		dev_err(&pdev->dev, "Cannot detect Blackfin on-chip ethernet MAC controller!\n");
		rc = -ENODEV;
		goto out_err_probe_mac;
	}

	/* set the GPIO pins to Ethernet mode */
	rc = peripheral_request_list(pin_req, DRV_NAME);
	if (rc) {
		dev_err(&pdev->dev, "Requesting peripherals failed!\n");
		rc = -EFAULT;
		goto out_err_setup_pin_mux;
	}

	/*
	 * Is it valid? (Did bootloader initialize it?)
	 * Grab the MAC from the board somehow
	 * this is done in the arch/blackfin/mach-bfxxx/boards/eth_mac.c
	 */
	if (!is_valid_ether_addr(ndev->dev_addr))
		bfin_get_ether_addr(ndev->dev_addr);

	/* If still not valid, get a random one */
	if (!is_valid_ether_addr(ndev->dev_addr))
		random_ether_addr(ndev->dev_addr);

	setup_mac_addr(ndev->dev_addr);

	/* MDIO bus initial */
	lp->mii_bus = mdiobus_alloc();
	if (lp->mii_bus == NULL)
		goto out_err_mdiobus_alloc;

	lp->mii_bus->priv = ndev;
	lp->mii_bus->read = bfin_mdiobus_read;
	lp->mii_bus->write = bfin_mdiobus_write;
	lp->mii_bus->reset = bfin_mdiobus_reset;
	lp->mii_bus->name = "bfin_mac_mdio";
	snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "0");
	lp->mii_bus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
	for (i = 0; i < PHY_MAX_ADDR; ++i)
		lp->mii_bus->irq[i] = PHY_POLL;

	rc = mdiobus_register(lp->mii_bus);
	if (rc) {
		dev_err(&pdev->dev, "Cannot register MDIO bus!\n");
		goto out_err_mdiobus_register;
	}

	rc = mii_probe(ndev);
	if (rc) {
		dev_err(&pdev->dev, "MII Probe failed!\n");
		goto out_err_mii_probe;
	}

	/* Fill in the fields of the device structure with ethernet values. */
	ether_setup(ndev);

	ndev->netdev_ops = &bfin_mac_netdev_ops;
	ndev->ethtool_ops = &bfin_mac_ethtool_ops;

	spin_lock_init(&lp->lock);

	/* now, enable interrupts */
	/* register irq handler */
	rc = request_irq(IRQ_MAC_RX, bfin_mac_interrupt,
			IRQF_DISABLED | IRQF_SHARED, "EMAC_RX", ndev);
	if (rc) {
		dev_err(&pdev->dev, "Cannot request Blackfin MAC RX IRQ!\n");
		rc = -EBUSY;
		goto out_err_request_irq;
	}

	rc = register_netdev(ndev);
	if (rc) {
		dev_err(&pdev->dev, "Cannot register net device!\n");
		goto out_err_reg_ndev;
	}

	/* now, print out the card info, in a short format.. */
	dev_info(&pdev->dev, "%s, Version %s\n", DRV_DESC, DRV_VERSION);

	return 0;

out_err_reg_ndev:
	free_irq(IRQ_MAC_RX, ndev);
out_err_request_irq:
out_err_mii_probe:
	mdiobus_unregister(lp->mii_bus);
out_err_mdiobus_register:
	mdiobus_free(lp->mii_bus);
out_err_mdiobus_alloc:
	peripheral_free_list(pin_req);
out_err_setup_pin_mux:
out_err_probe_mac:
	platform_set_drvdata(pdev, NULL);
	free_netdev(ndev);

	return rc;
}
示例#13
0
static void
ramips_mdio_cleanup(struct raeth_priv *re)
{
	mdiobus_unregister(re->mii_bus);
	kfree(re->mii_bus);
}