Commit 7a86be6a authored by Russell King (Oracle)'s avatar Russell King (Oracle) Committed by David S. Miller
Browse files

net: axienet: convert to phylink_pcs



Convert axienet to use the phylink_pcs layer, resulting in it no longer
being a legacy driver.

Signed-off-by: default avatarRussell King (Oracle) <rmk+kernel@armlinux.org.uk>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 71f390f5
Loading
Loading
Loading
Loading
+2 −0
Original line number Diff line number Diff line
@@ -386,6 +386,7 @@ struct axidma_bd {
 * @phylink:	Pointer to phylink instance
 * @phylink_config: phylink configuration settings
 * @pcs_phy:	Reference to PCS/PMA PHY if used
 * @pcs:	phylink pcs structure for PCS PHY
 * @switch_x_sgmii: Whether switchable 1000BaseX/SGMII mode is enabled in the core
 * @axi_clk:	AXI4-Lite bus clock
 * @misc_clks:	Misc ethernet clocks (AXI4-Stream, Ref, MGT clocks)
@@ -434,6 +435,7 @@ struct axienet_local {
	struct phylink_config phylink_config;

	struct mdio_device *pcs_phy;
	struct phylink_pcs pcs;

	bool switch_x_sgmii;

+53 −54
Original line number Diff line number Diff line
@@ -1537,78 +1537,79 @@ static const struct ethtool_ops axienet_ethtool_ops = {
	.nway_reset	= axienet_ethtools_nway_reset,
};

static void axienet_mac_pcs_get_state(struct phylink_config *config,
static struct axienet_local *pcs_to_axienet_local(struct phylink_pcs *pcs)
{
	return container_of(pcs, struct axienet_local, pcs);
}

static void axienet_pcs_get_state(struct phylink_pcs *pcs,
				  struct phylink_link_state *state)
{
	struct net_device *ndev = to_net_dev(config->dev);
	struct axienet_local *lp = netdev_priv(ndev);
	struct mdio_device *pcs_phy = pcs_to_axienet_local(pcs)->pcs_phy;

	switch (state->interface) {
	case PHY_INTERFACE_MODE_SGMII:
	case PHY_INTERFACE_MODE_1000BASEX:
		phylink_mii_c22_pcs_get_state(lp->pcs_phy, state);
		break;
	default:
		break;
	}
	phylink_mii_c22_pcs_get_state(pcs_phy, state);
}

static void axienet_mac_an_restart(struct phylink_config *config)
static void axienet_pcs_an_restart(struct phylink_pcs *pcs)
{
	struct net_device *ndev = to_net_dev(config->dev);
	struct axienet_local *lp = netdev_priv(ndev);
	struct mdio_device *pcs_phy = pcs_to_axienet_local(pcs)->pcs_phy;

	phylink_mii_c22_pcs_an_restart(lp->pcs_phy);
	phylink_mii_c22_pcs_an_restart(pcs_phy);
}

static int axienet_mac_prepare(struct phylink_config *config, unsigned int mode,
			       phy_interface_t iface)
static int axienet_pcs_config(struct phylink_pcs *pcs, unsigned int mode,
			      phy_interface_t interface,
			      const unsigned long *advertising,
			      bool permit_pause_to_mac)
{
	struct net_device *ndev = to_net_dev(config->dev);
	struct mdio_device *pcs_phy = pcs_to_axienet_local(pcs)->pcs_phy;
	struct net_device *ndev = pcs_to_axienet_local(pcs)->ndev;
	struct axienet_local *lp = netdev_priv(ndev);
	int ret;

	switch (iface) {
	case PHY_INTERFACE_MODE_SGMII:
	case PHY_INTERFACE_MODE_1000BASEX:
		if (!lp->switch_x_sgmii)
			return 0;

		ret = mdiobus_write(lp->pcs_phy->bus,
				    lp->pcs_phy->addr,
	if (lp->switch_x_sgmii) {
		ret = mdiobus_write(pcs_phy->bus, pcs_phy->addr,
				    XLNX_MII_STD_SELECT_REG,
				    iface == PHY_INTERFACE_MODE_SGMII ?
				    interface == PHY_INTERFACE_MODE_SGMII ?
					XLNX_MII_STD_SELECT_SGMII : 0);
		if (ret < 0)
			netdev_warn(ndev, "Failed to switch PHY interface: %d\n",
		if (ret < 0) {
			netdev_warn(ndev,
				    "Failed to switch PHY interface: %d\n",
				    ret);
			return ret;
	default:
		return 0;
		}
	}

static void axienet_mac_config(struct phylink_config *config, unsigned int mode,
			       const struct phylink_link_state *state)
	ret = phylink_mii_c22_pcs_config(pcs_phy, mode, interface, advertising);
	if (ret < 0)
		netdev_warn(ndev, "Failed to configure PCS: %d\n", ret);

	return ret;
}

static const struct phylink_pcs_ops axienet_pcs_ops = {
	.pcs_get_state = axienet_pcs_get_state,
	.pcs_config = axienet_pcs_config,
	.pcs_an_restart = axienet_pcs_an_restart,
};

static struct phylink_pcs *axienet_mac_select_pcs(struct phylink_config *config,
						  phy_interface_t interface)
{
	struct net_device *ndev = to_net_dev(config->dev);
	struct axienet_local *lp = netdev_priv(ndev);
	int ret;

	switch (state->interface) {
	case PHY_INTERFACE_MODE_SGMII:
	case PHY_INTERFACE_MODE_1000BASEX:
		ret = phylink_mii_c22_pcs_config(lp->pcs_phy, mode,
						 state->interface,
						 state->advertising);
		if (ret < 0)
			netdev_warn(ndev, "Failed to configure PCS: %d\n",
				    ret);
		break;
	if (interface == PHY_INTERFACE_MODE_1000BASEX ||
	    interface ==  PHY_INTERFACE_MODE_SGMII)
		return &lp->pcs;

	default:
		break;
	return NULL;
}

static void axienet_mac_config(struct phylink_config *config, unsigned int mode,
			       const struct phylink_link_state *state)
{
	/* nothing meaningful to do */
}

static void axienet_mac_link_down(struct phylink_config *config,
@@ -1663,9 +1664,7 @@ static void axienet_mac_link_up(struct phylink_config *config,

static const struct phylink_mac_ops axienet_phylink_ops = {
	.validate = phylink_generic_validate,
	.mac_pcs_get_state = axienet_mac_pcs_get_state,
	.mac_an_restart = axienet_mac_an_restart,
	.mac_prepare = axienet_mac_prepare,
	.mac_select_pcs = axienet_mac_select_pcs,
	.mac_config = axienet_mac_config,
	.mac_link_down = axienet_mac_link_down,
	.mac_link_up = axienet_mac_link_up,
@@ -2079,12 +2078,12 @@ static int axienet_probe(struct platform_device *pdev)
			ret = -EPROBE_DEFER;
			goto cleanup_mdio;
		}
		lp->phylink_config.pcs_poll = true;
		lp->pcs.ops = &axienet_pcs_ops;
		lp->pcs.poll = true;
	}

	lp->phylink_config.dev = &ndev->dev;
	lp->phylink_config.type = PHYLINK_NETDEV;
	lp->phylink_config.legacy_pre_march2020 = true;
	lp->phylink_config.mac_capabilities = MAC_SYM_PAUSE | MAC_ASYM_PAUSE |
		MAC_10FD | MAC_100FD | MAC_1000FD;