171947923SIoana Ciornei // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) 271947923SIoana Ciornei /* Copyright 2019 NXP */ 371947923SIoana Ciornei 471947923SIoana Ciornei #include "dpaa2-eth.h" 571947923SIoana Ciornei #include "dpaa2-mac.h" 671947923SIoana Ciornei 771947923SIoana Ciornei #define phylink_to_dpaa2_mac(config) \ 871947923SIoana Ciornei container_of((config), struct dpaa2_mac, phylink_config) 971947923SIoana Ciornei 10226df3efSIoana Ciornei static int phy_mode(enum dpmac_eth_if eth_if, phy_interface_t *if_mode) 1171947923SIoana Ciornei { 12226df3efSIoana Ciornei *if_mode = PHY_INTERFACE_MODE_NA; 13226df3efSIoana Ciornei 1471947923SIoana Ciornei switch (eth_if) { 1571947923SIoana Ciornei case DPMAC_ETH_IF_RGMII: 16226df3efSIoana Ciornei *if_mode = PHY_INTERFACE_MODE_RGMII; 17226df3efSIoana Ciornei break; 1894ae899bSIoana Ciornei case DPMAC_ETH_IF_USXGMII: 1994ae899bSIoana Ciornei *if_mode = PHY_INTERFACE_MODE_USXGMII; 2094ae899bSIoana Ciornei break; 2194ae899bSIoana Ciornei case DPMAC_ETH_IF_QSGMII: 2294ae899bSIoana Ciornei *if_mode = PHY_INTERFACE_MODE_QSGMII; 2394ae899bSIoana Ciornei break; 2494ae899bSIoana Ciornei case DPMAC_ETH_IF_SGMII: 2594ae899bSIoana Ciornei *if_mode = PHY_INTERFACE_MODE_SGMII; 2694ae899bSIoana Ciornei break; 2794ae899bSIoana Ciornei case DPMAC_ETH_IF_XFI: 2894ae899bSIoana Ciornei *if_mode = PHY_INTERFACE_MODE_10GBASER; 2994ae899bSIoana Ciornei break; 3071947923SIoana Ciornei default: 3171947923SIoana Ciornei return -EINVAL; 3271947923SIoana Ciornei } 33226df3efSIoana Ciornei 34226df3efSIoana Ciornei return 0; 3571947923SIoana Ciornei } 3671947923SIoana Ciornei 3771947923SIoana Ciornei /* Caller must call of_node_put on the returned value */ 3871947923SIoana Ciornei static struct device_node *dpaa2_mac_get_node(u16 dpmac_id) 3971947923SIoana Ciornei { 4071947923SIoana Ciornei struct device_node *dpmacs, *dpmac = NULL; 4171947923SIoana Ciornei u32 id; 4271947923SIoana Ciornei int err; 4371947923SIoana Ciornei 4471947923SIoana Ciornei dpmacs = of_find_node_by_name(NULL, "dpmacs"); 4571947923SIoana Ciornei if (!dpmacs) 4671947923SIoana Ciornei return NULL; 4771947923SIoana Ciornei 4871947923SIoana Ciornei while ((dpmac = of_get_next_child(dpmacs, dpmac)) != NULL) { 4971947923SIoana Ciornei err = of_property_read_u32(dpmac, "reg", &id); 5071947923SIoana Ciornei if (err) 5171947923SIoana Ciornei continue; 5271947923SIoana Ciornei if (id == dpmac_id) 5371947923SIoana Ciornei break; 5471947923SIoana Ciornei } 5571947923SIoana Ciornei 5671947923SIoana Ciornei of_node_put(dpmacs); 5771947923SIoana Ciornei 5871947923SIoana Ciornei return dpmac; 5971947923SIoana Ciornei } 6071947923SIoana Ciornei 6171947923SIoana Ciornei static int dpaa2_mac_get_if_mode(struct device_node *node, 6271947923SIoana Ciornei struct dpmac_attr attr) 6371947923SIoana Ciornei { 640c65b2b9SAndrew Lunn phy_interface_t if_mode; 650c65b2b9SAndrew Lunn int err; 6671947923SIoana Ciornei 670c65b2b9SAndrew Lunn err = of_get_phy_mode(node, &if_mode); 680c65b2b9SAndrew Lunn if (!err) 6971947923SIoana Ciornei return if_mode; 7071947923SIoana Ciornei 71226df3efSIoana Ciornei err = phy_mode(attr.eth_if, &if_mode); 72226df3efSIoana Ciornei if (!err) 7371947923SIoana Ciornei return if_mode; 7471947923SIoana Ciornei 75226df3efSIoana Ciornei return err; 7671947923SIoana Ciornei } 7771947923SIoana Ciornei 7871947923SIoana Ciornei static bool dpaa2_mac_phy_mode_mismatch(struct dpaa2_mac *mac, 7971947923SIoana Ciornei phy_interface_t interface) 8071947923SIoana Ciornei { 8171947923SIoana Ciornei switch (interface) { 8246c518c8SRussell King /* We can switch between SGMII and 1000BASE-X at runtime with 8346c518c8SRussell King * pcs-lynx 8446c518c8SRussell King */ 8546c518c8SRussell King case PHY_INTERFACE_MODE_SGMII: 8646c518c8SRussell King case PHY_INTERFACE_MODE_1000BASEX: 8746c518c8SRussell King if (mac->pcs && 8846c518c8SRussell King (mac->if_mode == PHY_INTERFACE_MODE_SGMII || 8946c518c8SRussell King mac->if_mode == PHY_INTERFACE_MODE_1000BASEX)) 9046c518c8SRussell King return false; 9146c518c8SRussell King return interface != mac->if_mode; 9246c518c8SRussell King 9394ae899bSIoana Ciornei case PHY_INTERFACE_MODE_10GBASER: 9494ae899bSIoana Ciornei case PHY_INTERFACE_MODE_USXGMII: 9594ae899bSIoana Ciornei case PHY_INTERFACE_MODE_QSGMII: 9671947923SIoana Ciornei case PHY_INTERFACE_MODE_RGMII: 9771947923SIoana Ciornei case PHY_INTERFACE_MODE_RGMII_ID: 9871947923SIoana Ciornei case PHY_INTERFACE_MODE_RGMII_RXID: 9971947923SIoana Ciornei case PHY_INTERFACE_MODE_RGMII_TXID: 10071947923SIoana Ciornei return (interface != mac->if_mode); 10171947923SIoana Ciornei default: 10271947923SIoana Ciornei return true; 10371947923SIoana Ciornei } 10471947923SIoana Ciornei } 10571947923SIoana Ciornei 10671947923SIoana Ciornei static void dpaa2_mac_validate(struct phylink_config *config, 10771947923SIoana Ciornei unsigned long *supported, 10871947923SIoana Ciornei struct phylink_link_state *state) 10971947923SIoana Ciornei { 11071947923SIoana Ciornei struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config); 11171947923SIoana Ciornei __ETHTOOL_DECLARE_LINK_MODE_MASK(mask) = { 0, }; 11271947923SIoana Ciornei 11371947923SIoana Ciornei if (state->interface != PHY_INTERFACE_MODE_NA && 11471947923SIoana Ciornei dpaa2_mac_phy_mode_mismatch(mac, state->interface)) { 11571947923SIoana Ciornei goto empty_set; 11671947923SIoana Ciornei } 11771947923SIoana Ciornei 11871947923SIoana Ciornei phylink_set_port_modes(mask); 11971947923SIoana Ciornei phylink_set(mask, Autoneg); 12071947923SIoana Ciornei phylink_set(mask, Pause); 12171947923SIoana Ciornei phylink_set(mask, Asym_Pause); 12271947923SIoana Ciornei 12371947923SIoana Ciornei switch (state->interface) { 12494ae899bSIoana Ciornei case PHY_INTERFACE_MODE_NA: 12594ae899bSIoana Ciornei case PHY_INTERFACE_MODE_10GBASER: 12694ae899bSIoana Ciornei case PHY_INTERFACE_MODE_USXGMII: 12794ae899bSIoana Ciornei phylink_set(mask, 10000baseT_Full); 12894ae899bSIoana Ciornei if (state->interface == PHY_INTERFACE_MODE_10GBASER) 12994ae899bSIoana Ciornei break; 13094ae899bSIoana Ciornei phylink_set(mask, 5000baseT_Full); 13194ae899bSIoana Ciornei phylink_set(mask, 2500baseT_Full); 13294ae899bSIoana Ciornei fallthrough; 13394ae899bSIoana Ciornei case PHY_INTERFACE_MODE_SGMII: 13494ae899bSIoana Ciornei case PHY_INTERFACE_MODE_QSGMII: 13546c518c8SRussell King case PHY_INTERFACE_MODE_1000BASEX: 13671947923SIoana Ciornei case PHY_INTERFACE_MODE_RGMII: 13771947923SIoana Ciornei case PHY_INTERFACE_MODE_RGMII_ID: 13871947923SIoana Ciornei case PHY_INTERFACE_MODE_RGMII_RXID: 13971947923SIoana Ciornei case PHY_INTERFACE_MODE_RGMII_TXID: 14046c518c8SRussell King phylink_set(mask, 1000baseX_Full); 14171947923SIoana Ciornei phylink_set(mask, 1000baseT_Full); 14246c518c8SRussell King if (state->interface == PHY_INTERFACE_MODE_1000BASEX) 14346c518c8SRussell King break; 14446c518c8SRussell King phylink_set(mask, 100baseT_Full); 14546c518c8SRussell King phylink_set(mask, 10baseT_Full); 14671947923SIoana Ciornei break; 14771947923SIoana Ciornei default: 14871947923SIoana Ciornei goto empty_set; 14971947923SIoana Ciornei } 15071947923SIoana Ciornei 15171947923SIoana Ciornei linkmode_and(supported, supported, mask); 15271947923SIoana Ciornei linkmode_and(state->advertising, state->advertising, mask); 15371947923SIoana Ciornei 15471947923SIoana Ciornei return; 15571947923SIoana Ciornei 15671947923SIoana Ciornei empty_set: 15771947923SIoana Ciornei linkmode_zero(supported); 15871947923SIoana Ciornei } 15971947923SIoana Ciornei 16071947923SIoana Ciornei static void dpaa2_mac_config(struct phylink_config *config, unsigned int mode, 16171947923SIoana Ciornei const struct phylink_link_state *state) 16271947923SIoana Ciornei { 16371947923SIoana Ciornei struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config); 16471947923SIoana Ciornei struct dpmac_link_state *dpmac_state = &mac->state; 16571947923SIoana Ciornei int err; 16671947923SIoana Ciornei 16771947923SIoana Ciornei if (state->an_enabled) 16871947923SIoana Ciornei dpmac_state->options |= DPMAC_LINK_OPT_AUTONEG; 16971947923SIoana Ciornei else 17071947923SIoana Ciornei dpmac_state->options &= ~DPMAC_LINK_OPT_AUTONEG; 17171947923SIoana Ciornei 17271947923SIoana Ciornei err = dpmac_set_link_state(mac->mc_io, 0, 17371947923SIoana Ciornei mac->mc_dev->mc_handle, dpmac_state); 17471947923SIoana Ciornei if (err) 17537556a4aSRussell King netdev_err(mac->net_dev, "%s: dpmac_set_link_state() = %d\n", 17637556a4aSRussell King __func__, err); 17771947923SIoana Ciornei } 17871947923SIoana Ciornei 17991a208f2SRussell King static void dpaa2_mac_link_up(struct phylink_config *config, 18091a208f2SRussell King struct phy_device *phy, 18191a208f2SRussell King unsigned int mode, phy_interface_t interface, 18291a208f2SRussell King int speed, int duplex, 18391a208f2SRussell King bool tx_pause, bool rx_pause) 18471947923SIoana Ciornei { 18571947923SIoana Ciornei struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config); 18671947923SIoana Ciornei struct dpmac_link_state *dpmac_state = &mac->state; 18771947923SIoana Ciornei int err; 18871947923SIoana Ciornei 18971947923SIoana Ciornei dpmac_state->up = 1; 19037556a4aSRussell King 19137556a4aSRussell King dpmac_state->rate = speed; 19237556a4aSRussell King 19337556a4aSRussell King if (duplex == DUPLEX_HALF) 19437556a4aSRussell King dpmac_state->options |= DPMAC_LINK_OPT_HALF_DUPLEX; 19537556a4aSRussell King else if (duplex == DUPLEX_FULL) 19637556a4aSRussell King dpmac_state->options &= ~DPMAC_LINK_OPT_HALF_DUPLEX; 19737556a4aSRussell King 19837556a4aSRussell King if (rx_pause) 19937556a4aSRussell King dpmac_state->options |= DPMAC_LINK_OPT_PAUSE; 20037556a4aSRussell King else 20137556a4aSRussell King dpmac_state->options &= ~DPMAC_LINK_OPT_PAUSE; 20237556a4aSRussell King 20337556a4aSRussell King if (rx_pause ^ tx_pause) 20437556a4aSRussell King dpmac_state->options |= DPMAC_LINK_OPT_ASYM_PAUSE; 20537556a4aSRussell King else 20637556a4aSRussell King dpmac_state->options &= ~DPMAC_LINK_OPT_ASYM_PAUSE; 20737556a4aSRussell King 20871947923SIoana Ciornei err = dpmac_set_link_state(mac->mc_io, 0, 20971947923SIoana Ciornei mac->mc_dev->mc_handle, dpmac_state); 21071947923SIoana Ciornei if (err) 21137556a4aSRussell King netdev_err(mac->net_dev, "%s: dpmac_set_link_state() = %d\n", 21237556a4aSRussell King __func__, err); 21371947923SIoana Ciornei } 21471947923SIoana Ciornei 21571947923SIoana Ciornei static void dpaa2_mac_link_down(struct phylink_config *config, 21671947923SIoana Ciornei unsigned int mode, 21771947923SIoana Ciornei phy_interface_t interface) 21871947923SIoana Ciornei { 21971947923SIoana Ciornei struct dpaa2_mac *mac = phylink_to_dpaa2_mac(config); 22071947923SIoana Ciornei struct dpmac_link_state *dpmac_state = &mac->state; 22171947923SIoana Ciornei int err; 22271947923SIoana Ciornei 22371947923SIoana Ciornei dpmac_state->up = 0; 22471947923SIoana Ciornei err = dpmac_set_link_state(mac->mc_io, 0, 22571947923SIoana Ciornei mac->mc_dev->mc_handle, dpmac_state); 22671947923SIoana Ciornei if (err) 22771947923SIoana Ciornei netdev_err(mac->net_dev, "dpmac_set_link_state() = %d\n", err); 22871947923SIoana Ciornei } 22971947923SIoana Ciornei 23071947923SIoana Ciornei static const struct phylink_mac_ops dpaa2_mac_phylink_ops = { 23171947923SIoana Ciornei .validate = dpaa2_mac_validate, 23271947923SIoana Ciornei .mac_config = dpaa2_mac_config, 23371947923SIoana Ciornei .mac_link_up = dpaa2_mac_link_up, 23471947923SIoana Ciornei .mac_link_down = dpaa2_mac_link_down, 23571947923SIoana Ciornei }; 23671947923SIoana Ciornei 23794ae899bSIoana Ciornei static int dpaa2_pcs_create(struct dpaa2_mac *mac, 23894ae899bSIoana Ciornei struct device_node *dpmac_node, int id) 23994ae899bSIoana Ciornei { 24094ae899bSIoana Ciornei struct mdio_device *mdiodev; 24194ae899bSIoana Ciornei struct device_node *node; 24294ae899bSIoana Ciornei 24394ae899bSIoana Ciornei node = of_parse_phandle(dpmac_node, "pcs-handle", 0); 24494ae899bSIoana Ciornei if (!node) { 24594ae899bSIoana Ciornei /* do not error out on old DTS files */ 24694ae899bSIoana Ciornei netdev_warn(mac->net_dev, "pcs-handle node not found\n"); 24794ae899bSIoana Ciornei return 0; 24894ae899bSIoana Ciornei } 24994ae899bSIoana Ciornei 25098179709SIoana Ciornei if (!of_device_is_available(node)) { 25194ae899bSIoana Ciornei netdev_err(mac->net_dev, "pcs-handle node not available\n"); 252bbef72c6SChristophe JAILLET of_node_put(node); 25394ae899bSIoana Ciornei return -ENODEV; 25494ae899bSIoana Ciornei } 25594ae899bSIoana Ciornei 25694ae899bSIoana Ciornei mdiodev = of_mdio_find_device(node); 25794ae899bSIoana Ciornei of_node_put(node); 25894ae899bSIoana Ciornei if (!mdiodev) 25994ae899bSIoana Ciornei return -EPROBE_DEFER; 26094ae899bSIoana Ciornei 26194ae899bSIoana Ciornei mac->pcs = lynx_pcs_create(mdiodev); 26294ae899bSIoana Ciornei if (!mac->pcs) { 26394ae899bSIoana Ciornei netdev_err(mac->net_dev, "lynx_pcs_create() failed\n"); 26494ae899bSIoana Ciornei put_device(&mdiodev->dev); 26594ae899bSIoana Ciornei return -ENOMEM; 26694ae899bSIoana Ciornei } 26794ae899bSIoana Ciornei 26894ae899bSIoana Ciornei return 0; 26994ae899bSIoana Ciornei } 27094ae899bSIoana Ciornei 27194ae899bSIoana Ciornei static void dpaa2_pcs_destroy(struct dpaa2_mac *mac) 27294ae899bSIoana Ciornei { 27394ae899bSIoana Ciornei struct lynx_pcs *pcs = mac->pcs; 27494ae899bSIoana Ciornei 27594ae899bSIoana Ciornei if (pcs) { 276b4f43483SGustavo A. R. Silva struct device *dev = &pcs->mdio->dev; 27794ae899bSIoana Ciornei lynx_pcs_destroy(pcs); 27894ae899bSIoana Ciornei put_device(dev); 27994ae899bSIoana Ciornei mac->pcs = NULL; 28094ae899bSIoana Ciornei } 28194ae899bSIoana Ciornei } 28294ae899bSIoana Ciornei 28371947923SIoana Ciornei int dpaa2_mac_connect(struct dpaa2_mac *mac) 28471947923SIoana Ciornei { 28571947923SIoana Ciornei struct net_device *net_dev = mac->net_dev; 28671947923SIoana Ciornei struct device_node *dpmac_node; 28771947923SIoana Ciornei struct phylink *phylink; 28871947923SIoana Ciornei int err; 28971947923SIoana Ciornei 290095dca16SIoana Ciornei mac->if_link_type = mac->attr.link_type; 291095dca16SIoana Ciornei 292*b193f2edSIoana Ciornei dpmac_node = mac->of_node; 293095dca16SIoana Ciornei if (!dpmac_node) { 294095dca16SIoana Ciornei netdev_err(net_dev, "No dpmac@%d node found.\n", mac->attr.id); 29571947923SIoana Ciornei return -ENODEV; 29671947923SIoana Ciornei } 29771947923SIoana Ciornei 298095dca16SIoana Ciornei err = dpaa2_mac_get_if_mode(dpmac_node, mac->attr); 299*b193f2edSIoana Ciornei if (err < 0) 300*b193f2edSIoana Ciornei return -EINVAL; 30171947923SIoana Ciornei mac->if_mode = err; 30271947923SIoana Ciornei 30371947923SIoana Ciornei /* The MAC does not have the capability to add RGMII delays so 30471947923SIoana Ciornei * error out if the interface mode requests them and there is no PHY 30571947923SIoana Ciornei * to act upon them 30671947923SIoana Ciornei */ 30771947923SIoana Ciornei if (of_phy_is_fixed_link(dpmac_node) && 30871947923SIoana Ciornei (mac->if_mode == PHY_INTERFACE_MODE_RGMII_ID || 30971947923SIoana Ciornei mac->if_mode == PHY_INTERFACE_MODE_RGMII_RXID || 31071947923SIoana Ciornei mac->if_mode == PHY_INTERFACE_MODE_RGMII_TXID)) { 31171947923SIoana Ciornei netdev_err(net_dev, "RGMII delay not supported\n"); 312*b193f2edSIoana Ciornei return -EINVAL; 31371947923SIoana Ciornei } 31471947923SIoana Ciornei 315085f1776SRussell King if ((mac->attr.link_type == DPMAC_LINK_TYPE_PHY && 316085f1776SRussell King mac->attr.eth_if != DPMAC_ETH_IF_RGMII) || 317085f1776SRussell King mac->attr.link_type == DPMAC_LINK_TYPE_BACKPLANE) { 318095dca16SIoana Ciornei err = dpaa2_pcs_create(mac, dpmac_node, mac->attr.id); 31994ae899bSIoana Ciornei if (err) 320*b193f2edSIoana Ciornei return err; 32194ae899bSIoana Ciornei } 32294ae899bSIoana Ciornei 32371947923SIoana Ciornei mac->phylink_config.dev = &net_dev->dev; 32471947923SIoana Ciornei mac->phylink_config.type = PHYLINK_NETDEV; 32571947923SIoana Ciornei 32671947923SIoana Ciornei phylink = phylink_create(&mac->phylink_config, 32771947923SIoana Ciornei of_fwnode_handle(dpmac_node), mac->if_mode, 32871947923SIoana Ciornei &dpaa2_mac_phylink_ops); 32971947923SIoana Ciornei if (IS_ERR(phylink)) { 33071947923SIoana Ciornei err = PTR_ERR(phylink); 33194ae899bSIoana Ciornei goto err_pcs_destroy; 33271947923SIoana Ciornei } 33371947923SIoana Ciornei mac->phylink = phylink; 33471947923SIoana Ciornei 33594ae899bSIoana Ciornei if (mac->pcs) 33694ae899bSIoana Ciornei phylink_set_pcs(mac->phylink, &mac->pcs->pcs); 33794ae899bSIoana Ciornei 33871947923SIoana Ciornei err = phylink_of_phy_connect(mac->phylink, dpmac_node, 0); 33971947923SIoana Ciornei if (err) { 34071947923SIoana Ciornei netdev_err(net_dev, "phylink_of_phy_connect() = %d\n", err); 34171947923SIoana Ciornei goto err_phylink_destroy; 34271947923SIoana Ciornei } 34371947923SIoana Ciornei 34471947923SIoana Ciornei return 0; 34571947923SIoana Ciornei 34671947923SIoana Ciornei err_phylink_destroy: 34771947923SIoana Ciornei phylink_destroy(mac->phylink); 34894ae899bSIoana Ciornei err_pcs_destroy: 34994ae899bSIoana Ciornei dpaa2_pcs_destroy(mac); 350095dca16SIoana Ciornei 35171947923SIoana Ciornei return err; 35271947923SIoana Ciornei } 35371947923SIoana Ciornei 35471947923SIoana Ciornei void dpaa2_mac_disconnect(struct dpaa2_mac *mac) 35571947923SIoana Ciornei { 35671947923SIoana Ciornei if (!mac->phylink) 35771947923SIoana Ciornei return; 35871947923SIoana Ciornei 35971947923SIoana Ciornei phylink_disconnect_phy(mac->phylink); 36071947923SIoana Ciornei phylink_destroy(mac->phylink); 36194ae899bSIoana Ciornei dpaa2_pcs_destroy(mac); 362095dca16SIoana Ciornei } 36394ae899bSIoana Ciornei 364095dca16SIoana Ciornei int dpaa2_mac_open(struct dpaa2_mac *mac) 365095dca16SIoana Ciornei { 366095dca16SIoana Ciornei struct fsl_mc_device *dpmac_dev = mac->mc_dev; 367095dca16SIoana Ciornei struct net_device *net_dev = mac->net_dev; 368095dca16SIoana Ciornei int err; 369095dca16SIoana Ciornei 370095dca16SIoana Ciornei err = dpmac_open(mac->mc_io, 0, dpmac_dev->obj_desc.id, 371095dca16SIoana Ciornei &dpmac_dev->mc_handle); 372095dca16SIoana Ciornei if (err || !dpmac_dev->mc_handle) { 373095dca16SIoana Ciornei netdev_err(net_dev, "dpmac_open() = %d\n", err); 374095dca16SIoana Ciornei return -ENODEV; 375095dca16SIoana Ciornei } 376095dca16SIoana Ciornei 377095dca16SIoana Ciornei err = dpmac_get_attributes(mac->mc_io, 0, dpmac_dev->mc_handle, 378095dca16SIoana Ciornei &mac->attr); 379095dca16SIoana Ciornei if (err) { 380095dca16SIoana Ciornei netdev_err(net_dev, "dpmac_get_attributes() = %d\n", err); 381095dca16SIoana Ciornei goto err_close_dpmac; 382095dca16SIoana Ciornei } 383095dca16SIoana Ciornei 384*b193f2edSIoana Ciornei /* Find the device node representing the MAC device and link the device 385*b193f2edSIoana Ciornei * behind the associated netdev to it. 386*b193f2edSIoana Ciornei */ 387*b193f2edSIoana Ciornei mac->of_node = dpaa2_mac_get_node(mac->attr.id); 388*b193f2edSIoana Ciornei net_dev->dev.of_node = mac->of_node; 389*b193f2edSIoana Ciornei 390095dca16SIoana Ciornei return 0; 391095dca16SIoana Ciornei 392095dca16SIoana Ciornei err_close_dpmac: 393095dca16SIoana Ciornei dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle); 394095dca16SIoana Ciornei return err; 395095dca16SIoana Ciornei } 396095dca16SIoana Ciornei 397095dca16SIoana Ciornei void dpaa2_mac_close(struct dpaa2_mac *mac) 398095dca16SIoana Ciornei { 399095dca16SIoana Ciornei struct fsl_mc_device *dpmac_dev = mac->mc_dev; 400095dca16SIoana Ciornei 401095dca16SIoana Ciornei dpmac_close(mac->mc_io, 0, dpmac_dev->mc_handle); 402*b193f2edSIoana Ciornei if (mac->of_node) 403*b193f2edSIoana Ciornei of_node_put(mac->of_node); 40471947923SIoana Ciornei } 405991df1fbSIoana Ciornei 406991df1fbSIoana Ciornei static char dpaa2_mac_ethtool_stats[][ETH_GSTRING_LEN] = { 407991df1fbSIoana Ciornei [DPMAC_CNT_ING_ALL_FRAME] = "[mac] rx all frames", 408991df1fbSIoana Ciornei [DPMAC_CNT_ING_GOOD_FRAME] = "[mac] rx frames ok", 409991df1fbSIoana Ciornei [DPMAC_CNT_ING_ERR_FRAME] = "[mac] rx frame errors", 410991df1fbSIoana Ciornei [DPMAC_CNT_ING_FRAME_DISCARD] = "[mac] rx frame discards", 411991df1fbSIoana Ciornei [DPMAC_CNT_ING_UCAST_FRAME] = "[mac] rx u-cast", 412991df1fbSIoana Ciornei [DPMAC_CNT_ING_BCAST_FRAME] = "[mac] rx b-cast", 413991df1fbSIoana Ciornei [DPMAC_CNT_ING_MCAST_FRAME] = "[mac] rx m-cast", 414991df1fbSIoana Ciornei [DPMAC_CNT_ING_FRAME_64] = "[mac] rx 64 bytes", 415991df1fbSIoana Ciornei [DPMAC_CNT_ING_FRAME_127] = "[mac] rx 65-127 bytes", 416991df1fbSIoana Ciornei [DPMAC_CNT_ING_FRAME_255] = "[mac] rx 128-255 bytes", 417991df1fbSIoana Ciornei [DPMAC_CNT_ING_FRAME_511] = "[mac] rx 256-511 bytes", 418991df1fbSIoana Ciornei [DPMAC_CNT_ING_FRAME_1023] = "[mac] rx 512-1023 bytes", 419991df1fbSIoana Ciornei [DPMAC_CNT_ING_FRAME_1518] = "[mac] rx 1024-1518 bytes", 420991df1fbSIoana Ciornei [DPMAC_CNT_ING_FRAME_1519_MAX] = "[mac] rx 1519-max bytes", 421991df1fbSIoana Ciornei [DPMAC_CNT_ING_FRAG] = "[mac] rx frags", 422991df1fbSIoana Ciornei [DPMAC_CNT_ING_JABBER] = "[mac] rx jabber", 423991df1fbSIoana Ciornei [DPMAC_CNT_ING_ALIGN_ERR] = "[mac] rx align errors", 424991df1fbSIoana Ciornei [DPMAC_CNT_ING_OVERSIZED] = "[mac] rx oversized", 425991df1fbSIoana Ciornei [DPMAC_CNT_ING_VALID_PAUSE_FRAME] = "[mac] rx pause", 426991df1fbSIoana Ciornei [DPMAC_CNT_ING_BYTE] = "[mac] rx bytes", 427991df1fbSIoana Ciornei [DPMAC_CNT_EGR_GOOD_FRAME] = "[mac] tx frames ok", 428991df1fbSIoana Ciornei [DPMAC_CNT_EGR_UCAST_FRAME] = "[mac] tx u-cast", 429991df1fbSIoana Ciornei [DPMAC_CNT_EGR_MCAST_FRAME] = "[mac] tx m-cast", 430991df1fbSIoana Ciornei [DPMAC_CNT_EGR_BCAST_FRAME] = "[mac] tx b-cast", 431991df1fbSIoana Ciornei [DPMAC_CNT_EGR_ERR_FRAME] = "[mac] tx frame errors", 432991df1fbSIoana Ciornei [DPMAC_CNT_EGR_UNDERSIZED] = "[mac] tx undersized", 433991df1fbSIoana Ciornei [DPMAC_CNT_EGR_VALID_PAUSE_FRAME] = "[mac] tx b-pause", 434991df1fbSIoana Ciornei [DPMAC_CNT_EGR_BYTE] = "[mac] tx bytes", 435991df1fbSIoana Ciornei }; 436991df1fbSIoana Ciornei 437991df1fbSIoana Ciornei #define DPAA2_MAC_NUM_STATS ARRAY_SIZE(dpaa2_mac_ethtool_stats) 438991df1fbSIoana Ciornei 439991df1fbSIoana Ciornei int dpaa2_mac_get_sset_count(void) 440991df1fbSIoana Ciornei { 441991df1fbSIoana Ciornei return DPAA2_MAC_NUM_STATS; 442991df1fbSIoana Ciornei } 443991df1fbSIoana Ciornei 444991df1fbSIoana Ciornei void dpaa2_mac_get_strings(u8 *data) 445991df1fbSIoana Ciornei { 446991df1fbSIoana Ciornei u8 *p = data; 447991df1fbSIoana Ciornei int i; 448991df1fbSIoana Ciornei 449991df1fbSIoana Ciornei for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) { 450991df1fbSIoana Ciornei strlcpy(p, dpaa2_mac_ethtool_stats[i], ETH_GSTRING_LEN); 451991df1fbSIoana Ciornei p += ETH_GSTRING_LEN; 452991df1fbSIoana Ciornei } 453991df1fbSIoana Ciornei } 454991df1fbSIoana Ciornei 455991df1fbSIoana Ciornei void dpaa2_mac_get_ethtool_stats(struct dpaa2_mac *mac, u64 *data) 456991df1fbSIoana Ciornei { 457991df1fbSIoana Ciornei struct fsl_mc_device *dpmac_dev = mac->mc_dev; 458991df1fbSIoana Ciornei int i, err; 459991df1fbSIoana Ciornei u64 value; 460991df1fbSIoana Ciornei 461991df1fbSIoana Ciornei for (i = 0; i < DPAA2_MAC_NUM_STATS; i++) { 462991df1fbSIoana Ciornei err = dpmac_get_counter(mac->mc_io, 0, dpmac_dev->mc_handle, 463991df1fbSIoana Ciornei i, &value); 464991df1fbSIoana Ciornei if (err) { 465991df1fbSIoana Ciornei netdev_err_once(mac->net_dev, 466991df1fbSIoana Ciornei "dpmac_get_counter error %d\n", err); 467991df1fbSIoana Ciornei *(data + i) = U64_MAX; 468991df1fbSIoana Ciornei continue; 469991df1fbSIoana Ciornei } 470991df1fbSIoana Ciornei *(data + i) = value; 471991df1fbSIoana Ciornei } 472991df1fbSIoana Ciornei } 473