static int fs_init_phy(struct net_device *dev) { struct fs_enet_private *fep = netdev_priv(dev); struct phy_device *phydev; phy_interface_t iface; fep->oldlink = 0; fep->oldspeed = 0; fep->oldduplex = -1; iface = fep->fpi->use_rmii ? PHY_INTERFACE_MODE_RMII : PHY_INTERFACE_MODE_MII; phydev = of_phy_connect(dev, fep->fpi->phy_node, &fs_adjust_link, 0, iface); if (!phydev) { phydev = of_phy_connect_fixed_link(dev, &fs_adjust_link, iface); } if (!phydev) { dev_err(&dev->dev, "Could not attach to PHY\n"); return -ENODEV; } fep->phydev = phydev; return 0; }
static int emac_mdio_probe(struct net_device *dev) { struct emac_board_info *db = netdev_priv(dev); struct phy_device *phydev; /* to-do: PHY interrupts are currently not supported */ /* attach the mac to the phy */ phydev = of_phy_connect(db->ndev, db->phy_node, &emac_handle_link_change, 0, db->phy_interface); if (!phydev) { netdev_err(db->ndev, "could not find the PHY\n"); return -ENODEV; } /* mask with MAC supported features */ phydev->supported &= PHY_BASIC_FEATURES; phydev->advertising = phydev->supported; db->link = 0; db->speed = 0; db->duplex = -1; return 0; }
/* slave device setup *******************************************************/ static int dsa_slave_phy_setup(struct dsa_slave_priv *p, struct net_device *slave_dev) { struct dsa_switch *ds = p->parent; struct dsa_chip_data *cd = ds->pd; struct device_node *phy_dn, *port_dn; bool phy_is_fixed = false; u32 phy_flags = 0; int mode, ret; port_dn = cd->port_dn[p->port]; mode = of_get_phy_mode(port_dn); if (mode < 0) mode = PHY_INTERFACE_MODE_NA; p->phy_interface = mode; phy_dn = of_parse_phandle(port_dn, "phy-handle", 0); if (of_phy_is_fixed_link(port_dn)) { /* In the case of a fixed PHY, the DT node associated * to the fixed PHY is the Port DT node */ ret = of_phy_register_fixed_link(port_dn); if (ret) { netdev_err(slave_dev, "failed to register fixed PHY\n"); return ret; } phy_is_fixed = true; phy_dn = port_dn; } if (ds->drv->get_phy_flags) phy_flags = ds->drv->get_phy_flags(ds, p->port); if (phy_dn) p->phy = of_phy_connect(slave_dev, phy_dn, dsa_slave_adjust_link, phy_flags, p->phy_interface); if (p->phy && phy_is_fixed) fixed_phy_set_link_update(p->phy, dsa_slave_fixed_link_update); /* We could not connect to a designated PHY, so use the switch internal * MDIO bus instead */ if (!p->phy) { p->phy = ds->slave_mii_bus->phy_map[p->port]; if (!p->phy) return -ENODEV; /* Use already configured phy mode */ p->phy_interface = p->phy->interface; phy_connect_direct(slave_dev, p->phy, dsa_slave_adjust_link, p->phy_interface); } else { netdev_info(slave_dev, "attached PHY at address %d [%s]\n", p->phy->addr, p->phy->drv->name); } return 0; }
int bcmgenet_mii_probe(struct net_device *dev) { struct bcmgenet_priv *priv = netdev_priv(dev); struct device_node *dn = priv->pdev->dev.of_node; struct phy_device *phydev; u32 phy_flags; int ret; /* Communicate the integrated PHY revision */ phy_flags = priv->gphy_rev; /* Initialize link state variables that bcmgenet_mii_setup() uses */ priv->old_link = -1; priv->old_speed = -1; priv->old_duplex = -1; priv->old_pause = -1; if (dn) { phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup, phy_flags, priv->phy_interface); if (!phydev) { pr_err("could not attach to PHY\n"); return -ENODEV; } } else { phydev = dev->phydev; phydev->dev_flags = phy_flags; ret = phy_connect_direct(dev, phydev, bcmgenet_mii_setup, priv->phy_interface); if (ret) { pr_err("could not attach to PHY\n"); return -ENODEV; } } /* Configure port multiplexer based on what the probed PHY device since * reading the 'max-speed' property determines the maximum supported * PHY speed which is needed for bcmgenet_mii_config() to configure * things appropriately. */ ret = bcmgenet_mii_config(dev, true); if (ret) { phy_disconnect(dev->phydev); return ret; } linkmode_copy(phydev->advertising, phydev->supported); /* The internal PHY has its link interrupts routed to the * Ethernet MAC ISRs. On GENETv5 there is a hardware issue * that prevents the signaling of link UP interrupts when * the link operates at 10Mbps, so fallback to polling for * those versions of GENET. */ if (priv->internal_phy && !GENET_IS_V5(priv)) dev->phydev->irq = PHY_IGNORE_INTERRUPT; return 0; }
static int octeon_mgmt_init_phy(struct net_device *netdev) { struct octeon_mgmt *p = netdev_priv(netdev); if (octeon_is_simulation() || p->phy_np == NULL) { /* No PHYs in the simulator. */ netif_carrier_on(netdev); return 0; } p->phydev = of_phy_connect(netdev, p->phy_np, octeon_mgmt_adjust_link, 0, PHY_INTERFACE_MODE_MII); if (!p->phydev) return -ENODEV; return 0; }
int mtk_connect_phy_node(struct mtk_eth *eth, struct mtk_mac *mac, struct device_node *phy_node) { const __be32 *_port = NULL; struct phy_device *phydev; int phy_mode, port; _port = of_get_property(phy_node, "reg", NULL); if (!_port || (be32_to_cpu(*_port) >= 0x20)) { pr_err("%s: invalid port id\n", phy_node->name); return -EINVAL; } port = be32_to_cpu(*_port); phy_mode = of_get_phy_mode(phy_node); if (phy_mode < 0) { dev_err(eth->dev, "incorrect phy-mode %d\n", phy_mode); eth->phy->phy_node[port] = NULL; return -EINVAL; } phydev = of_phy_connect(eth->netdev[mac->id], phy_node, mtk_phy_link_adjust, 0, phy_mode); if (!phydev) { dev_err(eth->dev, "could not connect to PHY\n"); eth->phy->phy_node[port] = NULL; return -ENODEV; } phydev->supported &= PHY_GBIT_FEATURES; phydev->advertising = phydev->supported; dev_info(eth->dev, "connected port %d to PHY at %s [uid=%08x, driver=%s]\n", port, phydev_name(phydev), phydev->phy_id, phydev->drv->name); eth->phy->phy[port] = phydev; eth->link[port] = 0; return 0; }
/** * cvm_oct_phy_setup_device - setup the PHY * * @dev: Device to setup * * Returns Zero on success, negative on failure */ int cvm_oct_phy_setup_device(struct net_device *dev) { struct octeon_ethernet *priv = netdev_priv(dev); struct device_node *phy_node; if (!priv->of_node) return 0; phy_node = of_parse_phandle(priv->of_node, "phy-handle", 0); if (!phy_node) return 0; priv->phydev = of_phy_connect(dev, phy_node, cvm_oct_adjust_link, 0, PHY_INTERFACE_MODE_GMII); if (priv->phydev == NULL) return -ENODEV; priv->last_link = 0; phy_start_aneg(priv->phydev); return 0; }
static int dsa_slave_phy_setup(struct dsa_slave_priv *p, struct net_device *slave_dev) { struct dsa_switch *ds = p->parent; struct dsa_chip_data *cd = ds->pd; struct device_node *phy_dn, *port_dn; bool phy_is_fixed = false; u32 phy_flags = 0; int mode, ret; port_dn = cd->port_dn[p->port]; mode = of_get_phy_mode(port_dn); if (mode < 0) mode = PHY_INTERFACE_MODE_NA; p->phy_interface = mode; phy_dn = of_parse_phandle(port_dn, "phy-handle", 0); if (of_phy_is_fixed_link(port_dn)) { /* In the case of a fixed PHY, the DT node associated * to the fixed PHY is the Port DT node */ ret = of_phy_register_fixed_link(port_dn); if (ret) { netdev_err(slave_dev, "failed to register fixed PHY: %d\n", ret); return ret; } phy_is_fixed = true; phy_dn = port_dn; } if (ds->drv->get_phy_flags) phy_flags = ds->drv->get_phy_flags(ds, p->port); if (phy_dn) { int phy_id = of_mdio_parse_addr(&slave_dev->dev, phy_dn); /* If this PHY address is part of phys_mii_mask, which means * that we need to divert reads and writes to/from it, then we * want to bind this device using the slave MII bus created by * DSA to make that happen. */ if (!phy_is_fixed && phy_id >= 0 && (ds->phys_mii_mask & (1 << phy_id))) { ret = dsa_slave_phy_connect(p, slave_dev, phy_id); if (ret) { netdev_err(slave_dev, "failed to connect to phy%d: %d\n", phy_id, ret); return ret; } } else { p->phy = of_phy_connect(slave_dev, phy_dn, dsa_slave_adjust_link, phy_flags, p->phy_interface); } } if (p->phy && phy_is_fixed) fixed_phy_set_link_update(p->phy, dsa_slave_fixed_link_update); /* We could not connect to a designated PHY, so use the switch internal * MDIO bus instead */ if (!p->phy) { ret = dsa_slave_phy_connect(p, slave_dev, p->port); if (ret) { netdev_err(slave_dev, "failed to connect to port %d: %d\n", p->port, ret); return ret; } } phy_attached_info(p->phy); return 0; }
static int bcmgenet_mii_probe(struct net_device *dev) { struct bcmgenet_priv *priv = netdev_priv(dev); struct device_node *dn = priv->pdev->dev.of_node; struct phy_device *phydev; u32 phy_flags; int ret; if (priv->phydev) { pr_info("PHY already attached\n"); return 0; } /* In the case of a fixed PHY, the DT node associated * to the PHY is the Ethernet MAC DT node. */ if (!priv->phy_dn && of_phy_is_fixed_link(dn)) { ret = of_phy_register_fixed_link(dn); if (ret) return ret; priv->phy_dn = of_node_get(dn); } /* Communicate the integrated PHY revision */ phy_flags = priv->gphy_rev; /* Initialize link state variables that bcmgenet_mii_setup() uses */ priv->old_link = -1; priv->old_speed = -1; priv->old_duplex = -1; priv->old_pause = -1; phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup, phy_flags, priv->phy_interface); if (!phydev) { pr_err("could not attach to PHY\n"); return -ENODEV; } priv->phydev = phydev; /* Configure port multiplexer based on what the probed PHY device since * reading the 'max-speed' property determines the maximum supported * PHY speed which is needed for bcmgenet_mii_config() to configure * things appropriately. */ ret = bcmgenet_mii_config(dev, true); if (ret) { phy_disconnect(priv->phydev); return ret; } phydev->advertising = phydev->supported; /* The internal PHY has its link interrupts routed to the * Ethernet MAC ISRs */ if (phy_is_internal(priv->phydev)) priv->mii_bus->irq[phydev->addr] = PHY_IGNORE_INTERRUPT; else priv->mii_bus->irq[phydev->addr] = PHY_POLL; pr_info("attached PHY at address %d [%s]\n", phydev->addr, phydev->drv->name); return 0; }
static int hip04_mac_probe(struct platform_device *pdev) { struct device *d = &pdev->dev; struct device_node *node = d->of_node; struct of_phandle_args arg; struct net_device *ndev; struct hip04_priv *priv; struct resource *res; int irq; int ret; ndev = alloc_etherdev(sizeof(struct hip04_priv)); if (!ndev) return -ENOMEM; priv = netdev_priv(ndev); priv->ndev = ndev; platform_set_drvdata(pdev, ndev); res = platform_get_resource(pdev, IORESOURCE_MEM, 0); priv->base = devm_ioremap_resource(d, res); if (IS_ERR(priv->base)) { ret = PTR_ERR(priv->base); goto init_fail; } ret = of_parse_phandle_with_fixed_args(node, "port-handle", 2, 0, &arg); if (ret < 0) { dev_warn(d, "no port-handle\n"); goto init_fail; } priv->port = arg.args[0]; priv->chan = arg.args[1] * RX_DESC_NUM; hrtimer_init(&priv->tx_coalesce_timer, CLOCK_MONOTONIC, HRTIMER_MODE_REL); /* BQL will try to keep the TX queue as short as possible, but it can't * be faster than tx_coalesce_usecs, so we need a fast timeout here, * but also long enough to gather up enough frames to ensure we don't * get more interrupts than necessary. * 200us is enough for 16 frames of 1500 bytes at gigabit ethernet rate */ priv->tx_coalesce_frames = TX_DESC_NUM * 3 / 4; priv->tx_coalesce_usecs = 200; priv->tx_coalesce_timer.function = tx_done; priv->map = syscon_node_to_regmap(arg.np); if (IS_ERR(priv->map)) { dev_warn(d, "no syscon hisilicon,hip04-ppe\n"); ret = PTR_ERR(priv->map); goto init_fail; } priv->phy_mode = of_get_phy_mode(node); if (priv->phy_mode < 0) { dev_warn(d, "not find phy-mode\n"); ret = -EINVAL; goto init_fail; } irq = platform_get_irq(pdev, 0); if (irq <= 0) { ret = -EINVAL; goto init_fail; } ret = devm_request_irq(d, irq, hip04_mac_interrupt, 0, pdev->name, ndev); if (ret) { netdev_err(ndev, "devm_request_irq failed\n"); goto init_fail; } priv->phy_node = of_parse_phandle(node, "phy-handle", 0); if (priv->phy_node) { priv->phy = of_phy_connect(ndev, priv->phy_node, &hip04_adjust_link, 0, priv->phy_mode); if (!priv->phy) { ret = -EPROBE_DEFER; goto init_fail; } } INIT_WORK(&priv->tx_timeout_task, hip04_tx_timeout_task); ether_setup(ndev); ndev->netdev_ops = &hip04_netdev_ops; ndev->ethtool_ops = &hip04_ethtool_ops; ndev->watchdog_timeo = TX_TIMEOUT; ndev->priv_flags |= IFF_UNICAST_FLT; ndev->irq = irq; netif_napi_add(ndev, &priv->napi, hip04_rx_poll, NAPI_POLL_WEIGHT); SET_NETDEV_DEV(ndev, &pdev->dev); hip04_reset_ppe(priv); if (priv->phy_mode == PHY_INTERFACE_MODE_MII) hip04_config_port(ndev, SPEED_100, DUPLEX_FULL); hip04_config_fifo(priv); random_ether_addr(ndev->dev_addr); hip04_update_mac_address(ndev); ret = hip04_alloc_ring(ndev, d); if (ret) { netdev_err(ndev, "alloc ring fail\n"); goto alloc_fail; } ret = register_netdev(ndev); if (ret) { free_netdev(ndev); goto alloc_fail; } return 0; alloc_fail: hip04_free_ring(ndev, d); init_fail: of_node_put(priv->phy_node); free_netdev(ndev); return ret; }
static int arc_emac_probe(struct platform_device *pdev) { struct resource res_regs; struct device_node *phy_node; struct arc_emac_priv *priv; struct net_device *ndev; const char *mac_addr; unsigned int id, clock_frequency, irq; int err; if (!pdev->dev.of_node) return -ENODEV; /* Get PHY from device tree */ phy_node = of_parse_phandle(pdev->dev.of_node, "phy", 0); if (!phy_node) { dev_err(&pdev->dev, "failed to retrieve phy description from device tree\n"); return -ENODEV; } /* Get EMAC registers base address from device tree */ err = of_address_to_resource(pdev->dev.of_node, 0, &res_regs); if (err) { dev_err(&pdev->dev, "failed to retrieve registers base from device tree\n"); return -ENODEV; } /* Get CPU clock frequency from device tree */ if (of_property_read_u32(pdev->dev.of_node, "clock-frequency", &clock_frequency)) { dev_err(&pdev->dev, "failed to retrieve <clock-frequency> from device tree\n"); return -EINVAL; } /* Get IRQ from device tree */ irq = irq_of_parse_and_map(pdev->dev.of_node, 0); if (!irq) { dev_err(&pdev->dev, "failed to retrieve <irq> value from device tree\n"); return -ENODEV; } ndev = alloc_etherdev(sizeof(struct arc_emac_priv)); if (!ndev) return -ENOMEM; platform_set_drvdata(pdev, ndev); SET_NETDEV_DEV(ndev, &pdev->dev); ndev->netdev_ops = &arc_emac_netdev_ops; ndev->ethtool_ops = &arc_emac_ethtool_ops; ndev->watchdog_timeo = TX_TIMEOUT; /* FIXME :: no multicast support yet */ ndev->flags &= ~IFF_MULTICAST; priv = netdev_priv(ndev); priv->dev = &pdev->dev; priv->ndev = ndev; priv->regs = devm_ioremap_resource(&pdev->dev, &res_regs); if (IS_ERR(priv->regs)) { err = PTR_ERR(priv->regs); goto out; } dev_dbg(&pdev->dev, "Registers base address is 0x%p\n", priv->regs); id = arc_reg_get(priv, R_ID); /* Check for EMAC revision 5 or 7, magic number */ if (!(id == 0x0005fd02 || id == 0x0007fd02)) { dev_err(&pdev->dev, "ARC EMAC not detected, id=0x%x\n", id); err = -ENODEV; goto out; } dev_info(&pdev->dev, "ARC EMAC detected with id: 0x%x\n", id); /* Set poll rate so that it polls every 1 ms */ arc_reg_set(priv, R_POLLRATE, clock_frequency / 1000000); /* Get max speed of operation from device tree */ if (of_property_read_u32(pdev->dev.of_node, "max-speed", &priv->max_speed)) { dev_err(&pdev->dev, "failed to retrieve <max-speed> from device tree\n"); err = -EINVAL; goto out; } ndev->irq = irq; dev_info(&pdev->dev, "IRQ is %d\n", ndev->irq); /* Register interrupt handler for device */ err = devm_request_irq(&pdev->dev, ndev->irq, arc_emac_intr, 0, ndev->name, ndev); if (err) { dev_err(&pdev->dev, "could not allocate IRQ\n"); goto out; } /* Get MAC address from device tree */ mac_addr = of_get_mac_address(pdev->dev.of_node); if (mac_addr) memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); else eth_hw_addr_random(ndev); dev_info(&pdev->dev, "MAC address is now %pM\n", ndev->dev_addr); /* Do 1 allocation instead of 2 separate ones for Rx and Tx BD rings */ priv->rxbd = dmam_alloc_coherent(&pdev->dev, RX_RING_SZ + TX_RING_SZ, &priv->rxbd_dma, GFP_KERNEL); if (!priv->rxbd) { dev_err(&pdev->dev, "failed to allocate data buffers\n"); err = -ENOMEM; goto out; } priv->txbd = priv->rxbd + RX_BD_NUM; priv->txbd_dma = priv->rxbd_dma + RX_RING_SZ; dev_dbg(&pdev->dev, "EMAC Device addr: Rx Ring [0x%x], Tx Ring[%x]\n", (unsigned int)priv->rxbd_dma, (unsigned int)priv->txbd_dma); err = arc_mdio_probe(pdev, priv); if (err) { dev_err(&pdev->dev, "failed to probe MII bus\n"); goto out; } priv->phy_dev = of_phy_connect(ndev, phy_node, arc_emac_adjust_link, 0, PHY_INTERFACE_MODE_MII); if (!priv->phy_dev) { dev_err(&pdev->dev, "of_phy_connect() failed\n"); err = -ENODEV; goto out; } dev_info(&pdev->dev, "connected to %s phy with id 0x%x\n", priv->phy_dev->drv->name, priv->phy_dev->phy_id); netif_napi_add(ndev, &priv->napi, arc_emac_poll, ARC_EMAC_NAPI_WEIGHT); err = register_netdev(ndev); if (err) { netif_napi_del(&priv->napi); dev_err(&pdev->dev, "failed to register network device\n"); goto out; } return 0; out: free_netdev(ndev); return err; }
static int bcmgenet_mii_probe(struct net_device *dev) { struct bcmgenet_priv *priv = netdev_priv(dev); struct device_node *dn = priv->pdev->dev.of_node; struct phy_device *phydev; unsigned int phy_flags; int ret; if (priv->phydev) { pr_info("PHY already attached\n"); return 0; } /* In the case of a fixed PHY, the DT node associated * to the PHY is the Ethernet MAC DT node. */ if (of_phy_is_fixed_link(dn)) { ret = of_phy_register_fixed_link(dn); if (ret) return ret; priv->phy_dn = dn; } phydev = of_phy_connect(dev, priv->phy_dn, bcmgenet_mii_setup, 0, priv->phy_interface); if (!phydev) { pr_err("could not attach to PHY\n"); return -ENODEV; } priv->old_link = -1; priv->old_duplex = -1; priv->old_pause = -1; priv->phydev = phydev; /* Configure port multiplexer based on what the probed PHY device since * reading the 'max-speed' property determines the maximum supported * PHY speed which is needed for bcmgenet_mii_config() to configure * things appropriately. */ ret = bcmgenet_mii_config(dev); if (ret) { phy_disconnect(priv->phydev); return ret; } phy_flags = PHY_BRCM_100MBPS_WAR; /* workarounds are only needed for 100Mpbs PHYs, and * never on GENET V1 hardware */ if ((phydev->supported & PHY_GBIT_FEATURES) || GENET_IS_V1(priv)) phy_flags = 0; phydev->dev_flags |= phy_flags; phydev->advertising = phydev->supported; /* The internal PHY has its link interrupts routed to the * Ethernet MAC ISRs */ if (phy_is_internal(priv->phydev)) priv->mii_bus->irq[phydev->addr] = PHY_IGNORE_INTERRUPT; else priv->mii_bus->irq[phydev->addr] = PHY_POLL; pr_info("attached PHY at address %d [%s]\n", phydev->addr, phydev->drv->name); return 0; }