/* 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; }
static int bcmgenet_mii_of_init(struct bcmgenet_priv *priv) { struct device_node *dn = priv->pdev->dev.of_node; struct device *kdev = &priv->pdev->dev; struct phy_device *phydev; int phy_mode; int ret; /* Fetch the PHY phandle */ priv->phy_dn = of_parse_phandle(dn, "phy-handle", 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); } /* Get the link mode */ phy_mode = of_get_phy_mode(dn); if (phy_mode < 0) { dev_err(kdev, "invalid PHY mode property\n"); return phy_mode; } priv->phy_interface = phy_mode; /* We need to specifically look up whether this PHY interface is internal * or not *before* we even try to probe the PHY driver over MDIO as we * may have shut down the internal PHY for power saving purposes. */ if (priv->phy_interface == PHY_INTERFACE_MODE_INTERNAL) priv->internal_phy = true; /* Make sure we initialize MoCA PHYs with a link down */ if (phy_mode == PHY_INTERFACE_MODE_MOCA) { phydev = of_phy_find_device(dn); if (phydev) { phydev->link = 0; put_device(&phydev->mdio.dev); } } 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 fs_enet_probe(struct platform_device *ofdev) { const struct of_device_id *match; struct net_device *ndev; struct fs_enet_private *fep; struct fs_platform_info *fpi; const u32 *data; struct clk *clk; int err; const u8 *mac_addr; const char *phy_connection_type; int privsize, len, ret = -ENODEV; match = of_match_device(fs_enet_match, &ofdev->dev); if (!match) return -EINVAL; fpi = kzalloc(sizeof(*fpi), GFP_KERNEL); if (!fpi) return -ENOMEM; if (!IS_FEC(match)) { data = of_get_property(ofdev->dev.of_node, "fsl,cpm-command", &len); if (!data || len != 4) goto out_free_fpi; fpi->cp_command = *data; } fpi->rx_ring = 32; fpi->tx_ring = 32; fpi->rx_copybreak = 240; fpi->napi_weight = 17; fpi->phy_node = of_parse_phandle(ofdev->dev.of_node, "phy-handle", 0); if (!fpi->phy_node && of_phy_is_fixed_link(ofdev->dev.of_node)) { err = of_phy_register_fixed_link(ofdev->dev.of_node); if (err) goto out_free_fpi; /* In the case of a fixed PHY, the DT node associated * to the PHY is the Ethernet MAC DT node. */ fpi->phy_node = of_node_get(ofdev->dev.of_node); } if (of_device_is_compatible(ofdev->dev.of_node, "fsl,mpc5125-fec")) { phy_connection_type = of_get_property(ofdev->dev.of_node, "phy-connection-type", NULL); if (phy_connection_type && !strcmp("rmii", phy_connection_type)) fpi->use_rmii = 1; } /* make clock lookup non-fatal (the driver is shared among platforms), * but require enable to succeed when a clock was specified/found, * keep a reference to the clock upon successful acquisition */ clk = devm_clk_get(&ofdev->dev, "per"); if (!IS_ERR(clk)) { err = clk_prepare_enable(clk); if (err) { ret = err; goto out_free_fpi; } fpi->clk_per = clk; } privsize = sizeof(*fep) + sizeof(struct sk_buff **) * (fpi->rx_ring + fpi->tx_ring); ndev = alloc_etherdev(privsize); if (!ndev) { ret = -ENOMEM; goto out_put; } SET_NETDEV_DEV(ndev, &ofdev->dev); platform_set_drvdata(ofdev, ndev); fep = netdev_priv(ndev); fep->dev = &ofdev->dev; fep->ndev = ndev; fep->fpi = fpi; fep->ops = match->data; ret = fep->ops->setup_data(ndev); if (ret) goto out_free_dev; fep->rx_skbuff = (struct sk_buff **)&fep[1]; fep->tx_skbuff = fep->rx_skbuff + fpi->rx_ring; spin_lock_init(&fep->lock); spin_lock_init(&fep->tx_lock); mac_addr = of_get_mac_address(ofdev->dev.of_node); if (mac_addr) memcpy(ndev->dev_addr, mac_addr, ETH_ALEN); ret = fep->ops->allocate_bd(ndev); if (ret) goto out_cleanup_data; fep->rx_bd_base = fep->ring_base; fep->tx_bd_base = fep->rx_bd_base + fpi->rx_ring; fep->tx_ring = fpi->tx_ring; fep->rx_ring = fpi->rx_ring; ndev->netdev_ops = &fs_enet_netdev_ops; ndev->watchdog_timeo = 2 * HZ; netif_napi_add(ndev, &fep->napi, fs_enet_rx_napi, fpi->napi_weight); netif_napi_add(ndev, &fep->napi_tx, fs_enet_tx_napi, 2); ndev->ethtool_ops = &fs_ethtool_ops; init_timer(&fep->phy_timer_list); netif_carrier_off(ndev); ret = register_netdev(ndev); if (ret) goto out_free_bd; pr_info("%s: fs_enet: %pM\n", ndev->name, ndev->dev_addr); return 0; out_free_bd: fep->ops->free_bd(ndev); out_cleanup_data: fep->ops->cleanup_data(ndev); out_free_dev: free_netdev(ndev); out_put: of_node_put(fpi->phy_node); if (fpi->clk_per) clk_disable_unprepare(fpi->clk_per); out_free_fpi: kfree(fpi); return ret; }
int dsa_port_bridge_join(struct dsa_port *dp, struct net_device *br) { struct dsa_notifier_bridge_info info = { .sw_index = dp->ds->index, .port = dp->index, .br = br, }; int err; /* Here the port is already bridged. Reflect the current configuration * so that drivers can program their chips accordingly. */ dp->bridge_dev = br; err = dsa_port_notify(dp, DSA_NOTIFIER_BRIDGE_JOIN, &info); /* The bridging is rolled back on error */ if (err) dp->bridge_dev = NULL; return err; } void dsa_port_bridge_leave(struct dsa_port *dp, struct net_device *br) { struct dsa_notifier_bridge_info info = { .sw_index = dp->ds->index, .port = dp->index, .br = br, }; int err; /* Here the port is already unbridged. Reflect the current configuration * so that drivers can program their chips accordingly. */ dp->bridge_dev = NULL; err = dsa_port_notify(dp, DSA_NOTIFIER_BRIDGE_LEAVE, &info); if (err) pr_err("DSA: failed to notify DSA_NOTIFIER_BRIDGE_LEAVE\n"); /* Port left the bridge, put in BR_STATE_DISABLED by the bridge layer, * so allow it to be in BR_STATE_FORWARDING to be kept functional */ dsa_port_set_state_now(dp, BR_STATE_FORWARDING); } int dsa_port_vlan_filtering(struct dsa_port *dp, bool vlan_filtering, struct switchdev_trans *trans) { struct dsa_switch *ds = dp->ds; /* bridge skips -EOPNOTSUPP, so skip the prepare phase */ if (switchdev_trans_ph_prepare(trans)) return 0; if (ds->ops->port_vlan_filtering) return ds->ops->port_vlan_filtering(ds, dp->index, vlan_filtering); return 0; } int dsa_port_ageing_time(struct dsa_port *dp, clock_t ageing_clock, struct switchdev_trans *trans) { unsigned long ageing_jiffies = clock_t_to_jiffies(ageing_clock); unsigned int ageing_time = jiffies_to_msecs(ageing_jiffies); struct dsa_notifier_ageing_time_info info = { .ageing_time = ageing_time, .trans = trans, }; if (switchdev_trans_ph_prepare(trans)) return dsa_port_notify(dp, DSA_NOTIFIER_AGEING_TIME, &info); dp->ageing_time = ageing_time; return dsa_port_notify(dp, DSA_NOTIFIER_AGEING_TIME, &info); } int dsa_port_fdb_add(struct dsa_port *dp, const unsigned char *addr, u16 vid) { struct dsa_notifier_fdb_info info = { .sw_index = dp->ds->index, .port = dp->index, .addr = addr, .vid = vid, }; return dsa_port_notify(dp, DSA_NOTIFIER_FDB_ADD, &info); } int dsa_port_fdb_del(struct dsa_port *dp, const unsigned char *addr, u16 vid) { struct dsa_notifier_fdb_info info = { .sw_index = dp->ds->index, .port = dp->index, .addr = addr, .vid = vid, }; return dsa_port_notify(dp, DSA_NOTIFIER_FDB_DEL, &info); } int dsa_port_fdb_dump(struct dsa_port *dp, dsa_fdb_dump_cb_t *cb, void *data) { struct dsa_switch *ds = dp->ds; int port = dp->index; if (!ds->ops->port_fdb_dump) return -EOPNOTSUPP; return ds->ops->port_fdb_dump(ds, port, cb, data); } int dsa_port_mdb_add(const struct dsa_port *dp, const struct switchdev_obj_port_mdb *mdb, struct switchdev_trans *trans) { struct dsa_notifier_mdb_info info = { .sw_index = dp->ds->index, .port = dp->index, .trans = trans, .mdb = mdb, }; return dsa_port_notify(dp, DSA_NOTIFIER_MDB_ADD, &info); } int dsa_port_mdb_del(const struct dsa_port *dp, const struct switchdev_obj_port_mdb *mdb) { struct dsa_notifier_mdb_info info = { .sw_index = dp->ds->index, .port = dp->index, .mdb = mdb, }; return dsa_port_notify(dp, DSA_NOTIFIER_MDB_DEL, &info); } int dsa_port_vlan_add(struct dsa_port *dp, const struct switchdev_obj_port_vlan *vlan, struct switchdev_trans *trans) { struct dsa_notifier_vlan_info info = { .sw_index = dp->ds->index, .port = dp->index, .trans = trans, .vlan = vlan, }; if (netif_is_bridge_master(vlan->obj.orig_dev)) return -EOPNOTSUPP; if (br_vlan_enabled(dp->bridge_dev)) return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_ADD, &info); return 0; } int dsa_port_vlan_del(struct dsa_port *dp, const struct switchdev_obj_port_vlan *vlan) { struct dsa_notifier_vlan_info info = { .sw_index = dp->ds->index, .port = dp->index, .vlan = vlan, }; if (netif_is_bridge_master(vlan->obj.orig_dev)) return -EOPNOTSUPP; if (br_vlan_enabled(dp->bridge_dev)) return dsa_port_notify(dp, DSA_NOTIFIER_VLAN_DEL, &info); return 0; } static struct phy_device *dsa_port_get_phy_device(struct dsa_port *dp) { struct device_node *phy_dn; struct phy_device *phydev; phy_dn = of_parse_phandle(dp->dn, "phy-handle", 0); if (!phy_dn) return NULL; phydev = of_phy_find_device(phy_dn); if (!phydev) { of_node_put(phy_dn); return ERR_PTR(-EPROBE_DEFER); } return phydev; } static int dsa_port_setup_phy_of(struct dsa_port *dp, bool enable) { struct dsa_switch *ds = dp->ds; struct phy_device *phydev; int port = dp->index; int err = 0; phydev = dsa_port_get_phy_device(dp); if (!phydev) return 0; if (IS_ERR(phydev)) return PTR_ERR(phydev); if (enable) { err = genphy_config_init(phydev); if (err < 0) goto err_put_dev; err = genphy_resume(phydev); if (err < 0) goto err_put_dev; err = genphy_read_status(phydev); if (err < 0) goto err_put_dev; } else { err = genphy_suspend(phydev); if (err < 0) goto err_put_dev; } if (ds->ops->adjust_link) ds->ops->adjust_link(ds, port, phydev); dev_dbg(ds->dev, "enabled port's phy: %s", phydev_name(phydev)); err_put_dev: put_device(&phydev->mdio.dev); return err; } static int dsa_port_fixed_link_register_of(struct dsa_port *dp) { struct device_node *dn = dp->dn; struct dsa_switch *ds = dp->ds; struct phy_device *phydev; int port = dp->index; int mode; int err; err = of_phy_register_fixed_link(dn); if (err) { dev_err(ds->dev, "failed to register the fixed PHY of port %d\n", port); return err; } phydev = of_phy_find_device(dn); mode = of_get_phy_mode(dn); if (mode < 0) mode = PHY_INTERFACE_MODE_NA; phydev->interface = mode; genphy_config_init(phydev); genphy_read_status(phydev); if (ds->ops->adjust_link) ds->ops->adjust_link(ds, port, phydev); put_device(&phydev->mdio.dev); return 0; } int dsa_port_link_register_of(struct dsa_port *dp) { if (of_phy_is_fixed_link(dp->dn)) return dsa_port_fixed_link_register_of(dp); else return dsa_port_setup_phy_of(dp, true); } void dsa_port_link_unregister_of(struct dsa_port *dp) { if (of_phy_is_fixed_link(dp->dn)) of_phy_deregister_fixed_link(dp->dn); else dsa_port_setup_phy_of(dp, false); } int dsa_port_get_phy_strings(struct dsa_port *dp, uint8_t *data) { struct phy_device *phydev; int ret = -EOPNOTSUPP; if (of_phy_is_fixed_link(dp->dn)) return ret; phydev = dsa_port_get_phy_device(dp); if (IS_ERR_OR_NULL(phydev)) return ret; ret = phy_ethtool_get_strings(phydev, data); put_device(&phydev->mdio.dev); return ret; } EXPORT_SYMBOL_GPL(dsa_port_get_phy_strings); int dsa_port_get_ethtool_phy_stats(struct dsa_port *dp, uint64_t *data) { struct phy_device *phydev; int ret = -EOPNOTSUPP; if (of_phy_is_fixed_link(dp->dn)) return ret; phydev = dsa_port_get_phy_device(dp); if (IS_ERR_OR_NULL(phydev)) return ret; ret = phy_ethtool_get_stats(phydev, NULL, data); put_device(&phydev->mdio.dev); return ret; } EXPORT_SYMBOL_GPL(dsa_port_get_ethtool_phy_stats); int dsa_port_get_phy_sset_count(struct dsa_port *dp) { struct phy_device *phydev; int ret = -EOPNOTSUPP; if (of_phy_is_fixed_link(dp->dn)) return ret; phydev = dsa_port_get_phy_device(dp); if (IS_ERR_OR_NULL(phydev)) return ret; ret = phy_ethtool_get_sset_count(phydev); put_device(&phydev->mdio.dev); return ret; } EXPORT_SYMBOL_GPL(dsa_port_get_phy_sset_count);
/** * stmmac_probe_config_dt - parse device-tree driver parameters * @pdev: platform_device structure * @plat: driver data platform structure * @mac: MAC address to use * Description: * this function is to read the driver parameters from device-tree and * set some private fields that will be used by the main at runtime. */ struct plat_stmmacenet_data * stmmac_probe_config_dt(struct platform_device *pdev, const char **mac) { struct device_node *np = pdev->dev.of_node; struct plat_stmmacenet_data *plat; struct stmmac_dma_cfg *dma_cfg; plat = devm_kzalloc(&pdev->dev, sizeof(*plat), GFP_KERNEL); if (!plat) return ERR_PTR(-ENOMEM); *mac = of_get_mac_address(np); plat->interface = of_get_phy_mode(np); /* Get max speed of operation from device tree */ if (of_property_read_u32(np, "max-speed", &plat->max_speed)) plat->max_speed = -1; plat->bus_id = of_alias_get_id(np, "ethernet"); if (plat->bus_id < 0) plat->bus_id = 0; /* Default to phy auto-detection */ plat->phy_addr = -1; /* If we find a phy-handle property, use it as the PHY */ plat->phy_node = of_parse_phandle(np, "phy-handle", 0); /* If phy-handle is not specified, check if we have a fixed-phy */ if (!plat->phy_node && of_phy_is_fixed_link(np)) { if ((of_phy_register_fixed_link(np) < 0)) return ERR_PTR(-ENODEV); plat->phy_node = of_node_get(np); } /* "snps,phy-addr" is not a standard property. Mark it as deprecated * and warn of its use. Remove this when phy node support is added. */ if (of_property_read_u32(np, "snps,phy-addr", &plat->phy_addr) == 0) dev_warn(&pdev->dev, "snps,phy-addr property is deprecated\n"); if ((plat->phy_node && !of_phy_is_fixed_link(np)) || plat->phy_bus_name) plat->mdio_bus_data = NULL; else plat->mdio_bus_data = devm_kzalloc(&pdev->dev, sizeof(struct stmmac_mdio_bus_data), GFP_KERNEL); of_property_read_u32(np, "tx-fifo-depth", &plat->tx_fifo_size); of_property_read_u32(np, "rx-fifo-depth", &plat->rx_fifo_size); plat->force_sf_dma_mode = of_property_read_bool(np, "snps,force_sf_dma_mode"); /* Set the maxmtu to a default of JUMBO_LEN in case the * parameter is not present in the device tree. */ plat->maxmtu = JUMBO_LEN; /* Set default value for multicast hash bins */ plat->multicast_filter_bins = HASH_TABLE_SIZE; /* Set default value for unicast filter entries */ plat->unicast_filter_entries = 1; /* * Currently only the properties needed on SPEAr600 * are provided. All other properties should be added * once needed on other platforms. */ if (of_device_is_compatible(np, "st,spear600-gmac") || of_device_is_compatible(np, "snps,dwmac-3.70a") || of_device_is_compatible(np, "snps,dwmac")) { /* Note that the max-frame-size parameter as defined in the * ePAPR v1.1 spec is defined as max-frame-size, it's * actually used as the IEEE definition of MAC Client * data, or MTU. The ePAPR specification is confusing as * the definition is max-frame-size, but usage examples * are clearly MTUs */ of_property_read_u32(np, "max-frame-size", &plat->maxmtu); of_property_read_u32(np, "snps,multicast-filter-bins", &plat->multicast_filter_bins); of_property_read_u32(np, "snps,perfect-filter-entries", &plat->unicast_filter_entries); plat->unicast_filter_entries = dwmac1000_validate_ucast_entries( plat->unicast_filter_entries); plat->multicast_filter_bins = dwmac1000_validate_mcast_bins( plat->multicast_filter_bins); plat->has_gmac = 1; plat->pmt = 1; } if (of_device_is_compatible(np, "snps,dwmac-3.610") || of_device_is_compatible(np, "snps,dwmac-3.710")) { plat->enh_desc = 1; plat->bugged_jumbo = 1; plat->force_sf_dma_mode = 1; } if (of_find_property(np, "snps,pbl", NULL)) { dma_cfg = devm_kzalloc(&pdev->dev, sizeof(*dma_cfg), GFP_KERNEL); if (!dma_cfg) { of_node_put(np); return ERR_PTR(-ENOMEM); } plat->dma_cfg = dma_cfg; of_property_read_u32(np, "snps,pbl", &dma_cfg->pbl); dma_cfg->fixed_burst = of_property_read_bool(np, "snps,fixed-burst"); dma_cfg->mixed_burst = of_property_read_bool(np, "snps,mixed-burst"); of_property_read_u32(np, "snps,burst_len", &dma_cfg->burst_len); if (dma_cfg->burst_len < 0 || dma_cfg->burst_len > 256) dma_cfg->burst_len = 0; } plat->force_thresh_dma_mode = of_property_read_bool(np, "snps,force_thresh_dma_mode"); if (plat->force_thresh_dma_mode) { plat->force_sf_dma_mode = 0; pr_warn("force_sf_dma_mode is ignored if force_thresh_dma_mode is set."); } return plat; }
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; }