diff options
Diffstat (limited to 'drivers/net/ethernet/freescale/fec_main.c')
| -rw-r--r-- | drivers/net/ethernet/freescale/fec_main.c | 78 | 
1 files changed, 67 insertions, 11 deletions
diff --git a/drivers/net/ethernet/freescale/fec_main.c b/drivers/net/ethernet/freescale/fec_main.c index e5610a4da539..d4d4c72adf49 100644 --- a/drivers/net/ethernet/freescale/fec_main.c +++ b/drivers/net/ethernet/freescale/fec_main.c @@ -208,8 +208,11 @@ MODULE_PARM_DESC(macaddr, "FEC Ethernet MAC address");  /* FEC MII MMFR bits definition */  #define FEC_MMFR_ST		(1 << 30) +#define FEC_MMFR_ST_C45		(0)  #define FEC_MMFR_OP_READ	(2 << 28) +#define FEC_MMFR_OP_READ_C45	(3 << 28)  #define FEC_MMFR_OP_WRITE	(1 << 28) +#define FEC_MMFR_OP_ADDR_WRITE	(0)  #define FEC_MMFR_PA(v)		((v & 0x1f) << 23)  #define FEC_MMFR_RA(v)		((v & 0x1f) << 18)  #define FEC_MMFR_TA		(2 << 16) @@ -365,7 +368,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,  		status = fec16_to_cpu(bdp->cbd_sc);  		status &= ~BD_ENET_TX_STATS;  		status |= (BD_ENET_TX_TC | BD_ENET_TX_READY); -		frag_len = skb_shinfo(skb)->frags[frag].size; +		frag_len = skb_frag_size(&skb_shinfo(skb)->frags[frag]);  		/* Handle the last BD specially */  		if (frag == nr_frags - 1) { @@ -387,7 +390,7 @@ fec_enet_txq_submit_frag_skb(struct fec_enet_priv_tx_q *txq,  			ebdp->cbd_esc = cpu_to_fec32(estatus);  		} -		bufaddr = page_address(this_frag->page.p) + this_frag->page_offset; +		bufaddr = skb_frag_address(this_frag);  		index = fec_enet_get_bd_index(bdp, &txq->bd);  		if (((unsigned long) bufaddr) & fep->tx_align || @@ -1767,7 +1770,8 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)  	struct fec_enet_private *fep = bus->priv;  	struct device *dev = &fep->pdev->dev;  	unsigned long time_left; -	int ret = 0; +	int ret = 0, frame_start, frame_addr, frame_op; +	bool is_c45 = !!(regnum & MII_ADDR_C45);  	ret = pm_runtime_get_sync(dev);  	if (ret < 0) @@ -1775,9 +1779,37 @@ static int fec_enet_mdio_read(struct mii_bus *bus, int mii_id, int regnum)  	reinit_completion(&fep->mdio_done); +	if (is_c45) { +		frame_start = FEC_MMFR_ST_C45; + +		/* write address */ +		frame_addr = (regnum >> 16); +		writel(frame_start | FEC_MMFR_OP_ADDR_WRITE | +		       FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | +		       FEC_MMFR_TA | (regnum & 0xFFFF), +		       fep->hwp + FEC_MII_DATA); + +		/* wait for end of transfer */ +		time_left = wait_for_completion_timeout(&fep->mdio_done, +				usecs_to_jiffies(FEC_MII_TIMEOUT)); +		if (time_left == 0) { +			netdev_err(fep->netdev, "MDIO address write timeout\n"); +			ret = -ETIMEDOUT; +			goto out; +		} + +		frame_op = FEC_MMFR_OP_READ_C45; + +	} else { +		/* C22 read */ +		frame_op = FEC_MMFR_OP_READ; +		frame_start = FEC_MMFR_ST; +		frame_addr = regnum; +	} +  	/* start a read op */ -	writel(FEC_MMFR_ST | FEC_MMFR_OP_READ | -		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | +	writel(frame_start | frame_op | +		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |  		FEC_MMFR_TA, fep->hwp + FEC_MII_DATA);  	/* wait for end of transfer */ @@ -1804,7 +1836,8 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,  	struct fec_enet_private *fep = bus->priv;  	struct device *dev = &fep->pdev->dev;  	unsigned long time_left; -	int ret; +	int ret, frame_start, frame_addr; +	bool is_c45 = !!(regnum & MII_ADDR_C45);  	ret = pm_runtime_get_sync(dev);  	if (ret < 0) @@ -1814,9 +1847,33 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,  	reinit_completion(&fep->mdio_done); +	if (is_c45) { +		frame_start = FEC_MMFR_ST_C45; + +		/* write address */ +		frame_addr = (regnum >> 16); +		writel(frame_start | FEC_MMFR_OP_ADDR_WRITE | +		       FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) | +		       FEC_MMFR_TA | (regnum & 0xFFFF), +		       fep->hwp + FEC_MII_DATA); + +		/* wait for end of transfer */ +		time_left = wait_for_completion_timeout(&fep->mdio_done, +			usecs_to_jiffies(FEC_MII_TIMEOUT)); +		if (time_left == 0) { +			netdev_err(fep->netdev, "MDIO address write timeout\n"); +			ret = -ETIMEDOUT; +			goto out; +		} +	} else { +		/* C22 write */ +		frame_start = FEC_MMFR_ST; +		frame_addr = regnum; +	} +  	/* start a write op */ -	writel(FEC_MMFR_ST | FEC_MMFR_OP_WRITE | -		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(regnum) | +	writel(frame_start | FEC_MMFR_OP_WRITE | +		FEC_MMFR_PA(mii_id) | FEC_MMFR_RA(frame_addr) |  		FEC_MMFR_TA | FEC_MMFR_DATA(value),  		fep->hwp + FEC_MII_DATA); @@ -1828,6 +1885,7 @@ static int fec_enet_mdio_write(struct mii_bus *bus, int mii_id, int regnum,  		ret  = -ETIMEDOUT;  	} +out:  	pm_runtime_mark_last_busy(dev);  	pm_runtime_put_autosuspend(dev); @@ -3338,7 +3396,6 @@ fec_probe(struct platform_device *pdev)  	struct fec_platform_data *pdata;  	struct net_device *ndev;  	int i, irq, ret = 0; -	struct resource *r;  	const struct of_device_id *of_id;  	static int dev_id;  	struct device_node *np = pdev->dev.of_node, *phy_node; @@ -3378,8 +3435,7 @@ fec_probe(struct platform_device *pdev)  	/* Select default pin state */  	pinctrl_pm_select_default_state(&pdev->dev); -	r = platform_get_resource(pdev, IORESOURCE_MEM, 0); -	fep->hwp = devm_ioremap_resource(&pdev->dev, r); +	fep->hwp = devm_platform_ioremap_resource(pdev, 0);  	if (IS_ERR(fep->hwp)) {  		ret = PTR_ERR(fep->hwp);  		goto failed_ioremap;  |