diff options
author | Iyappan Subramanian <isubramanian@apm.com> | 2016-07-25 17:12:39 -0700 |
---|---|---|
committer | David S. Miller <davem@davemloft.net> | 2016-07-25 21:51:43 -0700 |
commit | bc61167ac816621c94f722177d2ae718c103005f (patch) | |
tree | 7dff7725a564e25c5eac002043a0ba7dd5ba0342 /drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | |
parent | cb0366b7c16427a25923350b69f53a5b1345a34b (diff) |
drivers: net: xgene: Fix module unload crash - clkrst sequence
This patch fixes clock reset sequence.
- Added clock reset sequence for ACPI
- Added delay in clock reset sequence to make sure pulse is generated
- Added clk_unprepare_disable() in port shutdown to make sure
clock increment/decrement counts are matching
- Removed MII_MGMT_CONFIG programming, since it is not required
- Fixed programming XGENET_CONFIG_REG to enable SGMII mode
Signed-off-by: Iyappan Subramanian <isubramanian@apm.com>
Tested-by: Fushen Chen <fchen@apm.com>
Tested-by: Toan Le <toanle@apm.com>
Signed-off-by: David S. Miller <davem@davemloft.net>
Diffstat (limited to 'drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c')
-rw-r--r-- | drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c | 24 |
1 files changed, 23 insertions, 1 deletions
diff --git a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c index d0b441934091..9c6ad0dce00f 100644 --- a/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c +++ b/drivers/net/ethernet/apm/xgene/xgene_enet_xgmac.c @@ -258,13 +258,29 @@ static void xgene_xgmac_tx_disable(struct xgene_enet_pdata *pdata) static int xgene_enet_reset(struct xgene_enet_pdata *pdata) { + struct device *dev = &pdata->pdev->dev; + if (!xgene_ring_mgr_init(pdata)) return -ENODEV; - if (!IS_ERR(pdata->clk)) { + if (dev->of_node) { clk_prepare_enable(pdata->clk); + udelay(5); clk_disable_unprepare(pdata->clk); + udelay(5); clk_prepare_enable(pdata->clk); + udelay(5); + } else { +#ifdef CONFIG_ACPI + if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev), "_RST")) { + acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev), + "_RST", NULL, NULL); + } else if (acpi_has_method(ACPI_HANDLE(&pdata->pdev->dev), + "_INI")) { + acpi_evaluate_object(ACPI_HANDLE(&pdata->pdev->dev), + "_INI", NULL, NULL); + } +#endif } xgene_enet_ecc_init(pdata); @@ -292,6 +308,7 @@ static void xgene_enet_xgcle_bypass(struct xgene_enet_pdata *pdata, static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata) { + struct device *dev = &pdata->pdev->dev; struct xgene_enet_desc_ring *ring; u32 pb, val; int i; @@ -313,6 +330,11 @@ static void xgene_enet_shutdown(struct xgene_enet_pdata *pdata) pb |= BIT(val); } xgene_enet_wr_ring_if(pdata, ENET_CFGSSQMIWQRESET_ADDR, pb); + + if (dev->of_node) { + if (!IS_ERR(pdata->clk)) + clk_disable_unprepare(pdata->clk); + } } static void xgene_enet_clear(struct xgene_enet_pdata *pdata, |