nvethernet: Set the mac clk rate in driver

1) Setting mac clk rate correctly in driver
2) Set speed correctly if phy_iface_mode set to USX-5G/USX-10G
3) Set the mgbe/eqos rx clocks during interface up

Bug 4874956
Bug 4872381
Bug 4745869

Change-Id: Ie3c39f44b713661e10a4fb20090c26d09667beea
Signed-off-by: Mahesh Patil <maheshp@nvidia.com>
Reviewed-on: https://git-master.nvidia.com/r/c/linux-nv-oot/+/3216075
Reviewed-by: Srinivas Ramachandran <srinivasra@nvidia.com>
Reviewed-by: Michael Hsu <mhsu@nvidia.com>
GVS: buildbot_gerritrpt <buildbot_gerritrpt@nvidia.com>
This commit is contained in:
Mahesh Patil
2024-09-20 23:51:52 +00:00
committed by Jon Hunter
parent 2d1629804e
commit a1291a7323

View File

@@ -540,6 +540,63 @@ static void ether_disable_clks(struct ether_priv_data *pdata)
}
}
/**
* @brief Set clk rates for mgbe#_rx_input/mgbe#_rx_pcs_input
*
* Algorithm: Sets clk rates based on UPHY GBE mode for
* mgbe#_rx_input/mgbe#_rx_pcs_input clk ID's.
*
* @param[in] pdata: OSD private data.
*
* @retval 0 on success
* @retval "negative value" on failure.
*/
static int ether_set_mgbe_rx_clk_rates(struct ether_priv_data *pdata)
{
unsigned int uphy_gbe_mode = pdata->osi_core->uphy_gbe_mode;
unsigned long rx_rate, rx_pcs_rate, rx_ser_rate;
int ret;
if (uphy_gbe_mode == OSI_GBE_MODE_25G) {
rx_rate = ETHER_MGBE_TXRX_CLK_XAUI_25G;
rx_pcs_rate = ETHER_MGBE_TXRX_PCS_CLK_XAUI_25G;
/* Rx serdes rate same as Rx rate for 25G */
rx_ser_rate = rx_rate;
} else if (uphy_gbe_mode == OSI_GBE_MODE_10G) {
rx_rate = ETHER_MGBE_RX_CLK_USXGMII_10G;
rx_pcs_rate = ETHER_MGBE_RX_PCS_CLK_USXGMII_10G;
/* Rx serdes rate is half of Rx rate in 10G */
rx_ser_rate = (rx_rate / 2);
} else {
rx_rate = ETHER_MGBE_RX_CLK_USXGMII_5G;
rx_pcs_rate = ETHER_MGBE_RX_PCS_CLK_USXGMII_5G;
/* Rx serdes rate is half of Rx rate in 5G */
rx_ser_rate = (rx_rate / 2);
}
ret = clk_set_rate(pdata->rx_input_clk, rx_rate);
if (ret < 0) {
dev_err(pdata->dev, "failed to set rx_input_clk rate\n");
return ret;
}
if (!IS_ERR_OR_NULL(pdata->rx_ser_clk)) {
ret = clk_set_rate(pdata->rx_ser_clk, rx_ser_rate);
if (ret < 0) {
dev_err(pdata->dev, "failed to set MGBE rx_ser_clk rate\n");
return ret;
}
}
ret = clk_set_rate(pdata->rx_pcs_input_clk, rx_pcs_rate);
if (ret < 0) {
dev_err(pdata->dev, "failed to set rx_pcs_input_clk rate\n");
return ret;
}
return 0;
}
/**
* @brief Enable all MAC MGBE related clks.
*
@@ -558,6 +615,11 @@ static int ether_enable_mgbe_clks(struct ether_priv_data *pdata)
unsigned short mac= pdata->osi_core->mac;
struct clk *app_parent_clk;
ret = ether_set_mgbe_rx_clk_rates(pdata);
if (ret < 0)
return ret;
if (!IS_ERR_OR_NULL(pdata->rx_input_clk)) {
ret = clk_prepare_enable(pdata->rx_input_clk);
if (ret < 0) {
@@ -652,6 +714,20 @@ static int ether_enable_mgbe_clks(struct ether_priv_data *pdata)
}
if (!IS_ERR_OR_NULL(pdata->mac_clk)) {
if (mac == OSI_MAC_HW_MGBE_T26X) {
if (uphy_gbe_mode == OSI_GBE_MODE_25G)
rate = ETHER_MGBE_MAC_DIV_RATE_25G;
else if (uphy_gbe_mode == OSI_GBE_MODE_10G)
rate = ETHER_MGBE_MAC_DIV_RATE_10G;
else
rate = ETHER_MGBE_MAC_DIV_RATE_5G;
ret = clk_set_rate(pdata->mac_clk, rate);
if (ret < 0) {
dev_err(pdata->dev,
"failed to set MGBE mac_clk rate\n");
goto err_mac;
}
}
ret = clk_prepare_enable(pdata->mac_clk);
if (ret < 0) {
goto err_mac;
@@ -674,6 +750,11 @@ static int ether_enable_mgbe_clks(struct ether_priv_data *pdata)
rate = ETHER_MGBE_APP_10G_5G_CLK;
}
ret = clk_set_rate(app_parent_clk, rate);
if (ret < 0) {
dev_err(pdata->dev, "failed to set MGBE app_parent_clk rate\n");
goto err_ptp_ref;
}
ret = clk_set_parent(pdata->app_clk, app_parent_clk);
if (ret < 0) {
dev_err(pdata->dev, "failed to set MGBE app_parent_clk\n");
@@ -741,6 +822,49 @@ err_rx_pcs_input:
return ret;
}
static int ether_set_eqos_rx_clk_rates(struct ether_priv_data *pdata)
{
unsigned int uphy_gbe_mode = pdata->osi_core->uphy_gbe_mode;
unsigned long rx_rate, rx_pcs_rate, rx_clk, rx_m_clk;
int ret;
if (uphy_gbe_mode == OSI_GBE_MODE_2_5G) {
rx_rate = ETHER_EQOS_UPHY_LX_RX_2_5G_CLK;
rx_pcs_rate = ETHER_EQOS_RX_PCS_CLK_2_5G;
rx_clk = ETHER_EQOS_UPHY_LX_RX_2_5G_CLK;
rx_m_clk = ETHER_EQOS_UPHY_LX_RX_2_5G_CLK;
} else {
rx_rate = ETHER_EQOS_RX_CLK_1000M;
rx_pcs_rate = ETHER_EQOS_RX_CLK_1000M;
rx_clk = ETHER_EQOS_RX_CLK_1000M;
rx_m_clk = ETHER_EQOS_RX_CLK_1000M;
}
ret = clk_set_rate(pdata->rx_input_clk, rx_rate);
if (ret < 0) {
dev_err(pdata->dev, "failed to set rx_input_clk rate\n");
return ret;
}
ret = clk_set_rate(pdata->rx_pcs_input_clk, rx_pcs_rate);
if (ret < 0) {
dev_err(pdata->dev, "failed to set rx_pcs_input_clk rate\n");
return ret;
}
ret = clk_set_rate(pdata->rx_clk, rx_clk);
if (ret < 0) {
dev_err(pdata->dev, "failed to set rx_clk rate\n");
return ret;
}
ret = clk_set_rate(pdata->rx_m_clk, rx_m_clk);
if (ret < 0) {
dev_err(pdata->dev, "failed to set rx_clk rate\n");
return ret;
}
return 0;
}
/**
* @brief Enable all MAC T26x EQOS related clks.
*
@@ -757,6 +881,12 @@ static int ether_enable_eqos_clks_t26x(struct ether_priv_data *pdata)
unsigned long rate = 0;
int ret;
ret = ether_set_eqos_rx_clk_rates(pdata);
if (ret < 0) {
dev_err(pdata->dev, "failed to set eqos rx clks\n");
return ret;
}
if (!IS_ERR_OR_NULL(pdata->tx_pcs_clk)) {
if (uphy_gbe_mode == OSI_GBE_MODE_2_5G)
rate = ETHER_EQOS_TX_CLK_2_5G;
@@ -1143,11 +1273,13 @@ static inline void set_speed_work_func(struct work_struct *work)
/* Speed will be overwritten as per the PHY interface mode */
speed = phydev->speed;
/* MAC and XFI speed should match in XFI mode */
if (iface_mode == OSI_XFI_MODE_10G) {
/* MAC and XFI/USXGMII speed should match */
if ((iface_mode == OSI_XFI_MODE_10G) ||
(iface_mode == OSI_USXGMII_MODE_10G)) {
/* Set speed to 10G */
speed = OSI_SPEED_10000;
} else if (iface_mode == OSI_XFI_MODE_5G) {
} else if ((iface_mode == OSI_XFI_MODE_5G) ||
(iface_mode == OSI_USXGMII_MODE_5G)) {
/* Set speed to 5G */
speed = OSI_SPEED_5000;
}
@@ -1296,9 +1428,11 @@ static void ether_adjust_link(struct net_device *dev)
/* MGBE 25G don't have USXGMI mode, so set speed based on uphy gbe mode */
if (uphy_gbe_mode == OSI_GBE_MODE_25G) {
phydev->speed = OSI_SPEED_25000;
} else if (iface_mode == OSI_XFI_MODE_10G) {
} else if ((iface_mode == OSI_XFI_MODE_10G) ||
(iface_mode == OSI_USXGMII_MODE_10G)) {
phydev->speed = OSI_SPEED_10000;
} else if (iface_mode == OSI_XFI_MODE_5G) {
} else if ((iface_mode == OSI_XFI_MODE_5G) ||
(iface_mode == OSI_USXGMII_MODE_5G)) {
phydev->speed = OSI_SPEED_5000;
}
} else if (mac_ver == OSI_EQOS_MAC_5_40) {
@@ -5527,63 +5661,6 @@ static inline void ether_put_clks(struct ether_priv_data *pdata)
}
}
/**
* @brief Set clk rates for mgbe#_rx_input/mgbe#_rx_pcs_input
*
* Algorithm: Sets clk rates based on UPHY GBE mode for
* mgbe#_rx_input/mgbe#_rx_pcs_input clk ID's.
*
* @param[in] pdata: OSD private data.
*
* @retval 0 on success
* @retval "negative value" on failure.
*/
static int ether_set_mgbe_rx_clk_rates(struct ether_priv_data *pdata)
{
unsigned int uphy_gbe_mode = pdata->osi_core->uphy_gbe_mode;
unsigned long rx_rate, rx_pcs_rate, rx_ser_rate;
int ret;
if (uphy_gbe_mode == OSI_GBE_MODE_25G) {
rx_rate = ETHER_MGBE_TXRX_CLK_XAUI_25G;
rx_pcs_rate = ETHER_MGBE_TXRX_PCS_CLK_XAUI_25G;
/* Rx serdes rate same as Rx rate for 25G */
rx_ser_rate = rx_rate;
} else if (uphy_gbe_mode == OSI_GBE_MODE_10G) {
rx_rate = ETHER_MGBE_RX_CLK_USXGMII_10G;
rx_pcs_rate = ETHER_MGBE_RX_PCS_CLK_USXGMII_10G;
/* Rx serdes rate is half of Rx rate in 10G */
rx_ser_rate = (rx_rate / 2);
} else {
rx_rate = ETHER_MGBE_RX_CLK_USXGMII_5G;
rx_pcs_rate = ETHER_MGBE_RX_PCS_CLK_USXGMII_5G;
/* Rx serdes rate is half of Rx rate in 5G */
rx_ser_rate = (rx_rate / 2);
}
ret = clk_set_rate(pdata->rx_input_clk, rx_rate);
if (ret < 0) {
dev_err(pdata->dev, "failed to set rx_input_clk rate\n");
return ret;
}
if (!IS_ERR_OR_NULL(pdata->rx_ser_clk)) {
ret = clk_set_rate(pdata->rx_ser_clk, rx_ser_rate);
if (ret < 0) {
dev_err(pdata->dev, "failed to set MGBE rx_ser_clk rate\n");
return ret;
}
}
ret = clk_set_rate(pdata->rx_pcs_input_clk, rx_pcs_rate);
if (ret < 0) {
dev_err(pdata->dev, "failed to set rx_pcs_input_clk rate\n");
return ret;
}
return 0;
}
/**
* @brief Get MAC MGBE related clocks.
*
@@ -5719,10 +5796,6 @@ static int ether_get_mgbe_clks(struct ether_priv_data *pdata)
}
}
ret = ether_set_mgbe_rx_clk_rates(pdata);
if (ret < 0)
goto err_rx_input;
return 0;
err_rx_ser_clk:
devm_clk_put(dev, pdata->tx_ser_clk);
@@ -5762,49 +5835,6 @@ err_rx_m:
return ret;
}
static int ether_set_eqos_rx_clk_rates(struct ether_priv_data *pdata)
{
unsigned int uphy_gbe_mode = pdata->osi_core->uphy_gbe_mode;
unsigned long rx_rate, rx_pcs_rate, rx_clk, rx_m_clk;
int ret;
if (uphy_gbe_mode == OSI_GBE_MODE_2_5G) {
rx_rate = ETHER_EQOS_UPHY_LX_RX_2_5G_CLK;
rx_pcs_rate = ETHER_EQOS_RX_PCS_CLK_2_5G;
rx_clk = ETHER_EQOS_UPHY_LX_RX_2_5G_CLK;
rx_m_clk = ETHER_EQOS_UPHY_LX_RX_2_5G_CLK;
} else {
rx_rate = ETHER_EQOS_RX_CLK_1000M;
rx_pcs_rate = ETHER_EQOS_RX_CLK_1000M;
rx_clk = ETHER_EQOS_RX_CLK_1000M;
rx_m_clk = ETHER_EQOS_RX_CLK_1000M;
}
ret = clk_set_rate(pdata->rx_input_clk, rx_rate);
if (ret < 0) {
dev_err(pdata->dev, "failed to set rx_input_clk rate\n");
return ret;
}
ret = clk_set_rate(pdata->rx_pcs_input_clk, rx_pcs_rate);
if (ret < 0) {
dev_err(pdata->dev, "failed to set rx_pcs_input_clk rate\n");
return ret;
}
ret = clk_set_rate(pdata->rx_clk, rx_clk);
if (ret < 0) {
dev_err(pdata->dev, "failed to set rx_clk rate\n");
return ret;
}
ret = clk_set_rate(pdata->rx_m_clk, rx_m_clk);
if (ret < 0) {
dev_err(pdata->dev, "failed to set rx_clk rate\n");
return ret;
}
return 0;
}
/**
* @brief Get EQOS MAC related clocks.
*
@@ -5932,15 +5962,10 @@ static int ether_get_eqos_clks(struct ether_priv_data *pdata)
/* Set default rate to 1G */
if (!IS_ERR_OR_NULL(pdata->rx_input_clk)) {
clk_set_rate(pdata->rx_input_clk,
ret = clk_set_rate(pdata->rx_input_clk,
ETHER_RX_INPUT_CLK_RATE);
}
/* Overwrite the rx clocks for THOR */
if (pdata->osi_core->mac_ver_type == MAC_CORE_VER_TYPE_EQOS_5_40) {
ret = ether_set_eqos_rx_clk_rates(pdata);
if (ret < 0) {
dev_err(dev, "failed to get eqos rx clks\n");
dev_err(dev, "failed to set rx_input_clk clk\n");
goto err_rx_clk;
}
}