diff options
Diffstat (limited to 'drivers/net/ethernet/ti/davinci_emac.c')
| -rw-r--r-- | drivers/net/ethernet/ti/davinci_emac.c | 91 | 
1 files changed, 71 insertions, 20 deletions
diff --git a/drivers/net/ethernet/ti/davinci_emac.c b/drivers/net/ethernet/ti/davinci_emac.c index 67df09ea9d0..35a139e9a83 100644 --- a/drivers/net/ethernet/ti/davinci_emac.c +++ b/drivers/net/ethernet/ti/davinci_emac.c @@ -61,6 +61,7 @@  #include <linux/davinci_emac.h>  #include <linux/of.h>  #include <linux/of_address.h> +#include <linux/of_device.h>  #include <linux/of_irq.h>  #include <linux/of_net.h> @@ -876,8 +877,7 @@ static void emac_dev_mcast_set(struct net_device *ndev)  		    netdev_mc_count(ndev) > EMAC_DEF_MAX_MULTICAST_ADDRESSES) {  			mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST);  			emac_add_mcast(priv, EMAC_ALL_MULTI_SET, NULL); -		} -		if (!netdev_mc_empty(ndev)) { +		} else if (!netdev_mc_empty(ndev)) {  			struct netdev_hw_addr *ha;  			mbp_enable = (mbp_enable | EMAC_MBP_RXMCAST); @@ -1532,9 +1532,9 @@ static int emac_dev_open(struct net_device *ndev)  	struct device *emac_dev = &ndev->dev;  	u32 cnt;  	struct resource *res; -	int ret; +	int q, m, ret; +	int res_num = 0, irq_num = 0;  	int i = 0; -	int k = 0;  	struct emac_priv *priv = netdev_priv(ndev);  	pm_runtime_get(&priv->pdev->dev); @@ -1564,15 +1564,23 @@ static int emac_dev_open(struct net_device *ndev)  	}  	/* Request IRQ */ +	while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, +					    res_num))) { +		for (irq_num = res->start; irq_num <= res->end; irq_num++) { +			if (request_irq(irq_num, emac_irq, 0, ndev->name, +					ndev)) { +				dev_err(emac_dev, +					"DaVinci EMAC: request_irq() failed\n"); +				ret = -EBUSY; -	while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, k))) { -		for (i = res->start; i <= res->end; i++) { -			if (devm_request_irq(&priv->pdev->dev, i, emac_irq, -					     0, ndev->name, ndev))  				goto rollback; +			}  		} -		k++; +		res_num++;  	} +	/* prepare counters for rollback in case of an error */ +	res_num--; +	irq_num--;  	/* Start/Enable EMAC hardware */  	emac_hw_enable(priv); @@ -1639,11 +1647,23 @@ static int emac_dev_open(struct net_device *ndev)  	return 0; -rollback: - -	dev_err(emac_dev, "DaVinci EMAC: devm_request_irq() failed"); -	ret = -EBUSY;  err: +	emac_int_disable(priv); +	napi_disable(&priv->napi); + +rollback: +	for (q = res_num; q >= 0; q--) { +		res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, q); +		/* at the first iteration, irq_num is already set to the +		 * right value +		 */ +		if (q != res_num) +			irq_num = res->end; + +		for (m = irq_num; m >= res->start; m--) +			free_irq(m, ndev); +	} +	cpdma_ctlr_stop(priv->dma);  	pm_runtime_put(&priv->pdev->dev);  	return ret;  } @@ -1659,6 +1679,9 @@ err:   */  static int emac_dev_stop(struct net_device *ndev)  { +	struct resource *res; +	int i = 0; +	int irq_num;  	struct emac_priv *priv = netdev_priv(ndev);  	struct device *emac_dev = &ndev->dev; @@ -1674,6 +1697,13 @@ static int emac_dev_stop(struct net_device *ndev)  	if (priv->phydev)  		phy_disconnect(priv->phydev); +	/* Free IRQ */ +	while ((res = platform_get_resource(priv->pdev, IORESOURCE_IRQ, i))) { +		for (irq_num = res->start; irq_num <= res->end; irq_num++) +			free_irq(irq_num, priv->ndev); +		i++; +	} +  	if (netif_msg_drv(priv))  		dev_notice(emac_dev, "DaVinci EMAC: %s stopped\n", ndev->name); @@ -1753,10 +1783,14 @@ static const struct net_device_ops emac_netdev_ops = {  #endif  }; +static const struct of_device_id davinci_emac_of_match[]; +  static struct emac_platform_data *  davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)  {  	struct device_node *np; +	const struct of_device_id *match; +	const struct emac_platform_data *auxdata;  	struct emac_platform_data *pdata = NULL;  	const u8 *mac_addr; @@ -1794,7 +1828,20 @@ davinci_emac_of_get_pdata(struct platform_device *pdev, struct emac_priv *priv)  	priv->phy_node = of_parse_phandle(np, "phy-handle", 0);  	if (!priv->phy_node) -		pdata->phy_id = ""; +		pdata->phy_id = NULL; + +	auxdata = pdev->dev.platform_data; +	if (auxdata) { +		pdata->interrupt_enable = auxdata->interrupt_enable; +		pdata->interrupt_disable = auxdata->interrupt_disable; +	} + +	match = of_match_device(davinci_emac_of_match, &pdev->dev); +	if (match && match->data) { +		auxdata = match->data; +		pdata->version = auxdata->version; +		pdata->hw_ram_addr = auxdata->hw_ram_addr; +	}  	pdev->dev.platform_data = pdata; @@ -1817,7 +1864,6 @@ static int davinci_emac_probe(struct platform_device *pdev)  	struct emac_priv *priv;  	unsigned long hw_ram_addr;  	struct emac_platform_data *pdata; -	struct device *emac_dev;  	struct cpdma_params dma_params;  	struct clk *emac_clk;  	unsigned long emac_bus_frequency; @@ -1853,7 +1899,7 @@ static int davinci_emac_probe(struct platform_device *pdev)  	}  	/* MAC addr and PHY mask , RMII enable info from platform_data */ -	memcpy(priv->mac_addr, pdata->mac_addr, 6); +	memcpy(priv->mac_addr, pdata->mac_addr, ETH_ALEN);  	priv->phy_id = pdata->phy_id;  	priv->rmii_en = pdata->rmii_en;  	priv->version = pdata->version; @@ -1863,7 +1909,6 @@ static int davinci_emac_probe(struct platform_device *pdev)  	priv->coal_intvl = 0;  	priv->bus_freq_mhz = (u32)(emac_bus_frequency / 1000000); -	emac_dev = &ndev->dev;  	/* Get EMAC platform data */  	res = platform_get_resource(pdev, IORESOURCE_MEM, 0);  	priv->emac_base_phys = res->start + pdata->ctrl_reg_offset; @@ -1882,7 +1927,7 @@ static int davinci_emac_probe(struct platform_device *pdev)  		hw_ram_addr = (u32 __force)res->start + pdata->ctrl_ram_offset;  	memset(&dma_params, 0, sizeof(dma_params)); -	dma_params.dev			= emac_dev; +	dma_params.dev			= &pdev->dev;  	dma_params.dmaregs		= priv->emac_base;  	dma_params.rxthresh		= priv->emac_base + 0x120;  	dma_params.rxfree		= priv->emac_base + 0x140; @@ -1932,7 +1977,7 @@ static int davinci_emac_probe(struct platform_device *pdev)  	}  	ndev->netdev_ops = &emac_netdev_ops; -	SET_ETHTOOL_OPS(ndev, ðtool_ops); +	ndev->ethtool_ops = ðtool_ops;  	netif_napi_add(ndev, &priv->napi, emac_poll, EMAC_POLL_WEIGHT);  	/* register the network device */ @@ -1946,7 +1991,7 @@ static int davinci_emac_probe(struct platform_device *pdev)  	if (netif_msg_probe(priv)) { -		dev_notice(emac_dev, "DaVinci EMAC Probe found device "\ +		dev_notice(&pdev->dev, "DaVinci EMAC Probe found device "  			   "(regs: %p, irq: %d)\n",  			   (void *)priv->emac_base_phys, ndev->irq);  	} @@ -2021,8 +2066,14 @@ static const struct dev_pm_ops davinci_emac_pm_ops = {  };  #if IS_ENABLED(CONFIG_OF) +static const struct emac_platform_data am3517_emac_data = { +	.version		= EMAC_VERSION_2, +	.hw_ram_addr		= 0x01e20000, +}; +  static const struct of_device_id davinci_emac_of_match[] = {  	{.compatible = "ti,davinci-dm6467-emac", }, +	{.compatible = "ti,am3517-emac", .data = &am3517_emac_data, },  	{},  };  MODULE_DEVICE_TABLE(of, davinci_emac_of_match);  | 
