diff mbox series

[2/8] net: dwc_eth_qos: Fix the software reset

Message ID 20200430103656.29728-3-david.wu@rock-chips.com
State Superseded
Delegated to: Joe Hershberger
Headers show
Series Add dwc_eth_qos support for rockchip | expand

Commit Message

David Wu April 30, 2020, 10:36 a.m. UTC
When using rgmii Gigabit mode, the wait_for_bit_le32()
reset method resulting in RX can not receive data, after
this patch, works well.

Signed-off-by: David Wu <david.wu@rock-chips.com>
---

 drivers/net/dwc_eth_qos.c | 21 +++++++++++++++------
 1 file changed, 15 insertions(+), 6 deletions(-)

Comments

Patrice CHOTARD April 30, 2020, 3:28 p.m. UTC | #1
Hi David

On 4/30/20 12:36 PM, David Wu wrote:
> When using rgmii Gigabit mode, the wait_for_bit_le32()
> reset method resulting in RX can not receive data, after
> this patch, works well.
>
> Signed-off-by: David Wu <david.wu@rock-chips.com>
> ---
>
>  drivers/net/dwc_eth_qos.c | 21 +++++++++++++++------
>  1 file changed, 15 insertions(+), 6 deletions(-)
>
> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
> index a72132cacf..16988f6bdc 100644
> --- a/drivers/net/dwc_eth_qos.c
> +++ b/drivers/net/dwc_eth_qos.c
> @@ -1034,7 +1034,7 @@ static int eqos_write_hwaddr(struct udevice *dev)
>  static int eqos_start(struct udevice *dev)
>  {
>  	struct eqos_priv *eqos = dev_get_priv(dev);
> -	int ret, i;
> +	int ret, i, limit;
>  	ulong rate;
>  	u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl;
>  	ulong last_rx_desc;
> @@ -1060,12 +1060,21 @@ static int eqos_start(struct udevice *dev)
>  
>  	eqos->reg_access_ok = true;
>  
> -	ret = wait_for_bit_le32(&eqos->dma_regs->mode,
> -				EQOS_DMA_MODE_SWR, false,
> -				eqos->config->swr_wait, false);
> -	if (ret) {
> +	/* DMA SW reset */
> +	val = readl(&eqos->dma_regs->mode);
> +	val |= EQOS_DMA_MODE_SWR;
> +	writel(val, &eqos->dma_regs->mode);
> +	limit = eqos->config->swr_wait / 10;
> +	while (limit--) {
> +		if (!(readl(&eqos->dma_regs->mode) & EQOS_DMA_MODE_SWR))
> +			break;
> +		mdelay(10000);
> +	}

usage of wait_for_bit_le32() must still work, if the timeout is no enough in you case,

create a dedicated rockchip struct eqos_config


> +
> +	if (limit < 0) {
>  		pr_err("EQOS_DMA_MODE_SWR stuck");
> -		goto err_stop_resets;
why are you updating the error path here ?
> +		goto err_stop_clks;
> +		return -ETIMEDOUT;
the return after the goto is useless
>  	}
>  
>  	ret = eqos->config->ops->eqos_calibrate_pads(dev);
Stephen Warren April 30, 2020, 10:25 p.m. UTC | #2
On 4/30/20 4:36 AM, David Wu wrote:
> When using rgmii Gigabit mode, the wait_for_bit_le32()
> reset method resulting in RX can not receive data, after
> this patch, works well.

> diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c

> +	limit = eqos->config->swr_wait / 10;
> +	while (limit--) {
> +		if (!(readl(&eqos->dma_regs->mode) & EQOS_DMA_MODE_SWR))
> +			break;
> +		mdelay(10000);
> +	}

mdelay()'s parameter is in milliseconds judging by its implementation in
include/linux/delay.h. So, this delays 10 seconds in each loop
iteration. That can't possibly be right.
diff mbox series

Patch

diff --git a/drivers/net/dwc_eth_qos.c b/drivers/net/dwc_eth_qos.c
index a72132cacf..16988f6bdc 100644
--- a/drivers/net/dwc_eth_qos.c
+++ b/drivers/net/dwc_eth_qos.c
@@ -1034,7 +1034,7 @@  static int eqos_write_hwaddr(struct udevice *dev)
 static int eqos_start(struct udevice *dev)
 {
 	struct eqos_priv *eqos = dev_get_priv(dev);
-	int ret, i;
+	int ret, i, limit;
 	ulong rate;
 	u32 val, tx_fifo_sz, rx_fifo_sz, tqs, rqs, pbl;
 	ulong last_rx_desc;
@@ -1060,12 +1060,21 @@  static int eqos_start(struct udevice *dev)
 
 	eqos->reg_access_ok = true;
 
-	ret = wait_for_bit_le32(&eqos->dma_regs->mode,
-				EQOS_DMA_MODE_SWR, false,
-				eqos->config->swr_wait, false);
-	if (ret) {
+	/* DMA SW reset */
+	val = readl(&eqos->dma_regs->mode);
+	val |= EQOS_DMA_MODE_SWR;
+	writel(val, &eqos->dma_regs->mode);
+	limit = eqos->config->swr_wait / 10;
+	while (limit--) {
+		if (!(readl(&eqos->dma_regs->mode) & EQOS_DMA_MODE_SWR))
+			break;
+		mdelay(10000);
+	}
+
+	if (limit < 0) {
 		pr_err("EQOS_DMA_MODE_SWR stuck");
-		goto err_stop_resets;
+		goto err_stop_clks;
+		return -ETIMEDOUT;
 	}
 
 	ret = eqos->config->ops->eqos_calibrate_pads(dev);