]> www.infradead.org Git - users/jedix/linux-maple.git/commitdiff
net: ti: icssg-prueth: Add support for half duplex operation
authorMD Danish Anwar <danishanwar@ti.com>
Wed, 13 Sep 2023 09:10:11 +0000 (14:40 +0530)
committerDavid S. Miller <davem@davemloft.net>
Fri, 15 Sep 2023 12:54:34 +0000 (13:54 +0100)
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>
drivers/net/ethernet/ti/icssg/icssg_config.c
drivers/net/ethernet/ti/icssg/icssg_prueth.c
drivers/net/ethernet/ti/icssg/icssg_prueth.h

index 933b846665749d28327414ac6542b0e039bc1445..c1da70f247d49901472c54e2732de0bdde727307 100644 (file)
@@ -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;
@@ -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);
 }
index 92b13057d4debde67a358ea72ba308859e0f0d33..6635b28bc672abc8230f2958da38208e4ad2b76b 100644 (file)
@@ -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);
 
@@ -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);
@@ -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;
        }
 
@@ -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;
        }
 
index 3fe80a8758d303d8b1f34c9a73b220923663c480..8b6d6b497010c2ec13d14b8e66f6dc40981921d5 100644 (file)
@@ -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];
@@ -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);