|
|
|
@@ -101,17 +101,21 @@ mtk_wdma_read_reset(struct mtk_wed_device *dev)
|
|
|
|
|
return wdma_r32(dev, MTK_WDMA_GLO_CFG);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
static int
|
|
|
|
|
mtk_wdma_rx_reset(struct mtk_wed_device *dev)
|
|
|
|
|
{
|
|
|
|
|
u32 status, mask = MTK_WDMA_GLO_CFG_RX_DMA_BUSY;
|
|
|
|
|
int i;
|
|
|
|
|
int i, ret;
|
|
|
|
|
|
|
|
|
|
wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_RX_DMA_EN);
|
|
|
|
|
if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
|
|
|
|
|
!(status & mask), 0, 1000))
|
|
|
|
|
ret = readx_poll_timeout(mtk_wdma_read_reset, dev, status,
|
|
|
|
|
!(status & mask), 0, 10000);
|
|
|
|
|
if (ret)
|
|
|
|
|
dev_err(dev->hw->dev, "rx reset failed\n");
|
|
|
|
|
|
|
|
|
|
wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
|
|
|
|
|
wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++) {
|
|
|
|
|
if (dev->rx_wdma[i].desc)
|
|
|
|
|
continue;
|
|
|
|
@@ -119,6 +123,8 @@ mtk_wdma_rx_reset(struct mtk_wed_device *dev)
|
|
|
|
|
wdma_w32(dev,
|
|
|
|
|
MTK_WDMA_RING_RX(i) + MTK_WED_RING_OFS_CPU_IDX, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
@@ -129,16 +135,15 @@ mtk_wdma_tx_reset(struct mtk_wed_device *dev)
|
|
|
|
|
|
|
|
|
|
wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
|
|
|
|
|
if (readx_poll_timeout(mtk_wdma_read_reset, dev, status,
|
|
|
|
|
!(status & mask), 0, 1000))
|
|
|
|
|
!(status & mask), 0, 10000))
|
|
|
|
|
dev_err(dev->hw->dev, "tx reset failed\n");
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++) {
|
|
|
|
|
if (dev->tx_wdma[i].desc)
|
|
|
|
|
continue;
|
|
|
|
|
wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
|
|
|
|
|
wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(dev->tx_wdma); i++)
|
|
|
|
|
wdma_w32(dev,
|
|
|
|
|
MTK_WDMA_RING_TX(i) + MTK_WED_RING_OFS_CPU_IDX, 0);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
@@ -534,14 +539,8 @@ mtk_wed_dma_disable(struct mtk_wed_device *dev)
|
|
|
|
|
static void
|
|
|
|
|
mtk_wed_stop(struct mtk_wed_device *dev)
|
|
|
|
|
{
|
|
|
|
|
mtk_wed_dma_disable(dev);
|
|
|
|
|
mtk_wed_set_ext_int(dev, false);
|
|
|
|
|
|
|
|
|
|
wed_clr(dev, MTK_WED_CTRL,
|
|
|
|
|
MTK_WED_CTRL_WDMA_INT_AGENT_EN |
|
|
|
|
|
MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
|
|
|
|
|
MTK_WED_CTRL_WED_TX_BM_EN |
|
|
|
|
|
MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
|
|
|
|
|
wed_w32(dev, MTK_WED_WPDMA_INT_TRIGGER, 0);
|
|
|
|
|
wed_w32(dev, MTK_WED_WDMA_INT_TRIGGER, 0);
|
|
|
|
|
wdma_w32(dev, MTK_WDMA_INT_MASK, 0);
|
|
|
|
@@ -553,7 +552,27 @@ mtk_wed_stop(struct mtk_wed_device *dev)
|
|
|
|
|
|
|
|
|
|
wed_w32(dev, MTK_WED_EXT_INT_MASK1, 0);
|
|
|
|
|
wed_w32(dev, MTK_WED_EXT_INT_MASK2, 0);
|
|
|
|
|
wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
|
mtk_wed_deinit(struct mtk_wed_device *dev)
|
|
|
|
|
{
|
|
|
|
|
mtk_wed_stop(dev);
|
|
|
|
|
mtk_wed_dma_disable(dev);
|
|
|
|
|
|
|
|
|
|
wed_clr(dev, MTK_WED_CTRL,
|
|
|
|
|
MTK_WED_CTRL_WDMA_INT_AGENT_EN |
|
|
|
|
|
MTK_WED_CTRL_WPDMA_INT_AGENT_EN |
|
|
|
|
|
MTK_WED_CTRL_WED_TX_BM_EN |
|
|
|
|
|
MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
|
|
|
|
|
|
|
|
|
|
if (dev->hw->version == 1)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
wed_clr(dev, MTK_WED_CTRL,
|
|
|
|
|
MTK_WED_CTRL_RX_ROUTE_QM_EN |
|
|
|
|
|
MTK_WED_CTRL_WED_RX_BM_EN |
|
|
|
|
|
MTK_WED_CTRL_RX_RRO_QM_EN);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
@@ -563,18 +582,10 @@ mtk_wed_detach(struct mtk_wed_device *dev)
|
|
|
|
|
|
|
|
|
|
mutex_lock(&hw_lock);
|
|
|
|
|
|
|
|
|
|
mtk_wed_stop(dev);
|
|
|
|
|
|
|
|
|
|
wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
|
|
|
|
|
wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
|
|
|
|
|
mtk_wed_deinit(dev);
|
|
|
|
|
|
|
|
|
|
mtk_wdma_rx_reset(dev);
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_WED);
|
|
|
|
|
if (mtk_wed_get_rx_capa(dev)) {
|
|
|
|
|
wdma_clr(dev, MTK_WDMA_GLO_CFG, MTK_WDMA_GLO_CFG_TX_DMA_EN);
|
|
|
|
|
wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_TX);
|
|
|
|
|
wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mtk_wed_free_tx_buffer(dev);
|
|
|
|
|
mtk_wed_free_tx_rings(dev);
|
|
|
|
|
|
|
|
|
@@ -582,7 +593,6 @@ mtk_wed_detach(struct mtk_wed_device *dev)
|
|
|
|
|
mtk_wed_wo_reset(dev);
|
|
|
|
|
mtk_wed_free_rx_rings(dev);
|
|
|
|
|
mtk_wed_wo_deinit(hw);
|
|
|
|
|
mtk_wdma_rx_reset(dev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (dev->wlan.bus_type == MTK_WED_BUS_PCIE) {
|
|
|
|
@@ -674,7 +684,7 @@ mtk_wed_hw_init_early(struct mtk_wed_device *dev)
|
|
|
|
|
{
|
|
|
|
|
u32 mask, set;
|
|
|
|
|
|
|
|
|
|
mtk_wed_stop(dev);
|
|
|
|
|
mtk_wed_deinit(dev);
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_WED);
|
|
|
|
|
mtk_wed_set_wpdma(dev);
|
|
|
|
|
|
|
|
|
@@ -934,42 +944,130 @@ mtk_wed_ring_reset(struct mtk_wed_ring *ring, int size, bool tx)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static u32
|
|
|
|
|
mtk_wed_check_busy(struct mtk_wed_device *dev)
|
|
|
|
|
mtk_wed_check_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
|
|
|
|
|
{
|
|
|
|
|
if (wed_r32(dev, MTK_WED_GLO_CFG) & MTK_WED_GLO_CFG_TX_DMA_BUSY)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (wed_r32(dev, MTK_WED_WPDMA_GLO_CFG) &
|
|
|
|
|
MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (wed_r32(dev, MTK_WED_CTRL) & MTK_WED_CTRL_WDMA_INT_AGENT_BUSY)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (wed_r32(dev, MTK_WED_WDMA_GLO_CFG) &
|
|
|
|
|
MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (wdma_r32(dev, MTK_WDMA_GLO_CFG) &
|
|
|
|
|
MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY)
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
if (wed_r32(dev, MTK_WED_CTRL) &
|
|
|
|
|
(MTK_WED_CTRL_WED_TX_BM_BUSY | MTK_WED_CTRL_WED_TX_FREE_AGENT_BUSY))
|
|
|
|
|
return true;
|
|
|
|
|
|
|
|
|
|
return false;
|
|
|
|
|
return !!(wed_r32(dev, reg) & mask);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
mtk_wed_poll_busy(struct mtk_wed_device *dev)
|
|
|
|
|
mtk_wed_poll_busy(struct mtk_wed_device *dev, u32 reg, u32 mask)
|
|
|
|
|
{
|
|
|
|
|
int sleep = 15000;
|
|
|
|
|
int timeout = 100 * sleep;
|
|
|
|
|
u32 val;
|
|
|
|
|
|
|
|
|
|
return read_poll_timeout(mtk_wed_check_busy, val, !val, sleep,
|
|
|
|
|
timeout, false, dev);
|
|
|
|
|
timeout, false, dev, reg, mask);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
mtk_wed_rx_reset(struct mtk_wed_device *dev)
|
|
|
|
|
{
|
|
|
|
|
struct mtk_wed_wo *wo = dev->hw->wed_wo;
|
|
|
|
|
u8 val = MTK_WED_WO_STATE_SER_RESET;
|
|
|
|
|
int i, ret;
|
|
|
|
|
|
|
|
|
|
ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO,
|
|
|
|
|
MTK_WED_WO_CMD_CHANGE_STATE, &val,
|
|
|
|
|
sizeof(val), true);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG, MTK_WED_WPDMA_RX_D_RX_DRV_EN);
|
|
|
|
|
ret = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
|
|
|
|
|
MTK_WED_WPDMA_RX_D_RX_DRV_BUSY);
|
|
|
|
|
if (ret) {
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_RX_D_DRV);
|
|
|
|
|
} else {
|
|
|
|
|
wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX,
|
|
|
|
|
MTK_WED_WPDMA_RX_D_RST_CRX_IDX |
|
|
|
|
|
MTK_WED_WPDMA_RX_D_RST_DRV_IDX);
|
|
|
|
|
|
|
|
|
|
wed_set(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
|
|
|
|
|
MTK_WED_WPDMA_RX_D_RST_INIT_COMPLETE |
|
|
|
|
|
MTK_WED_WPDMA_RX_D_FSM_RETURN_IDLE);
|
|
|
|
|
wed_clr(dev, MTK_WED_WPDMA_RX_D_GLO_CFG,
|
|
|
|
|
MTK_WED_WPDMA_RX_D_RST_INIT_COMPLETE |
|
|
|
|
|
MTK_WED_WPDMA_RX_D_FSM_RETURN_IDLE);
|
|
|
|
|
|
|
|
|
|
wed_w32(dev, MTK_WED_WPDMA_RX_D_RST_IDX, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* reset rro qm */
|
|
|
|
|
wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_RRO_QM_EN);
|
|
|
|
|
ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
|
|
|
|
|
MTK_WED_CTRL_RX_RRO_QM_BUSY);
|
|
|
|
|
if (ret) {
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_RX_RRO_QM);
|
|
|
|
|
} else {
|
|
|
|
|
wed_set(dev, MTK_WED_RROQM_RST_IDX,
|
|
|
|
|
MTK_WED_RROQM_RST_IDX_MIOD |
|
|
|
|
|
MTK_WED_RROQM_RST_IDX_FDBK);
|
|
|
|
|
wed_w32(dev, MTK_WED_RROQM_RST_IDX, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* reset route qm */
|
|
|
|
|
wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_RX_ROUTE_QM_EN);
|
|
|
|
|
ret = mtk_wed_poll_busy(dev, MTK_WED_CTRL,
|
|
|
|
|
MTK_WED_CTRL_RX_ROUTE_QM_BUSY);
|
|
|
|
|
if (ret)
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_RX_ROUTE_QM);
|
|
|
|
|
else
|
|
|
|
|
wed_set(dev, MTK_WED_RTQM_GLO_CFG,
|
|
|
|
|
MTK_WED_RTQM_Q_RST);
|
|
|
|
|
|
|
|
|
|
/* reset tx wdma */
|
|
|
|
|
mtk_wdma_tx_reset(dev);
|
|
|
|
|
|
|
|
|
|
/* reset tx wdma drv */
|
|
|
|
|
wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_TX_DRV_EN);
|
|
|
|
|
mtk_wed_poll_busy(dev, MTK_WED_CTRL,
|
|
|
|
|
MTK_WED_CTRL_WDMA_INT_AGENT_BUSY);
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_WDMA_TX_DRV);
|
|
|
|
|
|
|
|
|
|
/* reset wed rx dma */
|
|
|
|
|
ret = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG,
|
|
|
|
|
MTK_WED_GLO_CFG_RX_DMA_BUSY);
|
|
|
|
|
wed_clr(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_RX_DMA_EN);
|
|
|
|
|
if (ret) {
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_WED_RX_DMA);
|
|
|
|
|
} else {
|
|
|
|
|
struct mtk_eth *eth = dev->hw->eth;
|
|
|
|
|
|
|
|
|
|
if (MTK_HAS_CAPS(eth->soc->caps, MTK_NETSYS_V2))
|
|
|
|
|
wed_set(dev, MTK_WED_RESET_IDX,
|
|
|
|
|
MTK_WED_RESET_IDX_RX_V2);
|
|
|
|
|
else
|
|
|
|
|
wed_set(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_RX);
|
|
|
|
|
wed_w32(dev, MTK_WED_RESET_IDX, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* reset rx bm */
|
|
|
|
|
wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_RX_BM_EN);
|
|
|
|
|
mtk_wed_poll_busy(dev, MTK_WED_CTRL,
|
|
|
|
|
MTK_WED_CTRL_WED_RX_BM_BUSY);
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_RX_BM);
|
|
|
|
|
|
|
|
|
|
/* wo change to enable state */
|
|
|
|
|
val = MTK_WED_WO_STATE_ENABLE;
|
|
|
|
|
ret = mtk_wed_mcu_send_msg(wo, MTK_WED_MODULE_ID_WO,
|
|
|
|
|
MTK_WED_WO_CMD_CHANGE_STATE, &val,
|
|
|
|
|
sizeof(val), true);
|
|
|
|
|
if (ret)
|
|
|
|
|
return ret;
|
|
|
|
|
|
|
|
|
|
/* wed_rx_ring_reset */
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(dev->rx_ring); i++) {
|
|
|
|
|
if (!dev->rx_ring[i].desc)
|
|
|
|
|
continue;
|
|
|
|
|
|
|
|
|
|
mtk_wed_ring_reset(&dev->rx_ring[i], MTK_WED_RX_RING_SIZE,
|
|
|
|
|
false);
|
|
|
|
|
}
|
|
|
|
|
mtk_wed_free_rx_buffer(dev);
|
|
|
|
|
|
|
|
|
|
return 0;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static void
|
|
|
|
@@ -987,23 +1085,23 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
|
|
|
|
|
true);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
if (mtk_wed_poll_busy(dev))
|
|
|
|
|
busy = mtk_wed_check_busy(dev);
|
|
|
|
|
|
|
|
|
|
/* 1. reset WED tx DMA */
|
|
|
|
|
wed_clr(dev, MTK_WED_GLO_CFG, MTK_WED_GLO_CFG_TX_DMA_EN);
|
|
|
|
|
busy = mtk_wed_poll_busy(dev, MTK_WED_GLO_CFG,
|
|
|
|
|
MTK_WED_GLO_CFG_TX_DMA_BUSY);
|
|
|
|
|
if (busy) {
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_WED_TX_DMA);
|
|
|
|
|
} else {
|
|
|
|
|
wed_w32(dev, MTK_WED_RESET_IDX,
|
|
|
|
|
MTK_WED_RESET_IDX_TX |
|
|
|
|
|
MTK_WED_RESET_IDX_RX);
|
|
|
|
|
wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_IDX_TX);
|
|
|
|
|
wed_w32(dev, MTK_WED_RESET_IDX, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
wdma_w32(dev, MTK_WDMA_RESET_IDX, MTK_WDMA_RESET_IDX_RX);
|
|
|
|
|
wdma_w32(dev, MTK_WDMA_RESET_IDX, 0);
|
|
|
|
|
|
|
|
|
|
if (mtk_wed_get_rx_capa(dev))
|
|
|
|
|
mtk_wdma_rx_reset(dev);
|
|
|
|
|
/* 2. reset WDMA rx DMA */
|
|
|
|
|
busy = !!mtk_wdma_rx_reset(dev);
|
|
|
|
|
wed_clr(dev, MTK_WED_WDMA_GLO_CFG, MTK_WED_WDMA_GLO_CFG_RX_DRV_EN);
|
|
|
|
|
if (!busy)
|
|
|
|
|
busy = mtk_wed_poll_busy(dev, MTK_WED_WDMA_GLO_CFG,
|
|
|
|
|
MTK_WED_WDMA_GLO_CFG_RX_DRV_BUSY);
|
|
|
|
|
|
|
|
|
|
if (busy) {
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_WDMA_INT_AGENT);
|
|
|
|
@@ -1020,6 +1118,9 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
|
|
|
|
|
MTK_WED_WDMA_GLO_CFG_RST_INIT_COMPLETE);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
/* 3. reset WED WPDMA tx */
|
|
|
|
|
wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_FREE_AGENT_EN);
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < 100; i++) {
|
|
|
|
|
val = wed_r32(dev, MTK_WED_TX_BM_INTF);
|
|
|
|
|
if (FIELD_GET(MTK_WED_TX_BM_INTF_TKFIFO_FDEP, val) == 0x40)
|
|
|
|
@@ -1027,8 +1128,19 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_TX_FREE_AGENT);
|
|
|
|
|
wed_clr(dev, MTK_WED_CTRL, MTK_WED_CTRL_WED_TX_BM_EN);
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_TX_BM);
|
|
|
|
|
|
|
|
|
|
/* 4. reset WED WPDMA tx */
|
|
|
|
|
busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
|
|
|
|
|
MTK_WED_WPDMA_GLO_CFG_TX_DRV_BUSY);
|
|
|
|
|
wed_clr(dev, MTK_WED_WPDMA_GLO_CFG,
|
|
|
|
|
MTK_WED_WPDMA_GLO_CFG_TX_DRV_EN |
|
|
|
|
|
MTK_WED_WPDMA_GLO_CFG_RX_DRV_EN);
|
|
|
|
|
if (!busy)
|
|
|
|
|
busy = mtk_wed_poll_busy(dev, MTK_WED_WPDMA_GLO_CFG,
|
|
|
|
|
MTK_WED_WPDMA_GLO_CFG_RX_DRV_BUSY);
|
|
|
|
|
|
|
|
|
|
if (busy) {
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_INT_AGENT);
|
|
|
|
|
mtk_wed_reset(dev, MTK_WED_RESET_WPDMA_TX_DRV);
|
|
|
|
@@ -1039,6 +1151,17 @@ mtk_wed_reset_dma(struct mtk_wed_device *dev)
|
|
|
|
|
MTK_WED_WPDMA_RESET_IDX_RX);
|
|
|
|
|
wed_w32(dev, MTK_WED_WPDMA_RESET_IDX, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
dev->init_done = false;
|
|
|
|
|
if (dev->hw->version == 1)
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
if (!busy) {
|
|
|
|
|
wed_w32(dev, MTK_WED_RESET_IDX, MTK_WED_RESET_WPDMA_IDX_RX);
|
|
|
|
|
wed_w32(dev, MTK_WED_RESET_IDX, 0);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
mtk_wed_rx_reset(dev);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
@@ -1058,7 +1181,8 @@ mtk_wed_ring_alloc(struct mtk_wed_device *dev, struct mtk_wed_ring *ring,
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
|
|
|
|
|
mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size,
|
|
|
|
|
bool reset)
|
|
|
|
|
{
|
|
|
|
|
u32 desc_size = sizeof(struct mtk_wdma_desc) * dev->hw->version;
|
|
|
|
|
struct mtk_wed_ring *wdma;
|
|
|
|
@@ -1067,8 +1191,8 @@ mtk_wed_wdma_rx_ring_setup(struct mtk_wed_device *dev, int idx, int size)
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
|
|
wdma = &dev->rx_wdma[idx];
|
|
|
|
|
if (mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE, desc_size,
|
|
|
|
|
true))
|
|
|
|
|
if (!reset && mtk_wed_ring_alloc(dev, wdma, MTK_WED_WDMA_RING_SIZE,
|
|
|
|
|
desc_size, true))
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
|
|
wdma_w32(dev, MTK_WDMA_RING_RX(idx) + MTK_WED_RING_OFS_BASE,
|
|
|
|
@@ -1261,9 +1385,12 @@ mtk_wed_start(struct mtk_wed_device *dev, u32 irq_mask)
|
|
|
|
|
{
|
|
|
|
|
int i;
|
|
|
|
|
|
|
|
|
|
if (mtk_wed_get_rx_capa(dev) && mtk_wed_rx_buffer_alloc(dev))
|
|
|
|
|
return;
|
|
|
|
|
|
|
|
|
|
for (i = 0; i < ARRAY_SIZE(dev->rx_wdma); i++)
|
|
|
|
|
if (!dev->rx_wdma[i].desc)
|
|
|
|
|
mtk_wed_wdma_rx_ring_setup(dev, i, 16);
|
|
|
|
|
mtk_wed_wdma_rx_ring_setup(dev, i, 16, false);
|
|
|
|
|
|
|
|
|
|
mtk_wed_hw_init(dev);
|
|
|
|
|
mtk_wed_configure_irq(dev, irq_mask);
|
|
|
|
@@ -1349,10 +1476,6 @@ mtk_wed_attach(struct mtk_wed_device *dev)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
if (mtk_wed_get_rx_capa(dev)) {
|
|
|
|
|
ret = mtk_wed_rx_buffer_alloc(dev);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto out;
|
|
|
|
|
|
|
|
|
|
ret = mtk_wed_rro_alloc(dev);
|
|
|
|
|
if (ret)
|
|
|
|
|
goto out;
|
|
|
|
@@ -1376,7 +1499,8 @@ unlock:
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
static int
|
|
|
|
|
mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
|
|
|
|
|
mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs,
|
|
|
|
|
bool reset)
|
|
|
|
|
{
|
|
|
|
|
struct mtk_wed_ring *ring = &dev->tx_ring[idx];
|
|
|
|
|
|
|
|
|
@@ -1395,11 +1519,12 @@ mtk_wed_tx_ring_setup(struct mtk_wed_device *dev, int idx, void __iomem *regs)
|
|
|
|
|
if (WARN_ON(idx >= ARRAY_SIZE(dev->tx_ring)))
|
|
|
|
|
return -EINVAL;
|
|
|
|
|
|
|
|
|
|
if (mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE,
|
|
|
|
|
sizeof(*ring->desc), true))
|
|
|
|
|
if (!reset && mtk_wed_ring_alloc(dev, ring, MTK_WED_TX_RING_SIZE,
|
|
|
|
|
sizeof(*ring->desc), true))
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
|
|
if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE))
|
|
|
|
|
if (mtk_wed_wdma_rx_ring_setup(dev, idx, MTK_WED_WDMA_RING_SIZE,
|
|
|
|
|
reset))
|
|
|
|
|
return -ENOMEM;
|
|
|
|
|
|
|
|
|
|
ring->reg_base = MTK_WED_RING_TX(idx);
|
|
|
|
|