nvethernet: Set MGBE TX, TX_PCS and MAC_DIV clks

There are three clks for MGBE which needs to be set based
on UPHY GBE mode and PHY line rate.

o MGBE_MAC_DIV_CLK will be set based on PHY line rate
o MGBE_MAC_TX/TX_PCS clks will be set based on UPHY GBE mode

Below are the settings -

UPHY GBE mode = 10G:
===================
Possible MAC working rates: 10G/5G/2.5G
1) MAC DIVISOR: 312.5MHz, 312.5/2MHZ and 312.5/4MHz
2) TX CLK: 644.5MHZ
3) TX PCS_CLK: 156.5MHz

UPHY GBE mode = 5G:
==================
Possible MAC working rates: 5G/2.5G
1) MAC DIVISOR: 312.5/2MHz and 312.5/4MHz
2) TX CLK: 322.2MHZ
3) TX PCS_CLK: 78.125MHz

Bug 200739493

Change-Id: Ie6b21f87d2077b8be621a32b2034b4eff1eb391e
Signed-off-by: Bhadram Varka <vbhadram@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nvidia/+/2541313
Reviewed-by: Rakesh Goyal <rgoyal@nvidia.com>
Reviewed-by: svcacv <svcacv@nvidia.com>
Reviewed-by: svc_kernel_abi <svc_kernel_abi@nvidia.com>
Reviewed-by: Narayan Reddy <narayanr@nvidia.com>
GVS: Gerrit_Virtual_Submit
This commit is contained in:
Bhadram Varka
2021-06-08 18:52:17 +05:30
committed by Revanth Kumar Uppala
parent 8553696ea7
commit 537d6aa16b
2 changed files with 116 additions and 13 deletions

104
drivers/net/ethernet/nvidia/nvethernet/ether_linux.c Executable file → Normal file
View File

@@ -350,6 +350,8 @@ static void ether_disable_clks(struct ether_priv_data *pdata)
*/
static int ether_enable_mgbe_clks(struct ether_priv_data *pdata)
{
unsigned int uphy_gbe_mode = pdata->osi_core->uphy_gbe_mode;
unsigned long rate = 0;
int ret;
if (!IS_ERR_OR_NULL(pdata->rx_m_clk)) {
@@ -381,6 +383,17 @@ static int ether_enable_mgbe_clks(struct ether_priv_data *pdata)
}
if (!IS_ERR_OR_NULL(pdata->tx_clk)) {
if (uphy_gbe_mode == OSI_ENABLE)
rate = ETHER_MGBE_TX_CLK_USXGMII_10G;
else
rate = ETHER_MGBE_TX_CLK_USXGMII_5G;
ret = clk_set_rate(pdata->tx_clk, rate);
if (ret < 0) {
dev_err(pdata->dev, "failed to set MGBE tx_clk rate\n");
goto err_tx;
}
ret = clk_prepare_enable(pdata->tx_clk);
if (ret < 0) {
goto err_tx;
@@ -388,6 +401,18 @@ static int ether_enable_mgbe_clks(struct ether_priv_data *pdata)
}
if (!IS_ERR_OR_NULL(pdata->tx_pcs_clk)) {
if (uphy_gbe_mode == OSI_ENABLE)
rate = ETHER_MGBE_TX_PCS_CLK_USXGMII_10G;
else
rate = ETHER_MGBE_TX_PCS_CLK_USXGMII_5G;
ret = clk_set_rate(pdata->tx_pcs_clk, rate);
if (ret < 0) {
dev_err(pdata->dev,
"failed to set MGBE tx_pcs_clk rate\n");
goto err_tx_pcs;
}
ret = clk_prepare_enable(pdata->tx_pcs_clk);
if (ret < 0) {
goto err_tx_pcs;
@@ -649,6 +674,64 @@ int ether_conf_eee(struct ether_priv_data *pdata, unsigned int tx_lpi_enable)
return ret;
}
/**
* @brief Set MGBE MAC_DIV/TX clk rate
*
* Algorithm: Sets MGBE MAC_DIV clk_rate which will be MAC_TX/MACSEC clk rate.
*
* @param[in] mac_div_clk: Pointer to MAC_DIV clk.
* @param[in] speed: PHY line speed.
*/
static inline void ether_set_mgbe_mac_div_rate(struct clk *mac_div_clk,
int speed)
{
unsigned long rate;
switch (speed) {
case SPEED_2500:
rate = ETHER_MGBE_MAC_DIV_RATE_2_5G;
break;
case SPEED_5000:
rate = ETHER_MGBE_MAC_DIV_RATE_5G;
break;
case SPEED_10000:
default:
rate = ETHER_MGBE_MAC_DIV_RATE_10G;
break;
}
if (clk_set_rate(mac_div_clk, rate) < 0)
pr_err("%s(): failed to set mac_div_clk rate\n", __func__);
}
/**
* @brief Set EQOS TX clk rate
*
* @param[in] tx_clk: Pointer to Tx clk.
* @param[in] speed: PHY line speed.
*/
static inline void ether_set_eqos_tx_clk(struct clk *tx_clk,
int speed)
{
unsigned long rate;
switch (speed) {
case SPEED_10:
rate = ETHER_EQOS_TX_CLK_10M;
break;
case SPEED_100:
rate = ETHER_EQOS_TX_CLK_100M;
break;
case SPEED_1000:
default:
rate = ETHER_EQOS_TX_CLK_1000M;
break;
}
if (clk_set_rate(tx_clk, rate) < 0)
pr_err("%s(): failed to set eqos tx_clk rate\n", __func__);
}
/**
* @brief Adjust link call back
*
@@ -736,19 +819,22 @@ static void ether_adjust_link(struct net_device *dev)
}
if (speed_changed) {
clk_set_rate(pdata->tx_clk,
(phydev->speed == SPEED_10) ? 2500 * 1000 :
(phydev->speed ==
SPEED_100) ? 25000 * 1000 : 125000 * 1000);
if (pdata->osi_core->mac == OSI_MAC_HW_MGBE) {
ether_set_mgbe_mac_div_rate(pdata->mac_div_clk,
phydev->speed);
} else {
ether_set_eqos_tx_clk(pdata->tx_clk,
phydev->speed);
if (phydev->speed != SPEED_10) {
ioctl_data.cmd = OSI_CMD_PAD_CALIBRATION;
if (osi_handle_ioctl(pdata->osi_core, &ioctl_data) <
0) {
if (osi_handle_ioctl(pdata->osi_core,
&ioctl_data) < 0) {
dev_err(pdata->dev,
"failed to do pad caliberation\n");
}
}
}
}
/* Configure EEE if it is enabled */
if (pdata->eee_enabled && pdata->tx_lpi_enabled) {
@@ -5227,6 +5313,12 @@ static int ether_parse_dt(struct ether_priv_data *pdata)
"failed to read UPHY GBE mode - default to 10G\n");
osi_core->uphy_gbe_mode = OSI_ENABLE;
}
if ((osi_core->uphy_gbe_mode != OSI_ENABLE) &&
(osi_core->uphy_gbe_mode != OSI_DISABLE)) {
dev_err(dev, "Invalid UPHY GBE mode - default to 10G\n");
osi_core->uphy_gbe_mode = OSI_ENABLE;
}
}
/* Enable VLAN strip by default */

View File

@@ -100,10 +100,21 @@
#define ETHER_DFLT_PTP_CLK 312500000U
/**
* @brief Ethernet default Rx Input clock frequency
* @brief Ethernet clk rates
*/
#define ETHER_RX_INPUT_CLK_RATE 125000000U
#define ETHER_RX_INPUT_CLK_RATE 125000000UL
#define ETHER_MGBE_MAC_DIV_RATE_10G 312500000UL
#define ETHER_MGBE_MAC_DIV_RATE_5G 156250000UL
#define ETHER_MGBE_MAC_DIV_RATE_2_5G 78125000UL
// gbe_pll2_txclkref (644 MHz) --> programmable link TX_CLK divider
// --> link_Tx_clk --> fixed 1/2 gear box divider --> lane TX clk.
#define ETHER_MGBE_TX_CLK_USXGMII_10G 644531250UL
#define ETHER_MGBE_TX_CLK_USXGMII_5G 322265625UL
#define ETHER_MGBE_TX_PCS_CLK_USXGMII_10G 156250000UL
#define ETHER_MGBE_TX_PCS_CLK_USXGMII_5G 78125000UL
#define ETHER_EQOS_TX_CLK_1000M 125000000UL
#define ETHER_EQOS_TX_CLK_100M 25000000UL
#define ETHER_EQOS_TX_CLK_10M 2500000UL
/**
* @addtogroup CONFIG Ethernet configuration error codes
*