Skip to content
/ linux Public
forked from torvalds/linux

Commit

Permalink
net: ethernet: ti: am65-cpsw: Add support for SERDES configuration
Browse files Browse the repository at this point in the history
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: Siddharth Vadapalli <s-vadapalli@ti.com>
Signed-off-by: Paolo Abeni <pabeni@redhat.com>
  • Loading branch information
Siddharth-Vadapalli-at-TI authored and Paolo Abeni committed Jan 5, 2023
1 parent 944131f commit dab2b26
Show file tree
Hide file tree
Showing 2 changed files with 69 additions and 0 deletions.
68 changes: 68 additions & 0 deletions drivers/net/ethernet/ti/am65-cpsw-nuss.c
Original file line number Diff line number Diff line change
Expand Up @@ -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)
{
Expand Down Expand Up @@ -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");

Expand Down Expand Up @@ -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);

Expand Down
1 change: 1 addition & 0 deletions drivers/net/ethernet/ti/am65-cpsw-nuss.h
Original file line number Diff line number Diff line change
Expand Up @@ -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];
Expand Down

0 comments on commit dab2b26

Please sign in to comment.