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); }
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; }
/* 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; }
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; }
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; }
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; }
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; }
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; }
/** * 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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
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; }
/** * 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; }
/** * @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; }
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); }
/** * 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; }
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; }
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; }
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; }
/* * 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; }
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; }