stmmac: add clk management support
this patch adds the way to enable/disable the MAC clock when call the open/close and resume/restore functions. This has been tested on ST platforms and SPEAr; thanks to Francesco and Deepak. Signed-off-by: Deepak Sikri <deepak.sikri@st.com> Tested-by: Francesco Virlinzi <francesco.virlinzi@st.com> Signed-off-by: Giuseppe Cavallaro <peppe.cavallaro@st.com> Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
parent
39b401dbd3
commit
ba1377ffe9
|
@ -22,6 +22,8 @@
|
|||
|
||||
#define STMMAC_RESOURCE_NAME "stmmaceth"
|
||||
#define DRV_MODULE_VERSION "Feb_2012"
|
||||
|
||||
#include <linux/clk.h>
|
||||
#include <linux/stmmac.h>
|
||||
#include <linux/phy.h>
|
||||
#include "common.h"
|
||||
|
@ -79,6 +81,9 @@ struct stmmac_priv {
|
|||
struct stmmac_counters mmc;
|
||||
struct dma_features dma_cap;
|
||||
int hw_cap_support;
|
||||
#ifdef CONFIG_HAVE_CLK
|
||||
struct clk *stmmac_clk;
|
||||
#endif
|
||||
};
|
||||
|
||||
extern int phyaddr;
|
||||
|
@ -97,3 +102,41 @@ int stmmac_dvr_remove(struct net_device *ndev);
|
|||
struct stmmac_priv *stmmac_dvr_probe(struct device *device,
|
||||
struct plat_stmmacenet_data *plat_dat,
|
||||
void __iomem *addr);
|
||||
|
||||
#ifdef CONFIG_HAVE_CLK
|
||||
static inline int stmmac_clk_enable(struct stmmac_priv *priv)
|
||||
{
|
||||
if (priv->stmmac_clk)
|
||||
return clk_enable(priv->stmmac_clk);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
||||
static inline void stmmac_clk_disable(struct stmmac_priv *priv)
|
||||
{
|
||||
if (priv->stmmac_clk)
|
||||
clk_disable(priv->stmmac_clk);
|
||||
}
|
||||
static inline int stmmac_clk_get(struct stmmac_priv *priv)
|
||||
{
|
||||
priv->stmmac_clk = clk_get(priv->device, NULL);
|
||||
|
||||
if (IS_ERR(priv->stmmac_clk)) {
|
||||
pr_err("%s: ERROR clk_get failed\n", __func__);
|
||||
return PTR_ERR(priv->stmmac_clk);
|
||||
}
|
||||
return 0;
|
||||
}
|
||||
#else
|
||||
static inline int stmmac_clk_enable(struct stmmac_priv *priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
static inline void stmmac_clk_disable(struct stmmac_priv *priv)
|
||||
{
|
||||
}
|
||||
static inline int stmmac_clk_get(struct stmmac_priv *priv)
|
||||
{
|
||||
return 0;
|
||||
}
|
||||
#endif /* CONFIG_HAVE_CLK */
|
||||
|
|
|
@ -904,6 +904,8 @@ static int stmmac_open(struct net_device *dev)
|
|||
struct stmmac_priv *priv = netdev_priv(dev);
|
||||
int ret;
|
||||
|
||||
stmmac_clk_enable(priv);
|
||||
|
||||
stmmac_check_ether_addr(priv);
|
||||
|
||||
/* MDIO bus Registration */
|
||||
|
@ -911,13 +913,15 @@ static int stmmac_open(struct net_device *dev)
|
|||
if (ret < 0) {
|
||||
pr_debug("%s: MDIO bus (id: %d) registration failed",
|
||||
__func__, priv->plat->bus_id);
|
||||
return ret;
|
||||
goto open_clk_dis;
|
||||
}
|
||||
|
||||
#ifdef CONFIG_STMMAC_TIMER
|
||||
priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
|
||||
if (unlikely(priv->tm == NULL))
|
||||
return -ENOMEM;
|
||||
if (unlikely(priv->tm == NULL)) {
|
||||
ret = -ENOMEM;
|
||||
goto open_clk_dis;
|
||||
}
|
||||
|
||||
priv->tm->freq = tmrate;
|
||||
|
||||
|
@ -1034,6 +1038,8 @@ open_error:
|
|||
if (priv->phydev)
|
||||
phy_disconnect(priv->phydev);
|
||||
|
||||
open_clk_dis:
|
||||
stmmac_clk_disable(priv);
|
||||
return ret;
|
||||
}
|
||||
|
||||
|
@ -1086,6 +1092,7 @@ static int stmmac_release(struct net_device *dev)
|
|||
stmmac_exit_fs();
|
||||
#endif
|
||||
stmmac_mdio_unregister(dev);
|
||||
stmmac_clk_disable(priv);
|
||||
|
||||
return 0;
|
||||
}
|
||||
|
@ -1880,6 +1887,9 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
|
|||
goto error;
|
||||
}
|
||||
|
||||
if (stmmac_clk_get(priv))
|
||||
goto error;
|
||||
|
||||
return priv;
|
||||
|
||||
error:
|
||||
|
@ -1949,9 +1959,11 @@ int stmmac_suspend(struct net_device *ndev)
|
|||
/* Enable Power down mode by programming the PMT regs */
|
||||
if (device_may_wakeup(priv->device))
|
||||
priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
|
||||
else
|
||||
else {
|
||||
stmmac_set_mac(priv->ioaddr, false);
|
||||
|
||||
/* Disable clock in case of PWM is off */
|
||||
stmmac_clk_disable(priv);
|
||||
}
|
||||
spin_unlock(&priv->lock);
|
||||
return 0;
|
||||
}
|
||||
|
@ -1972,6 +1984,9 @@ int stmmac_resume(struct net_device *ndev)
|
|||
* from another devices (e.g. serial console). */
|
||||
if (device_may_wakeup(priv->device))
|
||||
priv->hw->mac->pmt(priv->ioaddr, 0);
|
||||
else
|
||||
/* enable the clk prevously disabled */
|
||||
stmmac_clk_enable(priv);
|
||||
|
||||
netif_device_attach(ndev);
|
||||
|
||||
|
|
Loading…
Reference in New Issue