net: ti: icssg-prueth: am65x SR2.0 add 10M full duplex support

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>
This commit is contained in:
Grygorii Strashko 2023-08-24 17:16:18 +05:30 committed by David S. Miller
parent 186734c158
commit 443a2367ba
5 changed files with 62 additions and 2 deletions

View 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)
{

View 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 */

View 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");

View 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,

View 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 {