]> git.itanic.dy.fi Git - linux-stable/commitdiff
net: fman: memac: Add serdes support
authorSean Anderson <sean.anderson@seco.com>
Mon, 17 Oct 2022 20:22:36 +0000 (16:22 -0400)
committerDavid S. Miller <davem@davemloft.net>
Wed, 19 Oct 2022 12:25:09 +0000 (13:25 +0100)
This adds support for using a serdes which has to be configured. This is
primarly in preparation for phylink conversion, which will then change the
serdes mode dynamically.

Signed-off-by: Sean Anderson <sean.anderson@seco.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/freescale/fman/fman_memac.c

index 32d26cf178437d7a0b7e6577276cf0a62b54a5f4..56a29f5055901e10ee333c75ee1f8f034806f533 100644 (file)
@@ -13,6 +13,7 @@
 #include <linux/io.h>
 #include <linux/phy.h>
 #include <linux/phy_fixed.h>
+#include <linux/phy/phy.h>
 #include <linux/of_mdio.h>
 
 /* PCS registers */
@@ -324,6 +325,7 @@ struct fman_mac {
        void *fm;
        struct fman_rev_info fm_rev_info;
        bool basex_if;
+       struct phy *serdes;
        struct phy_device *pcsphy;
        bool allmulti_enabled;
 };
@@ -1203,17 +1205,56 @@ int memac_initialization(struct mac_device *mac_dev,
                }
        }
 
+       memac->serdes = devm_of_phy_get(mac_dev->dev, mac_node, "serdes");
+       err = PTR_ERR(memac->serdes);
+       if (err == -ENODEV || err == -ENOSYS) {
+               dev_dbg(mac_dev->dev, "could not get (optional) serdes\n");
+               memac->serdes = NULL;
+       } else if (IS_ERR(memac->serdes)) {
+               dev_err_probe(mac_dev->dev, err, "could not get serdes\n");
+               goto _return_fm_mac_free;
+       } else {
+               err = phy_init(memac->serdes);
+               if (err) {
+                       dev_err_probe(mac_dev->dev, err,
+                                     "could not initialize serdes\n");
+                       goto _return_fm_mac_free;
+               }
+
+               err = phy_power_on(memac->serdes);
+               if (err) {
+                       dev_err_probe(mac_dev->dev, err,
+                                     "could not power on serdes\n");
+                       goto _return_phy_exit;
+               }
+
+               if (memac->phy_if == PHY_INTERFACE_MODE_SGMII ||
+                   memac->phy_if == PHY_INTERFACE_MODE_1000BASEX ||
+                   memac->phy_if == PHY_INTERFACE_MODE_2500BASEX ||
+                   memac->phy_if == PHY_INTERFACE_MODE_QSGMII ||
+                   memac->phy_if == PHY_INTERFACE_MODE_XGMII) {
+                       err = phy_set_mode_ext(memac->serdes, PHY_MODE_ETHERNET,
+                                              memac->phy_if);
+                       if (err) {
+                               dev_err_probe(mac_dev->dev, err,
+                                             "could not set serdes mode to %s\n",
+                                             phy_modes(memac->phy_if));
+                               goto _return_phy_power_off;
+                       }
+               }
+       }
+
        if (!mac_dev->phy_node && of_phy_is_fixed_link(mac_node)) {
                struct phy_device *phy;
 
                err = of_phy_register_fixed_link(mac_node);
                if (err)
-                       goto _return_fm_mac_free;
+                       goto _return_phy_power_off;
 
                fixed_link = kzalloc(sizeof(*fixed_link), GFP_KERNEL);
                if (!fixed_link) {
                        err = -ENOMEM;
-                       goto _return_fm_mac_free;
+                       goto _return_phy_power_off;
                }
 
                mac_dev->phy_node = of_node_get(mac_node);
@@ -1242,6 +1283,10 @@ int memac_initialization(struct mac_device *mac_dev,
 
        goto _return;
 
+_return_phy_power_off:
+       phy_power_off(memac->serdes);
+_return_phy_exit:
+       phy_exit(memac->serdes);
 _return_fixed_link_free:
        kfree(fixed_link);
 _return_fm_mac_free: