Commit dab2b265 authored by Siddharth Vadapalli's avatar Siddharth Vadapalli Committed by Paolo Abeni
Browse files

net: ethernet: ti: am65-cpsw: Add support for SERDES configuration



Use PHY framework APIs to initialize the SERDES PHY connected to CPSW MAC.

Define the functions am65_cpsw_disable_phy(), am65_cpsw_enable_phy(),
am65_cpsw_disable_serdes_phy() and am65_cpsw_enable_serdes_phy().

Add new member "serdes_phy" to struct "am65_cpsw_slave_data" to store the
SERDES PHY for each port, if it exists. Use it later while disabling the
SERDES PHY for each port.

Power on and initialize the SerDes PHY in am65_cpsw_nuss_init_slave_ports()
by invoking am65_cpsw_enable_serdes_phy().

Power off the SerDes PHY in am65_cpsw_nuss_remove() by invoking
am65_cpsw_disable_serdes_phy().

Signed-off-by: default avatarSiddharth Vadapalli <s-vadapalli@ti.com>
Signed-off-by: default avatarPaolo Abeni <pabeni@redhat.com>
parent 944131fa
Loading
Loading
Loading
Loading
+68 −0
Original line number Diff line number Diff line
@@ -1416,6 +1416,68 @@ static const struct net_device_ops am65_cpsw_nuss_netdev_ops = {
	.ndo_setup_tc           = am65_cpsw_qos_ndo_setup_tc,
};

static void am65_cpsw_disable_phy(struct phy *phy)
{
	phy_power_off(phy);
	phy_exit(phy);
}

static int am65_cpsw_enable_phy(struct phy *phy)
{
	int ret;

	ret = phy_init(phy);
	if (ret < 0)
		return ret;

	ret = phy_power_on(phy);
	if (ret < 0) {
		phy_exit(phy);
		return ret;
	}

	return 0;
}

static void am65_cpsw_disable_serdes_phy(struct am65_cpsw_common *common)
{
	struct am65_cpsw_port *port;
	struct phy *phy;
	int i;

	for (i = 0; i < common->port_num; i++) {
		port = &common->ports[i];
		phy = port->slave.serdes_phy;
		if (phy)
			am65_cpsw_disable_phy(phy);
	}
}

static int am65_cpsw_init_serdes_phy(struct device *dev, struct device_node *port_np,
				     struct am65_cpsw_port *port)
{
	const char *name = "serdes-phy";
	struct phy *phy;
	int ret;

	phy = devm_of_phy_get(dev, port_np, name);
	if (PTR_ERR(phy) == -ENODEV)
		return 0;

	/* Serdes PHY exists. Store it. */
	port->slave.serdes_phy = phy;

	ret =  am65_cpsw_enable_phy(phy);
	if (ret < 0)
		goto err_phy;

	return 0;

err_phy:
	devm_phy_put(dev, phy);
	return ret;
}

static void am65_cpsw_nuss_mac_config(struct phylink_config *config, unsigned int mode,
				      const struct phylink_link_state *state)
{
@@ -1959,6 +2021,11 @@ static int am65_cpsw_nuss_init_slave_ports(struct am65_cpsw_common *common)
			goto of_node_put;
		}

		/* Initialize the Serdes PHY for the port */
		ret = am65_cpsw_init_serdes_phy(dev, port_np, port);
		if (ret)
			return ret;

		port->slave.mac_only =
				of_property_read_bool(port_np, "ti,mac-only");

@@ -2878,6 +2945,7 @@ static int am65_cpsw_nuss_remove(struct platform_device *pdev)
	 */
	am65_cpsw_nuss_cleanup_ndev(common);
	am65_cpsw_nuss_phylink_cleanup(common);
	am65_cpsw_disable_serdes_phy(common);

	of_platform_device_destroy(common->mdio_dev, NULL);

+1 −0
Original line number Diff line number Diff line
@@ -32,6 +32,7 @@ struct am65_cpsw_slave_data {
	struct device_node		*phy_node;
	phy_interface_t			phy_if;
	struct phy			*ifphy;
	struct phy			*serdes_phy;
	bool				rx_pause;
	bool				tx_pause;
	u8				mac_addr[ETH_ALEN];