1 From 1d20d3bd16eac561e14513c9e6cac543fab5a3f0 Mon Sep 17 00:00:00 2001
2 From: Yuichi Kusakabe <yuichi.kusakabe@jp.fujitsu.com>
3 Date: Thu, 18 May 2017 17:42:33 +0900
4 Subject: [PATCH 10/15] Add rcar-eth hibernation code
6 Signed-off-by: Yuichi Kusakabe <yuichi.kusakabe@jp.fujitsu.com>
8 drivers/net/ethernet/renesas/sh_eth.c | 57 +++++++++++++++++++++++++++++++++--
9 drivers/net/phy/phy_device.c | 41 +++++++++++++++++++++++++
10 2 files changed, 95 insertions(+), 3 deletions(-)
12 diff --git a/drivers/net/ethernet/renesas/sh_eth.c b/drivers/net/ethernet/renesas/sh_eth.c
13 index 991fa1e..7e91b26 100644
14 --- a/drivers/net/ethernet/renesas/sh_eth.c
15 +++ b/drivers/net/ethernet/renesas/sh_eth.c
18 #include <linux/of_device.h>
19 #include <linux/of_irq.h>
20 +#include <linux/of_gpio.h>
21 #include <linux/of_net.h>
22 #include <linux/phy.h>
23 #include <linux/cache.h>
24 @@ -999,6 +1000,7 @@ static unsigned long sh_eth_get_edtrr_trns(struct sh_eth_private *mdp)
26 void (*set_gate)(void *addr);
27 struct mdiobb_ctrl ctrl;
28 + struct sh_eth_private *mdp;
32 @@ -1029,6 +1031,8 @@ static void sh_mmd_ctrl(struct mdiobb_ctrl *ctrl, int bit)
34 struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
36 + pm_runtime_get_sync(&bitbang->mdp->pdev->dev);
38 if (bitbang->set_gate)
39 bitbang->set_gate(bitbang->addr);
41 @@ -1036,6 +1040,8 @@ static void sh_mmd_ctrl(struct mdiobb_ctrl *ctrl, int bit)
42 bb_set(bitbang->addr, bitbang->mmd_msk);
44 bb_clr(bitbang->addr, bitbang->mmd_msk);
46 + pm_runtime_put_sync(&bitbang->mdp->pdev->dev);
50 @@ -1043,6 +1049,8 @@ static void sh_set_mdio(struct mdiobb_ctrl *ctrl, int bit)
52 struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
54 + pm_runtime_get_sync(&bitbang->mdp->pdev->dev);
56 if (bitbang->set_gate)
57 bitbang->set_gate(bitbang->addr);
59 @@ -1050,17 +1058,26 @@ static void sh_set_mdio(struct mdiobb_ctrl *ctrl, int bit)
60 bb_set(bitbang->addr, bitbang->mdo_msk);
62 bb_clr(bitbang->addr, bitbang->mdo_msk);
64 + pm_runtime_put_sync(&bitbang->mdp->pdev->dev);
68 static int sh_get_mdio(struct mdiobb_ctrl *ctrl)
70 struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
73 + pm_runtime_get_sync(&bitbang->mdp->pdev->dev);
75 if (bitbang->set_gate)
76 bitbang->set_gate(bitbang->addr);
78 - return bb_read(bitbang->addr, bitbang->mdi_msk);
79 + ret = bb_read(bitbang->addr, bitbang->mdi_msk);
81 + pm_runtime_put_sync(&bitbang->mdp->pdev->dev);
87 @@ -1068,6 +1085,8 @@ static void sh_mdc_ctrl(struct mdiobb_ctrl *ctrl, int bit)
89 struct bb_info *bitbang = container_of(ctrl, struct bb_info, ctrl);
91 + pm_runtime_get_sync(&bitbang->mdp->pdev->dev);
93 if (bitbang->set_gate)
94 bitbang->set_gate(bitbang->addr);
96 @@ -1075,6 +1094,8 @@ static void sh_mdc_ctrl(struct mdiobb_ctrl *ctrl, int bit)
97 bb_set(bitbang->addr, bitbang->mdc_msk);
99 bb_clr(bitbang->addr, bitbang->mdc_msk);
101 + pm_runtime_put_sync(&bitbang->mdp->pdev->dev);
104 /* mdio bus control struct */
105 @@ -2664,6 +2685,7 @@ static int sh_mdio_init(struct sh_eth_private *mdp,
106 bitbang->mdo_msk = PIR_MDO;
107 bitbang->mmd_msk = PIR_MMD;
108 bitbang->mdc_msk = PIR_MDC;
109 + bitbang->mdp = mdp;
110 bitbang->ctrl.ops = &bb_ops;
112 /* MII controller setting */
113 @@ -3002,9 +3024,38 @@ static int sh_eth_runtime_nop(struct device *dev)
117 +static int sh_eth_suspend(struct device *dev)
120 + struct net_device *ndev = dev_get_drvdata(dev);
122 + if (netif_running(ndev)) {
123 + netif_device_detach(ndev);
124 + ret = sh_eth_close(ndev);
130 +static int sh_eth_resume(struct device *dev)
133 + struct net_device *ndev = dev_get_drvdata(dev);
135 + if (netif_running(ndev)) {
136 + ret = sh_eth_open(ndev);
139 + netif_device_attach(ndev);
146 static const struct dev_pm_ops sh_eth_dev_pm_ops = {
147 - .runtime_suspend = sh_eth_runtime_nop,
148 - .runtime_resume = sh_eth_runtime_nop,
149 + SET_RUNTIME_PM_OPS(sh_eth_runtime_nop, sh_eth_runtime_nop, NULL)
150 + SET_SYSTEM_SLEEP_PM_OPS(sh_eth_suspend, sh_eth_resume)
152 #define SH_ETH_PM_OPS (&sh_eth_dev_pm_ops)
154 diff --git a/drivers/net/phy/phy_device.c b/drivers/net/phy/phy_device.c
155 index 3657b4a..3ceb4f9 100644
156 --- a/drivers/net/phy/phy_device.c
157 +++ b/drivers/net/phy/phy_device.c
158 @@ -510,6 +510,32 @@ int phy_init_hw(struct phy_device *phydev)
159 return phydev->drv->config_init(phydev);
162 +int phy_suspend(struct phy_device *phydev)
164 + struct phy_driver *phydrv = to_phy_driver(phydev->dev.driver);
165 + struct ethtool_wolinfo wol = { .cmd = ETHTOOL_GWOL };
167 + /* If the device has WOL enabled, we cannot suspend the PHY */
168 + phy_ethtool_get_wol(phydev, &wol);
172 + if (phydrv->suspend)
173 + return phydrv->suspend(phydev);
176 +EXPORT_SYMBOL(phy_suspend);
178 +int phy_resume(struct phy_device *phydev)
180 + struct phy_driver *phydrv = to_phy_driver(phydev->dev.driver);
182 + if (phydrv->resume)
183 + return phydrv->resume(phydev);
186 +EXPORT_SYMBOL(phy_resume);
189 * phy_attach_direct - attach a network device to a given PHY device pointer
190 * @dev: network device to attach
191 @@ -528,6 +554,7 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
192 u32 flags, phy_interface_t interface)
194 struct device *d = &phydev->dev;
195 + struct module *bus_module;
198 /* Assume that if there is no driver, that it doesn't
199 @@ -553,6 +580,14 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
203 + /* Increment the bus module reference count */
204 + bus_module = phydev->bus->dev.driver ?
205 + phydev->bus->dev.driver->owner : NULL;
206 + if (!try_module_get(bus_module)) {
207 + dev_err(&dev->dev, "failed to get the bus module\n");
211 phydev->attached_dev = dev;
212 dev->phydev = phydev;
214 @@ -568,6 +603,8 @@ static int phy_attach_direct(struct net_device *dev, struct phy_device *phydev,
215 err = phy_init_hw(phydev);
219 + phy_resume(phydev);
223 @@ -612,8 +649,12 @@ EXPORT_SYMBOL(phy_attach);
225 void phy_detach(struct phy_device *phydev)
227 + if (phydev->bus->dev.driver)
228 + module_put(phydev->bus->dev.driver->owner);
230 phydev->attached_dev->phydev = NULL;
231 phydev->attached_dev = NULL;
232 + phy_suspend(phydev);
234 /* If the device had no specific driver before (i.e. - it
235 * was using the generic driver), we unbind the device