diff options
Diffstat (limited to 'drivers/net/ethernet/cadence/macb_main.c')
| -rw-r--r-- | drivers/net/ethernet/cadence/macb_main.c | 68 | 
1 files changed, 49 insertions, 19 deletions
| diff --git a/drivers/net/ethernet/cadence/macb_main.c b/drivers/net/ethernet/cadence/macb_main.c index 15362d016a87..0e94db9cd45d 100644 --- a/drivers/net/ethernet/cadence/macb_main.c +++ b/drivers/net/ethernet/cadence/macb_main.c @@ -694,6 +694,22 @@ static void macb_mac_config(struct phylink_config *config, unsigned int mode,  	if (old_ncr ^ ncr)  		macb_or_gem_writel(bp, NCR, ncr); +	/* Disable AN for SGMII fixed link configuration, enable otherwise. +	 * Must be written after PCSSEL is set in NCFGR, +	 * otherwise writes will not take effect. +	 */ +	if (macb_is_gem(bp) && state->interface == PHY_INTERFACE_MODE_SGMII) { +		u32 pcsctrl, old_pcsctrl; + +		old_pcsctrl = gem_readl(bp, PCSCNTRL); +		if (mode == MLO_AN_FIXED) +			pcsctrl = old_pcsctrl & ~GEM_BIT(PCSAUTONEG); +		else +			pcsctrl = old_pcsctrl | GEM_BIT(PCSAUTONEG); +		if (old_pcsctrl != pcsctrl) +			gem_writel(bp, PCSCNTRL, pcsctrl); +	} +  	spin_unlock_irqrestore(&bp->lock, flags);  } @@ -847,6 +863,15 @@ static int macb_phylink_connect(struct macb *bp)  	return 0;  } +static void macb_get_pcs_fixed_state(struct phylink_config *config, +				     struct phylink_link_state *state) +{ +	struct net_device *ndev = to_net_dev(config->dev); +	struct macb *bp = netdev_priv(ndev); + +	state->link = (macb_readl(bp, NSR) & MACB_BIT(NSR_LINK)) != 0; +} +  /* based on au1000_eth. c*/  static int macb_mii_probe(struct net_device *dev)  { @@ -855,6 +880,11 @@ static int macb_mii_probe(struct net_device *dev)  	bp->phylink_config.dev = &dev->dev;  	bp->phylink_config.type = PHYLINK_NETDEV; +	if (bp->phy_interface == PHY_INTERFACE_MODE_SGMII) { +		bp->phylink_config.poll_fixed_state = true; +		bp->phylink_config.get_fixed_state = macb_get_pcs_fixed_state; +	} +  	bp->phylink = phylink_create(&bp->phylink_config, bp->pdev->dev.fwnode,  				     bp->phy_interface, &macb_phylink_ops);  	if (IS_ERR(bp->phylink)) { @@ -3239,6 +3269,9 @@ static void gem_prog_cmp_regs(struct macb *bp, struct ethtool_rx_flow_spec *fs)  	bool cmp_b = false;  	bool cmp_c = false; +	if (!macb_is_gem(bp)) +		return; +  	tp4sp_v = &(fs->h_u.tcp_ip4_spec);  	tp4sp_m = &(fs->m_u.tcp_ip4_spec); @@ -3607,6 +3640,7 @@ static void macb_restore_features(struct macb *bp)  {  	struct net_device *netdev = bp->dev;  	netdev_features_t features = netdev->features; +	struct ethtool_rx_fs_item *item;  	/* TX checksum offload */  	macb_set_txcsum_feature(bp, features); @@ -3615,6 +3649,9 @@ static void macb_restore_features(struct macb *bp)  	macb_set_rxcsum_feature(bp, features);  	/* RX Flow Filters */ +	list_for_each_entry(item, &bp->rx_fs_list.list, list) +		gem_prog_cmp_regs(bp, &item->fs); +  	macb_set_rxflow_feature(bp, features);  } @@ -3728,17 +3765,15 @@ static int macb_clk_init(struct platform_device *pdev, struct clk **pclk,  		*hclk = devm_clk_get(&pdev->dev, "hclk");  	} -	if (IS_ERR_OR_NULL(*pclk)) { -		err = IS_ERR(*pclk) ? PTR_ERR(*pclk) : -ENODEV; -		dev_err(&pdev->dev, "failed to get macb_clk (%d)\n", err); -		return err; -	} +	if (IS_ERR_OR_NULL(*pclk)) +		return dev_err_probe(&pdev->dev, +				     IS_ERR(*pclk) ? PTR_ERR(*pclk) : -ENODEV, +				     "failed to get pclk\n"); -	if (IS_ERR_OR_NULL(*hclk)) { -		err = IS_ERR(*hclk) ? PTR_ERR(*hclk) : -ENODEV; -		dev_err(&pdev->dev, "failed to get hclk (%d)\n", err); -		return err; -	} +	if (IS_ERR_OR_NULL(*hclk)) +		return dev_err_probe(&pdev->dev, +				     IS_ERR(*hclk) ? PTR_ERR(*hclk) : -ENODEV, +				     "failed to get hclk\n");  	*tx_clk = devm_clk_get_optional(&pdev->dev, "tx_clk");  	if (IS_ERR(*tx_clk)) @@ -3911,6 +3946,7 @@ static int macb_init(struct platform_device *pdev)  	reg = gem_readl(bp, DCFG8);  	bp->max_tuples = min((GEM_BFEXT(SCR2CMP, reg) / 3),  			GEM_BFEXT(T2SCR, reg)); +	INIT_LIST_HEAD(&bp->rx_fs_list.list);  	if (bp->max_tuples > 0) {  		/* also needs one ethtype match to check IPv4 */  		if (GEM_BFEXT(SCR2ETH, reg) > 0) { @@ -3921,7 +3957,6 @@ static int macb_init(struct platform_device *pdev)  			/* Filtering is supported in hw but don't enable it in kernel now */  			dev->hw_features |= NETIF_F_NTUPLE;  			/* init Rx flow definitions */ -			INIT_LIST_HEAD(&bp->rx_fs_list.list);  			bp->rx_fs_list.count = 0;  			spin_lock_init(&bp->rx_fs_lock);  		} else @@ -4614,7 +4649,6 @@ static int macb_probe(struct platform_device *pdev)  	struct net_device *dev;  	struct resource *regs;  	void __iomem *mem; -	const char *mac;  	struct macb *bp;  	int err, val; @@ -4729,15 +4763,11 @@ static int macb_probe(struct platform_device *pdev)  	if (bp->caps & MACB_CAPS_NEEDS_RSTONUBR)  		bp->rx_intr_mask |= MACB_BIT(RXUBR); -	mac = of_get_mac_address(np); -	if (PTR_ERR(mac) == -EPROBE_DEFER) { -		err = -EPROBE_DEFER; +	err = of_get_mac_address(np, bp->dev->dev_addr); +	if (err == -EPROBE_DEFER)  		goto err_out_free_netdev; -	} else if (!IS_ERR_OR_NULL(mac)) { -		ether_addr_copy(bp->dev->dev_addr, mac); -	} else { +	else if (err)  		macb_get_hwaddr(bp); -	}  	err = of_get_phy_mode(np, &interface);  	if (err) | 
