/** * 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; }
/** * axienet_mdio_setup - MDIO setup function * @lp: Pointer to axienet local data structure. * @np: Pointer to device node * * Return: 0 on success, -ETIMEDOUT on a timeout, -ENOMEM when * mdiobus_alloc (to allocate memory for mii bus structure) fails. * * Sets up the MDIO interface by initializing the MDIO clock and enabling the * MDIO interface in hardware. Register the MDIO interface. **/ int axienet_mdio_setup(struct axienet_local *lp, struct device_node *np) { int ret; u32 clk_div, host_clock; struct mii_bus *bus; struct resource res; struct device_node *np1; /* clk_div can be calculated by deriving it from the equation: * fMDIO = fHOST / ((1 + clk_div) * 2) * * Where fMDIO <= 2500000, so we get: * fHOST / ((1 + clk_div) * 2) <= 2500000 * * Then we get: * 1 / ((1 + clk_div) * 2) <= (2500000 / fHOST) * * Then we get: * 1 / (1 + clk_div) <= ((2500000 * 2) / fHOST) * * Then we get: * 1 / (1 + clk_div) <= (5000000 / fHOST) * * So: * (1 + clk_div) >= (fHOST / 5000000) * * And finally: * clk_div >= (fHOST / 5000000) - 1 * * fHOST can be read from the flattened device tree as property * "clock-frequency" from the CPU */ np1 = of_find_node_by_name(NULL, "cpu"); if (!np1) { netdev_warn(lp->ndev, "Could not find CPU device node.\n"); netdev_warn(lp->ndev, "Setting MDIO clock divisor to default %d\n", DEFAULT_CLOCK_DIVISOR); clk_div = DEFAULT_CLOCK_DIVISOR; goto issue; } if (of_property_read_u32(np1, "clock-frequency", &host_clock)) { netdev_warn(lp->ndev, "clock-frequency property not found.\n"); netdev_warn(lp->ndev, "Setting MDIO clock divisor to default %d\n", DEFAULT_CLOCK_DIVISOR); clk_div = DEFAULT_CLOCK_DIVISOR; of_node_put(np1); goto issue; } clk_div = (host_clock / (MAX_MDIO_FREQ * 2)) - 1; /* If there is any remainder from the division of * fHOST / (MAX_MDIO_FREQ * 2), then we need to add * 1 to the clock divisor or we will surely be above 2.5 MHz */ if (host_clock % (MAX_MDIO_FREQ * 2)) clk_div++; netdev_dbg(lp->ndev, "Setting MDIO clock divisor to %u/%u Hz host clock.\n", clk_div, host_clock); of_node_put(np1); issue: axienet_iow(lp, XAE_MDIO_MC_OFFSET, (((u32) clk_div) | XAE_MDIO_MC_MDIOEN_MASK)); ret = axienet_mdio_wait_until_ready(lp); if (ret < 0) return ret; bus = mdiobus_alloc(); if (!bus) return -ENOMEM; np1 = of_get_parent(lp->phy_node); 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 Axi Ethernet MDIO"; bus->read = axienet_mdio_read; bus->write = axienet_mdio_write; bus->parent = lp->dev; lp->mii_bus = bus; ret = of_mdiobus_register(bus, np1); if (ret) { mdiobus_free(bus); return ret; } return 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->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_gmac4) { new_bus->read = &stmmac_mdio_read_gmac4; new_bus->write = &stmmac_mdio_write_gmac4; } else { 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; }
static void ixp4xx_mdio_remove(void) { mdiobus_unregister(mdio_bus); mdiobus_free(mdio_bus); }
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; }