The current driver depends on platform data to implement stop mode
request on/off that call api pdata->sleep_mode_enable().

To reduce arch platform redundancy code, since the function only set
SOC GPR register bit to request stop mode of/off, so we can move the
function into driver. And the specifix GPR register offset and MASK
bit can be transferred from DTS.

Signed-off-by: Fugang Duan <b38...@freescale.com>
---
 Documentation/devicetree/bindings/net/fsl-fec.txt |  3 +
 drivers/net/ethernet/freescale/fec.h              |  8 +++
 drivers/net/ethernet/freescale/fec_main.c         | 87 +++++++++++++++++++----
 3 files changed, 84 insertions(+), 14 deletions(-)

diff --git a/Documentation/devicetree/bindings/net/fsl-fec.txt 
b/Documentation/devicetree/bindings/net/fsl-fec.txt
index a9eb611..f0936c3 100644
--- a/Documentation/devicetree/bindings/net/fsl-fec.txt
+++ b/Documentation/devicetree/bindings/net/fsl-fec.txt
@@ -24,6 +24,9 @@ Optional properties:
   number to 1.
 - fsl,magic-packet : If present, indicates that the hardware supports waking
   up via magic packet.
+- fsl,wakeup_irq : The property defines the wakeup irq index in enet irq 
source.
+- stop-mode : The property defines gpr register bits of stop mode control, the
+  format is <&gpr req_gpr req_bit>.
 
 Optional subnodes:
 - mdio : specifies the mdio bus in the FEC, used as a container for phy nodes
diff --git a/drivers/net/ethernet/freescale/fec.h 
b/drivers/net/ethernet/freescale/fec.h
index 1eee73c..1a09b68 100644
--- a/drivers/net/ethernet/freescale/fec.h
+++ b/drivers/net/ethernet/freescale/fec.h
@@ -431,6 +431,12 @@ struct bufdesc_ex {
 /* Controller supports RACC register */
 #define FEC_QUIRK_HAS_RACC             (1 << 12)
 
+struct fec_enet_stop_mode {
+       struct regmap *gpr;
+       u8 req_gpr;
+       u8 req_bit;
+};
+
 struct fec_enet_priv_tx_q {
        int index;
        unsigned char *tx_bounce[TX_RING_SIZE];
@@ -518,6 +524,8 @@ struct fec_enet_private {
        bool    bufdesc_ex;
        int     pause_flag;
        int     wol_flag;
+       int     wake_irq;
+       struct  fec_enet_stop_mode gprctl;
        u32     quirks;
 
        struct  napi_struct napi;
diff --git a/drivers/net/ethernet/freescale/fec_main.c 
b/drivers/net/ethernet/freescale/fec_main.c
index 1f89c59..8ab03f4 100644
--- a/drivers/net/ethernet/freescale/fec_main.c
+++ b/drivers/net/ethernet/freescale/fec_main.c
@@ -58,6 +58,8 @@
 #include <linux/if_vlan.h>
 #include <linux/pinctrl/consumer.h>
 #include <linux/prefetch.h>
+#include <linux/mfd/syscon.h>
+#include <linux/regmap.h>
 
 #include <asm/cacheflush.h>
 
@@ -1099,11 +1101,27 @@ fec_restart(struct net_device *ndev)
 
 }
 
+static int fec_enet_stop_mode(struct fec_enet_private *fep, bool enabled)
+{
+       if (IS_ERR_OR_NULL(fep->gprctl.gpr))
+               return 0;
+
+       if (enabled)
+               regmap_update_bits(fep->gprctl.gpr, fep->gprctl.req_gpr,
+                                  1 << fep->gprctl.req_bit,
+                                  1 << fep->gprctl.req_bit);
+       else
+               regmap_update_bits(fep->gprctl.gpr, fep->gprctl.req_gpr,
+                                  1 << fep->gprctl.req_bit,
+                                  0);
+
+       return 0;
+}
+
 static void
 fec_stop(struct net_device *ndev)
 {
        struct fec_enet_private *fep = netdev_priv(ndev);
-       struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
        u32 rmii_mode = readl(fep->hwp + FEC_R_CNTRL) & (1 << 8);
        u32 val;
 
@@ -1133,8 +1151,7 @@ fec_stop(struct net_device *ndev)
                val |= (FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
                writel(val, fep->hwp + FEC_ECNTRL);
 
-               if (pdata && pdata->sleep_mode_enable)
-                       pdata->sleep_mode_enable(true);
+               fec_enet_stop_mode(fep, true);
        }
        writel(fep->phy_speed, fep->hwp + FEC_MII_SPEED);
 
@@ -2578,15 +2595,10 @@ fec_enet_set_wol(struct net_device *ndev, struct 
ethtool_wolinfo *wol)
                return -EINVAL;
 
        device_set_wakeup_enable(&ndev->dev, wol->wolopts & WAKE_MAGIC);
-       if (device_may_wakeup(&ndev->dev)) {
+       if (device_may_wakeup(&ndev->dev))
                fep->wol_flag |= FEC_WOL_FLAG_ENABLE;
-               if (fep->irq[0] > 0)
-                       enable_irq_wake(fep->irq[0]);
-       } else {
+       else
                fep->wol_flag &= (~FEC_WOL_FLAG_ENABLE);
-               if (fep->irq[0] > 0)
-                       disable_irq_wake(fep->irq[0]);
-       }
 
        return 0;
 }
@@ -3267,6 +3279,41 @@ fec_enet_get_queue_num(struct platform_device *pdev, int 
*num_tx, int *num_rx)
 
 }
 
+static void fec_enet_of_parse_stop_mode(struct platform_device *pdev)
+{
+       struct net_device *dev = platform_get_drvdata(pdev);
+       struct device_node *np = pdev->dev.of_node;
+       struct fec_enet_private *fep = netdev_priv(dev);
+       struct device_node *node;
+       phandle phandle;
+       u32 out_val[3];
+       int ret;
+
+       ret = of_property_read_u32_array(np, "stop-mode", out_val, 3);
+       if (ret) {
+               dev_dbg(&pdev->dev, "no stop-mode property\n");
+               return;
+       }
+
+       phandle = *out_val;
+       node = of_find_node_by_phandle(phandle);
+       if (!node) {
+               dev_dbg(&pdev->dev, "could not find gpr node by phandle\n");
+               return;
+       }
+
+       fep->gprctl.gpr = syscon_node_to_regmap(node);
+       if (IS_ERR(fep->gprctl.gpr)) {
+               dev_dbg(&pdev->dev, "could not find gpr regmap\n");
+               return;
+       }
+
+       of_node_put(node);
+
+       fep->gprctl.req_gpr = out_val[1];
+       fep->gprctl.req_bit = out_val[2];
+}
+
 static int
 fec_probe(struct platform_device *pdev)
 {
@@ -3324,6 +3371,8 @@ fec_probe(struct platform_device *pdev)
 
        platform_set_drvdata(pdev, ndev);
 
+       fec_enet_of_parse_stop_mode(pdev);
+
        if (of_get_property(np, "fsl,magic-packet", NULL))
                fep->wol_flag |= FEC_WOL_HAS_MAGIC_PACKET;
 
@@ -3425,6 +3474,12 @@ fec_probe(struct platform_device *pdev)
                fep->irq[i] = irq;
        }
 
+       ret = of_property_read_u32(np, "fsl,wakeup_irq", &irq);
+       if (!ret && irq < FEC_IRQ_NUM)
+               fep->wake_irq = fep->irq[irq];
+       else
+               fep->wake_irq = fep->irq[0];
+
        init_completion(&fep->mdio_done);
        ret = fec_enet_mii_init(pdev);
        if (ret)
@@ -3503,8 +3558,12 @@ static int __maybe_unused fec_suspend(struct device *dev)
                netif_tx_unlock_bh(ndev);
                fec_stop(ndev);
                fec_enet_clk_enable(ndev, false);
-               if (!(fep->wol_flag & FEC_WOL_FLAG_ENABLE))
+               if (!(fep->wol_flag & FEC_WOL_FLAG_ENABLE)) {
                        pinctrl_pm_select_sleep_state(&fep->pdev->dev);
+               } else {
+                       disable_irq(fep->wake_irq);
+                       enable_irq_wake(fep->wake_irq);
+               }
        }
        rtnl_unlock();
 
@@ -3524,7 +3583,6 @@ static int __maybe_unused fec_resume(struct device *dev)
 {
        struct net_device *ndev = dev_get_drvdata(dev);
        struct fec_enet_private *fep = netdev_priv(ndev);
-       struct fec_platform_data *pdata = fep->pdev->dev.platform_data;
        int ret;
        int val;
 
@@ -3542,8 +3600,9 @@ static int __maybe_unused fec_resume(struct device *dev)
                        goto failed_clk;
                }
                if (fep->wol_flag & FEC_WOL_FLAG_ENABLE) {
-                       if (pdata && pdata->sleep_mode_enable)
-                               pdata->sleep_mode_enable(false);
+                       disable_irq_wake(fep->wake_irq);
+                       fec_enet_stop_mode(fep, false);
+                       enable_irq(fep->wake_irq);
                        val = readl(fep->hwp + FEC_ECNTRL);
                        val &= ~(FEC_ECR_MAGICEN | FEC_ECR_SLEEP);
                        writel(val, fep->hwp + FEC_ECNTRL);
-- 
1.9.1

--
To unsubscribe from this list: send the line "unsubscribe netdev" in
the body of a message to majord...@vger.kernel.org
More majordomo info at  http://vger.kernel.org/majordomo-info.html

Reply via email to