Commit 0fc83bd7 authored by Sean Anderson's avatar Sean Anderson Committed by David S. Miller
Browse files

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: default avatarSean Anderson <sean.anderson@seco.com>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent f392a184
Loading
Loading
Loading
Loading
+47 −2
Original line number Diff line number Diff line
@@ -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: