diff options
Diffstat (limited to 'drivers/net/ethernet/stmicro/stmmac/stmmac_main.c')
| -rw-r--r-- | drivers/net/ethernet/stmicro/stmmac/stmmac_main.c | 205 | 
1 files changed, 107 insertions, 98 deletions
diff --git a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c index 96fa2da3076..6ee593a55a6 100644 --- a/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c +++ b/drivers/net/ethernet/stmicro/stmmac/stmmac_main.c @@ -241,7 +241,7 @@ static void stmmac_adjust_link(struct net_device *dev)  			case 1000:  				if (likely(priv->plat->has_gmac))  					ctrl &= ~priv->hw->link.port; -				stmmac_hw_fix_mac_speed(priv); +					stmmac_hw_fix_mac_speed(priv);  				break;  			case 100:  			case 10: @@ -785,7 +785,7 @@ static u32 stmmac_get_synopsys_id(struct stmmac_priv *priv)  		u32 uid = ((hwid & 0x0000ff00) >> 8);  		u32 synid = (hwid & 0x000000ff); -		pr_info("STMMAC - user ID: 0x%x, Synopsys ID: 0x%x\n", +		pr_info("stmmac - user ID: 0x%x, Synopsys ID: 0x%x\n",  			uid, synid);  		return synid; @@ -869,38 +869,6 @@ static int stmmac_get_hw_features(struct stmmac_priv *priv)  	return hw_cap;  } -/** - * stmmac_mac_device_setup - * @dev : device pointer - * Description: this is to attach the GMAC or MAC 10/100 - * main core structures that will be completed during the - * open step. - */ -static int stmmac_mac_device_setup(struct net_device *dev) -{ -	struct stmmac_priv *priv = netdev_priv(dev); - -	struct mac_device_info *device; - -	if (priv->plat->has_gmac) -		device = dwmac1000_setup(priv->ioaddr); -	else -		device = dwmac100_setup(priv->ioaddr); - -	if (!device) -		return -ENOMEM; - -	priv->hw = device; -	priv->hw->ring = &ring_mode_ops; - -	if (device_can_wakeup(priv->device)) { -		priv->wolopts = WAKE_MAGIC; /* Magic Frame as default */ -		enable_irq_wake(priv->wol_irq); -	} - -	return 0; -} -  static void stmmac_check_ether_addr(struct stmmac_priv *priv)  {  	/* verify if the MAC address is valid, in case of failures it @@ -930,20 +898,8 @@ static int stmmac_open(struct net_device *dev)  	struct stmmac_priv *priv = netdev_priv(dev);  	int ret; -	/* MAC HW device setup */ -	ret = stmmac_mac_device_setup(dev); -	if (ret < 0) -		return ret; -  	stmmac_check_ether_addr(priv); -	stmmac_verify_args(); - -	/* Override with kernel parameters if supplied XXX CRS XXX -	 * this needs to have multiple instances */ -	if ((phyaddr >= 0) && (phyaddr <= 31)) -		priv->plat->phy_addr = phyaddr; -  	/* MDIO bus Registration */  	ret = stmmac_mdio_register(dev);  	if (ret < 0) { @@ -976,44 +932,6 @@ static int stmmac_open(struct net_device *dev)  		goto open_error;  	} -	stmmac_get_synopsys_id(priv); - -	priv->hw_cap_support = stmmac_get_hw_features(priv); - -	if (priv->hw_cap_support) { -		pr_info(" Support DMA HW capability register"); - -		/* We can override some gmac/dma configuration fields: e.g. -		 * enh_desc, tx_coe (e.g. that are passed through the -		 * platform) with the values from the HW capability -		 * register (if supported). -		 */ -		priv->plat->enh_desc = priv->dma_cap.enh_desc; -		priv->plat->tx_coe = priv->dma_cap.tx_coe; -		priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; - -		/* By default disable wol on magic frame if not supported */ -		if (!priv->dma_cap.pmt_magic_frame) -			priv->wolopts &= ~WAKE_MAGIC; - -	} else -		pr_info(" No HW DMA feature register supported"); - -	/* Select the enhnaced/normal descriptor structures */ -	stmmac_selec_desc_mode(priv); - -	/* PMT module is not integrated in all the MAC devices. */ -	if (priv->plat->pmt) { -		pr_info(" Remote wake-up capable\n"); -		device_set_wakeup_capable(priv->device, 1); -	} - -	priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr); -	if (priv->rx_coe) -		pr_info(" Checksum Offload Engine supported\n"); -	if (priv->plat->tx_coe) -		pr_info(" Checksum insertion supported\n"); -  	/* Create and initialize the TX/RX descriptors chains. */  	priv->dma_tx_size = STMMAC_ALIGN(dma_txsize);  	priv->dma_rx_size = STMMAC_ALIGN(dma_rxsize); @@ -1030,14 +948,14 @@ static int stmmac_open(struct net_device *dev)  	/* Copy the MAC addr into the HW  */  	priv->hw->mac->set_umac_addr(priv->ioaddr, dev->dev_addr, 0); +  	/* If required, perform hw setup of the bus. */  	if (priv->plat->bus_setup)  		priv->plat->bus_setup(priv->ioaddr); +  	/* Initialize the MAC Core */  	priv->hw->mac->core_init(priv->ioaddr); -	netdev_update_features(dev); -  	/* Request the IRQ lines */  	ret = request_irq(dev->irq, stmmac_interrupt,  			 IRQF_SHARED, dev->name, dev); @@ -1047,6 +965,17 @@ static int stmmac_open(struct net_device *dev)  		goto open_error;  	} +	/* Request the Wake IRQ in case of another line is used for WoL */ +	if (priv->wol_irq != dev->irq) { +		ret = request_irq(priv->wol_irq, stmmac_interrupt, +				  IRQF_SHARED, dev->name, dev); +		if (unlikely(ret < 0)) { +			pr_err("%s: ERROR: allocating the ext WoL IRQ %d " +			       "(error: %d)\n",	__func__, priv->wol_irq, ret); +			goto open_error_wolirq; +		} +	} +  	/* Enable the MAC Rx/Tx */  	stmmac_set_mac(priv->ioaddr, true); @@ -1062,7 +991,7 @@ static int stmmac_open(struct net_device *dev)  #ifdef CONFIG_STMMAC_DEBUG_FS  	ret = stmmac_init_fs(dev);  	if (ret < 0) -		pr_warning("\tFailed debugFS registration"); +		pr_warning("%s: failed debugFS registration\n", __func__);  #endif  	/* Start the ball rolling... */  	DBG(probe, DEBUG, "%s: DMA RX/TX processes started...\n", dev->name); @@ -1072,6 +1001,7 @@ static int stmmac_open(struct net_device *dev)  #ifdef CONFIG_STMMAC_TIMER  	priv->tm->timer_start(tmrate);  #endif +  	/* Dump DMA/MAC registers */  	if (netif_msg_hw(priv)) {  		priv->hw->mac->dump_regs(priv->ioaddr); @@ -1087,6 +1017,9 @@ static int stmmac_open(struct net_device *dev)  	return 0; +open_error_wolirq: +	free_irq(dev->irq, dev); +  open_error:  #ifdef CONFIG_STMMAC_TIMER  	kfree(priv->tm); @@ -1127,6 +1060,8 @@ static int stmmac_release(struct net_device *dev)  	/* Free the IRQ lines */  	free_irq(dev->irq, dev); +	if (priv->wol_irq != dev->irq) +		free_irq(priv->wol_irq, dev);  	/* Stop TX/RX DMA and clear the descriptors */  	priv->hw->dma->stop_tx(priv->ioaddr); @@ -1789,13 +1724,77 @@ static const struct net_device_ops stmmac_netdev_ops = {  };  /** + *  stmmac_hw_init - Init the MAC device + *  @priv : pointer to the private device structure. + *  Description: this function detects which MAC device + *  (GMAC/MAC10-100) has to attached, checks the HW capability + *  (if supported) and sets the driver's features (for example + *  to use the ring or chaine mode or support the normal/enh + *  descriptor structure). + */ +static int stmmac_hw_init(struct stmmac_priv *priv) +{ +	int ret = 0; +	struct mac_device_info *mac; + +	/* Identify the MAC HW device */ +	if (priv->plat->has_gmac) +		mac = dwmac1000_setup(priv->ioaddr); +	else +		mac = dwmac100_setup(priv->ioaddr); +	if (!mac) +		return -ENOMEM; + +	priv->hw = mac; + +	/* To use the chained or ring mode */ +	priv->hw->ring = &ring_mode_ops; + +	/* Get and dump the chip ID */ +	stmmac_get_synopsys_id(priv); + +	/* Get the HW capability (new GMAC newer than 3.50a) */ +	priv->hw_cap_support = stmmac_get_hw_features(priv); +	if (priv->hw_cap_support) { +		pr_info(" DMA HW capability register supported"); + +		/* We can override some gmac/dma configuration fields: e.g. +		 * enh_desc, tx_coe (e.g. that are passed through the +		 * platform) with the values from the HW capability +		 * register (if supported). +		 */ +		priv->plat->enh_desc = priv->dma_cap.enh_desc; +		priv->plat->tx_coe = priv->dma_cap.tx_coe; +		priv->plat->pmt = priv->dma_cap.pmt_remote_wake_up; +	} else +		pr_info(" No HW DMA feature register supported"); + +	/* Select the enhnaced/normal descriptor structures */ +	stmmac_selec_desc_mode(priv); + +	priv->rx_coe = priv->hw->mac->rx_coe(priv->ioaddr); +	if (priv->rx_coe) +		pr_info(" RX Checksum Offload Engine supported\n"); +	if (priv->plat->tx_coe) +		pr_info(" TX Checksum insertion supported\n"); + +	if (priv->plat->pmt) { +		pr_info(" Wake-Up On Lan supported\n"); +		device_set_wakeup_capable(priv->device, 1); +	} + +	return ret; +} + +/**   * stmmac_dvr_probe   * @device: device pointer   * Description: this is the main probe function used to   * call the alloc_etherdev, allocate the priv structure.   */  struct stmmac_priv *stmmac_dvr_probe(struct device *device, -					struct plat_stmmacenet_data *plat_dat) +				     struct plat_stmmacenet_data *plat_dat, +				     void __iomem *addr)  {  	int ret = 0;  	struct net_device *ndev = NULL; @@ -1815,10 +1814,27 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,  	ether_setup(ndev); -	ndev->netdev_ops = &stmmac_netdev_ops;  	stmmac_set_ethtool_ops(ndev); +	priv->pause = pause; +	priv->plat = plat_dat; +	priv->ioaddr = addr; +	priv->dev->base_addr = (unsigned long)addr; + +	/* Verify driver arguments */ +	stmmac_verify_args(); + +	/* Override with kernel parameters if supplied XXX CRS XXX +	 * this needs to have multiple instances */ +	if ((phyaddr >= 0) && (phyaddr <= 31)) +		priv->plat->phy_addr = phyaddr; + +	/* Init MAC and get the capabilities */ +	stmmac_hw_init(priv); + +	ndev->netdev_ops = &stmmac_netdev_ops; -	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM; +	ndev->hw_features = NETIF_F_SG | NETIF_F_IP_CSUM | NETIF_F_IPV6_CSUM | +			    NETIF_F_RXCSUM;  	ndev->features |= ndev->hw_features | NETIF_F_HIGHDMA;  	ndev->watchdog_timeo = msecs_to_jiffies(watchdog);  #ifdef STMMAC_VLAN_TAG_USED @@ -1830,8 +1846,6 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,  	if (flow_ctrl)  		priv->flow_ctrl = FLOW_AUTO;	/* RX/TX pause on */ -	priv->pause = pause; -	priv->plat = plat_dat;  	netif_napi_add(ndev, &priv->napi, stmmac_poll, 64);  	spin_lock_init(&priv->lock); @@ -1839,15 +1853,10 @@ struct stmmac_priv *stmmac_dvr_probe(struct device *device,  	ret = register_netdev(ndev);  	if (ret) { -		pr_err("%s: ERROR %i registering the device\n", -		       __func__, ret); +		pr_err("%s: ERROR %i registering the device\n", __func__, ret);  		goto error;  	} -	DBG(probe, DEBUG, "%s: Scatter/Gather: %s - HW checksums: %s\n", -	    ndev->name, (ndev->features & NETIF_F_SG) ? "on" : "off", -	    (ndev->features & NETIF_F_IP_CSUM) ? "on" : "off"); -  	return priv;  error:  |