提交 ba1377ff 编写于 作者: G Giuseppe CAVALLARO 提交者: David S. Miller

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: NDeepak Sikri <deepak.sikri@st.com>
Tested-by: NFrancesco Virlinzi <francesco.virlinzi@st.com>
Signed-off-by: NGiuseppe Cavallaro <peppe.cavallaro@st.com>
Signed-off-by: NDavid S. Miller <davem@davemloft.net>
上级 39b401db
...@@ -22,6 +22,8 @@ ...@@ -22,6 +22,8 @@
#define STMMAC_RESOURCE_NAME "stmmaceth" #define STMMAC_RESOURCE_NAME "stmmaceth"
#define DRV_MODULE_VERSION "Feb_2012" #define DRV_MODULE_VERSION "Feb_2012"
#include <linux/clk.h>
#include <linux/stmmac.h> #include <linux/stmmac.h>
#include <linux/phy.h> #include <linux/phy.h>
#include "common.h" #include "common.h"
...@@ -79,6 +81,9 @@ struct stmmac_priv { ...@@ -79,6 +81,9 @@ struct stmmac_priv {
struct stmmac_counters mmc; struct stmmac_counters mmc;
struct dma_features dma_cap; struct dma_features dma_cap;
int hw_cap_support; int hw_cap_support;
#ifdef CONFIG_HAVE_CLK
struct clk *stmmac_clk;
#endif
}; };
extern int phyaddr; extern int phyaddr;
...@@ -97,3 +102,41 @@ int stmmac_dvr_remove(struct net_device *ndev); ...@@ -97,3 +102,41 @@ int stmmac_dvr_remove(struct net_device *ndev);
struct stmmac_priv *stmmac_dvr_probe(struct device *device, struct stmmac_priv *stmmac_dvr_probe(struct device *device,
struct plat_stmmacenet_data *plat_dat, struct plat_stmmacenet_data *plat_dat,
void __iomem *addr); 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) ...@@ -904,6 +904,8 @@ static int stmmac_open(struct net_device *dev)
struct stmmac_priv *priv = netdev_priv(dev); struct stmmac_priv *priv = netdev_priv(dev);
int ret; int ret;
stmmac_clk_enable(priv);
stmmac_check_ether_addr(priv); stmmac_check_ether_addr(priv);
/* MDIO bus Registration */ /* MDIO bus Registration */
...@@ -911,13 +913,15 @@ static int stmmac_open(struct net_device *dev) ...@@ -911,13 +913,15 @@ static int stmmac_open(struct net_device *dev)
if (ret < 0) { if (ret < 0) {
pr_debug("%s: MDIO bus (id: %d) registration failed", pr_debug("%s: MDIO bus (id: %d) registration failed",
__func__, priv->plat->bus_id); __func__, priv->plat->bus_id);
return ret; goto open_clk_dis;
} }
#ifdef CONFIG_STMMAC_TIMER #ifdef CONFIG_STMMAC_TIMER
priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL); priv->tm = kzalloc(sizeof(struct stmmac_timer *), GFP_KERNEL);
if (unlikely(priv->tm == NULL)) if (unlikely(priv->tm == NULL)) {
return -ENOMEM; ret = -ENOMEM;
goto open_clk_dis;
}
priv->tm->freq = tmrate; priv->tm->freq = tmrate;
...@@ -1034,6 +1038,8 @@ static int stmmac_open(struct net_device *dev) ...@@ -1034,6 +1038,8 @@ static int stmmac_open(struct net_device *dev)
if (priv->phydev) if (priv->phydev)
phy_disconnect(priv->phydev); phy_disconnect(priv->phydev);
open_clk_dis:
stmmac_clk_disable(priv);
return ret; return ret;
} }
...@@ -1086,6 +1092,7 @@ static int stmmac_release(struct net_device *dev) ...@@ -1086,6 +1092,7 @@ static int stmmac_release(struct net_device *dev)
stmmac_exit_fs(); stmmac_exit_fs();
#endif #endif
stmmac_mdio_unregister(dev); stmmac_mdio_unregister(dev);
stmmac_clk_disable(priv);
return 0; return 0;
} }
...@@ -1880,6 +1887,9 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device, ...@@ -1880,6 +1887,9 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
goto error; goto error;
} }
if (stmmac_clk_get(priv))
goto error;
return priv; return priv;
error: error:
...@@ -1949,9 +1959,11 @@ int stmmac_suspend(struct net_device *ndev) ...@@ -1949,9 +1959,11 @@ int stmmac_suspend(struct net_device *ndev)
/* Enable Power down mode by programming the PMT regs */ /* Enable Power down mode by programming the PMT regs */
if (device_may_wakeup(priv->device)) if (device_may_wakeup(priv->device))
priv->hw->mac->pmt(priv->ioaddr, priv->wolopts); priv->hw->mac->pmt(priv->ioaddr, priv->wolopts);
else else {
stmmac_set_mac(priv->ioaddr, false); stmmac_set_mac(priv->ioaddr, false);
/* Disable clock in case of PWM is off */
stmmac_clk_disable(priv);
}
spin_unlock(&priv->lock); spin_unlock(&priv->lock);
return 0; return 0;
} }
...@@ -1972,6 +1984,9 @@ int stmmac_resume(struct net_device *ndev) ...@@ -1972,6 +1984,9 @@ int stmmac_resume(struct net_device *ndev)
* from another devices (e.g. serial console). */ * from another devices (e.g. serial console). */
if (device_may_wakeup(priv->device)) if (device_may_wakeup(priv->device))
priv->hw->mac->pmt(priv->ioaddr, 0); priv->hw->mac->pmt(priv->ioaddr, 0);
else
/* enable the clk prevously disabled */
stmmac_clk_enable(priv);
netif_device_attach(ndev); netif_device_attach(ndev);
......
Markdown is supported
0% .
You are about to add 0 people to the discussion. Proceed with caution.
先完成此消息的编辑!
想要评论请 注册