Merge branch 'stmmac-wol'

Vincent Palatin says:

====================
net: stmmac: dwmac-rk: fixes for Wake-on-Lan on RK3288

In order to support Wake-On-Lan when using the RK3288 integrated MAC
(with an external RGMII PHY), we need to avoid shutting down the regulator
of the external PHY when the MAC is suspended as it's currently done in the MAC
platform code.
As a first step, create independant callbacks for suspend/resume rather than
re-using exit/init callbacks. So the dwmac platform driver can behave differently
on suspend where it might skip shutting the PHY and at module unloading.
Then update the dwmac-rk driver to switch off the PHY regulator only if we are
not planning to wake up from the LAN.
Finally add the PMT interrupt to the MAC device tree configuration, so we can
wake up the core from it when the PHY has received the magic packet.
====================

Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
David S. Miller 2016-06-16 14:14:58 -07:00
commit b4eccef8f3
4 changed files with 54 additions and 9 deletions

View File

@ -539,8 +539,9 @@
gmac: ethernet@ff290000 {
compatible = "rockchip,rk3288-gmac";
reg = <0xff290000 0x10000>;
interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "macirq";
interrupts = <GIC_SPI 27 IRQ_TYPE_LEVEL_HIGH>,
<GIC_SPI 28 IRQ_TYPE_LEVEL_HIGH>;
interrupt-names = "macirq", "eth_wake_irq";
rockchip,grf = <&grf>;
clocks = <&cru SCLK_MAC>,
<&cru SCLK_MAC_RX>, <&cru SCLK_MAC_TX>,

View File

@ -46,6 +46,7 @@ struct rk_priv_data {
struct platform_device *pdev;
int phy_iface;
struct regulator *regulator;
bool suspended;
const struct rk_gmac_ops *ops;
bool clk_enabled;
@ -529,9 +530,8 @@ static struct rk_priv_data *rk_gmac_setup(struct platform_device *pdev,
return bsp_priv;
}
static int rk_gmac_init(struct platform_device *pdev, void *priv)
static int rk_gmac_powerup(struct rk_priv_data *bsp_priv)
{
struct rk_priv_data *bsp_priv = priv;
int ret;
ret = phy_power_on(bsp_priv, true);
@ -545,14 +545,50 @@ static int rk_gmac_init(struct platform_device *pdev, void *priv)
return 0;
}
static void rk_gmac_exit(struct platform_device *pdev, void *priv)
static void rk_gmac_powerdown(struct rk_priv_data *gmac)
{
struct rk_priv_data *gmac = priv;
phy_power_on(gmac, false);
gmac_clk_enable(gmac, false);
}
static int rk_gmac_init(struct platform_device *pdev, void *priv)
{
struct rk_priv_data *bsp_priv = priv;
return rk_gmac_powerup(bsp_priv);
}
static void rk_gmac_exit(struct platform_device *pdev, void *priv)
{
struct rk_priv_data *bsp_priv = priv;
rk_gmac_powerdown(bsp_priv);
}
static void rk_gmac_suspend(struct platform_device *pdev, void *priv)
{
struct rk_priv_data *bsp_priv = priv;
/* Keep the PHY up if we use Wake-on-Lan. */
if (device_may_wakeup(&pdev->dev))
return;
rk_gmac_powerdown(bsp_priv);
bsp_priv->suspended = true;
}
static void rk_gmac_resume(struct platform_device *pdev, void *priv)
{
struct rk_priv_data *bsp_priv = priv;
/* The PHY was up for Wake-on-Lan. */
if (!bsp_priv->suspended)
return;
rk_gmac_powerup(bsp_priv);
bsp_priv->suspended = false;
}
static void rk_fix_speed(void *priv, unsigned int speed)
{
struct rk_priv_data *bsp_priv = priv;
@ -591,6 +627,8 @@ static int rk_gmac_probe(struct platform_device *pdev)
plat_dat->init = rk_gmac_init;
plat_dat->exit = rk_gmac_exit;
plat_dat->fix_mac_speed = rk_fix_speed;
plat_dat->suspend = rk_gmac_suspend;
plat_dat->resume = rk_gmac_resume;
plat_dat->bsp_priv = rk_gmac_setup(pdev, data);
if (IS_ERR(plat_dat->bsp_priv))

View File

@ -411,7 +411,9 @@ static int stmmac_pltfr_suspend(struct device *dev)
struct platform_device *pdev = to_platform_device(dev);
ret = stmmac_suspend(dev);
if (priv->plat->exit)
if (priv->plat->suspend)
priv->plat->suspend(pdev, priv->plat->bsp_priv);
else if (priv->plat->exit)
priv->plat->exit(pdev, priv->plat->bsp_priv);
return ret;
@ -430,7 +432,9 @@ static int stmmac_pltfr_resume(struct device *dev)
struct stmmac_priv *priv = netdev_priv(ndev);
struct platform_device *pdev = to_platform_device(dev);
if (priv->plat->init)
if (priv->plat->resume)
priv->plat->resume(pdev, priv->plat->bsp_priv);
else if (priv->plat->init)
priv->plat->init(pdev, priv->plat->bsp_priv);
return stmmac_resume(dev);

View File

@ -135,6 +135,8 @@ struct plat_stmmacenet_data {
void (*bus_setup)(void __iomem *ioaddr);
int (*init)(struct platform_device *pdev, void *priv);
void (*exit)(struct platform_device *pdev, void *priv);
void (*suspend)(struct platform_device *pdev, void *priv);
void (*resume)(struct platform_device *pdev, void *priv);
void *bsp_priv;
struct stmmac_axi *axi;
int has_gmac4;