Commit da7daf5b authored by David S. Miller's avatar David S. Miller

Merge branch 'stmmac-dwmac-socfpga-cleanup'

Joachim Eastwood says:

====================
stmmac: dwmac-socfpga refactor+cleanup

This patch aims to remove the init/exit callbacks from the dwmac-
socfpga driver and instead use standard PM callbacks. Doing this
will also allow us to cleanup the driver.

Eventually the init/exit callbacks will be deprecated and removed
from all drivers dwmac-* except for dwmac-generic. Drivers will be
refactored to use standard PM and remove callbacks.

This patch set should not change the behavior of the driver itself,
it only moves code around. The only exception to this is patch
number 4 which restores the resume callback behavior which was
changed in the "net: stmmac: socfpga: Remove re-registration of
reset controller" patch. I belive calling phy_resume() only
from the resume callback and not probe is the right thing to do.

Changes from v1:
 - Rebase on net-next

One heads-up here:
The first patch changes the prototype of a couple of
functions used in Alexandre's "add Ethernet glue logic for
stm32 chip" patch [1] and will cause build failures for
dwmac-stm32.c if not fixed up!
If Alexandre's patch set is applied first I will gladly
rebase my patch set to account for his driver as well.

[1] https://patchwork.ozlabs.org/patch/614405/
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents e03179fe 0f400a87
...@@ -49,6 +49,7 @@ struct socfpga_dwmac { ...@@ -49,6 +49,7 @@ struct socfpga_dwmac {
u32 reg_shift; u32 reg_shift;
struct device *dev; struct device *dev;
struct regmap *sys_mgr_base_addr; struct regmap *sys_mgr_base_addr;
struct reset_control *stmmac_rst;
void __iomem *splitter_base; void __iomem *splitter_base;
bool f2h_ptp_ref_clk; bool f2h_ptp_ref_clk;
}; };
...@@ -135,7 +136,7 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device * ...@@ -135,7 +136,7 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
return 0; return 0;
} }
static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac) static int socfpga_dwmac_set_phy_mode(struct socfpga_dwmac *dwmac)
{ {
struct regmap *sys_mgr_base_addr = dwmac->sys_mgr_base_addr; struct regmap *sys_mgr_base_addr = dwmac->sys_mgr_base_addr;
int phymode = dwmac->interface; int phymode = dwmac->interface;
...@@ -164,6 +165,10 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac) ...@@ -164,6 +165,10 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac)
if (dwmac->splitter_base) if (dwmac->splitter_base)
val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII; val = SYSMGR_EMACGRP_CTRL_PHYSEL_ENUM_GMII_MII;
/* Assert reset to the enet controller before changing the phy mode */
if (dwmac->stmmac_rst)
reset_control_assert(dwmac->stmmac_rst);
regmap_read(sys_mgr_base_addr, reg_offset, &ctrl); regmap_read(sys_mgr_base_addr, reg_offset, &ctrl);
ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift); ctrl &= ~(SYSMGR_EMACGRP_CTRL_PHYSEL_MASK << reg_shift);
ctrl |= val << reg_shift; ctrl |= val << reg_shift;
...@@ -181,57 +186,13 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac) ...@@ -181,57 +186,13 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac)
regmap_write(sys_mgr_base_addr, reg_offset, ctrl); regmap_write(sys_mgr_base_addr, reg_offset, ctrl);
return 0;
}
static int socfpga_dwmac_init(struct platform_device *pdev, void *priv)
{
struct socfpga_dwmac *dwmac = priv;
struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *stpriv = NULL;
int ret = 0;
if (!ndev)
return -EINVAL;
stpriv = netdev_priv(ndev);
if (!stpriv)
return -EINVAL;
/* Assert reset to the enet controller before changing the phy mode */
if (stpriv->stmmac_rst)
reset_control_assert(stpriv->stmmac_rst);
/* Setup the phy mode in the system manager registers according to
* devicetree configuration
*/
ret = socfpga_dwmac_setup(dwmac);
/* Deassert reset for the phy configuration to be sampled by /* Deassert reset for the phy configuration to be sampled by
* the enet controller, and operation to start in requested mode * the enet controller, and operation to start in requested mode
*/ */
if (stpriv->stmmac_rst) if (dwmac->stmmac_rst)
reset_control_deassert(stpriv->stmmac_rst); reset_control_deassert(dwmac->stmmac_rst);
/* Before the enet controller is suspended, the phy is suspended.
* This causes the phy clock to be gated. The enet controller is
* resumed before the phy, so the clock is still gated "off" when
* the enet controller is resumed. This code makes sure the phy
* is "resumed" before reinitializing the enet controller since
* the enet controller depends on an active phy clock to complete
* a DMA reset. A DMA reset will "time out" if executed
* with no phy clock input on the Synopsys enet controller.
* Verified through Synopsys Case #8000711656.
*
* Note that the phy clock is also gated when the phy is isolated.
* Phy "suspend" and "isolate" controls are located in phy basic
* control register 0, and can be modified by the phy driver
* framework.
*/
if (stpriv->phydev)
phy_resume(stpriv->phydev);
return ret; return 0;
} }
static int socfpga_dwmac_probe(struct platform_device *pdev) static int socfpga_dwmac_probe(struct platform_device *pdev)
...@@ -261,16 +222,57 @@ static int socfpga_dwmac_probe(struct platform_device *pdev) ...@@ -261,16 +222,57 @@ static int socfpga_dwmac_probe(struct platform_device *pdev)
} }
plat_dat->bsp_priv = dwmac; plat_dat->bsp_priv = dwmac;
plat_dat->init = socfpga_dwmac_init;
plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed; plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed;
ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
if (!ret) if (!ret) {
ret = socfpga_dwmac_init(pdev, dwmac); struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *stpriv = netdev_priv(ndev);
/* The socfpga driver needs to control the stmmac reset to
* set the phy mode. Create a copy of the core reset handel
* so it can be used by the driver later.
*/
dwmac->stmmac_rst = stpriv->stmmac_rst;
ret = socfpga_dwmac_set_phy_mode(dwmac);
}
return ret; return ret;
} }
#ifdef CONFIG_PM_SLEEP
static int socfpga_dwmac_resume(struct device *dev)
{
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev);
socfpga_dwmac_set_phy_mode(priv->plat->bsp_priv);
/* Before the enet controller is suspended, the phy is suspended.
* This causes the phy clock to be gated. The enet controller is
* resumed before the phy, so the clock is still gated "off" when
* the enet controller is resumed. This code makes sure the phy
* is "resumed" before reinitializing the enet controller since
* the enet controller depends on an active phy clock to complete
* a DMA reset. A DMA reset will "time out" if executed
* with no phy clock input on the Synopsys enet controller.
* Verified through Synopsys Case #8000711656.
*
* Note that the phy clock is also gated when the phy is isolated.
* Phy "suspend" and "isolate" controls are located in phy basic
* control register 0, and can be modified by the phy driver
* framework.
*/
if (priv->phydev)
phy_resume(priv->phydev);
return stmmac_resume(dev);
}
#endif /* CONFIG_PM_SLEEP */
SIMPLE_DEV_PM_OPS(socfpga_dwmac_pm_ops, stmmac_suspend, socfpga_dwmac_resume);
static const struct of_device_id socfpga_dwmac_match[] = { static const struct of_device_id socfpga_dwmac_match[] = {
{ .compatible = "altr,socfpga-stmmac" }, { .compatible = "altr,socfpga-stmmac" },
{ } { }
...@@ -282,7 +284,7 @@ static struct platform_driver socfpga_dwmac_driver = { ...@@ -282,7 +284,7 @@ static struct platform_driver socfpga_dwmac_driver = {
.remove = stmmac_pltfr_remove, .remove = stmmac_pltfr_remove,
.driver = { .driver = {
.name = "socfpga-dwmac", .name = "socfpga-dwmac",
.pm = &stmmac_pltfr_pm_ops, .pm = &socfpga_dwmac_pm_ops,
.of_match_table = socfpga_dwmac_match, .of_match_table = socfpga_dwmac_match,
}, },
}; };
......
...@@ -148,9 +148,9 @@ void stmmac_set_ethtool_ops(struct net_device *netdev); ...@@ -148,9 +148,9 @@ void stmmac_set_ethtool_ops(struct net_device *netdev);
int stmmac_ptp_register(struct stmmac_priv *priv); int stmmac_ptp_register(struct stmmac_priv *priv);
void stmmac_ptp_unregister(struct stmmac_priv *priv); void stmmac_ptp_unregister(struct stmmac_priv *priv);
int stmmac_resume(struct net_device *ndev); int stmmac_resume(struct device *dev);
int stmmac_suspend(struct net_device *ndev); int stmmac_suspend(struct device *dev);
int stmmac_dvr_remove(struct net_device *ndev); int stmmac_dvr_remove(struct device *dev);
int stmmac_dvr_probe(struct device *device, int stmmac_dvr_probe(struct device *device,
struct plat_stmmacenet_data *plat_dat, struct plat_stmmacenet_data *plat_dat,
struct stmmac_resources *res); struct stmmac_resources *res);
......
...@@ -3350,12 +3350,13 @@ EXPORT_SYMBOL_GPL(stmmac_dvr_probe); ...@@ -3350,12 +3350,13 @@ EXPORT_SYMBOL_GPL(stmmac_dvr_probe);
/** /**
* stmmac_dvr_remove * stmmac_dvr_remove
* @ndev: net device pointer * @dev: device pointer
* Description: this function resets the TX/RX processes, disables the MAC RX/TX * Description: this function resets the TX/RX processes, disables the MAC RX/TX
* changes the link status, releases the DMA descriptor rings. * changes the link status, releases the DMA descriptor rings.
*/ */
int stmmac_dvr_remove(struct net_device *ndev) int stmmac_dvr_remove(struct device *dev)
{ {
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_priv *priv = netdev_priv(ndev);
pr_info("%s:\n\tremoving driver", __func__); pr_info("%s:\n\tremoving driver", __func__);
...@@ -3381,13 +3382,14 @@ EXPORT_SYMBOL_GPL(stmmac_dvr_remove); ...@@ -3381,13 +3382,14 @@ EXPORT_SYMBOL_GPL(stmmac_dvr_remove);
/** /**
* stmmac_suspend - suspend callback * stmmac_suspend - suspend callback
* @ndev: net device pointer * @dev: device pointer
* Description: this is the function to suspend the device and it is called * Description: this is the function to suspend the device and it is called
* by the platform driver to stop the network queue, release the resources, * by the platform driver to stop the network queue, release the resources,
* program the PMT register (for WoL), clean and release driver resources. * program the PMT register (for WoL), clean and release driver resources.
*/ */
int stmmac_suspend(struct net_device *ndev) int stmmac_suspend(struct device *dev)
{ {
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_priv *priv = netdev_priv(ndev);
unsigned long flags; unsigned long flags;
...@@ -3430,12 +3432,13 @@ EXPORT_SYMBOL_GPL(stmmac_suspend); ...@@ -3430,12 +3432,13 @@ EXPORT_SYMBOL_GPL(stmmac_suspend);
/** /**
* stmmac_resume - resume callback * stmmac_resume - resume callback
* @ndev: net device pointer * @dev: device pointer
* Description: when resume this function is invoked to setup the DMA and CORE * Description: when resume this function is invoked to setup the DMA and CORE
* in a usable state. * in a usable state.
*/ */
int stmmac_resume(struct net_device *ndev) int stmmac_resume(struct device *dev)
{ {
struct net_device *ndev = dev_get_drvdata(dev);
struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_priv *priv = netdev_priv(ndev);
unsigned long flags; unsigned long flags;
......
...@@ -231,30 +231,10 @@ static int stmmac_pci_probe(struct pci_dev *pdev, ...@@ -231,30 +231,10 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
*/ */
static void stmmac_pci_remove(struct pci_dev *pdev) static void stmmac_pci_remove(struct pci_dev *pdev)
{ {
struct net_device *ndev = pci_get_drvdata(pdev); stmmac_dvr_remove(&pdev->dev);
stmmac_dvr_remove(ndev);
}
#ifdef CONFIG_PM_SLEEP
static int stmmac_pci_suspend(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct net_device *ndev = pci_get_drvdata(pdev);
return stmmac_suspend(ndev);
}
static int stmmac_pci_resume(struct device *dev)
{
struct pci_dev *pdev = to_pci_dev(dev);
struct net_device *ndev = pci_get_drvdata(pdev);
return stmmac_resume(ndev);
} }
#endif
static SIMPLE_DEV_PM_OPS(stmmac_pm_ops, stmmac_pci_suspend, stmmac_pci_resume); static SIMPLE_DEV_PM_OPS(stmmac_pm_ops, stmmac_suspend, stmmac_resume);
#define STMMAC_VENDOR_ID 0x700 #define STMMAC_VENDOR_ID 0x700
#define STMMAC_QUARK_ID 0x0937 #define STMMAC_QUARK_ID 0x0937
......
...@@ -386,7 +386,7 @@ int stmmac_pltfr_remove(struct platform_device *pdev) ...@@ -386,7 +386,7 @@ int stmmac_pltfr_remove(struct platform_device *pdev)
{ {
struct net_device *ndev = platform_get_drvdata(pdev); struct net_device *ndev = platform_get_drvdata(pdev);
struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_priv *priv = netdev_priv(ndev);
int ret = stmmac_dvr_remove(ndev); int ret = stmmac_dvr_remove(&pdev->dev);
if (priv->plat->exit) if (priv->plat->exit)
priv->plat->exit(pdev, priv->plat->bsp_priv); priv->plat->exit(pdev, priv->plat->bsp_priv);
...@@ -410,7 +410,7 @@ static int stmmac_pltfr_suspend(struct device *dev) ...@@ -410,7 +410,7 @@ static int stmmac_pltfr_suspend(struct device *dev)
struct stmmac_priv *priv = netdev_priv(ndev); struct stmmac_priv *priv = netdev_priv(ndev);
struct platform_device *pdev = to_platform_device(dev); struct platform_device *pdev = to_platform_device(dev);
ret = stmmac_suspend(ndev); ret = stmmac_suspend(dev);
if (priv->plat->exit) if (priv->plat->exit)
priv->plat->exit(pdev, priv->plat->bsp_priv); priv->plat->exit(pdev, priv->plat->bsp_priv);
...@@ -433,7 +433,7 @@ static int stmmac_pltfr_resume(struct device *dev) ...@@ -433,7 +433,7 @@ static int stmmac_pltfr_resume(struct device *dev)
if (priv->plat->init) if (priv->plat->init)
priv->plat->init(pdev, priv->plat->bsp_priv); priv->plat->init(pdev, priv->plat->bsp_priv);
return stmmac_resume(ndev); return stmmac_resume(dev);
} }
#endif /* CONFIG_PM_SLEEP */ #endif /* CONFIG_PM_SLEEP */
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment