diff options
Diffstat (limited to 'drivers/net/ethernet/freescale/fec_main.c')
| -rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 47 | 
1 files changed, 43 insertions, 4 deletions
| diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index 56a563f90b0b..a6e323f15637 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -89,10 +89,10 @@ static struct platform_device_id fec_devtype[] = {  		.driver_data = 0,  	}, {  		.name = "imx25-fec", -		.driver_data = FEC_QUIRK_USE_GASKET, +		.driver_data = FEC_QUIRK_USE_GASKET | FEC_QUIRK_MIB_CLEAR,  	}, {  		.name = "imx27-fec", -		.driver_data = 0, +		.driver_data = FEC_QUIRK_MIB_CLEAR,  	}, {  		.name = "imx28-fec",  		.driver_data = FEC_QUIRK_ENET_MAC | FEC_QUIRK_SWAP_FRAME | @@ -184,6 +184,9 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");  #define FEC_RACC_SHIFT16	BIT(7)  #define FEC_RACC_OPTIONS	(FEC_RACC_IPDIS | FEC_RACC_PRODIS) +/* MIB Control Register */ +#define FEC_MIB_CTRLSTAT_DISABLE	BIT(31) +  /*   * The 5270/5271/5280/5282/532x RX control register also contains maximum frame   * size bits. Other FEC hardware does not, so we need to take that into @@ -2356,11 +2359,30 @@ static int fec_enet_get_sset_count(struct net_device *dev, int sset)  	}  } +static void fec_enet_clear_ethtool_stats(struct net_device *dev) +{ +	struct fec_enet_private *fep = netdev_priv(dev); +	int i; + +	/* Disable MIB statistics counters */ +	writel(FEC_MIB_CTRLSTAT_DISABLE, fep->hwp + FEC_MIB_CTRLSTAT); + +	for (i = 0; i < ARRAY_SIZE(fec_stats); i++) +		writel(0, fep->hwp + fec_stats[i].offset); + +	/* Don't disable MIB statistics counters */ +	writel(0, fep->hwp + FEC_MIB_CTRLSTAT); +} +  #else	/* !defined(CONFIG_M5272) */  #define FEC_STATS_SIZE	0  static inline void fec_enet_update_ethtool_stats(struct net_device *dev)  {  } + +static inline void fec_enet_clear_ethtool_stats(struct net_device *dev) +{ +}  #endif /* !defined(CONFIG_M5272) */  /* ITR clock source is enet system clock (clk_ahb). @@ -3182,7 +3204,10 @@ static int fec_enet_init(struct net_device *ndev)  	fec_restart(ndev); -	fec_enet_update_ethtool_stats(ndev); +	if (fep->quirks & FEC_QUIRK_MIB_CLEAR) +		fec_enet_clear_ethtool_stats(ndev); +	else +		fec_enet_update_ethtool_stats(ndev);  	return 0;  } @@ -3192,7 +3217,7 @@ static int fec_reset_phy(struct platform_device *pdev)  {  	int err, phy_reset;  	bool active_high = false; -	int msec = 1; +	int msec = 1, phy_post_delay = 0;  	struct device_node *np = pdev->dev.of_node;  	if (!np) @@ -3209,6 +3234,11 @@ static int fec_reset_phy(struct platform_device *pdev)  	else if (!gpio_is_valid(phy_reset))  		return 0; +	err = of_property_read_u32(np, "phy-reset-post-delay", &phy_post_delay); +	/* valid reset duration should be less than 1s */ +	if (!err && phy_post_delay > 1000) +		return -EINVAL; +  	active_high = of_property_read_bool(np, "phy-reset-active-high");  	err = devm_gpio_request_one(&pdev->dev, phy_reset, @@ -3226,6 +3256,15 @@ static int fec_reset_phy(struct platform_device *pdev)  	gpio_set_value_cansleep(phy_reset, !active_high); +	if (!phy_post_delay) +		return 0; + +	if (phy_post_delay > 20) +		msleep(phy_post_delay); +	else +		usleep_range(phy_post_delay * 1000, +			     phy_post_delay * 1000 + 1000); +  	return 0;  }  #else /* CONFIG_OF */ | 
