openwrt/target/linux/generic/backport-6.6/715-01-v6.2-net-fman-memac-...

104 lines
3.0 KiB
Diff

From affa013f494486079c3c5ad2d00cebc41a3d7445 Mon Sep 17 00:00:00 2001
From: Sean Anderson <sean.anderson@seco.com>
Date: Mon, 17 Oct 2022 16:22:36 -0400
Subject: [PATCH 01/21] net: fman: memac: Add serdes support
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>
---
.../net/ethernet/freescale/fman/fman_memac.c | 49 ++++++++++++++++++-
1 file changed, 47 insertions(+), 2 deletions(-)
--- a/drivers/net/ethernet/freescale/fman/fman_memac.c
+++ b/drivers/net/ethernet/freescale/fman/fman_memac.c
@@ -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_devi
}
}
+ 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_devi
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: