aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Vasut <marex@denx.de>2016-04-21 08:11:50 -0400
committerDavid S. Miller <davem@davemloft.net>2016-04-24 14:40:24 -0400
commit3c201b5a84edd6ee2f9a8548efaa813980839b46 (patch)
tree3938e7e589409f246d1f805824098ecc2bc937d3
parentb6742cab0d79708d54774ce615c8c96ad71ce40b (diff)
net: stmmac: socfpga: Remove re-registration of reset controller
Both socfpga_dwmac_parse_data() in dwmac-socfpga.c and stmmac_dvr_probe() in stmmac_main.c functions call devm_reset_control_get() to register an reset controller for the stmmac. This results in an attempt to register two reset controllers for the same non-shared reset line. The first attempt to register the reset controller works fine. The second attempt fails with warning from the reset controller core, see below. The warning is produced because the reset line is non-shared and thus it is allowed to have only up-to one reset controller associated with that reset line, not two or more. The solution has multiple parts. First, the original socfpga_dwmac_init() is tweaked to use reset controller pointer from the stmmac_priv (private data of the stmmac core) instead of the local instance, which was used before. The local re-registration of the reset controller is removed. Next, the socfpga_dwmac_init() is moved after stmmac_dvr_probe() in the probe function. This order is legal according to Altera and it makes the code much easier, since there is no need to temporarily register and unregister the reset controller ; the reset controller is already registered by the stmmac_dvr_probe(). Finally, plat_dat->exit and socfpga_dwmac_exit() is no longer necessary, since the functionality is already performed by the stmmac core. ------------[ cut here ]------------ WARNING: CPU: 0 PID: 1 at drivers/reset/core.c:187 __of_reset_control_get+0x218/0x270 Modules linked in: CPU: 0 PID: 1 Comm: swapper/0 Not tainted 4.6.0-rc4-next-20160419-00015-gabb2477-dirty #4 Hardware name: Altera SOCFPGA [<c010f290>] (unwind_backtrace) from [<c010b82c>] (show_stack+0x10/0x14) [<c010b82c>] (show_stack) from [<c0373da4>] (dump_stack+0x94/0xa8) [<c0373da4>] (dump_stack) from [<c011bcc0>] (__warn+0xec/0x104) [<c011bcc0>] (__warn) from [<c011bd88>] (warn_slowpath_null+0x20/0x28) [<c011bd88>] (warn_slowpath_null) from [<c03a6eb4>] (__of_reset_control_get+0x218/0x270) [<c03a6eb4>] (__of_reset_control_get) from [<c03a701c>] (__devm_reset_control_get+0x54/0x90) [<c03a701c>] (__devm_reset_control_get) from [<c041fa30>] (stmmac_dvr_probe+0x1b4/0x8e8) [<c041fa30>] (stmmac_dvr_probe) from [<c04298c8>] (socfpga_dwmac_probe+0x1b8/0x28c) [<c04298c8>] (socfpga_dwmac_probe) from [<c03d6ffc>] (platform_drv_probe+0x4c/0xb0) [<c03d6ffc>] (platform_drv_probe) from [<c03d54ec>] (driver_probe_device+0x224/0x2bc) [<c03d54ec>] (driver_probe_device) from [<c03d5630>] (__driver_attach+0xac/0xb0) [<c03d5630>] (__driver_attach) from [<c03d382c>] (bus_for_each_dev+0x6c/0xa0) [<c03d382c>] (bus_for_each_dev) from [<c03d4ad4>] (bus_add_driver+0x1a4/0x21c) [<c03d4ad4>] (bus_add_driver) from [<c03d60ac>] (driver_register+0x78/0xf8) [<c03d60ac>] (driver_register) from [<c0101760>] (do_one_initcall+0x40/0x170) [<c0101760>] (do_one_initcall) from [<c0800e38>] (kernel_init_freeable+0x1dc/0x27c) [<c0800e38>] (kernel_init_freeable) from [<c05d1bd4>] (kernel_init+0x8/0x114) [<c05d1bd4>] (kernel_init) from [<c01076f8>] (ret_from_fork+0x14/0x3c) ---[ end trace 059d2fbe87608fa9 ]--- Signed-off-by: Marek Vasut <marex@denx.de> Cc: Matthew Gerlach <mgerlach@opensource.altera.com> Cc: Dinh Nguyen <dinguyen@opensource.altera.com> Cc: David S. Miller <davem@davemloft.net> Tested-by: Dinh Nguyen <dinguyen@opensource.altera.com> Signed-off-by: David S. Miller <davem@davemloft.net>
-rw-r--r--drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c50
1 files changed, 16 insertions, 34 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
index 44022b1845ce..afb90d129cb6 100644
--- a/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
+++ b/drivers/net/ethernet/stmicro/stmmac/dwmac-socfpga.c
@@ -49,7 +49,6 @@ struct socfpga_dwmac {
49 u32 reg_shift; 49 u32 reg_shift;
50 struct device *dev; 50 struct device *dev;
51 struct regmap *sys_mgr_base_addr; 51 struct regmap *sys_mgr_base_addr;
52 struct reset_control *stmmac_rst;
53 void __iomem *splitter_base; 52 void __iomem *splitter_base;
54 bool f2h_ptp_ref_clk; 53 bool f2h_ptp_ref_clk;
55}; 54};
@@ -92,15 +91,6 @@ static int socfpga_dwmac_parse_data(struct socfpga_dwmac *dwmac, struct device *
92 struct device_node *np_splitter; 91 struct device_node *np_splitter;
93 struct resource res_splitter; 92 struct resource res_splitter;
94 93
95 dwmac->stmmac_rst = devm_reset_control_get(dev,
96 STMMAC_RESOURCE_NAME);
97 if (IS_ERR(dwmac->stmmac_rst)) {
98 dev_info(dev, "Could not get reset control!\n");
99 if (PTR_ERR(dwmac->stmmac_rst) == -EPROBE_DEFER)
100 return -EPROBE_DEFER;
101 dwmac->stmmac_rst = NULL;
102 }
103
104 dwmac->interface = of_get_phy_mode(np); 94 dwmac->interface = of_get_phy_mode(np);
105 95
106 sys_mgr_base_addr = syscon_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon"); 96 sys_mgr_base_addr = syscon_regmap_lookup_by_phandle(np, "altr,sysmgr-syscon");
@@ -194,30 +184,23 @@ static int socfpga_dwmac_setup(struct socfpga_dwmac *dwmac)
194 return 0; 184 return 0;
195} 185}
196 186
197static void socfpga_dwmac_exit(struct platform_device *pdev, void *priv)
198{
199 struct socfpga_dwmac *dwmac = priv;
200
201 /* On socfpga platform exit, assert and hold reset to the
202 * enet controller - the default state after a hard reset.
203 */
204 if (dwmac->stmmac_rst)
205 reset_control_assert(dwmac->stmmac_rst);
206}
207
208static int socfpga_dwmac_init(struct platform_device *pdev, void *priv) 187static int socfpga_dwmac_init(struct platform_device *pdev, void *priv)
209{ 188{
210 struct socfpga_dwmac *dwmac = priv; 189 struct socfpga_dwmac *dwmac = priv;
211 struct net_device *ndev = platform_get_drvdata(pdev); 190 struct net_device *ndev = platform_get_drvdata(pdev);
212 struct stmmac_priv *stpriv = NULL; 191 struct stmmac_priv *stpriv = NULL;
213 int ret = 0; 192 int ret = 0;
214 193
215 if (ndev) 194 if (!ndev)
216 stpriv = netdev_priv(ndev); 195 return -EINVAL;
196
197 stpriv = netdev_priv(ndev);
198 if (!stpriv)
199 return -EINVAL;
217 200
218 /* Assert reset to the enet controller before changing the phy mode */ 201 /* Assert reset to the enet controller before changing the phy mode */
219 if (dwmac->stmmac_rst) 202 if (stpriv->stmmac_rst)
220 reset_control_assert(dwmac->stmmac_rst); 203 reset_control_assert(stpriv->stmmac_rst);
221 204
222 /* Setup the phy mode in the system manager registers according to 205 /* Setup the phy mode in the system manager registers according to
223 * devicetree configuration 206 * devicetree configuration
@@ -227,8 +210,8 @@ static int socfpga_dwmac_init(struct platform_device *pdev, void *priv)
227 /* Deassert reset for the phy configuration to be sampled by 210 /* Deassert reset for the phy configuration to be sampled by
228 * the enet controller, and operation to start in requested mode 211 * the enet controller, and operation to start in requested mode
229 */ 212 */
230 if (dwmac->stmmac_rst) 213 if (stpriv->stmmac_rst)
231 reset_control_deassert(dwmac->stmmac_rst); 214 reset_control_deassert(stpriv->stmmac_rst);
232 215
233 /* Before the enet controller is suspended, the phy is suspended. 216 /* Before the enet controller is suspended, the phy is suspended.
234 * This causes the phy clock to be gated. The enet controller is 217 * This causes the phy clock to be gated. The enet controller is
@@ -245,7 +228,7 @@ static int socfpga_dwmac_init(struct platform_device *pdev, void *priv)
245 * control register 0, and can be modified by the phy driver 228 * control register 0, and can be modified by the phy driver
246 * framework. 229 * framework.
247 */ 230 */
248 if (stpriv && stpriv->phydev) 231 if (stpriv->phydev)
249 phy_resume(stpriv->phydev); 232 phy_resume(stpriv->phydev);
250 233
251 return ret; 234 return ret;
@@ -285,14 +268,13 @@ static int socfpga_dwmac_probe(struct platform_device *pdev)
285 268
286 plat_dat->bsp_priv = dwmac; 269 plat_dat->bsp_priv = dwmac;
287 plat_dat->init = socfpga_dwmac_init; 270 plat_dat->init = socfpga_dwmac_init;
288 plat_dat->exit = socfpga_dwmac_exit;
289 plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed; 271 plat_dat->fix_mac_speed = socfpga_dwmac_fix_mac_speed;
290 272
291 ret = socfpga_dwmac_init(pdev, plat_dat->bsp_priv); 273 ret = stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res);
292 if (ret) 274 if (!ret)
293 return ret; 275 ret = socfpga_dwmac_init(pdev, dwmac);
294 276
295 return stmmac_dvr_probe(&pdev->dev, plat_dat, &stmmac_res); 277 return ret;
296} 278}
297 279
298static const struct of_device_id socfpga_dwmac_match[] = { 280static const struct of_device_id socfpga_dwmac_match[] = {