aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorFlorian Fainelli <f.fainelli@gmail.com>2014-11-26 00:16:35 -0500
committerDavid S. Miller <davem@davemloft.net>2014-11-26 15:08:05 -0500
commit6ef398ea60d931b97d69ed080bd0bd00fac38ec6 (patch)
treecab57c23b1a3506cd0ae88c80540f475d517b219
parentd0a6db8dd05da6d65ac1ba111da911de6a34d76a (diff)
net: bcmgenet: add EEE support
Allow enabling and disabling EEE using the designated ethtool getters and setters. GENET allows controlling EEE at the UniMAC, RBUF and TBUF levels. We also take care of restoring EEE after a suspend/resume cycle if it was enabled prior to suspending. Signed-off-by: Florian Fainelli <f.fainelli@gmail.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.c96
-rw-r--r--drivers/net/ethernet/broadcom/genet/bcmgenet.h4
2 files changed, 100 insertions, 0 deletions
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.c b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
index fcbf1255ae5a..bf44e0e23799 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.c
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.c
@@ -714,6 +714,91 @@ static void bcmgenet_get_ethtool_stats(struct net_device *dev,
714 } 714 }
715} 715}
716 716
717static void bcmgenet_eee_enable_set(struct net_device *dev, bool enable)
718{
719 struct bcmgenet_priv *priv = netdev_priv(dev);
720 u32 off = priv->hw_params->tbuf_offset + TBUF_ENERGY_CTRL;
721 u32 reg;
722
723 if (enable && !priv->clk_eee_enabled) {
724 clk_prepare_enable(priv->clk_eee);
725 priv->clk_eee_enabled = true;
726 }
727
728 reg = bcmgenet_umac_readl(priv, UMAC_EEE_CTRL);
729 if (enable)
730 reg |= EEE_EN;
731 else
732 reg &= ~EEE_EN;
733 bcmgenet_umac_writel(priv, reg, UMAC_EEE_CTRL);
734
735 /* Enable EEE and switch to a 27Mhz clock automatically */
736 reg = __raw_readl(priv->base + off);
737 if (enable)
738 reg |= TBUF_EEE_EN | TBUF_PM_EN;
739 else
740 reg &= ~(TBUF_EEE_EN | TBUF_PM_EN);
741 __raw_writel(reg, priv->base + off);
742
743 /* Do the same for thing for RBUF */
744 reg = bcmgenet_rbuf_readl(priv, RBUF_ENERGY_CTRL);
745 if (enable)
746 reg |= RBUF_EEE_EN | RBUF_PM_EN;
747 else
748 reg &= ~(RBUF_EEE_EN | RBUF_PM_EN);
749 bcmgenet_rbuf_writel(priv, reg, RBUF_ENERGY_CTRL);
750
751 if (!enable && priv->clk_eee_enabled) {
752 clk_disable_unprepare(priv->clk_eee);
753 priv->clk_eee_enabled = false;
754 }
755
756 priv->eee.eee_enabled = enable;
757 priv->eee.eee_active = enable;
758}
759
760static int bcmgenet_get_eee(struct net_device *dev, struct ethtool_eee *e)
761{
762 struct bcmgenet_priv *priv = netdev_priv(dev);
763 struct ethtool_eee *p = &priv->eee;
764
765 if (GENET_IS_V1(priv))
766 return -EOPNOTSUPP;
767
768 e->eee_enabled = p->eee_enabled;
769 e->eee_active = p->eee_active;
770 e->tx_lpi_timer = bcmgenet_umac_readl(priv, UMAC_EEE_LPI_TIMER);
771
772 return phy_ethtool_get_eee(priv->phydev, e);
773}
774
775static int bcmgenet_set_eee(struct net_device *dev, struct ethtool_eee *e)
776{
777 struct bcmgenet_priv *priv = netdev_priv(dev);
778 struct ethtool_eee *p = &priv->eee;
779 int ret = 0;
780
781 if (GENET_IS_V1(priv))
782 return -EOPNOTSUPP;
783
784 p->eee_enabled = e->eee_enabled;
785
786 if (!p->eee_enabled) {
787 bcmgenet_eee_enable_set(dev, false);
788 } else {
789 ret = phy_init_eee(priv->phydev, 0);
790 if (ret) {
791 netif_err(priv, hw, dev, "EEE initialization failed\n");
792 return ret;
793 }
794
795 bcmgenet_umac_writel(priv, e->tx_lpi_timer, UMAC_EEE_LPI_TIMER);
796 bcmgenet_eee_enable_set(dev, true);
797 }
798
799 return phy_ethtool_set_eee(priv->phydev, e);
800}
801
717/* standard ethtool support functions. */ 802/* standard ethtool support functions. */
718static struct ethtool_ops bcmgenet_ethtool_ops = { 803static struct ethtool_ops bcmgenet_ethtool_ops = {
719 .get_strings = bcmgenet_get_strings, 804 .get_strings = bcmgenet_get_strings,
@@ -727,6 +812,8 @@ static struct ethtool_ops bcmgenet_ethtool_ops = {
727 .set_msglevel = bcmgenet_set_msglevel, 812 .set_msglevel = bcmgenet_set_msglevel,
728 .get_wol = bcmgenet_get_wol, 813 .get_wol = bcmgenet_get_wol,
729 .set_wol = bcmgenet_set_wol, 814 .set_wol = bcmgenet_set_wol,
815 .get_eee = bcmgenet_get_eee,
816 .set_eee = bcmgenet_set_eee,
730}; 817};
731 818
732/* Power down the unimac, based on mode. */ 819/* Power down the unimac, based on mode. */
@@ -2585,6 +2672,12 @@ static int bcmgenet_probe(struct platform_device *pdev)
2585 if (IS_ERR(priv->clk_wol)) 2672 if (IS_ERR(priv->clk_wol))
2586 dev_warn(&priv->pdev->dev, "failed to get enet-wol clock\n"); 2673 dev_warn(&priv->pdev->dev, "failed to get enet-wol clock\n");
2587 2674
2675 priv->clk_eee = devm_clk_get(&priv->pdev->dev, "enet-eee");
2676 if (IS_ERR(priv->clk_eee)) {
2677 dev_warn(&priv->pdev->dev, "failed to get enet-eee clock\n");
2678 priv->clk_eee = NULL;
2679 }
2680
2588 err = reset_umac(priv); 2681 err = reset_umac(priv);
2589 if (err) 2682 if (err)
2590 goto err_clk_disable; 2683 goto err_clk_disable;
@@ -2735,6 +2828,9 @@ static int bcmgenet_resume(struct device *d)
2735 2828
2736 phy_resume(priv->phydev); 2829 phy_resume(priv->phydev);
2737 2830
2831 if (priv->eee.eee_enabled)
2832 bcmgenet_eee_enable_set(dev, true);
2833
2738 bcmgenet_netif_start(dev); 2834 bcmgenet_netif_start(dev);
2739 2835
2740 return 0; 2836 return 0;
diff --git a/drivers/net/ethernet/broadcom/genet/bcmgenet.h b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
index ea6f0ab566bf..b36ddec0cc0a 100644
--- a/drivers/net/ethernet/broadcom/genet/bcmgenet.h
+++ b/drivers/net/ethernet/broadcom/genet/bcmgenet.h
@@ -573,6 +573,8 @@ struct bcmgenet_priv {
573 struct device_node *phy_dn; 573 struct device_node *phy_dn;
574 struct mii_bus *mii_bus; 574 struct mii_bus *mii_bus;
575 u16 gphy_rev; 575 u16 gphy_rev;
576 struct clk *clk_eee;
577 bool clk_eee_enabled;
576 578
577 /* PHY device variables */ 579 /* PHY device variables */
578 int old_link; 580 int old_link;
@@ -609,6 +611,8 @@ struct bcmgenet_priv {
609 u32 wolopts; 611 u32 wolopts;
610 612
611 struct bcmgenet_mib_counters mib; 613 struct bcmgenet_mib_counters mib;
614
615 struct ethtool_eee eee;
612}; 616};
613 617
614#define GENET_IO_MACRO(name, offset) \ 618#define GENET_IO_MACRO(name, offset) \