180c8c852SWei Fang // SPDX-License-Identifier: (GPL-2.0+ OR BSD-3-Clause) 280c8c852SWei Fang /* Copyright 2024 NXP */ 380c8c852SWei Fang 480c8c852SWei Fang #include <linux/fsl/enetc_mdio.h> 580c8c852SWei Fang #include <linux/of_mdio.h> 680c8c852SWei Fang #include <linux/of_net.h> 780c8c852SWei Fang 880c8c852SWei Fang #include "enetc_pf_common.h" 980c8c852SWei Fang 103774409fSWei Fang static void enetc_set_si_hw_addr(struct enetc_pf *pf, int si, 113774409fSWei Fang const u8 *mac_addr) 123774409fSWei Fang { 133774409fSWei Fang struct enetc_hw *hw = &pf->si->hw; 143774409fSWei Fang 153774409fSWei Fang pf->ops->set_si_primary_mac(hw, si, mac_addr); 163774409fSWei Fang } 173774409fSWei Fang 183774409fSWei Fang static void enetc_get_si_hw_addr(struct enetc_pf *pf, int si, u8 *mac_addr) 193774409fSWei Fang { 203774409fSWei Fang struct enetc_hw *hw = &pf->si->hw; 213774409fSWei Fang 223774409fSWei Fang pf->ops->get_si_primary_mac(hw, si, mac_addr); 233774409fSWei Fang } 243774409fSWei Fang 2580c8c852SWei Fang int enetc_pf_set_mac_addr(struct net_device *ndev, void *addr) 2680c8c852SWei Fang { 2780c8c852SWei Fang struct enetc_ndev_priv *priv = netdev_priv(ndev); 283774409fSWei Fang struct enetc_pf *pf = enetc_si_priv(priv->si); 2980c8c852SWei Fang struct sockaddr *saddr = addr; 3080c8c852SWei Fang 3180c8c852SWei Fang if (!is_valid_ether_addr(saddr->sa_data)) 3280c8c852SWei Fang return -EADDRNOTAVAIL; 3380c8c852SWei Fang 3480c8c852SWei Fang eth_hw_addr_set(ndev, saddr->sa_data); 353774409fSWei Fang enetc_set_si_hw_addr(pf, 0, saddr->sa_data); 3680c8c852SWei Fang 3780c8c852SWei Fang return 0; 3880c8c852SWei Fang } 393774409fSWei Fang EXPORT_SYMBOL_GPL(enetc_pf_set_mac_addr); 4080c8c852SWei Fang 4180c8c852SWei Fang static int enetc_setup_mac_address(struct device_node *np, struct enetc_pf *pf, 4280c8c852SWei Fang int si) 4380c8c852SWei Fang { 4480c8c852SWei Fang struct device *dev = &pf->si->pdev->dev; 4580c8c852SWei Fang u8 mac_addr[ETH_ALEN] = { 0 }; 4680c8c852SWei Fang int err; 4780c8c852SWei Fang 4880c8c852SWei Fang /* (1) try to get the MAC address from the device tree */ 4980c8c852SWei Fang if (np) { 5080c8c852SWei Fang err = of_get_mac_address(np, mac_addr); 5180c8c852SWei Fang if (err == -EPROBE_DEFER) 5280c8c852SWei Fang return err; 5380c8c852SWei Fang } 5480c8c852SWei Fang 5580c8c852SWei Fang /* (2) bootloader supplied MAC address */ 5680c8c852SWei Fang if (is_zero_ether_addr(mac_addr)) 573774409fSWei Fang enetc_get_si_hw_addr(pf, si, mac_addr); 5880c8c852SWei Fang 5980c8c852SWei Fang /* (3) choose a random one */ 6080c8c852SWei Fang if (is_zero_ether_addr(mac_addr)) { 6180c8c852SWei Fang eth_random_addr(mac_addr); 6280c8c852SWei Fang dev_info(dev, "no MAC address specified for SI%d, using %pM\n", 6380c8c852SWei Fang si, mac_addr); 6480c8c852SWei Fang } 6580c8c852SWei Fang 663774409fSWei Fang enetc_set_si_hw_addr(pf, si, mac_addr); 6780c8c852SWei Fang 6880c8c852SWei Fang return 0; 6980c8c852SWei Fang } 7080c8c852SWei Fang 7180c8c852SWei Fang int enetc_setup_mac_addresses(struct device_node *np, struct enetc_pf *pf) 7280c8c852SWei Fang { 7380c8c852SWei Fang int err, i; 7480c8c852SWei Fang 7580c8c852SWei Fang /* The PF might take its MAC from the device tree */ 7680c8c852SWei Fang err = enetc_setup_mac_address(np, pf, 0); 7780c8c852SWei Fang if (err) 7880c8c852SWei Fang return err; 7980c8c852SWei Fang 8080c8c852SWei Fang for (i = 0; i < pf->total_vfs; i++) { 8180c8c852SWei Fang err = enetc_setup_mac_address(NULL, pf, i + 1); 8280c8c852SWei Fang if (err) 8380c8c852SWei Fang return err; 8480c8c852SWei Fang } 8580c8c852SWei Fang 8680c8c852SWei Fang return 0; 8780c8c852SWei Fang } 883774409fSWei Fang EXPORT_SYMBOL_GPL(enetc_setup_mac_addresses); 8980c8c852SWei Fang 9080c8c852SWei Fang void enetc_pf_netdev_setup(struct enetc_si *si, struct net_device *ndev, 9180c8c852SWei Fang const struct net_device_ops *ndev_ops) 9280c8c852SWei Fang { 9380c8c852SWei Fang struct enetc_ndev_priv *priv = netdev_priv(ndev); 943774409fSWei Fang struct enetc_pf *pf = enetc_si_priv(si); 9580c8c852SWei Fang 9680c8c852SWei Fang SET_NETDEV_DEV(ndev, &si->pdev->dev); 9780c8c852SWei Fang priv->ndev = ndev; 9880c8c852SWei Fang priv->si = si; 9980c8c852SWei Fang priv->dev = &si->pdev->dev; 10080c8c852SWei Fang si->ndev = ndev; 10180c8c852SWei Fang 10280c8c852SWei Fang priv->msg_enable = (NETIF_MSG_WOL << 1) - 1; 10399100d0dSWei Fang priv->sysclk_freq = si->drvdata->sysclk_freq; 10493c5d5a0SWei Fang priv->max_frags = si->drvdata->max_frags; 10580c8c852SWei Fang ndev->netdev_ops = ndev_ops; 10680c8c852SWei Fang enetc_set_ethtool_ops(ndev); 10780c8c852SWei Fang ndev->watchdog_timeo = 5 * HZ; 10880c8c852SWei Fang ndev->max_mtu = ENETC_MAX_MTU; 10980c8c852SWei Fang 11080c8c852SWei Fang ndev->hw_features = NETIF_F_SG | NETIF_F_RXCSUM | 11180c8c852SWei Fang NETIF_F_HW_VLAN_CTAG_TX | NETIF_F_HW_VLAN_CTAG_RX | 11280c8c852SWei Fang NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK | 113*c12e82c0SWei Fang NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6 | 114*c12e82c0SWei Fang NETIF_F_GSO_UDP_L4; 11580c8c852SWei Fang ndev->features = NETIF_F_HIGHDMA | NETIF_F_SG | NETIF_F_RXCSUM | 11680c8c852SWei Fang NETIF_F_HW_VLAN_CTAG_TX | 11780c8c852SWei Fang NETIF_F_HW_VLAN_CTAG_RX | 118*c12e82c0SWei Fang NETIF_F_HW_CSUM | NETIF_F_TSO | NETIF_F_TSO6 | 119*c12e82c0SWei Fang NETIF_F_GSO_UDP_L4; 12080c8c852SWei Fang ndev->vlan_features = NETIF_F_SG | NETIF_F_HW_CSUM | 12180c8c852SWei Fang NETIF_F_TSO | NETIF_F_TSO6; 12280c8c852SWei Fang 12399100d0dSWei Fang ndev->priv_flags |= IFF_UNICAST_FLT; 12499100d0dSWei Fang 125d9a093d2SWei Fang if (si->drvdata->tx_csum) 126d9a093d2SWei Fang priv->active_offloads |= ENETC_F_TXCSUM; 127d9a093d2SWei Fang 12869797ff8SWei Fang if (si->hw_features & ENETC_SI_F_LSO) 12969797ff8SWei Fang priv->active_offloads |= ENETC_F_LSO; 13069797ff8SWei Fang 13199100d0dSWei Fang /* TODO: currently, i.MX95 ENETC driver does not support advanced features */ 13299100d0dSWei Fang if (!is_enetc_rev1(si)) { 13399100d0dSWei Fang ndev->hw_features &= ~(NETIF_F_HW_VLAN_CTAG_FILTER | NETIF_F_LOOPBACK); 13499100d0dSWei Fang goto end; 13599100d0dSWei Fang } 13699100d0dSWei Fang 13780c8c852SWei Fang if (si->num_rss) 13880c8c852SWei Fang ndev->hw_features |= NETIF_F_RXHASH; 13980c8c852SWei Fang 14080c8c852SWei Fang ndev->xdp_features = NETDEV_XDP_ACT_BASIC | NETDEV_XDP_ACT_REDIRECT | 14180c8c852SWei Fang NETDEV_XDP_ACT_NDO_XMIT | NETDEV_XDP_ACT_RX_SG | 14280c8c852SWei Fang NETDEV_XDP_ACT_NDO_XMIT_SG; 14380c8c852SWei Fang 1443774409fSWei Fang if (si->hw_features & ENETC_SI_F_PSFP && pf->ops->enable_psfp && 1453774409fSWei Fang !pf->ops->enable_psfp(priv)) { 14680c8c852SWei Fang priv->active_offloads |= ENETC_F_QCI; 14780c8c852SWei Fang ndev->features |= NETIF_F_HW_TC; 14880c8c852SWei Fang ndev->hw_features |= NETIF_F_HW_TC; 14980c8c852SWei Fang } 15080c8c852SWei Fang 15199100d0dSWei Fang end: 15280c8c852SWei Fang /* pick up primary MAC address from SI */ 15380c8c852SWei Fang enetc_load_primary_mac_addr(&si->hw, ndev); 15480c8c852SWei Fang } 1553774409fSWei Fang EXPORT_SYMBOL_GPL(enetc_pf_netdev_setup); 15680c8c852SWei Fang 15780c8c852SWei Fang static int enetc_mdio_probe(struct enetc_pf *pf, struct device_node *np) 15880c8c852SWei Fang { 15980c8c852SWei Fang struct device *dev = &pf->si->pdev->dev; 16080c8c852SWei Fang struct enetc_mdio_priv *mdio_priv; 16180c8c852SWei Fang struct mii_bus *bus; 16280c8c852SWei Fang int err; 16380c8c852SWei Fang 16480c8c852SWei Fang bus = devm_mdiobus_alloc_size(dev, sizeof(*mdio_priv)); 16580c8c852SWei Fang if (!bus) 16680c8c852SWei Fang return -ENOMEM; 16780c8c852SWei Fang 16880c8c852SWei Fang bus->name = "Freescale ENETC MDIO Bus"; 16980c8c852SWei Fang bus->read = enetc_mdio_read_c22; 17080c8c852SWei Fang bus->write = enetc_mdio_write_c22; 17180c8c852SWei Fang bus->read_c45 = enetc_mdio_read_c45; 17280c8c852SWei Fang bus->write_c45 = enetc_mdio_write_c45; 17380c8c852SWei Fang bus->parent = dev; 17480c8c852SWei Fang mdio_priv = bus->priv; 17580c8c852SWei Fang mdio_priv->hw = &pf->si->hw; 17680c8c852SWei Fang mdio_priv->mdio_base = ENETC_EMDIO_BASE; 17780c8c852SWei Fang snprintf(bus->id, MII_BUS_ID_SIZE, "%s", dev_name(dev)); 17880c8c852SWei Fang 17980c8c852SWei Fang err = of_mdiobus_register(bus, np); 18080c8c852SWei Fang if (err) 18180c8c852SWei Fang return dev_err_probe(dev, err, "cannot register MDIO bus\n"); 18280c8c852SWei Fang 18380c8c852SWei Fang pf->mdio = bus; 18480c8c852SWei Fang 18580c8c852SWei Fang return 0; 18680c8c852SWei Fang } 18780c8c852SWei Fang 18880c8c852SWei Fang static void enetc_mdio_remove(struct enetc_pf *pf) 18980c8c852SWei Fang { 19080c8c852SWei Fang if (pf->mdio) 19180c8c852SWei Fang mdiobus_unregister(pf->mdio); 19280c8c852SWei Fang } 19380c8c852SWei Fang 19480c8c852SWei Fang static int enetc_imdio_create(struct enetc_pf *pf) 19580c8c852SWei Fang { 19680c8c852SWei Fang struct device *dev = &pf->si->pdev->dev; 19780c8c852SWei Fang struct enetc_mdio_priv *mdio_priv; 19880c8c852SWei Fang struct phylink_pcs *phylink_pcs; 19980c8c852SWei Fang struct mii_bus *bus; 20080c8c852SWei Fang int err; 20180c8c852SWei Fang 2023774409fSWei Fang if (!pf->ops->create_pcs) { 2033774409fSWei Fang dev_err(dev, "Creating PCS is not supported\n"); 2043774409fSWei Fang 2053774409fSWei Fang return -EOPNOTSUPP; 2063774409fSWei Fang } 2073774409fSWei Fang 20880c8c852SWei Fang bus = mdiobus_alloc_size(sizeof(*mdio_priv)); 20980c8c852SWei Fang if (!bus) 21080c8c852SWei Fang return -ENOMEM; 21180c8c852SWei Fang 21280c8c852SWei Fang bus->name = "Freescale ENETC internal MDIO Bus"; 21380c8c852SWei Fang bus->read = enetc_mdio_read_c22; 21480c8c852SWei Fang bus->write = enetc_mdio_write_c22; 21580c8c852SWei Fang bus->read_c45 = enetc_mdio_read_c45; 21680c8c852SWei Fang bus->write_c45 = enetc_mdio_write_c45; 21780c8c852SWei Fang bus->parent = dev; 21880c8c852SWei Fang bus->phy_mask = ~0; 21980c8c852SWei Fang mdio_priv = bus->priv; 22080c8c852SWei Fang mdio_priv->hw = &pf->si->hw; 22180c8c852SWei Fang mdio_priv->mdio_base = ENETC_PM_IMDIO_BASE; 22280c8c852SWei Fang snprintf(bus->id, MII_BUS_ID_SIZE, "%s-imdio", dev_name(dev)); 22380c8c852SWei Fang 22480c8c852SWei Fang err = mdiobus_register(bus); 22580c8c852SWei Fang if (err) { 22680c8c852SWei Fang dev_err(dev, "cannot register internal MDIO bus (%d)\n", err); 22780c8c852SWei Fang goto free_mdio_bus; 22880c8c852SWei Fang } 22980c8c852SWei Fang 2303774409fSWei Fang phylink_pcs = pf->ops->create_pcs(pf, bus); 23180c8c852SWei Fang if (IS_ERR(phylink_pcs)) { 23280c8c852SWei Fang err = PTR_ERR(phylink_pcs); 23380c8c852SWei Fang dev_err(dev, "cannot create lynx pcs (%d)\n", err); 23480c8c852SWei Fang goto unregister_mdiobus; 23580c8c852SWei Fang } 23680c8c852SWei Fang 23780c8c852SWei Fang pf->imdio = bus; 23880c8c852SWei Fang pf->pcs = phylink_pcs; 23980c8c852SWei Fang 24080c8c852SWei Fang return 0; 24180c8c852SWei Fang 24280c8c852SWei Fang unregister_mdiobus: 24380c8c852SWei Fang mdiobus_unregister(bus); 24480c8c852SWei Fang free_mdio_bus: 24580c8c852SWei Fang mdiobus_free(bus); 24680c8c852SWei Fang return err; 24780c8c852SWei Fang } 24880c8c852SWei Fang 24980c8c852SWei Fang static void enetc_imdio_remove(struct enetc_pf *pf) 25080c8c852SWei Fang { 2513774409fSWei Fang if (pf->pcs && pf->ops->destroy_pcs) 2523774409fSWei Fang pf->ops->destroy_pcs(pf->pcs); 25380c8c852SWei Fang 25480c8c852SWei Fang if (pf->imdio) { 25580c8c852SWei Fang mdiobus_unregister(pf->imdio); 25680c8c852SWei Fang mdiobus_free(pf->imdio); 25780c8c852SWei Fang } 25880c8c852SWei Fang } 25980c8c852SWei Fang 26080c8c852SWei Fang static bool enetc_port_has_pcs(struct enetc_pf *pf) 26180c8c852SWei Fang { 26280c8c852SWei Fang return (pf->if_mode == PHY_INTERFACE_MODE_SGMII || 26380c8c852SWei Fang pf->if_mode == PHY_INTERFACE_MODE_1000BASEX || 26480c8c852SWei Fang pf->if_mode == PHY_INTERFACE_MODE_2500BASEX || 26580c8c852SWei Fang pf->if_mode == PHY_INTERFACE_MODE_USXGMII); 26680c8c852SWei Fang } 26780c8c852SWei Fang 26880c8c852SWei Fang int enetc_mdiobus_create(struct enetc_pf *pf, struct device_node *node) 26980c8c852SWei Fang { 27080c8c852SWei Fang struct device_node *mdio_np; 27180c8c852SWei Fang int err; 27280c8c852SWei Fang 27380c8c852SWei Fang mdio_np = of_get_child_by_name(node, "mdio"); 27480c8c852SWei Fang if (mdio_np) { 27580c8c852SWei Fang err = enetc_mdio_probe(pf, mdio_np); 27680c8c852SWei Fang 27780c8c852SWei Fang of_node_put(mdio_np); 27880c8c852SWei Fang if (err) 27980c8c852SWei Fang return err; 28080c8c852SWei Fang } 28180c8c852SWei Fang 28280c8c852SWei Fang if (enetc_port_has_pcs(pf)) { 28380c8c852SWei Fang err = enetc_imdio_create(pf); 28480c8c852SWei Fang if (err) { 28580c8c852SWei Fang enetc_mdio_remove(pf); 28680c8c852SWei Fang return err; 28780c8c852SWei Fang } 28880c8c852SWei Fang } 28980c8c852SWei Fang 29080c8c852SWei Fang return 0; 29180c8c852SWei Fang } 2923774409fSWei Fang EXPORT_SYMBOL_GPL(enetc_mdiobus_create); 29380c8c852SWei Fang 29480c8c852SWei Fang void enetc_mdiobus_destroy(struct enetc_pf *pf) 29580c8c852SWei Fang { 29680c8c852SWei Fang enetc_mdio_remove(pf); 29780c8c852SWei Fang enetc_imdio_remove(pf); 29880c8c852SWei Fang } 2993774409fSWei Fang EXPORT_SYMBOL_GPL(enetc_mdiobus_destroy); 30080c8c852SWei Fang 30180c8c852SWei Fang int enetc_phylink_create(struct enetc_ndev_priv *priv, struct device_node *node, 30280c8c852SWei Fang const struct phylink_mac_ops *ops) 30380c8c852SWei Fang { 30480c8c852SWei Fang struct enetc_pf *pf = enetc_si_priv(priv->si); 30580c8c852SWei Fang struct phylink *phylink; 30680c8c852SWei Fang int err; 30780c8c852SWei Fang 30880c8c852SWei Fang pf->phylink_config.dev = &priv->ndev->dev; 30980c8c852SWei Fang pf->phylink_config.type = PHYLINK_NETDEV; 31080c8c852SWei Fang pf->phylink_config.mac_capabilities = MAC_ASYM_PAUSE | MAC_SYM_PAUSE | 31180c8c852SWei Fang MAC_10 | MAC_100 | MAC_1000 | MAC_2500FD; 31280c8c852SWei Fang 31380c8c852SWei Fang __set_bit(PHY_INTERFACE_MODE_INTERNAL, 31480c8c852SWei Fang pf->phylink_config.supported_interfaces); 31580c8c852SWei Fang __set_bit(PHY_INTERFACE_MODE_SGMII, 31680c8c852SWei Fang pf->phylink_config.supported_interfaces); 31780c8c852SWei Fang __set_bit(PHY_INTERFACE_MODE_1000BASEX, 31880c8c852SWei Fang pf->phylink_config.supported_interfaces); 31980c8c852SWei Fang __set_bit(PHY_INTERFACE_MODE_2500BASEX, 32080c8c852SWei Fang pf->phylink_config.supported_interfaces); 32180c8c852SWei Fang __set_bit(PHY_INTERFACE_MODE_USXGMII, 32280c8c852SWei Fang pf->phylink_config.supported_interfaces); 32380c8c852SWei Fang phy_interface_set_rgmii(pf->phylink_config.supported_interfaces); 32480c8c852SWei Fang 32580c8c852SWei Fang phylink = phylink_create(&pf->phylink_config, of_fwnode_handle(node), 32680c8c852SWei Fang pf->if_mode, ops); 32780c8c852SWei Fang if (IS_ERR(phylink)) { 32880c8c852SWei Fang err = PTR_ERR(phylink); 32980c8c852SWei Fang return err; 33080c8c852SWei Fang } 33180c8c852SWei Fang 33280c8c852SWei Fang priv->phylink = phylink; 33380c8c852SWei Fang 33480c8c852SWei Fang return 0; 33580c8c852SWei Fang } 3363774409fSWei Fang EXPORT_SYMBOL_GPL(enetc_phylink_create); 33780c8c852SWei Fang 33880c8c852SWei Fang void enetc_phylink_destroy(struct enetc_ndev_priv *priv) 33980c8c852SWei Fang { 34080c8c852SWei Fang phylink_destroy(priv->phylink); 34180c8c852SWei Fang } 3423774409fSWei Fang EXPORT_SYMBOL_GPL(enetc_phylink_destroy); 3433774409fSWei Fang 3443774409fSWei Fang MODULE_DESCRIPTION("NXP ENETC PF common functionality driver"); 3453774409fSWei Fang MODULE_LICENSE("Dual BSD/GPL"); 346