Branch data Line data Source code
1 : : // SPDX-License-Identifier: GPL-2.0 OR BSD-3-Clause
2 : : /* Copyright(c) 2018-2019 Realtek Corporation
3 : : */
4 : :
5 : : #include "main.h"
6 : : #include "mac.h"
7 : : #include "reg.h"
8 : : #include "fw.h"
9 : : #include "debug.h"
10 : :
11 : 0 : void rtw_set_channel_mac(struct rtw_dev *rtwdev, u8 channel, u8 bw,
12 : : u8 primary_ch_idx)
13 : : {
14 : 0 : u8 txsc40 = 0, txsc20 = 0;
15 : 0 : u32 value32;
16 : 0 : u8 value8;
17 : :
18 : 0 : txsc20 = primary_ch_idx;
19 [ # # ]: 0 : if (bw == RTW_CHANNEL_WIDTH_80) {
20 [ # # # # ]: 0 : if (txsc20 == 1 || txsc20 == 3)
21 : : txsc40 = 9;
22 : : else
23 : 0 : txsc40 = 10;
24 : : }
25 : 0 : rtw_write8(rtwdev, REG_DATA_SC,
26 : 0 : BIT_TXSC_20M(txsc20) | BIT_TXSC_40M(txsc40));
27 : :
28 : 0 : value32 = rtw_read32(rtwdev, REG_WMAC_TRXPTCL_CTL);
29 : 0 : value32 &= ~BIT_RFMOD;
30 [ # # # ]: 0 : switch (bw) {
31 : 0 : case RTW_CHANNEL_WIDTH_80:
32 : 0 : value32 |= BIT_RFMOD_80M;
33 : 0 : break;
34 : 0 : case RTW_CHANNEL_WIDTH_40:
35 : 0 : value32 |= BIT_RFMOD_40M;
36 : 0 : break;
37 : : case RTW_CHANNEL_WIDTH_20:
38 : : default:
39 : : break;
40 : : }
41 : 0 : rtw_write32(rtwdev, REG_WMAC_TRXPTCL_CTL, value32);
42 : :
43 : 0 : value32 = rtw_read32(rtwdev, REG_AFE_CTRL1) & ~(BIT_MAC_CLK_SEL);
44 : 0 : value32 |= (MAC_CLK_HW_DEF_80M << BIT_SHIFT_MAC_CLK_SEL);
45 : 0 : rtw_write32(rtwdev, REG_AFE_CTRL1, value32);
46 : :
47 : 0 : rtw_write8(rtwdev, REG_USTIME_TSF, MAC_CLK_SPEED);
48 : 0 : rtw_write8(rtwdev, REG_USTIME_EDCA, MAC_CLK_SPEED);
49 : :
50 : 0 : value8 = rtw_read8(rtwdev, REG_CCK_CHECK);
51 : 0 : value8 = value8 & ~BIT_CHECK_CCK_EN;
52 [ # # # # : 0 : if (IS_CH_5G_BAND(channel))
# # # # ]
53 : 0 : value8 |= BIT_CHECK_CCK_EN;
54 : 0 : rtw_write8(rtwdev, REG_CCK_CHECK, value8);
55 : 0 : }
56 : :
57 : 13 : static int rtw_mac_pre_system_cfg(struct rtw_dev *rtwdev)
58 : : {
59 : 13 : u32 value32;
60 : 13 : u8 value8;
61 : :
62 : 13 : rtw_write8(rtwdev, REG_RSV_CTRL, 0);
63 : :
64 [ + - - ]: 13 : switch (rtw_hci_type(rtwdev)) {
65 : : case RTW_HCI_TYPE_PCIE:
66 : 13 : rtw_write32_set(rtwdev, REG_HCI_OPT_CTRL, BIT_BT_DIG_CLK_EN);
67 : : break;
68 : : case RTW_HCI_TYPE_USB:
69 : : break;
70 : : default:
71 : : return -EINVAL;
72 : : }
73 : :
74 : : /* config PIN Mux */
75 : 13 : value32 = rtw_read32(rtwdev, REG_PAD_CTRL1);
76 : 13 : value32 |= BIT_PAPE_WLBT_SEL | BIT_LNAON_WLBT_SEL;
77 : 13 : rtw_write32(rtwdev, REG_PAD_CTRL1, value32);
78 : :
79 : 13 : value32 = rtw_read32(rtwdev, REG_LED_CFG);
80 : 13 : value32 &= ~(BIT_PAPE_SEL_EN | BIT_LNAON_SEL_EN);
81 : 13 : rtw_write32(rtwdev, REG_LED_CFG, value32);
82 : :
83 : 13 : value32 = rtw_read32(rtwdev, REG_GPIO_MUXCFG);
84 : 13 : value32 |= BIT_WLRFE_4_5_EN;
85 : 13 : rtw_write32(rtwdev, REG_GPIO_MUXCFG, value32);
86 : :
87 : : /* disable BB/RF */
88 : 13 : value8 = rtw_read8(rtwdev, REG_SYS_FUNC_EN);
89 : 13 : value8 &= ~(BIT_FEN_BB_RSTB | BIT_FEN_BB_GLB_RST);
90 : 13 : rtw_write8(rtwdev, REG_SYS_FUNC_EN, value8);
91 : :
92 : 13 : value8 = rtw_read8(rtwdev, REG_RF_CTRL);
93 : 13 : value8 &= ~(BIT_RF_SDM_RSTB | BIT_RF_RSTB | BIT_RF_EN);
94 : 13 : rtw_write8(rtwdev, REG_RF_CTRL, value8);
95 : :
96 : 13 : value32 = rtw_read32(rtwdev, REG_WLRF1);
97 : 13 : value32 &= ~BIT_WLRF1_BBRF_EN;
98 : 13 : rtw_write32(rtwdev, REG_WLRF1, value32);
99 : :
100 : 13 : return 0;
101 : : }
102 : :
103 : 34 : static int rtw_pwr_cmd_polling(struct rtw_dev *rtwdev,
104 : : struct rtw_pwr_seq_cmd *cmd)
105 : : {
106 : 34 : u8 value;
107 : 34 : u8 flag = 0;
108 : 34 : u32 offset;
109 : 34 : u32 cnt = RTW_PWR_POLLING_CNT;
110 : :
111 [ - + ]: 34 : if (cmd->base == RTW_PWR_ADDR_SDIO)
112 : 0 : offset = cmd->offset | SDIO_LOCAL_OFFSET;
113 : : else
114 : 34 : offset = cmd->offset;
115 : :
116 : 62 : do {
117 : 62 : cnt--;
118 : 62 : value = rtw_read8(rtwdev, offset);
119 : 62 : value &= cmd->mask;
120 [ + + ]: 62 : if (value == (cmd->value & cmd->mask))
121 : : return 0;
122 [ - + ]: 28 : if (cnt == 0) {
123 [ # # # # ]: 0 : if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_PCIE &&
124 : : flag == 0) {
125 : 0 : value = rtw_read8(rtwdev, REG_SYS_PW_CTRL);
126 : 0 : value |= BIT(3);
127 : 0 : rtw_write8(rtwdev, REG_SYS_PW_CTRL, value);
128 : 0 : value &= ~BIT(3);
129 : 0 : rtw_write8(rtwdev, REG_SYS_PW_CTRL, value);
130 : 0 : cnt = RTW_PWR_POLLING_CNT;
131 : 0 : flag = 1;
132 : : } else {
133 : : return -EBUSY;
134 : : }
135 : : } else {
136 : 28 : udelay(50);
137 : : }
138 : : } while (1);
139 : : }
140 : :
141 : 48 : static int rtw_sub_pwr_seq_parser(struct rtw_dev *rtwdev, u8 intf_mask,
142 : : u8 cut_mask, struct rtw_pwr_seq_cmd *cmd)
143 : : {
144 : 48 : struct rtw_pwr_seq_cmd *cur_cmd;
145 : 48 : u32 offset;
146 : 48 : u8 value;
147 : :
148 [ + + ]: 848 : for (cur_cmd = cmd; cur_cmd->cmd != RTW_PWR_CMD_END; cur_cmd++) {
149 [ + + ]: 800 : if (!(cur_cmd->intf_mask & intf_mask) ||
150 [ - + ]: 402 : !(cur_cmd->cut_mask & cut_mask))
151 : 398 : continue;
152 : :
153 [ + + - - : 402 : switch (cur_cmd->cmd) {
- ]
154 : 368 : case RTW_PWR_CMD_WRITE:
155 : 368 : offset = cur_cmd->offset;
156 : :
157 [ - + ]: 368 : if (cur_cmd->base == RTW_PWR_ADDR_SDIO)
158 : 0 : offset |= SDIO_LOCAL_OFFSET;
159 : :
160 : 368 : value = rtw_read8(rtwdev, offset);
161 : 368 : value &= ~cur_cmd->mask;
162 : 368 : value |= (cur_cmd->value & cur_cmd->mask);
163 : 368 : rtw_write8(rtwdev, offset, value);
164 : : break;
165 : 34 : case RTW_PWR_CMD_POLLING:
166 [ + - ]: 34 : if (rtw_pwr_cmd_polling(rtwdev, cur_cmd))
167 : : return -EBUSY;
168 : : break;
169 : 0 : case RTW_PWR_CMD_DELAY:
170 [ # # ]: 0 : if (cur_cmd->value == RTW_PWR_DELAY_US)
171 [ # # # # ]: 0 : udelay(cur_cmd->offset);
172 : : else
173 [ # # # # : 0 : mdelay(cur_cmd->offset);
# # # # #
# ]
174 : : break;
175 : : case RTW_PWR_CMD_READ:
176 : : break;
177 : : default:
178 : : return -EINVAL;
179 : : }
180 : : }
181 : :
182 : : return 0;
183 : : }
184 : :
185 : 24 : static int rtw_pwr_seq_parser(struct rtw_dev *rtwdev,
186 : : struct rtw_pwr_seq_cmd **cmd_seq)
187 : : {
188 : 24 : u8 cut_mask;
189 : 24 : u8 intf_mask;
190 : 24 : u8 cut;
191 : 24 : u32 idx = 0;
192 : 24 : struct rtw_pwr_seq_cmd *cmd;
193 : 24 : int ret;
194 : :
195 : 24 : cut = rtwdev->hal.cut_version;
196 : 24 : cut_mask = cut_version_to_mask(cut);
197 [ - + - ]: 24 : switch (rtw_hci_type(rtwdev)) {
198 : : case RTW_HCI_TYPE_PCIE:
199 : : intf_mask = BIT(2);
200 : : break;
201 : 0 : case RTW_HCI_TYPE_USB:
202 : 0 : intf_mask = BIT(1);
203 : 0 : break;
204 : : default:
205 : : return -EINVAL;
206 : : }
207 : :
208 : 72 : do {
209 : 72 : cmd = cmd_seq[idx];
210 [ + + ]: 72 : if (!cmd)
211 : : break;
212 : :
213 : 48 : ret = rtw_sub_pwr_seq_parser(rtwdev, intf_mask, cut_mask, cmd);
214 [ + - ]: 48 : if (ret)
215 : : return -EBUSY;
216 : :
217 : 48 : idx++;
218 : 48 : } while (1);
219 : :
220 : : return 0;
221 : : }
222 : :
223 : 31 : static int rtw_mac_power_switch(struct rtw_dev *rtwdev, bool pwr_on)
224 : : {
225 : 31 : struct rtw_chip_info *chip = rtwdev->chip;
226 : 31 : struct rtw_pwr_seq_cmd **pwr_seq;
227 : 31 : u8 rpwm;
228 : 31 : bool cur_pwr;
229 : :
230 : 31 : rpwm = rtw_read8(rtwdev, rtwdev->hci.rpwm_addr);
231 : :
232 : : /* Check FW still exist or not */
233 [ + + ]: 31 : if (rtw_read16(rtwdev, REG_MCUFW_CTRL) == 0xC078) {
234 : 1 : rpwm = (rpwm ^ BIT_RPWM_TOGGLE) & BIT_RPWM_TOGGLE;
235 : 1 : rtw_write8(rtwdev, rtwdev->hci.rpwm_addr, rpwm);
236 : : }
237 : :
238 [ + + ]: 31 : if (rtw_read8(rtwdev, REG_CR) == 0xea)
239 : : cur_pwr = false;
240 [ - + ]: 12 : else if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB &&
241 : : (rtw_read8(rtwdev, REG_SYS_STATUS1 + 1) & BIT(0)))
242 : : cur_pwr = false;
243 : : else
244 : : cur_pwr = true;
245 : :
246 [ + + + + ]: 31 : if (pwr_on && cur_pwr)
247 : : return -EALREADY;
248 : :
249 [ + + ]: 24 : pwr_seq = pwr_on ? chip->pwr_on_seq : chip->pwr_off_seq;
250 [ - + ]: 24 : if (rtw_pwr_seq_parser(rtwdev, pwr_seq))
251 : 0 : return -EINVAL;
252 : :
253 : : return 0;
254 : : }
255 : :
256 : 10 : static int rtw_mac_init_system_cfg(struct rtw_dev *rtwdev)
257 : : {
258 : 10 : u8 sys_func_en = rtwdev->chip->sys_func_en;
259 : 10 : u8 value8;
260 : 10 : u32 value, tmp;
261 : :
262 : 10 : value = rtw_read32(rtwdev, REG_CPU_DMEM_CON);
263 : 10 : value |= BIT_WL_PLATFORM_RST | BIT_DDMA_EN;
264 : 10 : rtw_write32(rtwdev, REG_CPU_DMEM_CON, value);
265 : :
266 : 10 : rtw_write8_set(rtwdev, REG_SYS_FUNC_EN + 1, sys_func_en);
267 : 10 : value8 = (rtw_read8(rtwdev, REG_CR_EXT + 3) & 0xF0) | 0x0C;
268 : 10 : rtw_write8(rtwdev, REG_CR_EXT + 3, value8);
269 : :
270 : : /* disable boot-from-flash for driver's DL FW */
271 : 10 : tmp = rtw_read32(rtwdev, REG_MCUFW_CTRL);
272 [ + - ]: 10 : if (tmp & BIT_BOOT_FSPI_EN) {
273 : 10 : rtw_write32(rtwdev, REG_MCUFW_CTRL, tmp & (~BIT_BOOT_FSPI_EN));
274 : 10 : value = rtw_read32(rtwdev, REG_GPIO_MUXCFG) & (~BIT_FSPI_EN);
275 : 10 : rtw_write32(rtwdev, REG_GPIO_MUXCFG, value);
276 : : }
277 : :
278 : 10 : return 0;
279 : : }
280 : :
281 : 13 : int rtw_mac_power_on(struct rtw_dev *rtwdev)
282 : : {
283 : 13 : int ret = 0;
284 : :
285 : 13 : ret = rtw_mac_pre_system_cfg(rtwdev);
286 [ - + ]: 13 : if (ret)
287 : 0 : goto err;
288 : :
289 : 13 : ret = rtw_mac_power_switch(rtwdev, true);
290 [ + + ]: 13 : if (ret == -EALREADY) {
291 : 4 : rtw_mac_power_switch(rtwdev, false);
292 : 4 : ret = rtw_mac_power_switch(rtwdev, true);
293 [ + + ]: 4 : if (ret)
294 : 3 : goto err;
295 [ - + ]: 9 : } else if (ret) {
296 : 0 : goto err;
297 : : }
298 : :
299 : 10 : ret = rtw_mac_init_system_cfg(rtwdev);
300 [ - + ]: 10 : if (ret)
301 : 0 : goto err;
302 : :
303 : : return 0;
304 : :
305 : 3 : err:
306 : 3 : rtw_err(rtwdev, "mac power on failed");
307 : 3 : return ret;
308 : : }
309 : :
310 : 10 : void rtw_mac_power_off(struct rtw_dev *rtwdev)
311 : : {
312 : 10 : rtw_mac_power_switch(rtwdev, false);
313 : 10 : }
314 : :
315 : 10 : static bool check_firmware_size(const u8 *data, u32 size)
316 : : {
317 : 10 : const struct rtw_fw_hdr *fw_hdr = (const struct rtw_fw_hdr *)data;
318 : 10 : u32 dmem_size;
319 : 10 : u32 imem_size;
320 : 10 : u32 emem_size;
321 : 10 : u32 real_size;
322 : :
323 : 10 : dmem_size = le32_to_cpu(fw_hdr->dmem_size);
324 : 10 : imem_size = le32_to_cpu(fw_hdr->imem_size);
325 : 10 : emem_size = (fw_hdr->mem_usage & BIT(4)) ?
326 [ - + ]: 10 : le32_to_cpu(fw_hdr->emem_size) : 0;
327 : :
328 : 10 : printk(KERN_INFO "dmem_size: %x, imem_size: %x, emem_size: %x\n",
329 : : dmem_size, imem_size, emem_size);
330 : :
331 : 10 : dmem_size += FW_HDR_CHKSUM_SIZE;
332 : 10 : imem_size += FW_HDR_CHKSUM_SIZE;
333 [ + - ]: 10 : emem_size += emem_size ? FW_HDR_CHKSUM_SIZE : 0;
334 : 10 : real_size = FW_HDR_SIZE + dmem_size + imem_size + emem_size;
335 : :
336 : 10 : printk(KERN_INFO "real_size: %x, size: %x\n", real_size, size);
337 [ - + ]: 10 : if (real_size != size)
338 : 0 : return false;
339 : :
340 : : return true;
341 : : }
342 : :
343 : 20 : static void wlan_cpu_enable(struct rtw_dev *rtwdev, bool enable)
344 : : {
345 [ + + ]: 20 : if (enable) {
346 : : /* cpu io interface enable */
347 : 10 : rtw_write8_set(rtwdev, REG_RSV_CTRL + 1, BIT_WLMCU_IOIF);
348 : :
349 : : /* cpu enable */
350 : 10 : rtw_write8_set(rtwdev, REG_SYS_FUNC_EN + 1, BIT_FEN_CPUEN);
351 : : } else {
352 : : /* cpu io interface disable */
353 : 10 : rtw_write8_clr(rtwdev, REG_SYS_FUNC_EN + 1, BIT_FEN_CPUEN);
354 : :
355 : : /* cpu disable */
356 : 10 : rtw_write8_clr(rtwdev, REG_RSV_CTRL + 1, BIT_WLMCU_IOIF);
357 : : }
358 : 20 : }
359 : :
360 : : #define DLFW_RESTORE_REG_NUM 6
361 : :
362 : 10 : static void download_firmware_reg_backup(struct rtw_dev *rtwdev,
363 : : struct rtw_backup_info *bckp)
364 : : {
365 : 10 : u8 tmp;
366 : 10 : u8 bckp_idx = 0;
367 : :
368 : : /* set HIQ to hi priority */
369 : 10 : bckp[bckp_idx].len = 1;
370 : 10 : bckp[bckp_idx].reg = REG_TXDMA_PQ_MAP + 1;
371 : 10 : bckp[bckp_idx].val = rtw_read8(rtwdev, REG_TXDMA_PQ_MAP + 1);
372 : 10 : bckp_idx++;
373 : 10 : tmp = RTW_DMA_MAPPING_HIGH << 6;
374 : 10 : rtw_write8(rtwdev, REG_TXDMA_PQ_MAP + 1, tmp);
375 : :
376 : : /* DLFW only use HIQ, map HIQ to hi priority */
377 : 10 : bckp[bckp_idx].len = 1;
378 : 10 : bckp[bckp_idx].reg = REG_CR;
379 : 10 : bckp[bckp_idx].val = rtw_read8(rtwdev, REG_CR);
380 : 10 : bckp_idx++;
381 : 10 : bckp[bckp_idx].len = 4;
382 : 10 : bckp[bckp_idx].reg = REG_H2CQ_CSR;
383 : 10 : bckp[bckp_idx].val = BIT_H2CQ_FULL;
384 : 10 : bckp_idx++;
385 : 10 : tmp = BIT_HCI_TXDMA_EN | BIT_TXDMA_EN;
386 : 10 : rtw_write8(rtwdev, REG_CR, tmp);
387 : 10 : rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL);
388 : :
389 : : /* Config hi priority queue and public priority queue page number */
390 : 10 : bckp[bckp_idx].len = 2;
391 : 10 : bckp[bckp_idx].reg = REG_FIFOPAGE_INFO_1;
392 : 10 : bckp[bckp_idx].val = rtw_read16(rtwdev, REG_FIFOPAGE_INFO_1);
393 : 10 : bckp_idx++;
394 : 10 : bckp[bckp_idx].len = 4;
395 : 10 : bckp[bckp_idx].reg = REG_RQPN_CTRL_2;
396 : 10 : bckp[bckp_idx].val = rtw_read32(rtwdev, REG_RQPN_CTRL_2) | BIT_LD_RQPN;
397 : 10 : bckp_idx++;
398 : 10 : rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, 0x200);
399 : 10 : rtw_write32(rtwdev, REG_RQPN_CTRL_2, bckp[bckp_idx - 1].val);
400 : :
401 : : /* Disable beacon related functions */
402 : 10 : tmp = rtw_read8(rtwdev, REG_BCN_CTRL);
403 : 10 : bckp[bckp_idx].len = 1;
404 : 10 : bckp[bckp_idx].reg = REG_BCN_CTRL;
405 : 10 : bckp[bckp_idx].val = tmp;
406 : 10 : bckp_idx++;
407 : 10 : tmp = (u8)((tmp & (~BIT_EN_BCN_FUNCTION)) | BIT_DIS_TSF_UDT);
408 : 10 : rtw_write8(rtwdev, REG_BCN_CTRL, tmp);
409 : :
410 : 10 : WARN(bckp_idx != DLFW_RESTORE_REG_NUM, "wrong backup number\n");
411 : 10 : }
412 : :
413 : 10 : static void download_firmware_reset_platform(struct rtw_dev *rtwdev)
414 : : {
415 : 10 : rtw_write8_clr(rtwdev, REG_CPU_DMEM_CON + 2, BIT_WL_PLATFORM_RST >> 16);
416 : 10 : rtw_write8_clr(rtwdev, REG_SYS_CLK_CTRL + 1, BIT_CPU_CLK_EN >> 8);
417 : 10 : rtw_write8_set(rtwdev, REG_CPU_DMEM_CON + 2, BIT_WL_PLATFORM_RST >> 16);
418 : 10 : rtw_write8_set(rtwdev, REG_SYS_CLK_CTRL + 1, BIT_CPU_CLK_EN >> 8);
419 : 10 : }
420 : :
421 : 10 : static void download_firmware_reg_restore(struct rtw_dev *rtwdev,
422 : : struct rtw_backup_info *bckp,
423 : : u8 bckp_num)
424 : : {
425 : 10 : rtw_restore_reg(rtwdev, bckp, bckp_num);
426 : : }
427 : :
428 : : #define TX_DESC_SIZE 48
429 : :
430 : 380 : static int send_firmware_pkt_rsvd_page(struct rtw_dev *rtwdev, u16 pg_addr,
431 : : const u8 *data, u32 size)
432 : : {
433 : 380 : u8 *buf;
434 : 380 : int ret;
435 : :
436 : 380 : buf = kmemdup(data, size, GFP_KERNEL);
437 [ + - ]: 380 : if (!buf)
438 : : return -ENOMEM;
439 : :
440 : 380 : ret = rtw_fw_write_data_rsvd_page(rtwdev, pg_addr, buf, size);
441 : 380 : kfree(buf);
442 : 380 : return ret;
443 : : }
444 : :
445 : : static int
446 : 380 : send_firmware_pkt(struct rtw_dev *rtwdev, u16 pg_addr, const u8 *data, u32 size)
447 : : {
448 : 380 : int ret;
449 : :
450 [ - + ]: 380 : if (rtw_hci_type(rtwdev) == RTW_HCI_TYPE_USB &&
451 [ # # ]: 0 : !((size + TX_DESC_SIZE) & (512 - 1)))
452 : 0 : size += 1;
453 : :
454 : 380 : ret = send_firmware_pkt_rsvd_page(rtwdev, pg_addr, data, size);
455 [ - + ]: 380 : if (ret)
456 : 0 : rtw_err(rtwdev, "failed to download rsvd page\n");
457 : :
458 : 380 : return ret;
459 : : }
460 : :
461 : : static int
462 : 380 : iddma_enable(struct rtw_dev *rtwdev, u32 src, u32 dst, u32 ctrl)
463 : : {
464 : 380 : rtw_write32(rtwdev, REG_DDMA_CH0SA, src);
465 : 380 : rtw_write32(rtwdev, REG_DDMA_CH0DA, dst);
466 : 380 : rtw_write32(rtwdev, REG_DDMA_CH0CTRL, ctrl);
467 : :
468 [ - + ]: 380 : if (!check_hw_ready(rtwdev, REG_DDMA_CH0CTRL, BIT_DDMACH0_OWN, 0))
469 : 0 : return -EBUSY;
470 : :
471 : : return 0;
472 : : }
473 : :
474 : 380 : static int iddma_download_firmware(struct rtw_dev *rtwdev, u32 src, u32 dst,
475 : : u32 len, u8 first)
476 : : {
477 : 380 : u32 ch0_ctrl = BIT_DDMACH0_CHKSUM_EN | BIT_DDMACH0_OWN;
478 : :
479 [ + - ]: 380 : if (!check_hw_ready(rtwdev, REG_DDMA_CH0CTRL, BIT_DDMACH0_OWN, 0))
480 : : return -EBUSY;
481 : :
482 : 380 : ch0_ctrl |= len & BIT_MASK_DDMACH0_DLEN;
483 [ + + ]: 380 : if (!first)
484 : 360 : ch0_ctrl |= BIT_DDMACH0_CHKSUM_CONT;
485 : :
486 [ - + ]: 380 : if (iddma_enable(rtwdev, src, dst, ch0_ctrl))
487 : 0 : return -EBUSY;
488 : :
489 : : return 0;
490 : : }
491 : :
492 : : static bool
493 : 20 : check_fw_checksum(struct rtw_dev *rtwdev, u32 addr)
494 : : {
495 : 20 : u8 fw_ctrl;
496 : :
497 : 20 : fw_ctrl = rtw_read8(rtwdev, REG_MCUFW_CTRL);
498 : :
499 [ - + ]: 20 : if (rtw_read32(rtwdev, REG_DDMA_CH0CTRL) & BIT_DDMACH0_CHKSUM_STS) {
500 [ # # ]: 0 : if (addr < OCPBASE_DMEM_88XX) {
501 : 0 : fw_ctrl |= BIT_IMEM_DW_OK;
502 : 0 : fw_ctrl &= ~BIT_IMEM_CHKSUM_OK;
503 : 0 : rtw_write8(rtwdev, REG_MCUFW_CTRL, fw_ctrl);
504 : : } else {
505 : 0 : fw_ctrl |= BIT_DMEM_DW_OK;
506 : 0 : fw_ctrl &= ~BIT_DMEM_CHKSUM_OK;
507 : 0 : rtw_write8(rtwdev, REG_MCUFW_CTRL, fw_ctrl);
508 : : }
509 : :
510 : 0 : rtw_err(rtwdev, "invalid fw checksum\n");
511 : :
512 : 0 : return false;
513 : : }
514 : :
515 [ + + ]: 20 : if (addr < OCPBASE_DMEM_88XX) {
516 : 10 : fw_ctrl |= (BIT_IMEM_DW_OK | BIT_IMEM_CHKSUM_OK);
517 : 10 : rtw_write8(rtwdev, REG_MCUFW_CTRL, fw_ctrl);
518 : : } else {
519 : 10 : fw_ctrl |= (BIT_DMEM_DW_OK | BIT_DMEM_CHKSUM_OK);
520 : 10 : rtw_write8(rtwdev, REG_MCUFW_CTRL, fw_ctrl);
521 : : }
522 : :
523 : : return true;
524 : : }
525 : :
526 : : static int
527 : 20 : download_firmware_to_mem(struct rtw_dev *rtwdev, const u8 *data,
528 : : u32 src, u32 dst, u32 size)
529 : : {
530 : 20 : struct rtw_chip_info *chip = rtwdev->chip;
531 : 20 : u32 desc_size = chip->tx_pkt_desc_sz;
532 : 20 : u8 first_part;
533 : 20 : u32 mem_offset;
534 : 20 : u32 residue_size;
535 : 20 : u32 pkt_size;
536 : 20 : u32 max_size = 0x1000;
537 : 20 : u32 val;
538 : 20 : int ret;
539 : :
540 : 20 : mem_offset = 0;
541 : 20 : first_part = 1;
542 : 20 : residue_size = size;
543 : :
544 : 20 : val = rtw_read32(rtwdev, REG_DDMA_CH0CTRL);
545 : 20 : val |= BIT_DDMACH0_RESET_CHKSUM_STS;
546 : 20 : rtw_write32(rtwdev, REG_DDMA_CH0CTRL, val);
547 : :
548 [ + + ]: 400 : while (residue_size) {
549 : 380 : if (residue_size >= max_size)
550 : : pkt_size = max_size;
551 : : else
552 : : pkt_size = residue_size;
553 : :
554 : 380 : ret = send_firmware_pkt(rtwdev, (u16)(src >> 7),
555 : : data + mem_offset, pkt_size);
556 [ - + ]: 380 : if (ret)
557 : 0 : return ret;
558 : :
559 : 380 : ret = iddma_download_firmware(rtwdev, OCPBASE_TXBUF_88XX +
560 : 380 : src + desc_size,
561 : : dst + mem_offset, pkt_size,
562 : : first_part);
563 [ - + ]: 380 : if (ret)
564 : 0 : return ret;
565 : :
566 : 380 : first_part = 0;
567 : 380 : mem_offset += pkt_size;
568 : 380 : residue_size -= pkt_size;
569 : : }
570 : :
571 [ - + ]: 20 : if (!check_fw_checksum(rtwdev, dst))
572 : 0 : return -EINVAL;
573 : :
574 : : return 0;
575 : : }
576 : :
577 : : static int
578 : : start_download_firmware(struct rtw_dev *rtwdev, const u8 *data, u32 size)
579 : : {
580 : : const struct rtw_fw_hdr *fw_hdr = (const struct rtw_fw_hdr *)data;
581 : : const u8 *cur_fw;
582 : : u16 val;
583 : : u32 imem_size;
584 : : u32 dmem_size;
585 : : u32 emem_size;
586 : : u32 addr;
587 : : int ret;
588 : :
589 : : dmem_size = le32_to_cpu(fw_hdr->dmem_size);
590 : : imem_size = le32_to_cpu(fw_hdr->imem_size);
591 : : emem_size = (fw_hdr->mem_usage & BIT(4)) ?
592 : : le32_to_cpu(fw_hdr->emem_size) : 0;
593 : : dmem_size += FW_HDR_CHKSUM_SIZE;
594 : : imem_size += FW_HDR_CHKSUM_SIZE;
595 : : emem_size += emem_size ? FW_HDR_CHKSUM_SIZE : 0;
596 : :
597 : : val = (u16)(rtw_read16(rtwdev, REG_MCUFW_CTRL) & 0x3800);
598 : : val |= BIT_MCUFWDL_EN;
599 : : rtw_write16(rtwdev, REG_MCUFW_CTRL, val);
600 : :
601 : : cur_fw = data + FW_HDR_SIZE;
602 : : addr = le32_to_cpu(fw_hdr->dmem_addr);
603 : : addr &= ~BIT(31);
604 : : ret = download_firmware_to_mem(rtwdev, cur_fw, 0, addr, dmem_size);
605 : : if (ret)
606 : : return ret;
607 : :
608 : : cur_fw = data + FW_HDR_SIZE + dmem_size;
609 : : addr = le32_to_cpu(fw_hdr->imem_addr);
610 : : addr &= ~BIT(31);
611 : : ret = download_firmware_to_mem(rtwdev, cur_fw, 0, addr, imem_size);
612 : : if (ret)
613 : : return ret;
614 : :
615 : : if (emem_size) {
616 : : cur_fw = data + FW_HDR_SIZE + dmem_size + imem_size;
617 : : addr = le32_to_cpu(fw_hdr->emem_addr);
618 : : addr &= ~BIT(31);
619 : : ret = download_firmware_to_mem(rtwdev, cur_fw, 0, addr,
620 : : emem_size);
621 : : if (ret)
622 : : return ret;
623 : : }
624 : :
625 : : return 0;
626 : : }
627 : :
628 : 10 : static int download_firmware_validate(struct rtw_dev *rtwdev)
629 : : {
630 : 10 : u32 fw_key;
631 : :
632 [ + + ]: 10 : if (!check_hw_ready(rtwdev, REG_MCUFW_CTRL, FW_READY_MASK, FW_READY)) {
633 : 1 : fw_key = rtw_read32(rtwdev, REG_FW_DBG7) & FW_KEY_MASK;
634 [ - + ]: 1 : if (fw_key == ILLEGAL_KEY_GROUP)
635 : 0 : rtw_err(rtwdev, "invalid fw key\n");
636 : 1 : return -EINVAL;
637 : : }
638 : :
639 : : return 0;
640 : : }
641 : :
642 : 10 : static void download_firmware_end_flow(struct rtw_dev *rtwdev)
643 : : {
644 : 10 : u16 fw_ctrl;
645 : :
646 : 10 : rtw_write32(rtwdev, REG_TXDMA_STATUS, BTI_PAGE_OVF);
647 : :
648 : : /* Check IMEM & DMEM checksum is OK or not */
649 : 10 : fw_ctrl = rtw_read16(rtwdev, REG_MCUFW_CTRL);
650 [ - + ]: 10 : if ((fw_ctrl & BIT_CHECK_SUM_OK) != BIT_CHECK_SUM_OK)
651 : : return;
652 : :
653 : 0 : fw_ctrl = (fw_ctrl | BIT_FW_DW_RDY) & ~BIT_MCUFWDL_EN;
654 : 0 : rtw_write16(rtwdev, REG_MCUFW_CTRL, fw_ctrl);
655 : : }
656 : :
657 : 10 : int rtw_download_firmware(struct rtw_dev *rtwdev, struct rtw_fw_state *fw)
658 : : {
659 : 10 : struct rtw_backup_info bckp[DLFW_RESTORE_REG_NUM];
660 : 10 : const u8 *data = fw->firmware->data;
661 : 10 : u32 size = fw->firmware->size;
662 : 10 : u32 ltecoex_bckp;
663 : 10 : int ret;
664 : :
665 [ + - ]: 10 : if (!check_firmware_size(data, size))
666 : : return -EINVAL;
667 : :
668 [ + - ]: 10 : if (!ltecoex_read_reg(rtwdev, 0x38, <ecoex_bckp))
669 : : return -EBUSY;
670 : :
671 : 10 : wlan_cpu_enable(rtwdev, false);
672 : :
673 : 10 : download_firmware_reg_backup(rtwdev, bckp);
674 : 10 : download_firmware_reset_platform(rtwdev);
675 : :
676 : 10 : ret = start_download_firmware(rtwdev, data, size);
677 [ - + ]: 10 : if (ret)
678 : 0 : goto dlfw_fail;
679 : :
680 : 10 : download_firmware_reg_restore(rtwdev, bckp, DLFW_RESTORE_REG_NUM);
681 : :
682 : 10 : download_firmware_end_flow(rtwdev);
683 : :
684 : 10 : wlan_cpu_enable(rtwdev, true);
685 : :
686 [ + - ]: 10 : if (!ltecoex_reg_write(rtwdev, 0x38, ltecoex_bckp))
687 : : return -EBUSY;
688 : :
689 : 10 : ret = download_firmware_validate(rtwdev);
690 [ + + ]: 10 : if (ret)
691 : 1 : goto dlfw_fail;
692 : :
693 : : /* reset desc and index */
694 : 9 : rtw_hci_setup(rtwdev);
695 : :
696 : 9 : rtwdev->h2c.last_box_num = 0;
697 : 9 : rtwdev->h2c.seq = 0;
698 : :
699 : 9 : set_bit(RTW_FLAG_FW_RUNNING, rtwdev->flags);
700 : :
701 : 9 : return 0;
702 : :
703 : 1 : dlfw_fail:
704 : : /* Disable FWDL_EN */
705 : 1 : rtw_write8_clr(rtwdev, REG_MCUFW_CTRL, BIT_MCUFWDL_EN);
706 : 1 : rtw_write8_set(rtwdev, REG_SYS_FUNC_EN + 1, BIT_FEN_CPUEN);
707 : :
708 : 1 : return ret;
709 : : }
710 : :
711 : : static u32 get_priority_queues(struct rtw_dev *rtwdev, u32 queues)
712 : : {
713 : : struct rtw_rqpn *rqpn = rtwdev->fifo.rqpn;
714 : : u32 prio_queues = 0;
715 : :
716 : : if (queues & BIT(IEEE80211_AC_VO))
717 : : prio_queues |= BIT(rqpn->dma_map_vo);
718 : : if (queues & BIT(IEEE80211_AC_VI))
719 : : prio_queues |= BIT(rqpn->dma_map_vi);
720 : : if (queues & BIT(IEEE80211_AC_BE))
721 : : prio_queues |= BIT(rqpn->dma_map_be);
722 : : if (queues & BIT(IEEE80211_AC_BK))
723 : : prio_queues |= BIT(rqpn->dma_map_bk);
724 : :
725 : : return prio_queues;
726 : : }
727 : :
728 : 0 : static void __rtw_mac_flush_prio_queue(struct rtw_dev *rtwdev,
729 : : u32 prio_queue, bool drop)
730 : : {
731 : 0 : u32 addr;
732 : 0 : u16 avail_page, rsvd_page;
733 : 0 : int i;
734 : :
735 [ # # ]: 0 : switch (prio_queue) {
736 : : case RTW_DMA_MAPPING_EXTRA:
737 : : addr = REG_FIFOPAGE_INFO_4;
738 : : break;
739 : : case RTW_DMA_MAPPING_LOW:
740 : : addr = REG_FIFOPAGE_INFO_2;
741 : : break;
742 : : case RTW_DMA_MAPPING_NORMAL:
743 : : addr = REG_FIFOPAGE_INFO_3;
744 : : break;
745 : : case RTW_DMA_MAPPING_HIGH:
746 : : addr = REG_FIFOPAGE_INFO_1;
747 : : break;
748 : : default:
749 : : return;
750 : : }
751 : :
752 : : /* check if all of the reserved pages are available for 100 msecs */
753 [ # # ]: 0 : for (i = 0; i < 5; i++) {
754 : 0 : rsvd_page = rtw_read16(rtwdev, addr);
755 : 0 : avail_page = rtw_read16(rtwdev, addr + 2);
756 [ # # ]: 0 : if (rsvd_page == avail_page)
757 : : return;
758 : :
759 : 0 : msleep(20);
760 : : }
761 : :
762 : : /* priority queue is still not empty, throw a warning,
763 : : *
764 : : * Note that if we want to flush the tx queue when having a lot of
765 : : * traffic (ex, 100Mbps up), some of the packets could be dropped.
766 : : * And it requires like ~2secs to flush the full priority queue.
767 : : */
768 [ # # ]: 0 : if (!drop)
769 : 0 : rtw_warn(rtwdev, "timed out to flush queue %d\n", prio_queue);
770 : : }
771 : :
772 : 0 : static void rtw_mac_flush_prio_queues(struct rtw_dev *rtwdev,
773 : : u32 prio_queues, bool drop)
774 : : {
775 : 0 : u32 q;
776 : :
777 [ # # ]: 0 : for (q = 0; q < RTW_DMA_MAPPING_MAX; q++)
778 [ # # ]: 0 : if (prio_queues & BIT(q))
779 : 0 : __rtw_mac_flush_prio_queue(rtwdev, q, drop);
780 : : }
781 : :
782 : 0 : void rtw_mac_flush_queues(struct rtw_dev *rtwdev, u32 queues, bool drop)
783 : : {
784 : 0 : u32 prio_queues = 0;
785 : :
786 : : /* If all of the hardware queues are requested to flush,
787 : : * or the priority queues are not mapped yet,
788 : : * flush all of the priority queues
789 : : */
790 [ # # # # ]: 0 : if (queues == BIT(rtwdev->hw->queues) - 1 || !rtwdev->fifo.rqpn)
791 : : prio_queues = BIT(RTW_DMA_MAPPING_MAX) - 1;
792 : : else
793 : 0 : prio_queues = get_priority_queues(rtwdev, queues);
794 : :
795 : 0 : rtw_mac_flush_prio_queues(rtwdev, prio_queues, drop);
796 : 0 : }
797 : :
798 : 0 : static int txdma_queue_mapping(struct rtw_dev *rtwdev)
799 : : {
800 : 0 : struct rtw_chip_info *chip = rtwdev->chip;
801 : 0 : struct rtw_rqpn *rqpn = NULL;
802 : 0 : u16 txdma_pq_map = 0;
803 : :
804 [ # # # ]: 0 : switch (rtw_hci_type(rtwdev)) {
805 : 0 : case RTW_HCI_TYPE_PCIE:
806 : 0 : rqpn = &chip->rqpn_table[1];
807 : 0 : break;
808 : 0 : case RTW_HCI_TYPE_USB:
809 [ # # ]: 0 : if (rtwdev->hci.bulkout_num == 2)
810 : 0 : rqpn = &chip->rqpn_table[2];
811 [ # # ]: 0 : else if (rtwdev->hci.bulkout_num == 3)
812 : 0 : rqpn = &chip->rqpn_table[3];
813 [ # # ]: 0 : else if (rtwdev->hci.bulkout_num == 4)
814 : 0 : rqpn = &chip->rqpn_table[4];
815 : : else
816 : : return -EINVAL;
817 : : break;
818 : : default:
819 : : return -EINVAL;
820 : : }
821 : :
822 : 0 : rtwdev->fifo.rqpn = rqpn;
823 : 0 : txdma_pq_map |= BIT_TXDMA_HIQ_MAP(rqpn->dma_map_hi);
824 : 0 : txdma_pq_map |= BIT_TXDMA_MGQ_MAP(rqpn->dma_map_mg);
825 : 0 : txdma_pq_map |= BIT_TXDMA_BKQ_MAP(rqpn->dma_map_bk);
826 : 0 : txdma_pq_map |= BIT_TXDMA_BEQ_MAP(rqpn->dma_map_be);
827 : 0 : txdma_pq_map |= BIT_TXDMA_VIQ_MAP(rqpn->dma_map_vi);
828 : 0 : txdma_pq_map |= BIT_TXDMA_VOQ_MAP(rqpn->dma_map_vo);
829 : 0 : rtw_write16(rtwdev, REG_TXDMA_PQ_MAP, txdma_pq_map);
830 : :
831 : 0 : rtw_write8(rtwdev, REG_CR, 0);
832 : 0 : rtw_write8(rtwdev, REG_CR, MAC_TRX_ENABLE);
833 : 0 : rtw_write32(rtwdev, REG_H2CQ_CSR, BIT_H2CQ_FULL);
834 : :
835 : 0 : return 0;
836 : : }
837 : :
838 : 0 : static int set_trx_fifo_info(struct rtw_dev *rtwdev)
839 : : {
840 : 0 : struct rtw_fifo_conf *fifo = &rtwdev->fifo;
841 : 0 : struct rtw_chip_info *chip = rtwdev->chip;
842 : 0 : u16 cur_pg_addr;
843 : 0 : u8 csi_buf_pg_num = chip->csi_buf_pg_num;
844 : :
845 : : /* config rsvd page num */
846 : 0 : fifo->rsvd_drv_pg_num = 8;
847 : 0 : fifo->txff_pg_num = chip->txff_size >> 7;
848 : 0 : fifo->rsvd_pg_num = fifo->rsvd_drv_pg_num +
849 : : RSVD_PG_H2C_EXTRAINFO_NUM +
850 : : RSVD_PG_H2C_STATICINFO_NUM +
851 : : RSVD_PG_H2CQ_NUM +
852 : : RSVD_PG_CPU_INSTRUCTION_NUM +
853 : 0 : RSVD_PG_FW_TXBUF_NUM +
854 : : csi_buf_pg_num;
855 : :
856 [ # # ]: 0 : if (fifo->rsvd_pg_num > fifo->txff_pg_num)
857 : : return -ENOMEM;
858 : :
859 : 0 : fifo->acq_pg_num = fifo->txff_pg_num - fifo->rsvd_pg_num;
860 : 0 : fifo->rsvd_boundary = fifo->txff_pg_num - fifo->rsvd_pg_num;
861 : :
862 : 0 : cur_pg_addr = fifo->txff_pg_num;
863 : 0 : cur_pg_addr -= csi_buf_pg_num;
864 : 0 : fifo->rsvd_csibuf_addr = cur_pg_addr;
865 : 0 : cur_pg_addr -= RSVD_PG_FW_TXBUF_NUM;
866 : 0 : fifo->rsvd_fw_txbuf_addr = cur_pg_addr;
867 : 0 : cur_pg_addr -= RSVD_PG_CPU_INSTRUCTION_NUM;
868 : 0 : fifo->rsvd_cpu_instr_addr = cur_pg_addr;
869 : 0 : cur_pg_addr -= RSVD_PG_H2CQ_NUM;
870 : 0 : fifo->rsvd_h2cq_addr = cur_pg_addr;
871 : 0 : cur_pg_addr -= RSVD_PG_H2C_STATICINFO_NUM;
872 : 0 : fifo->rsvd_h2c_sta_info_addr = cur_pg_addr;
873 : 0 : cur_pg_addr -= RSVD_PG_H2C_EXTRAINFO_NUM;
874 : 0 : fifo->rsvd_h2c_info_addr = cur_pg_addr;
875 : 0 : cur_pg_addr -= fifo->rsvd_drv_pg_num;
876 : 0 : fifo->rsvd_drv_addr = cur_pg_addr;
877 : :
878 [ # # ]: 0 : if (fifo->rsvd_boundary != fifo->rsvd_drv_addr) {
879 : 0 : rtw_err(rtwdev, "wrong rsvd driver address\n");
880 : 0 : return -EINVAL;
881 : : }
882 : :
883 : : return 0;
884 : : }
885 : :
886 : 0 : static int priority_queue_cfg(struct rtw_dev *rtwdev)
887 : : {
888 : 0 : struct rtw_fifo_conf *fifo = &rtwdev->fifo;
889 : 0 : struct rtw_chip_info *chip = rtwdev->chip;
890 : 0 : struct rtw_page_table *pg_tbl = NULL;
891 : 0 : u16 pubq_num;
892 : 0 : int ret;
893 : :
894 : 0 : ret = set_trx_fifo_info(rtwdev);
895 [ # # ]: 0 : if (ret)
896 : : return ret;
897 : :
898 [ # # # ]: 0 : switch (rtw_hci_type(rtwdev)) {
899 : 0 : case RTW_HCI_TYPE_PCIE:
900 : 0 : pg_tbl = &chip->page_table[1];
901 : 0 : break;
902 : 0 : case RTW_HCI_TYPE_USB:
903 [ # # ]: 0 : if (rtwdev->hci.bulkout_num == 2)
904 : 0 : pg_tbl = &chip->page_table[2];
905 [ # # ]: 0 : else if (rtwdev->hci.bulkout_num == 3)
906 : 0 : pg_tbl = &chip->page_table[3];
907 [ # # ]: 0 : else if (rtwdev->hci.bulkout_num == 4)
908 : 0 : pg_tbl = &chip->page_table[4];
909 : : else
910 : : return -EINVAL;
911 : : break;
912 : : default:
913 : : return -EINVAL;
914 : : }
915 : :
916 : 0 : pubq_num = fifo->acq_pg_num - pg_tbl->hq_num - pg_tbl->lq_num -
917 : 0 : pg_tbl->nq_num - pg_tbl->exq_num - pg_tbl->gapq_num;
918 : 0 : rtw_write16(rtwdev, REG_FIFOPAGE_INFO_1, pg_tbl->hq_num);
919 : 0 : rtw_write16(rtwdev, REG_FIFOPAGE_INFO_2, pg_tbl->lq_num);
920 : 0 : rtw_write16(rtwdev, REG_FIFOPAGE_INFO_3, pg_tbl->nq_num);
921 : 0 : rtw_write16(rtwdev, REG_FIFOPAGE_INFO_4, pg_tbl->exq_num);
922 : 0 : rtw_write16(rtwdev, REG_FIFOPAGE_INFO_5, pubq_num);
923 : 0 : rtw_write32_set(rtwdev, REG_RQPN_CTRL_2, BIT_LD_RQPN);
924 : :
925 : 0 : rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2, fifo->rsvd_boundary);
926 : 0 : rtw_write8_set(rtwdev, REG_FWHW_TXQ_CTRL + 2, BIT_EN_WR_FREE_TAIL >> 16);
927 : :
928 : 0 : rtw_write16(rtwdev, REG_BCNQ_BDNY_V1, fifo->rsvd_boundary);
929 : 0 : rtw_write16(rtwdev, REG_FIFOPAGE_CTRL_2 + 2, fifo->rsvd_boundary);
930 : 0 : rtw_write16(rtwdev, REG_BCNQ1_BDNY_V1, fifo->rsvd_boundary);
931 : 0 : rtw_write32(rtwdev, REG_RXFF_BNDY, chip->rxff_size - C2H_PKT_BUF - 1);
932 : 0 : rtw_write8_set(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1);
933 : :
934 [ # # ]: 0 : if (!check_hw_ready(rtwdev, REG_AUTO_LLT_V1, BIT_AUTO_INIT_LLT_V1, 0))
935 : : return -EBUSY;
936 : :
937 : 0 : rtw_write8(rtwdev, REG_CR + 3, 0);
938 : :
939 : 0 : return 0;
940 : : }
941 : :
942 : 0 : static int init_h2c(struct rtw_dev *rtwdev)
943 : : {
944 : 0 : struct rtw_fifo_conf *fifo = &rtwdev->fifo;
945 : 0 : u8 value8;
946 : 0 : u32 value32;
947 : 0 : u32 h2cq_addr;
948 : 0 : u32 h2cq_size;
949 : 0 : u32 h2cq_free;
950 : 0 : u32 wp, rp;
951 : :
952 : 0 : h2cq_addr = fifo->rsvd_h2cq_addr << TX_PAGE_SIZE_SHIFT;
953 : 0 : h2cq_size = RSVD_PG_H2CQ_NUM << TX_PAGE_SIZE_SHIFT;
954 : :
955 : 0 : value32 = rtw_read32(rtwdev, REG_H2C_HEAD);
956 : 0 : value32 = (value32 & 0xFFFC0000) | h2cq_addr;
957 : 0 : rtw_write32(rtwdev, REG_H2C_HEAD, value32);
958 : :
959 : 0 : value32 = rtw_read32(rtwdev, REG_H2C_READ_ADDR);
960 : 0 : value32 = (value32 & 0xFFFC0000) | h2cq_addr;
961 : 0 : rtw_write32(rtwdev, REG_H2C_READ_ADDR, value32);
962 : :
963 : 0 : value32 = rtw_read32(rtwdev, REG_H2C_TAIL);
964 : 0 : value32 &= 0xFFFC0000;
965 : 0 : value32 |= (h2cq_addr + h2cq_size);
966 : 0 : rtw_write32(rtwdev, REG_H2C_TAIL, value32);
967 : :
968 : 0 : value8 = rtw_read8(rtwdev, REG_H2C_INFO);
969 : 0 : value8 = (u8)((value8 & 0xFC) | 0x01);
970 : 0 : rtw_write8(rtwdev, REG_H2C_INFO, value8);
971 : :
972 : 0 : value8 = rtw_read8(rtwdev, REG_H2C_INFO);
973 : 0 : value8 = (u8)((value8 & 0xFB) | 0x04);
974 : 0 : rtw_write8(rtwdev, REG_H2C_INFO, value8);
975 : :
976 : 0 : value8 = rtw_read8(rtwdev, REG_TXDMA_OFFSET_CHK + 1);
977 : 0 : value8 = (u8)((value8 & 0x7f) | 0x80);
978 : 0 : rtw_write8(rtwdev, REG_TXDMA_OFFSET_CHK + 1, value8);
979 : :
980 : 0 : wp = rtw_read32(rtwdev, REG_H2C_PKT_WRITEADDR) & 0x3FFFF;
981 : 0 : rp = rtw_read32(rtwdev, REG_H2C_PKT_READADDR) & 0x3FFFF;
982 [ # # ]: 0 : h2cq_free = wp >= rp ? h2cq_size - (wp - rp) : rp - wp;
983 : :
984 [ # # ]: 0 : if (h2cq_size != h2cq_free) {
985 : 0 : rtw_err(rtwdev, "H2C queue mismatch\n");
986 : 0 : return -EINVAL;
987 : : }
988 : :
989 : : return 0;
990 : : }
991 : :
992 : 0 : static int rtw_init_trx_cfg(struct rtw_dev *rtwdev)
993 : : {
994 : 0 : int ret;
995 : :
996 : 0 : ret = txdma_queue_mapping(rtwdev);
997 [ # # ]: 0 : if (ret)
998 : : return ret;
999 : :
1000 : 0 : ret = priority_queue_cfg(rtwdev);
1001 [ # # ]: 0 : if (ret)
1002 : : return ret;
1003 : :
1004 : 0 : ret = init_h2c(rtwdev);
1005 [ # # ]: 0 : if (ret)
1006 : 0 : return ret;
1007 : :
1008 : : return 0;
1009 : : }
1010 : :
1011 : 0 : static int rtw_drv_info_cfg(struct rtw_dev *rtwdev)
1012 : : {
1013 : 0 : u8 value8;
1014 : :
1015 : 0 : rtw_write8(rtwdev, REG_RX_DRVINFO_SZ, PHY_STATUS_SIZE);
1016 : 0 : value8 = rtw_read8(rtwdev, REG_TRXFF_BNDY + 1);
1017 : 0 : value8 &= 0xF0;
1018 : : /* For rxdesc len = 0 issue */
1019 : 0 : value8 |= 0xF;
1020 : 0 : rtw_write8(rtwdev, REG_TRXFF_BNDY + 1, value8);
1021 : 0 : rtw_write32_set(rtwdev, REG_RCR, BIT_APP_PHYSTS);
1022 : 0 : rtw_write32_clr(rtwdev, REG_WMAC_OPTION_FUNCTION + 4, BIT(8) | BIT(9));
1023 : :
1024 : 0 : return 0;
1025 : : }
1026 : :
1027 : 0 : int rtw_mac_init(struct rtw_dev *rtwdev)
1028 : : {
1029 : 0 : struct rtw_chip_info *chip = rtwdev->chip;
1030 : 0 : int ret;
1031 : :
1032 : 0 : ret = rtw_init_trx_cfg(rtwdev);
1033 [ # # ]: 0 : if (ret)
1034 : : return ret;
1035 : :
1036 : 0 : ret = chip->ops->mac_init(rtwdev);
1037 [ # # ]: 0 : if (ret)
1038 : : return ret;
1039 : :
1040 : 0 : ret = rtw_drv_info_cfg(rtwdev);
1041 [ # # ]: 0 : if (ret)
1042 : : return ret;
1043 : :
1044 : 0 : rtw_hci_interface_cfg(rtwdev);
1045 : :
1046 : 0 : return 0;
1047 : : }
|