1 // SPDX-License-Identifier: ISC
2 /* Copyright (C) 2019 MediaTek Inc.
4 * Author: Ryder Lee <ryder.lee@mediatek.com>
5 * Roy Luo <royluo@google.com>
6 * Lorenzo Bianconi <lorenzo@kernel.org>
7 * Felix Fietkau <nbd@nbd.name>
15 mt7615_init_tx_queues(struct mt7615_dev
*dev
, int n_desc
)
17 struct mt76_sw_queue
*q
;
18 struct mt76_queue
*hwq
;
21 hwq
= devm_kzalloc(dev
->mt76
.dev
, sizeof(*hwq
), GFP_KERNEL
);
25 err
= mt76_queue_alloc(dev
, hwq
, 0, n_desc
, 0, MT_TX_RING_BASE
);
29 for (i
= 0; i
< MT_TXQ_MCU
; i
++) {
30 q
= &dev
->mt76
.q_tx
[i
];
31 INIT_LIST_HEAD(&q
->swq
);
39 mt7615_init_mcu_queue(struct mt7615_dev
*dev
, struct mt76_sw_queue
*q
,
42 struct mt76_queue
*hwq
;
45 hwq
= devm_kzalloc(dev
->mt76
.dev
, sizeof(*hwq
), GFP_KERNEL
);
49 err
= mt76_queue_alloc(dev
, hwq
, idx
, n_desc
, 0, MT_TX_RING_BASE
);
53 INIT_LIST_HEAD(&q
->swq
);
59 void mt7615_queue_rx_skb(struct mt76_dev
*mdev
, enum mt76_rxq_id q
,
62 struct mt7615_dev
*dev
= container_of(mdev
, struct mt7615_dev
, mt76
);
63 __le32
*rxd
= (__le32
*)skb
->data
;
64 __le32
*end
= (__le32
*)&skb
->data
[skb
->len
];
65 enum rx_pkt_type type
;
67 type
= FIELD_GET(MT_RXD0_PKT_TYPE
, le32_to_cpu(rxd
[0]));
71 for (rxd
++; rxd
+ 7 <= end
; rxd
+= 7)
72 mt7615_mac_add_txs(dev
, rxd
);
75 case PKT_TYPE_TXRX_NOTIFY
:
76 mt7615_mac_tx_free(dev
, skb
);
78 case PKT_TYPE_RX_EVENT
:
79 mt76_mcu_rx_event(&dev
->mt76
, skb
);
82 if (!mt7615_mac_fill_rx(dev
, skb
)) {
83 mt76_rx(&dev
->mt76
, q
, skb
);
93 static void mt7615_tx_tasklet(unsigned long data
)
95 struct mt7615_dev
*dev
= (struct mt7615_dev
*)data
;
96 static const u8 queue_map
[] = {
102 for (i
= 0; i
< ARRAY_SIZE(queue_map
); i
++)
103 mt76_queue_tx_cleanup(dev
, queue_map
[i
], false);
105 mt76_txq_schedule_all(&dev
->mt76
);
107 mt7615_irq_enable(dev
, MT_INT_TX_DONE_ALL
);
110 int mt7615_dma_init(struct mt7615_dev
*dev
)
114 mt76_dma_attach(&dev
->mt76
);
116 tasklet_init(&dev
->mt76
.tx_tasklet
, mt7615_tx_tasklet
,
119 mt76_wr(dev
, MT_WPDMA_GLO_CFG
,
120 MT_WPDMA_GLO_CFG_TX_WRITEBACK_DONE
|
121 MT_WPDMA_GLO_CFG_FIFO_LITTLE_ENDIAN
|
122 MT_WPDMA_GLO_CFG_FIRST_TOKEN_ONLY
|
123 MT_WPDMA_GLO_CFG_OMIT_TX_INFO
);
125 mt76_rmw_field(dev
, MT_WPDMA_GLO_CFG
,
126 MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT0
, 0x1);
128 mt76_rmw_field(dev
, MT_WPDMA_GLO_CFG
,
129 MT_WPDMA_GLO_CFG_TX_BT_SIZE_BIT21
, 0x1);
131 mt76_rmw_field(dev
, MT_WPDMA_GLO_CFG
,
132 MT_WPDMA_GLO_CFG_DMA_BURST_SIZE
, 0x3);
134 mt76_rmw_field(dev
, MT_WPDMA_GLO_CFG
,
135 MT_WPDMA_GLO_CFG_MULTI_DMA_EN
, 0x3);
137 mt76_wr(dev
, MT_WPDMA_GLO_CFG1
, 0x1);
138 mt76_wr(dev
, MT_WPDMA_TX_PRE_CFG
, 0xf0000);
139 mt76_wr(dev
, MT_WPDMA_RX_PRE_CFG
, 0xf7f0000);
140 mt76_wr(dev
, MT_WPDMA_ABT_CFG
, 0x4000026);
141 mt76_wr(dev
, MT_WPDMA_ABT_CFG1
, 0x18811881);
142 mt76_set(dev
, 0x7158, BIT(16));
143 mt76_clear(dev
, 0x7000, BIT(23));
144 mt76_wr(dev
, MT_WPDMA_RST_IDX
, ~0);
146 ret
= mt7615_init_tx_queues(dev
, MT7615_TX_RING_SIZE
);
150 ret
= mt7615_init_mcu_queue(dev
, &dev
->mt76
.q_tx
[MT_TXQ_MCU
],
152 MT7615_TX_MCU_RING_SIZE
);
156 ret
= mt7615_init_mcu_queue(dev
, &dev
->mt76
.q_tx
[MT_TXQ_FWDL
],
158 MT7615_TX_FWDL_RING_SIZE
);
163 ret
= mt76_queue_alloc(dev
, &dev
->mt76
.q_rx
[MT_RXQ_MCU
], 1,
164 MT7615_RX_MCU_RING_SIZE
, MT_RX_BUF_SIZE
,
169 ret
= mt76_queue_alloc(dev
, &dev
->mt76
.q_rx
[MT_RXQ_MAIN
], 0,
170 MT7615_RX_RING_SIZE
, MT_RX_BUF_SIZE
,
175 mt76_wr(dev
, MT_DELAY_INT_CFG
, 0);
177 ret
= mt76_init_queues(dev
);
181 mt76_poll(dev
, MT_WPDMA_GLO_CFG
,
182 MT_WPDMA_GLO_CFG_TX_DMA_BUSY
|
183 MT_WPDMA_GLO_CFG_RX_DMA_BUSY
, 0, 1000);
185 /* start dma engine */
186 mt76_set(dev
, MT_WPDMA_GLO_CFG
,
187 MT_WPDMA_GLO_CFG_TX_DMA_EN
|
188 MT_WPDMA_GLO_CFG_RX_DMA_EN
);
190 /* enable interrupts for TX/RX rings */
191 mt7615_irq_enable(dev
, MT_INT_RX_DONE_ALL
| MT_INT_TX_DONE_ALL
);
196 void mt7615_dma_cleanup(struct mt7615_dev
*dev
)
198 mt76_clear(dev
, MT_WPDMA_GLO_CFG
,
199 MT_WPDMA_GLO_CFG_TX_DMA_EN
|
200 MT_WPDMA_GLO_CFG_RX_DMA_EN
);
201 mt76_set(dev
, MT_WPDMA_GLO_CFG
, MT_WPDMA_GLO_CFG_SW_RESET
);
203 tasklet_kill(&dev
->mt76
.tx_tasklet
);
204 mt76_dma_cleanup(&dev
->mt76
);