Commit 1585a8ae authored by David S. Miller's avatar David S. Miller

Merge branch 'bcmgenet_eee'

Florian Fainelli says:

====================
net: bcmgenet: EEE support

This patch series add EEE support to the Broadcom GENET driver, first patch
basically adds register definitions for the hardware, the second patch does the
actual implementation and hooks the {get,set}_eee ethtool callbacks, the last
patch adds auto-negotiation restart capability.
====================
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parents 8b7f8a99 6b0c5406
......@@ -714,6 +714,98 @@ static void bcmgenet_get_ethtool_stats(struct net_device *dev,
}
}
static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
u32 off = priv->hw_params->tbuf_offset + TBUF_ENERGY_CTRL;
u32 reg;
if (enable && !priv->clk_eee_enabled) {
clk_prepare_enable(priv->clk_eee);
priv->clk_eee_enabled = true;
}
reg = bcmgenet_umac_readl(priv, UMAC_EEE_CTRL);
if (enable)
reg |= EEE_EN;
else
reg &= ~EEE_EN;
bcmgenet_umac_writel(priv, reg, UMAC_EEE_CTRL);
/* Enable EEE and switch to a 27Mhz clock automatically */
reg = __raw_readl(priv->base + off);
if (enable)
reg |= TBUF_EEE_EN | TBUF_PM_EN;
else
reg &= ~(TBUF_EEE_EN | TBUF_PM_EN);
__raw_writel(reg, priv->base + off);
/* Do the same for thing for RBUF */
reg = bcmgenet_rbuf_readl(priv, RBUF_ENERGY_CTRL);
if (enable)
reg |= RBUF_EEE_EN | RBUF_PM_EN;
else
reg &= ~(RBUF_EEE_EN | RBUF_PM_EN);
bcmgenet_rbuf_writel(priv, reg, RBUF_ENERGY_CTRL);
if (!enable && priv->clk_eee_enabled) {
clk_disable_unprepare(priv->clk_eee);
priv->clk_eee_enabled = false;
}
priv->eee.eee_enabled = enable;
priv->eee.eee_active = enable;
}
static int bcmgenet_get_eee(struct net_device *dev, struct ethtool_eee *e)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
struct ethtool_eee *p = &priv->eee;
if (GENET_IS_V1(priv))
return -EOPNOTSUPP;
e->eee_enabled = p->eee_enabled;
e->eee_active = p->eee_active;
e->tx_lpi_timer = bcmgenet_umac_readl(priv, UMAC_EEE_LPI_TIMER);
return phy_ethtool_get_eee(priv->phydev, e);
}
static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
struct ethtool_eee *p = &priv->eee;
int ret = 0;
if (GENET_IS_V1(priv))
return -EOPNOTSUPP;
p->eee_enabled = e->eee_enabled;
if (!p->eee_enabled) {
bcmgenet_eee_enable_set(dev, false);
} else {
ret = phy_init_eee(priv->phydev, 0);
if (ret) {
netif_err(priv, hw, dev, "EEE initialization failed\n");
return ret;
}
bcmgenet_umac_writel(priv, e->tx_lpi_timer, UMAC_EEE_LPI_TIMER);
bcmgenet_eee_enable_set(dev, true);
}
return phy_ethtool_set_eee(priv->phydev, e);
}
static int bcmgenet_nway_reset(struct net_device *dev)
{
struct bcmgenet_priv *priv = netdev_priv(dev);
return genphy_restart_aneg(priv->phydev);
}
/* standard ethtool support functions. */
static struct ethtool_ops bcmgenet_ethtool_ops = {
.get_strings = bcmgenet_get_strings,
......@@ -727,6 +819,9 @@ static struct ethtool_ops bcmgenet_ethtool_ops = {
.set_msglevel = bcmgenet_set_msglevel,
.get_wol = bcmgenet_get_wol,
.set_wol = bcmgenet_set_wol,
.get_eee = bcmgenet_get_eee,
.set_eee = bcmgenet_set_eee,
.nway_reset = bcmgenet_nway_reset,
};
/* Power down the unimac, based on mode. */
......@@ -2585,6 +2680,12 @@ static int bcmgenet_probe(struct platform_device *pdev)
if (IS_ERR(priv->clk_wol))
dev_warn(&priv->pdev->dev, "failed to get enet-wol clock\n");
priv->clk_eee = devm_clk_get(&priv->pdev->dev, "enet-eee");
if (IS_ERR(priv->clk_eee)) {
dev_warn(&priv->pdev->dev, "failed to get enet-eee clock\n");
priv->clk_eee = NULL;
}
err = reset_umac(priv);
if (err)
goto err_clk_disable;
......@@ -2735,6 +2836,9 @@ static int bcmgenet_resume(struct device *d)
phy_resume(priv->phydev);
if (priv->eee.eee_enabled)
bcmgenet_eee_enable_set(dev, true);
bcmgenet_netif_start(dev);
return 0;
......
......@@ -185,6 +185,21 @@ struct bcmgenet_mib_counters {
#define UMAC_MAC1 0x010
#define UMAC_MAX_FRAME_LEN 0x014
#define UMAC_EEE_CTRL 0x064
#define EN_LPI_RX_PAUSE (1 << 0)
#define EN_LPI_TX_PFC (1 << 1)
#define EN_LPI_TX_PAUSE (1 << 2)
#define EEE_EN (1 << 3)
#define RX_FIFO_CHECK (1 << 4)
#define EEE_TX_CLK_DIS (1 << 5)
#define DIS_EEE_10M (1 << 6)
#define LP_IDLE_PREDICTION_MODE (1 << 7)
#define UMAC_EEE_LPI_TIMER 0x068
#define UMAC_EEE_WAKE_TIMER 0x06C
#define UMAC_EEE_REF_COUNT 0x070
#define EEE_REFERENCE_COUNT_MASK 0xffff
#define UMAC_TX_FLUSH 0x334
#define UMAC_MIB_START 0x400
......@@ -232,6 +247,10 @@ struct bcmgenet_mib_counters {
#define RBUF_RXCHK_EN (1 << 0)
#define RBUF_SKIP_FCS (1 << 4)
#define RBUF_ENERGY_CTRL 0x9c
#define RBUF_EEE_EN (1 << 0)
#define RBUF_PM_EN (1 << 1)
#define RBUF_TBUF_SIZE_CTRL 0xb4
#define RBUF_HFB_CTRL_V1 0x38
......@@ -247,6 +266,9 @@ struct bcmgenet_mib_counters {
#define TBUF_CTRL 0x00
#define TBUF_BP_MC 0x0C
#define TBUF_ENERGY_CTRL 0x14
#define TBUF_EEE_EN (1 << 0)
#define TBUF_PM_EN (1 << 1)
#define TBUF_CTRL_V1 0x80
#define TBUF_BP_MC_V1 0xA0
......@@ -551,6 +573,8 @@ struct bcmgenet_priv {
struct device_node *phy_dn;
struct mii_bus *mii_bus;
u16 gphy_rev;
struct clk *clk_eee;
bool clk_eee_enabled;
/* PHY device variables */
int old_link;
......@@ -587,6 +611,8 @@ struct bcmgenet_priv {
u32 wolopts;
struct bcmgenet_mib_counters mib;
struct ethtool_eee eee;
};
#define GENET_IO_MACRO(name, offset) \
......
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