Skip to content

Commit

Permalink
net: ti: icssg-prueth: Add support for half duplex operation
Browse files Browse the repository at this point in the history
This patch adds support for half duplex operation at 10M and 100M link
speeds for AM654x/AM64x devices.
- Driver configures rand_seed, a random number, in DMEM HD_RAND_SEED_OFFSET
field, which will be used by firmware for Back off time calculation.
- Driver informs FW about half duplex link operation in DMEM
PORT_LINK_SPEED_OFFSET field by setting bit 7 for 10/100M HD.

Hence, the half duplex operation depends on board design the
"ti,half-duplex-capable" property has to be enabled for ICSS-G ports if HW
is capable to perform half duplex.

Reviewed-by: Andrew Lunn <andrew@lunn.ch>
Reviewed-by: Roger Quadros <rogerq@kernel.org>
Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
  • Loading branch information
MD Danish Anwar authored and David S. Miller committed Sep 15, 2023
1 parent 927c568 commit 0a205f0
Show file tree
Hide file tree
Showing 3 changed files with 31 additions and 2 deletions.
14 changes: 14 additions & 0 deletions drivers/net/ethernet/ti/icssg/icssg_config.c
Original file line number Diff line number Diff line change
Expand Up @@ -433,6 +433,17 @@ int emac_set_port_state(struct prueth_emac *emac,
return ret;
}

void icssg_config_half_duplex(struct prueth_emac *emac)
{
u32 val;

if (!emac->half_duplex)
return;

val = get_random_u32();
writel(val, emac->dram.va + HD_RAND_SEED_OFFSET);
}

void icssg_config_set_speed(struct prueth_emac *emac)
{
u8 fw_speed;
Expand All @@ -453,5 +464,8 @@ void icssg_config_set_speed(struct prueth_emac *emac)
return;
}

if (emac->duplex == DUPLEX_HALF)
fw_speed |= FW_LINK_SPEED_HD;

writeb(fw_speed, emac->dram.va + PORT_LINK_SPEED_OFFSET);
}
17 changes: 15 additions & 2 deletions drivers/net/ethernet/ti/icssg/icssg_prueth.c
Original file line number Diff line number Diff line change
Expand Up @@ -1029,6 +1029,8 @@ static void emac_adjust_link(struct net_device *ndev)
* values
*/
if (emac->link) {
if (emac->duplex == DUPLEX_HALF)
icssg_config_half_duplex(emac);
/* Set the RGMII cfg for gig en and full duplex */
icssg_update_rgmii_cfg(prueth->miig_rt, emac);

Expand Down Expand Up @@ -1147,9 +1149,13 @@ static int emac_phy_connect(struct prueth_emac *emac)
return -ENODEV;
}

if (!emac->half_duplex) {
dev_dbg(prueth->dev, "half duplex mode is not supported\n");
phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
}

/* remove unsupported modes */
phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_100baseT_Half_BIT);
phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_1000baseT_Half_BIT);
phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_Pause_BIT);
phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_Asym_Pause_BIT);
Expand Down Expand Up @@ -2113,6 +2119,10 @@ static int prueth_probe(struct platform_device *pdev)
eth0_node->name);
goto exit_iep;
}

if (of_find_property(eth0_node, "ti,half-duplex-capable", NULL))
prueth->emac[PRUETH_MAC0]->half_duplex = 1;

prueth->emac[PRUETH_MAC0]->iep = prueth->iep0;
}

Expand All @@ -2124,6 +2134,9 @@ static int prueth_probe(struct platform_device *pdev)
goto netdev_exit;
}

if (of_find_property(eth1_node, "ti,half-duplex-capable", NULL))
prueth->emac[PRUETH_MAC1]->half_duplex = 1;

prueth->emac[PRUETH_MAC1]->iep = prueth->iep0;
}

Expand Down
2 changes: 2 additions & 0 deletions drivers/net/ethernet/ti/icssg/icssg_prueth.h
Original file line number Diff line number Diff line change
Expand Up @@ -145,6 +145,7 @@ struct prueth_emac {
struct icss_iep *iep;
unsigned int rx_ts_enabled : 1;
unsigned int tx_ts_enabled : 1;
unsigned int half_duplex : 1;

/* DMA related */
struct prueth_tx_chn tx_chns[PRUETH_MAX_TX_QUEUES];
Expand Down Expand Up @@ -271,6 +272,7 @@ int icssg_config(struct prueth *prueth, struct prueth_emac *emac,
int emac_set_port_state(struct prueth_emac *emac,
enum icssg_port_state_cmd state);
void icssg_config_set_speed(struct prueth_emac *emac);
void icssg_config_half_duplex(struct prueth_emac *emac);

/* Buffer queue helpers */
int icssg_queue_pop(struct prueth *prueth, u8 queue);
Expand Down

0 comments on commit 0a205f0

Please sign in to comment.