net: stmmac: Add support for optional reset control

The DWMAC has a reset assert line, which is used on some SoCs. Add an
optional reset control to stmmac driver core.

To support reset control deferred probing, this patch changes the driver
probe function to return the actual error, instead of just -EINVAL.

Signed-off-by: Chen-Yu Tsai <wens@csie.org>
Signed-off-by: David S. Miller <davem@davemloft.net>
This commit is contained in:
Chen-Yu Tsai 2014-01-17 21:24:41 +08:00 committed by David S. Miller
parent 62866e9873
commit c5e4ddbdfa
6 changed files with 28 additions and 5 deletions

View File

@ -30,6 +30,9 @@ Required properties:
Optional properties:
- mac-address: 6 bytes, mac address
- resets: Should contain a phandle to the STMMAC reset signal, if any
- reset-names: Should contain the reset signal name "stmmaceth", if a
reset phandle is given
Examples:

View File

@ -5,6 +5,7 @@ config STMMAC_ETH
select PHYLIB
select CRC32
select PTP_1588_CLOCK
select RESET_CONTROLLER
---help---
This is the driver for the Ethernet IPs are built around a
Synopsys IP Core and only tested on the STMicroelectronics

View File

@ -32,6 +32,7 @@
#include <linux/pci.h>
#include "common.h"
#include <linux/ptp_clock_kernel.h>
#include <linux/reset.h>
struct stmmac_priv {
/* Frequently used values are kept adjacent for cache effect */
@ -91,6 +92,7 @@ struct stmmac_priv {
int wolopts;
int wol_irq;
struct clk *stmmac_clk;
struct reset_control *stmmac_rst;
int clk_csr;
struct timer_list eee_ctrl_timer;
int lpi_irq;

View File

@ -51,6 +51,7 @@
#include <linux/net_tstamp.h>
#include "stmmac_ptp.h"
#include "stmmac.h"
#include <linux/reset.h>
#define STMMAC_ALIGN(x) L1_CACHE_ALIGN(x)
#define JUMBO_LEN 9000
@ -2728,10 +2729,24 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
if (IS_ERR(priv->stmmac_clk)) {
dev_warn(priv->device, "%s: warning: cannot get CSR clock\n",
__func__);
ret = PTR_ERR(priv->stmmac_clk);
goto error_clk_get;
}
clk_prepare_enable(priv->stmmac_clk);
priv->stmmac_rst = devm_reset_control_get(priv->device,
STMMAC_RESOURCE_NAME);
if (IS_ERR(priv->stmmac_rst)) {
if (PTR_ERR(priv->stmmac_rst) == -EPROBE_DEFER) {
ret = -EPROBE_DEFER;
goto error_hw_init;
}
dev_info(priv->device, "no reset control found\n");
priv->stmmac_rst = NULL;
}
if (priv->stmmac_rst)
reset_control_deassert(priv->stmmac_rst);
/* Init MAC and get the capabilities */
ret = stmmac_hw_init(priv);
if (ret)
@ -2808,7 +2823,7 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,
error_clk_get:
free_netdev(ndev);
return NULL;
return ERR_PTR(ret);
}
/**
@ -2832,6 +2847,8 @@ int stmmac_dvr_remove(struct net_device *ndev)
stmmac_mdio_unregister(ndev);
netif_carrier_off(ndev);
unregister_netdev(ndev);
if (priv->stmmac_rst)
reset_control_assert(priv->stmmac_rst);
clk_disable_unprepare(priv->stmmac_clk);
free_netdev(ndev);

View File

@ -100,9 +100,9 @@ static int stmmac_pci_probe(struct pci_dev *pdev,
stmmac_default_data();
priv = stmmac_dvr_probe(&(pdev->dev), &plat_dat, addr);
if (!priv) {
if (IS_ERR(priv)) {
pr_err("%s: main driver probe failed", __func__);
ret = -ENODEV;
ret = PTR_ERR(priv);
goto err_out;
}
priv->dev->irq = pdev->irq;

View File

@ -152,9 +152,9 @@ static int stmmac_pltfr_probe(struct platform_device *pdev)
}
priv = stmmac_dvr_probe(&(pdev->dev), plat_dat, addr);
if (!priv) {
if (IS_ERR(priv)) {
pr_err("%s: main driver probe failed", __func__);
return -ENODEV;
return PTR_ERR(priv);
}
/* Get MAC address if available (DT) */