mirror of
git://nv-tegra.nvidia.com/linux-nv-oot.git
synced 2025-12-24 02:01:36 +03:00
nvethernet: Reset MAC registers on interface down and up.
Issue: MAC registers are not getting reset on ether_close(), which lead to old values in MAC registers at the time of osi_hw_core_init(). Fix: Assert MAC-RST gpio and disable clocks in ether_close(). Enable clock, reset MAC_RST gpio and poll for swr, which will reset all MAC registers. Note: To read MAC registers, you must have clocks enable and MAC out of reset Bug 200512422 Change-Id: If253eff0ae456702d3cdcbe1f177dd91a5aae20d Signed-off-by: Rakesh Goyal <rgoyal@nvidia.com> Reviewed-on: https://git-master.nvidia.com/r/2138031 Reviewed-by: Narayan Reddy <narayanr@nvidia.com> GVS: Gerrit_Virtual_Submit Reviewed-by: Sachin Nikam <snikam@nvidia.com> Reviewed-by: mobile promotions <svcmobile_promotions@nvidia.com> Tested-by: mobile promotions <svcmobile_promotions@nvidia.com>
This commit is contained in:
committed by
Revanth Kumar Uppala
parent
d3161de4da
commit
f71600879c
@@ -16,6 +16,130 @@
|
||||
|
||||
#include "ether_linux.h"
|
||||
|
||||
/**
|
||||
* ether_disable_clks - Disable all MAC related clks.
|
||||
* @pdata: OSD private data.
|
||||
*
|
||||
* Algorithm: Release the reference counter for the clks by using
|
||||
* clock subsystem provided API's.
|
||||
*
|
||||
* Dependencies: None.
|
||||
*
|
||||
* Protection: None.
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
static void ether_disable_clks(struct ether_priv_data *pdata)
|
||||
{
|
||||
if (!IS_ERR_OR_NULL(pdata->axi_cbb_clk)) {
|
||||
clk_disable_unprepare(pdata->axi_cbb_clk);
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->axi_clk)) {
|
||||
clk_disable_unprepare(pdata->axi_clk);
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->rx_clk)) {
|
||||
clk_disable_unprepare(pdata->rx_clk);
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->ptp_ref_clk)) {
|
||||
clk_disable_unprepare(pdata->ptp_ref_clk);
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->tx_clk)) {
|
||||
clk_disable_unprepare(pdata->tx_clk);
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->pllrefe_clk)) {
|
||||
clk_disable_unprepare(pdata->pllrefe_clk);
|
||||
}
|
||||
}
|
||||
|
||||
/**
|
||||
* ether_enable_clks - Enable all MAC related clks.
|
||||
* @pdata: OSD private data.
|
||||
*
|
||||
* Algorithm: Enables the clks by using clock subsystem provided API's.
|
||||
*
|
||||
* Dependencies: None.
|
||||
*
|
||||
* Protection: None.
|
||||
*
|
||||
* Return: 0 - success, negative value - failure.
|
||||
*/
|
||||
static int ether_enable_clks(struct ether_priv_data *pdata)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->pllrefe_clk)) {
|
||||
ret = clk_prepare_enable(pdata->pllrefe_clk);
|
||||
if (ret < 0) {
|
||||
return ret;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->axi_cbb_clk)) {
|
||||
ret = clk_prepare_enable(pdata->axi_cbb_clk);
|
||||
if (ret) {
|
||||
goto err_axi_cbb;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->axi_clk)) {
|
||||
ret = clk_prepare_enable(pdata->axi_clk);
|
||||
if (ret < 0) {
|
||||
goto err_axi;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->rx_clk)) {
|
||||
ret = clk_prepare_enable(pdata->rx_clk);
|
||||
if (ret < 0) {
|
||||
goto err_rx;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->ptp_ref_clk)) {
|
||||
ret = clk_prepare_enable(pdata->ptp_ref_clk);
|
||||
if (ret < 0) {
|
||||
goto err_ptp_ref;
|
||||
}
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->tx_clk)) {
|
||||
ret = clk_prepare_enable(pdata->tx_clk);
|
||||
if (ret < 0) {
|
||||
goto err_tx;
|
||||
}
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_tx:
|
||||
if (!IS_ERR_OR_NULL(pdata->ptp_ref_clk)) {
|
||||
clk_disable_unprepare(pdata->ptp_ref_clk);
|
||||
}
|
||||
err_ptp_ref:
|
||||
if (!IS_ERR_OR_NULL(pdata->rx_clk)) {
|
||||
clk_disable_unprepare(pdata->rx_clk);
|
||||
}
|
||||
err_rx:
|
||||
if (!IS_ERR_OR_NULL(pdata->axi_clk)) {
|
||||
clk_disable_unprepare(pdata->axi_clk);
|
||||
}
|
||||
err_axi:
|
||||
if (!IS_ERR_OR_NULL(pdata->axi_cbb_clk)) {
|
||||
clk_disable_unprepare(pdata->axi_cbb_clk);
|
||||
}
|
||||
err_axi_cbb:
|
||||
if (!IS_ERR_OR_NULL(pdata->pllrefe_clk)) {
|
||||
clk_disable_unprepare(pdata->pllrefe_clk);
|
||||
}
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ether_adjust_link - Adjust link call back
|
||||
* @dev: Net device data.
|
||||
@@ -1021,14 +1145,35 @@ static int ether_therm_init(struct ether_priv_data *pdata)
|
||||
static int ether_open(struct net_device *dev)
|
||||
{
|
||||
struct ether_priv_data *pdata = netdev_priv(dev);
|
||||
struct osi_core_priv_data *osi_core = pdata->osi_core;
|
||||
int ret = 0;
|
||||
|
||||
ret = ether_enable_clks(pdata);
|
||||
if (ret < 0) {
|
||||
dev_err(&dev->dev, "failed to enable clks\n");
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (pdata->mac_rst) {
|
||||
ret = reset_control_reset(pdata->mac_rst);
|
||||
if (ret < 0) {
|
||||
dev_err(&dev->dev, "failed to reset MAC HW\n");
|
||||
goto err_mac_rst;
|
||||
}
|
||||
}
|
||||
|
||||
ret = osi_poll_for_swr(osi_core);
|
||||
if (ret < 0) {
|
||||
dev_err(&dev->dev, "failed to poll MAC Software reset\n");
|
||||
goto err_poll_swr;
|
||||
}
|
||||
|
||||
/* PHY reset and initialization */
|
||||
ret = ether_phy_init(dev);
|
||||
if (ret < 0) {
|
||||
dev_err(&dev->dev, "%s: Cannot attach to PHY (error: %d)\n",
|
||||
__func__, ret);
|
||||
return ret;
|
||||
goto err_phy_init;
|
||||
}
|
||||
|
||||
/* request tx/rx/common irq */
|
||||
@@ -1109,8 +1254,16 @@ err_therm:
|
||||
err_alloc:
|
||||
ether_free_irqs(pdata);
|
||||
err_r_irq:
|
||||
if (pdata->phydev)
|
||||
if (pdata->phydev) {
|
||||
phy_disconnect(pdata->phydev);
|
||||
}
|
||||
err_phy_init:
|
||||
err_poll_swr:
|
||||
if (pdata->mac_rst) {
|
||||
reset_control_assert(pdata->mac_rst);
|
||||
}
|
||||
err_mac_rst:
|
||||
ether_disable_clks(pdata);
|
||||
|
||||
return ret;
|
||||
}
|
||||
@@ -1131,17 +1284,17 @@ err_r_irq:
|
||||
*/
|
||||
static int ether_close(struct net_device *dev)
|
||||
{
|
||||
int ret = 0;
|
||||
struct ether_priv_data *pdata = netdev_priv(dev);
|
||||
int ret = 0;
|
||||
|
||||
/* Stop and disconnect the PHY */
|
||||
if (pdata->phydev != NULL) {
|
||||
phy_stop(pdata->phydev);
|
||||
phy_disconnect(pdata->phydev);
|
||||
|
||||
if (gpio_is_valid(pdata->phy_reset))
|
||||
if (gpio_is_valid(pdata->phy_reset)) {
|
||||
gpio_set_value(pdata->phy_reset, 0);
|
||||
|
||||
}
|
||||
pdata->phydev = NULL;
|
||||
}
|
||||
|
||||
@@ -1169,6 +1322,14 @@ static int ether_close(struct net_device *dev)
|
||||
|
||||
ether_napi_disable(pdata);
|
||||
|
||||
/* Assert MAC RST gpio */
|
||||
if (pdata->mac_rst) {
|
||||
reset_control_assert(pdata->mac_rst);
|
||||
}
|
||||
|
||||
/* Disable clock */
|
||||
ether_disable_clks(pdata);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
@@ -2387,113 +2548,6 @@ static int ether_get_mac_address(struct ether_priv_data *pdata)
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ether_disable_clks - Disable all MAC related clks.
|
||||
* @pdata: OSD private data.
|
||||
*
|
||||
* Algorithm: Release the reference counter for the clks by using
|
||||
* clock subsystem provided API's.
|
||||
*
|
||||
* Dependencies: None.
|
||||
*
|
||||
* Protection: None.
|
||||
*
|
||||
* Return: None.
|
||||
*/
|
||||
static void ether_disable_clks(struct ether_priv_data *pdata)
|
||||
{
|
||||
if (!IS_ERR_OR_NULL(pdata->axi_cbb_clk))
|
||||
clk_disable_unprepare(pdata->axi_cbb_clk);
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->axi_clk))
|
||||
clk_disable_unprepare(pdata->axi_clk);
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->rx_clk))
|
||||
clk_disable_unprepare(pdata->rx_clk);
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->ptp_ref_clk))
|
||||
clk_disable_unprepare(pdata->ptp_ref_clk);
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->tx_clk))
|
||||
clk_disable_unprepare(pdata->tx_clk);
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->pllrefe_clk))
|
||||
clk_disable_unprepare(pdata->pllrefe_clk);
|
||||
}
|
||||
|
||||
/**
|
||||
* ether_enable_clks - Enable all MAC related clks.
|
||||
* @pdata: OSD private data.
|
||||
*
|
||||
* Algorithm: Enables the clks by using clock subsystem provided API's.
|
||||
*
|
||||
* Dependencies: None.
|
||||
*
|
||||
* Protection: None.
|
||||
*
|
||||
* Return: 0 - success, negative value - failure.
|
||||
*/
|
||||
static int ether_enable_clks(struct ether_priv_data *pdata)
|
||||
{
|
||||
int ret;
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->pllrefe_clk)) {
|
||||
ret = clk_prepare_enable(pdata->pllrefe_clk);
|
||||
if (ret < 0)
|
||||
return ret;
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->axi_cbb_clk)) {
|
||||
ret = clk_prepare_enable(pdata->axi_cbb_clk);
|
||||
if (ret)
|
||||
goto err_axi_cbb;
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->axi_clk)) {
|
||||
ret = clk_prepare_enable(pdata->axi_clk);
|
||||
if (ret < 0)
|
||||
goto err_axi;
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->rx_clk)) {
|
||||
ret = clk_prepare_enable(pdata->rx_clk);
|
||||
if (ret < 0)
|
||||
goto err_rx;
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->ptp_ref_clk)) {
|
||||
ret = clk_prepare_enable(pdata->ptp_ref_clk);
|
||||
if (ret < 0)
|
||||
goto err_ptp_ref;
|
||||
}
|
||||
|
||||
if (!IS_ERR_OR_NULL(pdata->tx_clk)) {
|
||||
ret = clk_prepare_enable(pdata->tx_clk);
|
||||
if (ret < 0)
|
||||
goto err_tx;
|
||||
}
|
||||
|
||||
return 0;
|
||||
|
||||
err_tx:
|
||||
if (!IS_ERR_OR_NULL(pdata->ptp_ref_clk))
|
||||
clk_disable_unprepare(pdata->ptp_ref_clk);
|
||||
err_ptp_ref:
|
||||
if (!IS_ERR_OR_NULL(pdata->rx_clk))
|
||||
clk_disable_unprepare(pdata->rx_clk);
|
||||
err_rx:
|
||||
if (!IS_ERR_OR_NULL(pdata->axi_clk))
|
||||
clk_disable_unprepare(pdata->axi_clk);
|
||||
err_axi:
|
||||
if (!IS_ERR_OR_NULL(pdata->axi_cbb_clk))
|
||||
clk_disable_unprepare(pdata->axi_cbb_clk);
|
||||
err_axi_cbb:
|
||||
if (!IS_ERR_OR_NULL(pdata->pllrefe_clk))
|
||||
clk_disable_unprepare(pdata->pllrefe_clk);
|
||||
|
||||
return ret;
|
||||
}
|
||||
|
||||
/**
|
||||
* ether_put_clks - Put back MAC related clocks.
|
||||
* @pdata: OSD private data.
|
||||
@@ -2695,8 +2749,9 @@ static int ether_configure_car(struct platform_device *pdev,
|
||||
return ret;
|
||||
|
||||
err_swr:
|
||||
if (pdata->mac_rst)
|
||||
reset_control_deassert(pdata->mac_rst);
|
||||
if (pdata->mac_rst) {
|
||||
reset_control_assert(pdata->mac_rst);
|
||||
}
|
||||
err_rst:
|
||||
ether_disable_clks(pdata);
|
||||
err_enable_clks:
|
||||
@@ -3326,6 +3381,8 @@ static int ether_probe(struct platform_device *pdev)
|
||||
spin_lock_init(&pdata->lock);
|
||||
spin_lock_init(&pdata->ioctl_lock);
|
||||
init_filter_values(pdata);
|
||||
/* Disable Clocks */
|
||||
ether_disable_clks(pdata);
|
||||
|
||||
dev_info(&pdev->dev,
|
||||
"%s (HW ver: %02x) created with %u DMA channels\n",
|
||||
@@ -3377,6 +3434,10 @@ static int ether_remove(struct platform_device *pdev)
|
||||
}
|
||||
|
||||
ether_disable_clks(pdata);
|
||||
/* Assert MAC RST gpio */
|
||||
if (pdata->mac_rst) {
|
||||
reset_control_assert(pdata->mac_rst);
|
||||
}
|
||||
free_netdev(ndev);
|
||||
|
||||
return 0;
|
||||
|
||||
Reference in New Issue
Block a user