Message ID | 20200430103656.29728-3-david.wu@rock-chips.com |
---|---|
State | New |
Headers | show |
Series | Add dwc_eth_qos support for rockchip | expand |
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 at 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);
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 --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);
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 at rock-chips.com> --- drivers/net/dwc_eth_qos.c | 21 +++++++++++++++------ 1 file changed, 15 insertions(+), 6 deletions(-)