Ejemplo n.º 1
0
struct mii_bus *bcma_mdio_mii_register(struct bgmac *bgmac)
{
	struct bcma_device *core = bgmac->bcma.core;
	struct mii_bus *mii_bus;
	int err;

	mii_bus = mdiobus_alloc();
	if (!mii_bus) {
		err = -ENOMEM;
		goto err;
	}

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

	err = mdiobus_register(mii_bus);
	if (err) {
		dev_err(&core->dev, "Registration of mii bus failed\n");
		goto err_free_bus;
	}

	return mii_bus;

err_free_bus:
	mdiobus_free(mii_bus);
err:
	return ERR_PTR(err);
}
Ejemplo n.º 2
0
static int bcmgenet_mii_alloc(struct bcmgenet_priv *priv)
{
	struct mii_bus *bus;

	if (priv->mii_bus)
		return 0;

	priv->mii_bus = mdiobus_alloc();
	if (!priv->mii_bus) {
		pr_err("failed to allocate\n");
		return -ENOMEM;
	}

	bus = priv->mii_bus;
	bus->priv = priv->dev;
	bus->name = "bcmgenet MII bus";
	bus->parent = &priv->pdev->dev;
	bus->read = bcmgenet_mii_read;
	bus->write = bcmgenet_mii_write;
	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d",
		 priv->pdev->name, priv->pdev->id);

	bus->irq = kcalloc(PHY_MAX_ADDR, sizeof(int), GFP_KERNEL);
	if (!bus->irq) {
		mdiobus_free(priv->mii_bus);
		return -ENOMEM;
	}

	return 0;
}
Ejemplo n.º 3
0
/* use phylib infrastructure */
static int ax88172a_init_mdio(struct usbnet *dev)
{
	struct ax88172a_private *priv = dev->driver_priv;
	int ret;

	priv->mdio = mdiobus_alloc();
	if (!priv->mdio) {
		netdev_err(dev->net, "Could not allocate MDIO bus\n");
		return -ENOMEM;
	}

	priv->mdio->priv = (void *)dev;
	priv->mdio->read = &asix_mdio_bus_read;
	priv->mdio->write = &asix_mdio_bus_write;
	priv->mdio->name = "Asix MDIO Bus";
	/* mii bus name is usb-<usb bus number>-<usb device number> */
	snprintf(priv->mdio->id, MII_BUS_ID_SIZE, "usb-%03d:%03d",
		 dev->udev->bus->busnum, dev->udev->devnum);

	ret = mdiobus_register(priv->mdio);
	if (ret) {
		netdev_err(dev->net, "Could not register MDIO bus\n");
		goto mfree;
	}

	netdev_info(dev->net, "registered mdio bus %s\n", priv->mdio->id);
	return 0;

mfree:
	mdiobus_free(priv->mdio);
	return ret;
}
Ejemplo n.º 4
0
static int rtl8366_smi_mii_init(struct rtl8366_smi *smi)
{
	int ret;
	int i;

	smi->mii_bus = mdiobus_alloc();
	if (smi->mii_bus == NULL) {
		ret = -ENOMEM;
		goto err;
	}

	smi->mii_bus->priv = (void *) smi;
	smi->mii_bus->name = dev_name(smi->parent);
	smi->mii_bus->read = smi->ops->mii_read;
	smi->mii_bus->write = smi->ops->mii_write;
	snprintf(smi->mii_bus->id, MII_BUS_ID_SIZE, "%s",
		 dev_name(smi->parent));
	smi->mii_bus->parent = smi->parent;
	smi->mii_bus->phy_mask = ~(0x1f);
	smi->mii_bus->irq = smi->mii_irq;
	for (i = 0; i < PHY_MAX_ADDR; i++)
		smi->mii_irq[i] = PHY_POLL;

	ret = mdiobus_register(smi->mii_bus);
	if (ret)
		goto err_free;

	return 0;

 err_free:
	mdiobus_free(smi->mii_bus);
 err:
	return ret;
}
Ejemplo n.º 5
0
static int ixp4xx_mdio_register(void)
{
	int err;

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

	if (cpu_is_ixp43x()) {
		/* IXP43x lacks NPE-B and uses NPE-C for MII PHY access */
		if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEC_ETH))
			return -ENOSYS;
		mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthC_BASE_VIRT;
	} else {
		/* All MII PHY accesses use NPE-B Ethernet registers */
		if (!(ixp4xx_read_feature_bits() & IXP4XX_FEATURE_NPEB_ETH0))
			return -ENOSYS;
		mdio_regs = (struct eth_regs __iomem *)IXP4XX_EthB_BASE_VIRT;
	}

	__raw_writel(DEFAULT_CORE_CNTRL, &mdio_regs->core_control);
	spin_lock_init(&mdio_lock);
	mdio_bus->name = "IXP4xx MII Bus";
	mdio_bus->read = &ixp4xx_mdio_read;
	mdio_bus->write = &ixp4xx_mdio_write;
	strcpy(mdio_bus->id, "0");

	if ((err = mdiobus_register(mdio_bus)))
		mdiobus_free(mdio_bus);
	return err;
}
Ejemplo n.º 6
0
static int
ramips_mdio_init(struct raeth_priv *re)
{
    int err;
    int i;

    re->mii_bus = mdiobus_alloc();
    if (re->mii_bus == NULL)
        return -ENOMEM;

    re->mii_bus->name = "ramips_mdio";
    re->mii_bus->read = ramips_mdio_read;
    re->mii_bus->write = ramips_mdio_write;
    re->mii_bus->reset = ramips_mdio_reset;
    re->mii_bus->irq = re->mii_irq;
    re->mii_bus->priv = re;
    re->mii_bus->parent = re->parent;

    snprintf(re->mii_bus->id, MII_BUS_ID_SIZE, "%s", "ramips_mdio");
    re->mii_bus->phy_mask = 0;

    for (i = 0; i < PHY_MAX_ADDR; i++)
        re->mii_irq[i] = PHY_POLL;

    err = mdiobus_register(re->mii_bus);
    if (err)
        goto err_free_bus;

    return 0;

err_free_bus:
    kfree(re->mii_bus);
    return err;
}
Ejemplo n.º 7
0
static int tc_mii_init(struct net_device *dev)
{
	struct tc35815_local *lp = netdev_priv(dev);
	int err;

	lp->mii_bus = mdiobus_alloc();
	if (lp->mii_bus == NULL) {
		err = -ENOMEM;
		goto err_out;
	}

	lp->mii_bus->name = "tc35815_mii_bus";
	lp->mii_bus->read = tc_mdio_read;
	lp->mii_bus->write = tc_mdio_write;
	snprintf(lp->mii_bus->id, MII_BUS_ID_SIZE, "%x",
		 (lp->pci_dev->bus->number << 8) | lp->pci_dev->devfn);
	lp->mii_bus->priv = dev;
	lp->mii_bus->parent = &lp->pci_dev->dev;
	err = mdiobus_register(lp->mii_bus);
	if (err)
		goto err_out_free_mii_bus;
	err = tc_mii_probe(dev);
	if (err)
		goto err_out_unregister_bus;
	return 0;

err_out_unregister_bus:
	mdiobus_unregister(lp->mii_bus);
err_out_free_mii_bus:
	mdiobus_free(lp->mii_bus);
err_out:
	return err;
}
Ejemplo n.º 8
0
static int mpc52xx_fec_mdio_probe(struct platform_device *of)
{
	struct device *dev = &of->dev;
	struct device_node *np = of->dev.of_node;
	struct mii_bus *bus;
	struct mpc52xx_fec_mdio_priv *priv;
	struct resource res;
	int err;

	bus = mdiobus_alloc();
	if (bus == NULL)
		return -ENOMEM;
	priv = kzalloc(sizeof(*priv), GFP_KERNEL);
	if (priv == NULL) {
		err = -ENOMEM;
		goto out_free;
	}

	bus->name = "mpc52xx MII bus";
	bus->read = mpc52xx_fec_mdio_read;
	bus->write = mpc52xx_fec_mdio_write;

	/* setup irqs */
	bus->irq = priv->mdio_irqs;

	/* setup registers */
	err = of_address_to_resource(np, 0, &res);
	if (err)
		goto out_free;
	priv->regs = ioremap(res.start, resource_size(&res));
	if (priv->regs == NULL) {
		err = -ENOMEM;
		goto out_free;
	}

	snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
	bus->priv = priv;

	bus->parent = dev;
	dev_set_drvdata(dev, bus);

	/* set MII speed */
	out_be32(&priv->regs->mii_speed,
		((mpc5xxx_get_bus_frequency(of->dev.of_node) >> 20) / 5) << 1);

	err = of_mdiobus_register(bus, np);
	if (err)
		goto out_unmap;

	return 0;

 out_unmap:
	iounmap(priv->regs);
 out_free:
	kfree(priv);
	mdiobus_free(bus);

	return err;
}
Ejemplo 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);
	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;
}
Ejemplo n.º 10
0
Archivo: bgmac.c Proyecto: 7799/linux
static int bgmac_mii_register(struct bgmac *bgmac)
{
	struct mii_bus *mii_bus;
	struct phy_device *phy_dev;
	char bus_id[MII_BUS_ID_SIZE + 3];
	int i, err = 0;

	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;
}
Ejemplo n.º 11
0
static int __init octeon_mdiobus_probe(struct platform_device *pdev)
{
	struct octeon_mdiobus *bus;
	union cvmx_smix_en smi_en;
	int i;
	int err = -ENOENT;

	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
	if (!bus)
		return -ENOMEM;

	/* The platform_device id is our unit number.  */
	bus->unit = pdev->id;

	bus->mii_bus = mdiobus_alloc();

	if (!bus->mii_bus)
		goto err;

	smi_en.u64 = 0;
	smi_en.s.en = 1;
	cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);

	/*
	 * Standard Octeon evaluation boards don't support phy
	 * interrupts, we need to poll.
	 */
	for (i = 0; i < PHY_MAX_ADDR; i++)
		bus->phy_irq[i] = PHY_POLL;

	bus->mii_bus->priv = bus;
	bus->mii_bus->irq = bus->phy_irq;
	bus->mii_bus->name = "mdio-octeon";
	snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%x", bus->unit);
	bus->mii_bus->parent = &pdev->dev;

	bus->mii_bus->read = octeon_mdiobus_read;
	bus->mii_bus->write = octeon_mdiobus_write;

	dev_set_drvdata(&pdev->dev, bus);

	err = mdiobus_register(bus->mii_bus);
	if (err)
		goto err_register;

	dev_info(&pdev->dev, "Version " DRV_VERSION "\n");

	return 0;
err_register:
	mdiobus_free(bus->mii_bus);

err:
	devm_kfree(&pdev->dev, bus);
	smi_en.u64 = 0;
	cvmx_write_csr(CVMX_SMIX_EN(bus->unit), smi_en.u64);
	return err;
}
Ejemplo n.º 12
0
static int __devinit gpio_mdio_probe(struct platform_device *ofdev,
				     const struct of_device_id *match)
{
	struct device *dev = &ofdev->dev;
	struct device_node *np = ofdev->dev.of_node;
	struct mii_bus *new_bus;
	struct gpio_priv *priv;
	const unsigned int *prop;
	int err;

	err = -ENOMEM;
	priv = kzalloc(sizeof(struct gpio_priv), GFP_KERNEL);
	if (!priv)
		goto out;

	new_bus = mdiobus_alloc();

	if (!new_bus)
		goto out_free_priv;

	new_bus->name = "pasemi gpio mdio bus";
	new_bus->read = &gpio_mdio_read;
	new_bus->write = &gpio_mdio_write;
	new_bus->reset = &gpio_mdio_reset;

	prop = of_get_property(np, "reg", NULL);
	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", *prop);
	new_bus->priv = priv;

	new_bus->irq = priv->mdio_irqs;

	prop = of_get_property(np, "mdc-pin", NULL);
	priv->mdc_pin = *prop;

	prop = of_get_property(np, "mdio-pin", NULL);
	priv->mdio_pin = *prop;

	new_bus->parent = dev;
	dev_set_drvdata(dev, new_bus);

	err = of_mdiobus_register(new_bus, np);

	if (err != 0) {
		printk(KERN_ERR "%s: Cannot register as MDIO bus, err %d\n",
				new_bus->name, err);
		goto out_free_irq;
	}

	return 0;

out_free_irq:
	kfree(new_bus);
out_free_priv:
	kfree(priv);
out:
	return err;
}
Ejemplo n.º 13
0
static int lpc_mii_init(struct netdata_local *pldat)
{
	int err = -ENXIO, i;

	pldat->mii_bus = mdiobus_alloc();
	if (!pldat->mii_bus) {
		err = -ENOMEM;
		goto err_out;
	}

	/* Setup MII mode */
	if (lpc_phy_interface_mode(&pldat->pdev->dev) == PHY_INTERFACE_MODE_MII)
		writel(LPC_COMMAND_PASSRUNTFRAME,
		       LPC_ENET_COMMAND(pldat->net_base));
	else {
		writel((LPC_COMMAND_PASSRUNTFRAME | LPC_COMMAND_RMII),
		       LPC_ENET_COMMAND(pldat->net_base));
		writel(LPC_SUPP_RESET_RMII, LPC_ENET_SUPP(pldat->net_base));
	}

	pldat->mii_bus->name = "lpc_mii_bus";
	pldat->mii_bus->read = &lpc_mdio_read;
	pldat->mii_bus->write = &lpc_mdio_write;
	pldat->mii_bus->reset = &lpc_mdio_reset;
	snprintf(pldat->mii_bus->id, MII_BUS_ID_SIZE, "%s-%x",
		 pldat->pdev->name, pldat->pdev->id);
	pldat->mii_bus->priv = pldat;
	pldat->mii_bus->parent = &pldat->pdev->dev;

	pldat->mii_bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
	if (!pldat->mii_bus->irq) {
		err = -ENOMEM;
		goto err_out_1;
	}

	for (i = 0; i < PHY_MAX_ADDR; i++)
		pldat->mii_bus->irq[i] = PHY_POLL;

	platform_set_drvdata(pldat->pdev, pldat->mii_bus);

	if (mdiobus_register(pldat->mii_bus))
		goto err_out_free_mdio_irq;

	if (lpc_mii_probe(pldat->ndev) != 0)
		goto err_out_unregister_bus;

	return 0;

err_out_unregister_bus:
	mdiobus_unregister(pldat->mii_bus);
err_out_free_mdio_irq:
	kfree(pldat->mii_bus->irq);
err_out_1:
	mdiobus_free(pldat->mii_bus);
err_out:
	return err;
}
Ejemplo n.º 14
0
static int mdio_mux_iproc_probe(struct platform_device *pdev)
{
	struct iproc_mdiomux_desc *md;
	struct mii_bus *bus;
	struct resource *res;
	int rc;

	md = devm_kzalloc(&pdev->dev, sizeof(*md), GFP_KERNEL);
	if (!md)
		return -ENOMEM;
	md->dev = &pdev->dev;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	md->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(md->base)) {
		dev_err(&pdev->dev, "failed to ioremap register\n");
		return PTR_ERR(md->base);
	}

	md->mii_bus = mdiobus_alloc();
	if (!md->mii_bus) {
		dev_err(&pdev->dev, "mdiomux bus alloc failed\n");
		return -ENOMEM;
	}

	bus = md->mii_bus;
	bus->priv = md;
	bus->name = "iProc MDIO mux bus";
	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", pdev->name, pdev->id);
	bus->parent = &pdev->dev;
	bus->read = iproc_mdiomux_read;
	bus->write = iproc_mdiomux_write;

	bus->phy_mask = ~0;
	bus->dev.of_node = pdev->dev.of_node;
	rc = mdiobus_register(bus);
	if (rc) {
		dev_err(&pdev->dev, "mdiomux registration failed\n");
		goto out;
	}

	platform_set_drvdata(pdev, md);

	rc = mdio_mux_init(md->dev, mdio_mux_iproc_switch_fn,
			   &md->mux_handle, md, md->mii_bus);
	if (rc) {
		dev_info(md->dev, "mdiomux initialization failed\n");
		goto out;
	}

	dev_info(md->dev, "iProc mdiomux registered\n");
	return 0;
out:
	mdiobus_free(bus);
	return rc;
}
Ejemplo n.º 15
0
static int vsc848x_nexus_probe(struct platform_device *pdev)
{
	struct vsc848x_nexus_mdiobus *bus;
	const char *bus_id;
	int len;
	int err = 0;

	bus = devm_kzalloc(&pdev->dev, sizeof(*bus), GFP_KERNEL);
	if (!bus)
		return -ENOMEM;

	bus->parent_mii_bus = container_of(pdev->dev.parent,
					   struct mii_bus, dev);

	/* The PHY nexux  must have a reg property in the range [0-31] */
	err = of_property_read_u32(pdev->dev.of_node, "reg", &bus->reg_offset);
	if (err) {
		dev_err(&pdev->dev, "%s has invalid PHY address\n",
			pdev->dev.of_node->full_name);
		return err;
	}

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

	bus->mii_bus->priv = bus;
	bus->mii_bus->irq = bus->phy_irq;
	bus->mii_bus->name = "vsc848x_nexus";
	bus_id = bus->parent_mii_bus->id;
	len = strlen(bus_id);
	if (len > MII_BUS_ID_SIZE - 4)
		bus_id += len - (MII_BUS_ID_SIZE - 4);
	snprintf(bus->mii_bus->id, MII_BUS_ID_SIZE, "%s:%02x",
		 bus_id, bus->reg_offset);
	bus->mii_bus->parent = &pdev->dev;

	bus->mii_bus->read = vsc848x_nexus_read;
	bus->mii_bus->write = vsc848x_nexus_write;
	mutex_init(&bus->lock);

	dev_set_drvdata(&pdev->dev, bus);

	err = of_mdiobus_register(bus->mii_bus, pdev->dev.of_node);
	if (err) {
		dev_err(&pdev->dev, "Error registering with device tree\n");
		goto fail_register;
	}

	return 0;

fail_register:
	dev_err(&pdev->dev, "Failed to register\n");
	mdiobus_free(bus->mii_bus);
	return err;
}
Ejemplo n.º 16
0
int temac_mdio_setup(struct temac_local *lp, struct device_node *np)
{
	struct mii_bus *bus;
	u32 bus_hz;
	int clk_div;
	int rc;
	struct resource res;
	struct device_node *np1 = of_get_parent(lp->phy_node);

	/* Calculate a reasonable divisor for the clock rate */
	clk_div = 0x3f; /* worst-case default setting */
	if (of_property_read_u32(np, "clock-frequency", &bus_hz) == 0) {
		clk_div = bus_hz / (2500 * 1000 * 2) - 1;
		if (clk_div < 1)
			clk_div = 1;
		if (clk_div > 0x3f)
			clk_div = 0x3f;
	}

	/* Enable the MDIO bus by asserting the enable bit and writing
	 * in the clock config */
	mutex_lock(&lp->indirect_mutex);
	temac_indirect_out32(lp, XTE_MC_OFFSET, 1 << 6 | clk_div);
	mutex_unlock(&lp->indirect_mutex);

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

	of_address_to_resource(np1, 0, &res);
	snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
		 (unsigned long long)res.start);
	bus->priv = lp;
	bus->name = "Xilinx TEMAC MDIO";
	bus->read = temac_mdio_read;
	bus->write = temac_mdio_write;
	bus->parent = lp->dev;

	lp->mii_bus = bus;

	rc = of_mdiobus_register(bus, np1);
	if (rc)
		goto err_register;

	mutex_lock(&lp->indirect_mutex);
	dev_dbg(lp->dev, "MDIO bus registered;  MC:%x\n",
		temac_indirect_in32(lp, XTE_MC_OFFSET));
	mutex_unlock(&lp->indirect_mutex);
	return 0;

 err_register:
	mdiobus_free(bus);
	return rc;
}
int temac_mdio_setup(struct temac_local *lp, struct device_node *np)
{
	struct mii_bus *bus;
	const u32 *bus_hz;
	int clk_div;
	int rc, size;
	struct resource res;

	
	clk_div = 0x3f; 
	bus_hz = of_get_property(np, "clock-frequency", &size);
	if (bus_hz && size >= sizeof(*bus_hz)) {
		clk_div = (*bus_hz) / (2500 * 1000 * 2) - 1;
		if (clk_div < 1)
			clk_div = 1;
		if (clk_div > 0x3f)
			clk_div = 0x3f;
	}

	mutex_lock(&lp->indirect_mutex);
	temac_indirect_out32(lp, XTE_MC_OFFSET, 1 << 6 | clk_div);
	mutex_unlock(&lp->indirect_mutex);

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

	of_address_to_resource(np, 0, &res);
	snprintf(bus->id, MII_BUS_ID_SIZE, "%.8llx",
		 (unsigned long long)res.start);
	bus->priv = lp;
	bus->name = "Xilinx TEMAC MDIO";
	bus->read = temac_mdio_read;
	bus->write = temac_mdio_write;
	bus->parent = lp->dev;
	bus->irq = lp->mdio_irqs; 

	lp->mii_bus = bus;

	rc = of_mdiobus_register(bus, np);
	if (rc)
		goto err_register;

	mutex_lock(&lp->indirect_mutex);
	dev_dbg(lp->dev, "MDIO bus registered;  MC:%x\n",
		temac_indirect_in32(lp, XTE_MC_OFFSET));
	mutex_unlock(&lp->indirect_mutex);
	return 0;

 err_register:
	mdiobus_free(bus);
	return rc;
}
Ejemplo n.º 18
0
Archivo: mdio.c Proyecto: Lyude/linux
int mtk_mdio_init(struct mtk_eth *eth)
{
	struct device_node *mii_np;
	int err;

	if (!eth->soc->mdio_read || !eth->soc->mdio_write)
		return 0;

	spin_lock_init(&phy_ralink.lock);
	eth->phy = &phy_ralink;

	mii_np = of_get_child_by_name(eth->dev->of_node, "mdio-bus");
	if (!mii_np) {
		dev_err(eth->dev, "no %s child node found", "mdio-bus");
		return -ENODEV;
	}

	if (!of_device_is_available(mii_np)) {
		err = 0;
		goto err_put_node;
	}

	eth->mii_bus = mdiobus_alloc();
	if (!eth->mii_bus) {
		err = -ENOMEM;
		goto err_put_node;
	}

	eth->mii_bus->name = "mdio";
	eth->mii_bus->read = eth->soc->mdio_read;
	eth->mii_bus->write = eth->soc->mdio_write;
	eth->mii_bus->reset = mtk_mdio_reset;
	eth->mii_bus->priv = eth;
	eth->mii_bus->parent = eth->dev;

	snprintf(eth->mii_bus->id, MII_BUS_ID_SIZE, "%s", mii_np->name);
	err = of_mdiobus_register(eth->mii_bus, mii_np);
	if (err)
		goto err_free_bus;

	return 0;

err_free_bus:
	kfree(eth->mii_bus);
err_put_node:
	of_node_put(mii_np);
	eth->mii_bus = NULL;
	return err;
}
Ejemplo n.º 19
0
static int iproc_mdio_probe(struct platform_device *pdev)
{
	struct iproc_mdio_priv *priv;
	struct mii_bus *bus;
	struct resource *res;
	int rc;

	priv = devm_kzalloc(&pdev->dev, sizeof(*priv), GFP_KERNEL);
	if (!priv)
		return -ENOMEM;

	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	priv->base = devm_ioremap_resource(&pdev->dev, res);
	if (IS_ERR(priv->base)) {
		dev_err(&pdev->dev, "failed to ioremap register\n");
		return PTR_ERR(priv->base);
	}

	priv->mii_bus = mdiobus_alloc();
	if (!priv->mii_bus) {
		dev_err(&pdev->dev, "MDIO bus alloc failed\n");
		return -ENOMEM;
	}

	bus = priv->mii_bus;
	bus->priv = priv;
	bus->name = "iProc MDIO bus";
	snprintf(bus->id, MII_BUS_ID_SIZE, "%s-%d", pdev->name, pdev->id);
	bus->parent = &pdev->dev;
	bus->read = iproc_mdio_read;
	bus->write = iproc_mdio_write;

	rc = of_mdiobus_register(bus, pdev->dev.of_node);
	if (rc) {
		dev_err(&pdev->dev, "MDIO bus registration failed\n");
		goto err_iproc_mdio;
	}

	platform_set_drvdata(pdev, priv);

	dev_info(&pdev->dev, "Broadcom iProc MDIO bus at 0x%p\n", priv->base);

	return 0;

err_iproc_mdio:
	mdiobus_free(bus);
	return rc;
}
Ejemplo n.º 20
0
static int __devinit bfin_mii_bus_probe(struct platform_device *pdev)
{
	struct mii_bus *miibus;
	int rc, i;

	/*
	 * We are setting up a network card,
	 * so 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");
		return rc;
	}

	rc = -ENOMEM;
	miibus = mdiobus_alloc();
	if (miibus == NULL)
		goto out_err_alloc;
	miibus->read = bfin_mdiobus_read;
	miibus->write = bfin_mdiobus_write;
	miibus->reset = bfin_mdiobus_reset;

	miibus->parent = &pdev->dev;
	miibus->name = "bfin_mii_bus";
	snprintf(miibus->id, MII_BUS_ID_SIZE, "0");
	miibus->irq = kmalloc(sizeof(int)*PHY_MAX_ADDR, GFP_KERNEL);
	if (miibus->irq == NULL)
		goto out_err_alloc;
	for (i = 0; i < PHY_MAX_ADDR; ++i)
		miibus->irq[i] = PHY_POLL;

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

	platform_set_drvdata(pdev, miibus);
	return 0;

out_err_mdiobus_register:
	mdiobus_free(miibus);
out_err_alloc:
	peripheral_free_list(pin_req);

	return rc;
}
Ejemplo n.º 21
0
struct mii_bus *alloc_mdio_bitbang(struct mdiobb_ctrl *ctrl)
{
	struct mii_bus *bus;

	bus = mdiobus_alloc();
	if (!bus)
		return NULL;

	__module_get(ctrl->ops->owner);

	bus->read = mdiobb_read;
	bus->write = mdiobb_write;
	bus->reset = mdiobb_reset;
	bus->priv = ctrl;

	return bus;
}
Ejemplo n.º 22
0
/**
 * arc_mdio_probe - MDIO probe function.
 * @priv:	Pointer to ARC EMAC private data structure.
 *
 * returns:	0 on success, -ENOMEM when mdiobus_alloc
 * (to allocate memory for MII bus structure) fails.
 *
 * Sets up and registers the MDIO interface.
 */
int arc_mdio_probe(struct arc_emac_priv *priv)
{
	struct arc_emac_mdio_bus_data *data = &priv->bus_data;
	struct device_node *np = priv->dev->of_node;
	struct mii_bus *bus;
	int error;

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

	priv->bus = bus;
	bus->priv = priv;
	bus->parent = priv->dev;
	bus->name = "Synopsys MII Bus";
	bus->read = &arc_mdio_read;
	bus->write = &arc_mdio_write;
	bus->reset = &arc_mdio_reset;

	/* optional reset-related properties */
	data->reset_gpio = devm_gpiod_get_optional(priv->dev, "phy-reset",
						   GPIOD_OUT_LOW);
	if (IS_ERR(data->reset_gpio)) {
		error = PTR_ERR(data->reset_gpio);
		dev_err(priv->dev, "Failed to request gpio: %d\n", error);
		return error;
	}

	of_property_read_u32(np, "phy-reset-duration", &data->msec);
	/* A sane reset duration should not be longer than 1s */
	if (data->msec > 1000)
		data->msec = 1;

	snprintf(bus->id, MII_BUS_ID_SIZE, "%s", bus->name);

	error = of_mdiobus_register(bus, priv->dev->of_node);
	if (error) {
		dev_err(priv->dev, "cannot register MDIO bus %s\n", bus->name);
		mdiobus_free(bus);
		return error;
	}

	return 0;
}
Ejemplo n.º 23
0
/**
 * @brief Initialize and register MDIO bus
 * @param[in] pointer to nss_gmac_dev
 * @return 0 on Success
 */
int32_t nss_gmac_init_mdiobus(struct nss_gmac_dev *gmacdev)
{
	struct mii_bus *miibus = NULL;
	struct phy_device *phydev = NULL;

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

	miibus->name = "nss gmac mdio bus";
	snprintf(miibus->id, MII_BUS_ID_SIZE, "mdiobus%x", gmacdev->macid);

	miibus->priv = (void *)gmacdev;
	miibus->read = nss_gmac_mdiobus_read;
	miibus->write = nss_gmac_mdiobus_write;
	miibus->reset = nss_gmac_mdiobus_reset;
	mutex_init(&(miibus->mdio_lock));
	miibus->parent = &(gmacdev->pdev->dev);

	phy_irq[gmacdev->phy_base] = PHY_POLL;
	miibus->irq = phy_irq;
	miibus->phy_mask = ~((uint32_t)(1 << gmacdev->phy_base));

	if (mdiobus_register(miibus) != 0) {
		mdiobus_free(miibus);
		netdev_dbg(gmacdev->netdev, "%s: mdiobus_reg failed\n", __func__);
		return -EIO;
	}

	phydev = miibus->phy_map[gmacdev->phy_base];
	if (!phydev) {
		netdev_dbg(gmacdev->netdev, "%s: No phy device\n", __func__);
		mdiobus_unregister(miibus);
		mdiobus_free(miibus);
		return -ENODEV;
	}

	phydev->interface = gmacdev->phy_mii_type;

	gmacdev->miibus = miibus;
	return 0;
}
Ejemplo n.º 24
0
static int yatse_mdio_register(struct yatse_private *priv){
	struct mii_bus *mdio;
	struct yatse_mdio_priv *mdio_priv;
	int ret;
	int i;

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

	mdio->name = "yatse MII bus";
	mdio->read = &yatse_mdio_read;
	mdio->write = &yatse_mdio_write;
	snprintf(mdio->id, MII_BUS_ID_SIZE, "%u", priv->config->mii_id);


	mdio->priv = kmalloc(sizeof(*mdio_priv), GFP_KERNEL);
	if(!mdio->priv) return -ENOMEM;

	mdio_priv = mdio->priv;
	mdio_priv->mac = priv->mac;
	spin_lock_init(&mdio_priv->lock);

	for(i = 0;i < 32;i++){
		mdio_priv->irqs[i] = priv->phy_irq;
	}
	mdio->irq = (void *)&mdio_priv->irqs;

	ret = mdiobus_register(mdio);
	if(ret){
		printk(KERN_ERR "%s:%d: mdiobus_register() failed\n", __FILE__, __LINE__);
		mdiobus_free(mdio);
		return ret;
	}

	return yatse_detect_phys(priv, mdio);
}
Ejemplo n.º 25
0
/**
 * gmac_mdio_register
 * @ndev: net device structure
 * Description: it registers the MII bus
 */
int gmac_mdio_register(struct net_device *ndev)
{
	int err = 0;
	struct mii_bus *new_bus;
	int *irqlist;
	struct gmac_priv *priv = netdev_priv(ndev);
	struct gmac_mdio_bus_data *mdio_bus_data = priv->plat->mdio_bus_data;
	int addr, found;

	if (!mdio_bus_data)
		return 0;

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

	if (mdio_bus_data->irqs)
		irqlist = mdio_bus_data->irqs;
	else
		irqlist = priv->mii_irq;

	new_bus->name = "sunxi_gmac";
	new_bus->read = &gmac_mdio_read;
	new_bus->write = &gmac_mdio_write;
	new_bus->reset = &gmac_mdio_reset;
	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%s-%x",
		new_bus->name, mdio_bus_data->bus_id);
	new_bus->priv = ndev;
	new_bus->irq = irqlist;
	new_bus->phy_mask = mdio_bus_data->phy_mask;
	new_bus->parent = priv->device;
	err = mdiobus_register(new_bus);
	if (err != 0) {
		printk(KERN_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 < PHY_MAX_ADDR; addr++) {
		struct phy_device *phydev = new_bus->phy_map[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)) {
				irqlist[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->bus_id == mdio_bus_data->bus_id) &&
			    (priv->plat->phy_addr == -1))
				priv->plat->phy_addr = addr;

			act = (priv->plat->bus_id == mdio_bus_data->bus_id) &&
				(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, dev_name(&phydev->dev),
			//	act ? " active" : "");
			found = 1;
		}
	}

	if (!found){
		printk(KERN_WARNING "%s: No PHY found\n", ndev->name);
		err = -ENXIO;
		goto out_err;
	}

	return 0;

out_err:
	mdiobus_unregister(new_bus);
bus_register_fail:
	mdiobus_free(new_bus);
	priv->mii = NULL;
	return err;
}
Ejemplo n.º 26
0
static int __devinit s6gmac_probe(struct platform_device *pdev)
{
	struct net_device *dev;
	struct s6gmac *pd;
	int res;
	unsigned long i;
	struct mii_bus *mb;
	dev = alloc_etherdev(sizeof(*pd));
	if (!dev) {
		printk(KERN_ERR DRV_PRMT "etherdev alloc failed, aborting.\n");
		return -ENOMEM;
	}
	dev->open = s6gmac_open;
	dev->stop = s6gmac_stop;
	dev->hard_start_xmit = s6gmac_tx;
	dev->tx_timeout = s6gmac_tx_timeout;
	dev->watchdog_timeo = HZ;
	dev->get_stats = s6gmac_stats;
	dev->irq = platform_get_irq(pdev, 0);
	pd = netdev_priv(dev);
	memset(pd, 0, sizeof(*pd));
	spin_lock_init(&pd->lock);
	pd->reg = platform_get_resource(pdev, IORESOURCE_MEM, 0)->start;
	i = platform_get_resource(pdev, IORESOURCE_DMA, 0)->start;
	pd->tx_dma = DMA_MASK_DMAC(i);
	pd->tx_chan = DMA_INDEX_CHNL(i);
	i = platform_get_resource(pdev, IORESOURCE_DMA, 1)->start;
	pd->rx_dma = DMA_MASK_DMAC(i);
	pd->rx_chan = DMA_INDEX_CHNL(i);
	pd->io = platform_get_resource(pdev, IORESOURCE_IO, 0)->start;
	res = request_irq(dev->irq, s6gmac_interrupt, 0, dev->name, dev);
	if (res) {
		printk(KERN_ERR DRV_PRMT "irq request failed: %d\n", dev->irq);
		goto errirq;
	}
	res = register_netdev(dev);
	if (res) {
		printk(KERN_ERR DRV_PRMT "error registering device %s\n",
			dev->name);
		goto errdev;
	}
	mb = mdiobus_alloc();
	if (!mb) {
		printk(KERN_ERR DRV_PRMT "error allocating mii bus\n");
		goto errmii;
	}
	mb->name = "s6gmac_mii";
	mb->read = s6mii_read;
	mb->write = s6mii_write;
	mb->reset = s6mii_reset;
	mb->priv = pd;
	snprintf(mb->id, MII_BUS_ID_SIZE, "0");
	mb->phy_mask = ~(1 << 0);
	mb->irq = &pd->mii.irq[0];
	for (i = 0; i < PHY_MAX_ADDR; i++) {
		int n = platform_get_irq(pdev, i + 1);
		if (n < 0)
			n = PHY_POLL;
		pd->mii.irq[i] = n;
	}
	mdiobus_register(mb);
	pd->mii.bus = mb;
	res = s6gmac_phy_start(dev);
	if (res)
		return res;
	platform_set_drvdata(pdev, dev);
	return 0;
errmii:
	unregister_netdev(dev);
errdev:
	free_irq(dev->irq, dev);
errirq:
	free_netdev(dev);
	return res;
}
Ejemplo n.º 27
0
static int mpc52xx_fec_mdio_probe(struct of_device *of,
                                  const struct of_device_id *match)
{
    struct device *dev = &of->dev;
    struct device_node *np = of->node;
    struct device_node *child = NULL;
    struct mii_bus *bus;
    struct mpc52xx_fec_mdio_priv *priv;
    struct resource res = {};
    int err;
    int i;

    bus = mdiobus_alloc();
    if (bus == NULL)
        return -ENOMEM;
    priv = kzalloc(sizeof(*priv), GFP_KERNEL);
    if (priv == NULL) {
        err = -ENOMEM;
        goto out_free;
    }

    bus->name = "mpc52xx MII bus";
    bus->read = mpc52xx_fec_mdio_read;
    bus->write = mpc52xx_fec_mdio_write;

    /* setup irqs */
    bus->irq = kmalloc(sizeof(bus->irq[0]) * PHY_MAX_ADDR, GFP_KERNEL);
    if (bus->irq == NULL) {
        err = -ENOMEM;
        goto out_free;
    }
    for (i=0; i<PHY_MAX_ADDR; i++)
        bus->irq[i] = PHY_POLL;

    while ((child = of_get_next_child(np, child)) != NULL) {
        int irq = irq_of_parse_and_map(child, 0);
        if (irq != NO_IRQ) {
            const u32 *id = of_get_property(child, "reg", NULL);
            if (id)
                bus->irq[*id] = irq;
        }
    }

    /* setup registers */
    err = of_address_to_resource(np, 0, &res);
    if (err)
        goto out_free;
    priv->regs = ioremap(res.start, res.end - res.start + 1);
    if (priv->regs == NULL) {
        err = -ENOMEM;
        goto out_free;
    }

    snprintf(bus->id, MII_BUS_ID_SIZE, "%x", res.start);
    bus->priv = priv;

    bus->parent = dev;
    dev_set_drvdata(dev, bus);

    /* set MII speed */
    out_be32(&priv->regs->mii_speed,
             ((mpc52xx_find_ipb_freq(of->node) >> 20) / 5) << 1);

    err = mdiobus_register(bus);
    if (err)
        goto out_unmap;

    return 0;

out_unmap:
    iounmap(priv->regs);
out_free:
    for (i=0; i<PHY_MAX_ADDR; i++)
        if (bus->irq[i] != PHY_POLL)
            irq_dispose_mapping(bus->irq[i]);
    kfree(bus->irq);
    kfree(priv);
    mdiobus_free(bus);

    return err;
}
Ejemplo n.º 28
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 mii_bus *mii_bus;
	struct phy_device *phy_dev;
	char bus_id[MII_BUS_ID_SIZE + 3];
	int err = 0;

	if (bgmac_is_bcm4707_family(bgmac))
		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);

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

	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 connection 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_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);
	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 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);
	}

	/* This (reset &) enable is not preset in specs or reference driver but
	 * Broadcom does it in arch PCI code when enabling fake PCI device.
	 */
	bcma_core_enable(core, 0);

	/* 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 (bgmac_is_bcm4707_family(bgmac)) {
		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;
}
Ejemplo n.º 29
0
/*
 * allocate netdevice, request register memory and register device.
 */
static int __devinit bcm_enet_probe(struct platform_device *pdev)
{
	struct bcm_enet_priv *priv;
	struct net_device *dev;
	struct bcm63xx_enet_platform_data *pd;
	struct resource *res_mem, *res_irq, *res_irq_rx, *res_irq_tx;
	struct mii_bus *bus;
	const char *clk_name;
	unsigned int iomem_size;
	int i, ret;

	/* stop if shared driver failed, assume driver->probe will be
	 * called in the same order we register devices (correct ?) */
	if (!bcm_enet_shared_base)
		return -ENODEV;

	res_mem = platform_get_resource(pdev, IORESOURCE_MEM, 0);
	res_irq = platform_get_resource(pdev, IORESOURCE_IRQ, 0);
	res_irq_rx = platform_get_resource(pdev, IORESOURCE_IRQ, 1);
	res_irq_tx = platform_get_resource(pdev, IORESOURCE_IRQ, 2);
	if (!res_mem || !res_irq || !res_irq_rx || !res_irq_tx)
		return -ENODEV;

	ret = 0;
	dev = alloc_etherdev(sizeof(*priv));
	if (!dev)
		return -ENOMEM;
	priv = netdev_priv(dev);
	memset(priv, 0, sizeof(*priv));

	ret = compute_hw_mtu(priv, dev->mtu);
	if (ret)
		goto out;

	iomem_size = res_mem->end - res_mem->start + 1;
	if (!request_mem_region(res_mem->start, iomem_size, "bcm63xx_enet")) {
		ret = -EBUSY;
		goto out;
	}

	priv->base = ioremap(res_mem->start, iomem_size);
	if (priv->base == NULL) {
		ret = -ENOMEM;
		goto out_release_mem;
	}
	dev->irq = priv->irq = res_irq->start;
	priv->irq_rx = res_irq_rx->start;
	priv->irq_tx = res_irq_tx->start;
	priv->mac_id = pdev->id;

	/* get rx & tx dma channel id for this mac */
	if (priv->mac_id == 0) {
		priv->rx_chan = 0;
		priv->tx_chan = 1;
		clk_name = "enet0";
	} else {
		priv->rx_chan = 2;
		priv->tx_chan = 3;
		clk_name = "enet1";
	}

	priv->mac_clk = clk_get(&pdev->dev, clk_name);
	if (IS_ERR(priv->mac_clk)) {
		ret = PTR_ERR(priv->mac_clk);
		goto out_unmap;
	}
	clk_enable(priv->mac_clk);

	/* initialize default and fetch platform data */
	priv->rx_ring_size = BCMENET_DEF_RX_DESC;
	priv->tx_ring_size = BCMENET_DEF_TX_DESC;

	pd = pdev->dev.platform_data;
	if (pd) {
		memcpy(dev->dev_addr, pd->mac_addr, ETH_ALEN);
		priv->has_phy = pd->has_phy;
		priv->phy_id = pd->phy_id;
		priv->has_phy_interrupt = pd->has_phy_interrupt;
		priv->phy_interrupt = pd->phy_interrupt;
		priv->use_external_mii = !pd->use_internal_phy;
		priv->pause_auto = pd->pause_auto;
		priv->pause_rx = pd->pause_rx;
		priv->pause_tx = pd->pause_tx;
		priv->force_duplex_full = pd->force_duplex_full;
		priv->force_speed_100 = pd->force_speed_100;
	}

	if (priv->mac_id == 0 && priv->has_phy && !priv->use_external_mii) {
		/* using internal PHY, enable clock */
		priv->phy_clk = clk_get(&pdev->dev, "ephy");
		if (IS_ERR(priv->phy_clk)) {
			ret = PTR_ERR(priv->phy_clk);
			priv->phy_clk = NULL;
			goto out_put_clk_mac;
		}
		clk_enable(priv->phy_clk);
	}

	/* do minimal hardware init to be able to probe mii bus */
	bcm_enet_hw_preinit(priv);

	/* MII bus registration */
	if (priv->has_phy) {

		priv->mii_bus = mdiobus_alloc();
		if (!priv->mii_bus) {
			ret = -ENOMEM;
			goto out_uninit_hw;
		}

		bus = priv->mii_bus;
		bus->name = "bcm63xx_enet MII bus";
		bus->parent = &pdev->dev;
		bus->priv = priv;
		bus->read = bcm_enet_mdio_read_phylib;
		bus->write = bcm_enet_mdio_write_phylib;
		sprintf(bus->id, "%d", priv->mac_id);

		/* only probe bus where we think the PHY is, because
		 * the mdio read operation return 0 instead of 0xffff
		 * if a slave is not present on hw */
		bus->phy_mask = ~(1 << priv->phy_id);

		bus->irq = kmalloc(sizeof(int) * PHY_MAX_ADDR, GFP_KERNEL);
		if (!bus->irq) {
			ret = -ENOMEM;
			goto out_free_mdio;
		}

		if (priv->has_phy_interrupt)
			bus->irq[priv->phy_id] = priv->phy_interrupt;
		else
			bus->irq[priv->phy_id] = PHY_POLL;

		ret = mdiobus_register(bus);
		if (ret) {
			dev_err(&pdev->dev, "unable to register mdio bus\n");
			goto out_free_mdio;
		}
	} else {

		/* run platform code to initialize PHY device */
		if (pd->mii_config &&
		    pd->mii_config(dev, 1, bcm_enet_mdio_read_mii,
				   bcm_enet_mdio_write_mii)) {
			dev_err(&pdev->dev, "unable to configure mdio bus\n");
			goto out_uninit_hw;
		}
	}

	spin_lock_init(&priv->rx_lock);

	/* init rx timeout (used for oom) */
	init_timer(&priv->rx_timeout);
	priv->rx_timeout.function = bcm_enet_refill_rx_timer;
	priv->rx_timeout.data = (unsigned long)dev;

	/* init the mib update lock&work */
	mutex_init(&priv->mib_update_lock);
	INIT_WORK(&priv->mib_update_task, bcm_enet_update_mib_counters_defer);

	/* zero mib counters */
	for (i = 0; i < ENET_MIB_REG_COUNT; i++)
		enet_writel(priv, 0, ENET_MIB_REG(i));

	/* register netdevice */
	dev->netdev_ops = &bcm_enet_ops;
	netif_napi_add(dev, &priv->napi, bcm_enet_poll, 16);

	SET_ETHTOOL_OPS(dev, &bcm_enet_ethtool_ops);
	SET_NETDEV_DEV(dev, &pdev->dev);

	ret = register_netdev(dev);
	if (ret)
		goto out_unregister_mdio;

	netif_carrier_off(dev);
	platform_set_drvdata(pdev, dev);
	priv->pdev = pdev;
	priv->net_dev = dev;

	return 0;

out_unregister_mdio:
	if (priv->mii_bus) {
		mdiobus_unregister(priv->mii_bus);
		kfree(priv->mii_bus->irq);
	}

out_free_mdio:
	if (priv->mii_bus)
		mdiobus_free(priv->mii_bus);

out_uninit_hw:
	/* turn off mdc clock */
	enet_writel(priv, 0, ENET_MIISC_REG);
	if (priv->phy_clk) {
		clk_disable(priv->phy_clk);
		clk_put(priv->phy_clk);
	}

out_put_clk_mac:
	clk_disable(priv->mac_clk);
	clk_put(priv->mac_clk);

out_unmap:
	iounmap(priv->base);

out_release_mem:
	release_mem_region(res_mem->start, iomem_size);
out:
	free_netdev(dev);
	return ret;
}
Ejemplo n.º 30
0
static int fs_enet_mdio_probe(struct platform_device *ofdev)
{
	const struct of_device_id *match;
	struct resource res;
	struct mii_bus *new_bus;
	struct fec_info *fec;
	int (*get_bus_freq)(struct device_node *);
	int ret = -ENOMEM, clock, speed;

	match = of_match_device(fs_enet_mdio_fec_match, &ofdev->dev);
	if (!match)
		return -EINVAL;
	get_bus_freq = match->data;

	new_bus = mdiobus_alloc();
	if (!new_bus)
		goto out;

	fec = kzalloc(sizeof(struct fec_info), GFP_KERNEL);
	if (!fec)
		goto out_mii;

	new_bus->priv = fec;
	new_bus->name = "FEC MII Bus";
	new_bus->read = &fs_enet_fec_mii_read;
	new_bus->write = &fs_enet_fec_mii_write;

	ret = of_address_to_resource(ofdev->dev.of_node, 0, &res);
	if (ret)
		goto out_res;

	snprintf(new_bus->id, MII_BUS_ID_SIZE, "%x", res.start);

	fec->fecp = ioremap(res.start, resource_size(&res));
	if (!fec->fecp) {
		ret = -ENOMEM;
		goto out_fec;
	}

	if (get_bus_freq) {
		clock = get_bus_freq(ofdev->dev.of_node);
		if (!clock) {
			/* Use maximum divider if clock is unknown */
			dev_warn(&ofdev->dev, "could not determine IPS clock\n");
			clock = 0x3F * 5000000;
		}
	} else
		clock = ppc_proc_freq;

	/*
	 * Scale for a MII clock <= 2.5 MHz
	 * Note that only 6 bits (25:30) are available for MII speed.
	 */
	speed = (clock + 4999999) / 5000000;
	if (speed > 0x3F) {
		speed = 0x3F;
		dev_err(&ofdev->dev,
			"MII clock (%d Hz) exceeds max (2.5 MHz)\n",
			clock / speed);
	}

	fec->mii_speed = speed << 1;

	setbits32(&fec->fecp->fec_r_cntrl, FEC_RCNTRL_MII_MODE);
	setbits32(&fec->fecp->fec_ecntrl, FEC_ECNTRL_PINMUX |
	                                  FEC_ECNTRL_ETHER_EN);
	out_be32(&fec->fecp->fec_ievent, FEC_ENET_MII);
	clrsetbits_be32(&fec->fecp->fec_mii_speed, 0x7E, fec->mii_speed);

	new_bus->phy_mask = ~0;

	new_bus->parent = &ofdev->dev;
	platform_set_drvdata(ofdev, new_bus);

	ret = of_mdiobus_register(new_bus, ofdev->dev.of_node);
	if (ret)
		goto out_unmap_regs;

	return 0;

out_unmap_regs:
	iounmap(fec->fecp);
out_res:
out_fec:
	kfree(fec);
out_mii:
	mdiobus_free(new_bus);
out:
	return ret;
}