net: ti: icssg-prueth: am65x SR2.0 add 10M full duplex support
authorGrygorii Strashko <grygorii.strashko@ti.com>
Thu, 24 Aug 2023 11:46:18 +0000 (17:16 +0530)
committerDavid S. Miller <davem@davemloft.net>
Sun, 27 Aug 2023 06:13:24 +0000 (07:13 +0100)
For AM65x SR2.0 it's required to enable IEP1 in raw 64bit mode which is
used by PRU FW to monitor the link and apply w/a for 10M link issue.
Note. No public errata available yet.

Without this w/a the PRU FW will stuck if link state changes under TX
traffic pressure.

Hence, add support for 10M full duplex for AM65x SR2.0:
 - add new IEP API to enable IEP, but without PTP support
 - add pdata quirk_10m_link_issue to enable 10M link issue w/a.

Signed-off-by: Grygorii Strashko <grygorii.strashko@ti.com>
Signed-off-by: Vignesh Raghavendra <vigneshr@ti.com>
Reviewed-by: Roger Quadros <rogerq@kernel.org>
Reviewed-by: Simon Horman <horms@kernel.org>
Reviewed-by: Jacob Keller <jacob.e.keller@intel.com>
Signed-off-by: MD Danish Anwar <danishanwar@ti.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
drivers/net/ethernet/ti/icssg/icss_iep.c
drivers/net/ethernet/ti/icssg/icss_iep.h
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 bcc056b..4cf2a52 100644 (file)
@@ -727,6 +727,32 @@ void icss_iep_put(struct icss_iep *iep)
 }
 EXPORT_SYMBOL_GPL(icss_iep_put);
 
+void icss_iep_init_fw(struct icss_iep *iep)
+{
+       /* start IEP for FW use in raw 64bit mode, no PTP support */
+       iep->clk_tick_time = iep->def_inc;
+       iep->cycle_time_ns = 0;
+       iep->ops = NULL;
+       iep->clockops_data = NULL;
+       icss_iep_set_default_inc(iep, iep->def_inc);
+       icss_iep_set_compensation_inc(iep, iep->def_inc);
+       icss_iep_set_compensation_count(iep, 0);
+       regmap_write(iep->map, ICSS_IEP_SYNC_PWIDTH_REG, iep->refclk_freq / 10); /* 100 ms pulse */
+       regmap_write(iep->map, ICSS_IEP_SYNC0_PERIOD_REG, 0);
+       if (iep->plat_data->flags & ICSS_IEP_SLOW_COMPEN_REG_SUPPORT)
+               icss_iep_set_slow_compensation_count(iep, 0);
+
+       icss_iep_enable(iep);
+       icss_iep_settime(iep, 0);
+}
+EXPORT_SYMBOL_GPL(icss_iep_init_fw);
+
+void icss_iep_exit_fw(struct icss_iep *iep)
+{
+       icss_iep_disable(iep);
+}
+EXPORT_SYMBOL_GPL(icss_iep_exit_fw);
+
 int icss_iep_init(struct icss_iep *iep, const struct icss_iep_clockops *clkops,
                  void *clockops_data, u32 cycle_time_ns)
 {
index 9c7f4d0..803a4b7 100644 (file)
@@ -35,5 +35,7 @@ int icss_iep_exit(struct icss_iep *iep);
 int icss_iep_get_count_low(struct icss_iep *iep);
 int icss_iep_get_count_hi(struct icss_iep *iep);
 int icss_iep_get_ptp_clock_idx(struct icss_iep *iep);
+void icss_iep_init_fw(struct icss_iep *iep);
+void icss_iep_exit_fw(struct icss_iep *iep);
 
 #endif /* __NET_TI_ICSS_IEP_H */
index ab648d3..933b846 100644 (file)
@@ -210,6 +210,10 @@ void icssg_config_ipg(struct prueth_emac *emac)
        case SPEED_100:
                icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M);
                break;
+       case SPEED_10:
+               /* IPG for 10M is same as 100M */
+               icssg_mii_update_ipg(prueth->mii_rt, slice, MII_RT_TX_IPG_100M);
+               break;
        default:
                /* Other links speeds not supported */
                netdev_err(emac->ndev, "Unsupported link speed\n");
@@ -440,6 +444,9 @@ void icssg_config_set_speed(struct prueth_emac *emac)
        case SPEED_100:
                fw_speed = FW_LINK_SPEED_100M;
                break;
+       case SPEED_10:
+               fw_speed = FW_LINK_SPEED_10M;
+               break;
        default:
                /* Other links speeds not supported */
                netdev_err(emac->ndev, "Unsupported link speed\n");
index 1bcb4e1..410612f 100644 (file)
@@ -1149,7 +1149,6 @@ static int emac_phy_connect(struct prueth_emac *emac)
 
        /* remove unsupported modes */
        phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_10baseT_Half_BIT);
-       phy_remove_link_mode(ndev->phydev, ETHTOOL_LINK_MODE_10baseT_Full_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);
@@ -2090,13 +2089,29 @@ static int prueth_probe(struct platform_device *pdev)
                goto free_pool;
        }
 
+       prueth->iep1 = icss_iep_get_idx(np, 1);
+       if (IS_ERR(prueth->iep1)) {
+               ret = dev_err_probe(dev, PTR_ERR(prueth->iep1), "iep1 get failed\n");
+               icss_iep_put(prueth->iep0);
+               prueth->iep0 = NULL;
+               prueth->iep1 = NULL;
+               goto free_pool;
+       }
+
+       if (prueth->pdata.quirk_10m_link_issue) {
+               /* Enable IEP1 for FW in 64bit mode as W/A for 10M FD link detect issue under TX
+                * traffic.
+                */
+               icss_iep_init_fw(prueth->iep1);
+       }
+
        /* setup netdev interfaces */
        if (eth0_node) {
                ret = prueth_netdev_init(prueth, eth0_node);
                if (ret) {
                        dev_err_probe(dev, ret, "netdev init %s failed\n",
                                      eth0_node->name);
-                       goto netdev_exit;
+                       goto exit_iep;
                }
                prueth->emac[PRUETH_MAC0]->iep = prueth->iep0;
        }
@@ -2167,6 +2182,10 @@ netdev_exit:
                prueth_netdev_exit(prueth, eth_node);
        }
 
+exit_iep:
+       if (prueth->pdata.quirk_10m_link_issue)
+               icss_iep_exit_fw(prueth->iep1);
+
 free_pool:
        gen_pool_free(prueth->sram_pool,
                      (unsigned long)prueth->msmcram.va, msmc_ram_size);
@@ -2212,6 +2231,10 @@ static void prueth_remove(struct platform_device *pdev)
                prueth_netdev_exit(prueth, eth_node);
        }
 
+       if (prueth->pdata.quirk_10m_link_issue)
+               icss_iep_exit_fw(prueth->iep1);
+
+       icss_iep_put(prueth->iep1);
        icss_iep_put(prueth->iep0);
 
        gen_pool_free(prueth->sram_pool,
index a56ab4c..3fe80a8 100644 (file)
@@ -208,6 +208,7 @@ struct prueth_pdata {
  * @icssg_hwcmdseq: seq counter or HWQ messages
  * @emacs_initialized: num of EMACs/ext ports that are up/running
  * @iep0: pointer to IEP0 device
+ * @iep1: pointer to IEP1 device
  */
 struct prueth {
        struct device *dev;
@@ -231,6 +232,7 @@ struct prueth {
        u8 icssg_hwcmdseq;
        int emacs_initialized;
        struct icss_iep *iep0;
+       struct icss_iep *iep1;
 };
 
 struct emac_tx_ts_response {