Commit 8beb79b7 authored by Harini Katakam's avatar Harini Katakam Committed by David S. Miller

net: macb: Check MDIO state before read/write and use timeouts

Replace the while loop in MDIO read/write functions with a timeout.
In addition, add a check for MDIO bus busy before initiating a new
operation as well to make sure there is no ongoing MDIO operation.
Signed-off-by: default avatarShubhrajyoti Datta <shubhrajyoti.datta@xilinx.com>
Signed-off-by: default avatarSai Pavan Boddu <sai.pavan.boddu@xilinx.com>
Signed-off-by: default avatarHarini Katakam <harini.katakam@xilinx.com>
Reviewed-by: default avatarAndrew Lunn <andrew@lunn.ch>
Signed-off-by: default avatarDavid S. Miller <davem@davemloft.net>
parent 41bc0ddb
......@@ -715,6 +715,8 @@
__v; \
})
#define MACB_READ_NSR(bp) macb_readl(bp, NSR)
/* struct macb_dma_desc - Hardware DMA descriptor
* @addr: DMA address of data buffer
* @ctrl: Control and status bits
......
......@@ -36,6 +36,7 @@
#include <linux/ip.h>
#include <linux/udp.h>
#include <linux/tcp.h>
#include <linux/iopoll.h>
#include "macb.h"
#define MACB_RX_BUFFER_SIZE 128
......@@ -79,6 +80,8 @@
*/
#define MACB_HALT_TIMEOUT 1230
#define MACB_MDIO_TIMEOUT 1000000 /* in usecs */
/* DMA buffer descriptor might be different size
* depends on hardware configuration:
*
......@@ -318,10 +321,23 @@ static void macb_get_hwaddr(struct macb *bp)
eth_hw_addr_random(bp->dev);
}
static int macb_mdio_wait_for_idle(struct macb *bp)
{
u32 val;
return readx_poll_timeout(MACB_READ_NSR, bp, val, val & MACB_BIT(IDLE),
1, MACB_MDIO_TIMEOUT);
}
static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
{
struct macb *bp = bus->priv;
int value;
int err;
err = macb_mdio_wait_for_idle(bp);
if (err < 0)
return err;
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
| MACB_BF(RW, MACB_MAN_READ)
......@@ -329,9 +345,9 @@ static int macb_mdio_read(struct mii_bus *bus, int mii_id, int regnum)
| MACB_BF(REGA, regnum)
| MACB_BF(CODE, MACB_MAN_CODE)));
/* wait for end of transfer */
while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
cpu_relax();
err = macb_mdio_wait_for_idle(bp);
if (err < 0)
return err;
value = MACB_BFEXT(DATA, macb_readl(bp, MAN));
......@@ -342,6 +358,11 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
u16 value)
{
struct macb *bp = bus->priv;
int err;
err = macb_mdio_wait_for_idle(bp);
if (err < 0)
return err;
macb_writel(bp, MAN, (MACB_BF(SOF, MACB_MAN_SOF)
| MACB_BF(RW, MACB_MAN_WRITE)
......@@ -350,9 +371,9 @@ static int macb_mdio_write(struct mii_bus *bus, int mii_id, int regnum,
| MACB_BF(CODE, MACB_MAN_CODE)
| MACB_BF(DATA, value)));
/* wait for end of transfer */
while (!MACB_BFEXT(IDLE, macb_readl(bp, NSR)))
cpu_relax();
err = macb_mdio_wait_for_idle(bp);
if (err < 0)
return err;
return 0;
}
......
Markdown is supported
0%
or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment