1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2012 Realtek Corporation.*/
11 static void _rtl92s_fw_set_rqpn(struct ieee80211_hw
*hw
)
13 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
15 rtl_write_dword(rtlpriv
, RQPN
, 0xffffffff);
16 rtl_write_dword(rtlpriv
, RQPN
+ 4, 0xffffffff);
17 rtl_write_byte(rtlpriv
, RQPN
+ 8, 0xff);
18 rtl_write_byte(rtlpriv
, RQPN
+ 0xB, 0x80);
21 static bool _rtl92s_firmware_enable_cpu(struct ieee80211_hw
*hw
)
23 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
26 u8 tmpu1b
, cpustatus
= 0;
28 _rtl92s_fw_set_rqpn(hw
);
31 tmpu1b
= rtl_read_byte(rtlpriv
, SYS_CLKR
);
33 rtl_write_byte(rtlpriv
, SYS_CLKR
, (tmpu1b
| SYS_CPU_CLKSEL
));
35 tmpu2b
= rtl_read_word(rtlpriv
, REG_SYS_FUNC_EN
);
36 rtl_write_word(rtlpriv
, REG_SYS_FUNC_EN
, (tmpu2b
| FEN_CPUEN
));
38 /* Polling IMEM Ready after CPU has refilled. */
40 cpustatus
= rtl_read_byte(rtlpriv
, TCR
);
41 if (cpustatus
& IMEM_RDY
) {
42 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
43 "IMEM Ready after CPU has refilled\n");
48 } while (ichecktime
--);
50 if (!(cpustatus
& IMEM_RDY
))
56 static enum fw_status
_rtl92s_firmware_get_nextstatus(
57 enum fw_status fw_currentstatus
)
59 enum fw_status next_fwstatus
= 0;
61 switch (fw_currentstatus
) {
63 next_fwstatus
= FW_STATUS_LOAD_IMEM
;
65 case FW_STATUS_LOAD_IMEM
:
66 next_fwstatus
= FW_STATUS_LOAD_EMEM
;
68 case FW_STATUS_LOAD_EMEM
:
69 next_fwstatus
= FW_STATUS_LOAD_DMEM
;
71 case FW_STATUS_LOAD_DMEM
:
72 next_fwstatus
= FW_STATUS_READY
;
81 static u8
_rtl92s_firmware_header_map_rftype(struct ieee80211_hw
*hw
)
83 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
84 struct rtl_phy
*rtlphy
= &(rtlpriv
->phy
);
86 switch (rtlphy
->rf_type
) {
94 pr_err("Unknown RF type(%x)\n", rtlphy
->rf_type
);
100 static void _rtl92s_firmwareheader_priveupdate(struct ieee80211_hw
*hw
,
101 struct fw_priv
*pfw_priv
)
103 /* Update RF types for RATR settings. */
104 pfw_priv
->rf_config
= _rtl92s_firmware_header_map_rftype(hw
);
109 static bool _rtl92s_cmd_send_packet(struct ieee80211_hw
*hw
,
110 struct sk_buff
*skb
, u8 last
)
112 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
113 struct rtl_pci
*rtlpci
= rtl_pcidev(rtl_pcipriv(hw
));
114 struct rtl8192_tx_ring
*ring
;
115 struct rtl_tx_desc
*pdesc
;
119 ring
= &rtlpci
->tx_ring
[TXCMD_QUEUE
];
121 spin_lock_irqsave(&rtlpriv
->locks
.irq_th_lock
, flags
);
123 idx
= (ring
->idx
+ skb_queue_len(&ring
->queue
)) % ring
->entries
;
124 pdesc
= &ring
->desc
[idx
];
125 rtlpriv
->cfg
->ops
->fill_tx_cmddesc(hw
, (u8
*)pdesc
, 1, 1, skb
);
126 __skb_queue_tail(&ring
->queue
, skb
);
128 spin_unlock_irqrestore(&rtlpriv
->locks
.irq_th_lock
, flags
);
133 static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw
*hw
,
134 u8
*code_virtual_address
, u32 buffer_len
)
136 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
138 struct rtl_tcb_desc
*tcb_desc
;
139 u16 frag_threshold
= MAX_FIRMWARE_CODE_SIZE
;
140 u16 frag_length
, frag_offset
= 0;
141 u16 extra_descoffset
= 0;
144 _rtl92s_fw_set_rqpn(hw
);
146 if (buffer_len
>= MAX_FIRMWARE_CODE_SIZE
) {
147 pr_err("Size over FIRMWARE_CODE_SIZE!\n");
151 extra_descoffset
= 0;
154 if ((buffer_len
- frag_offset
) > frag_threshold
) {
155 frag_length
= frag_threshold
+ extra_descoffset
;
157 frag_length
= (u16
)(buffer_len
- frag_offset
+
162 /* Allocate skb buffer to contain firmware */
163 /* info and tx descriptor info. */
164 skb
= dev_alloc_skb(frag_length
);
167 skb_reserve(skb
, extra_descoffset
);
168 skb_put_data(skb
, code_virtual_address
+ frag_offset
,
169 (u32
)(frag_length
- extra_descoffset
));
171 tcb_desc
= (struct rtl_tcb_desc
*)(skb
->cb
);
172 tcb_desc
->queue_index
= TXCMD_QUEUE
;
173 tcb_desc
->cmd_or_init
= DESC_PACKET_TYPE_INIT
;
174 tcb_desc
->last_inipkt
= last_inipkt
;
176 _rtl92s_cmd_send_packet(hw
, skb
, last_inipkt
);
178 frag_offset
+= (frag_length
- extra_descoffset
);
180 } while (frag_offset
< buffer_len
);
182 rtl_write_byte(rtlpriv
, TP_POLL
, TPPOLL_CQ
);
187 static bool _rtl92s_firmware_checkready(struct ieee80211_hw
*hw
,
190 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
191 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
192 struct rt_firmware
*firmware
= (struct rt_firmware
*)rtlhal
->pfirmware
;
195 short pollingcnt
= 1000;
196 bool rtstatus
= true;
198 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
199 "LoadStaus(%d)\n", loadfw_status
);
201 firmware
->fwstatus
= (enum fw_status
)loadfw_status
;
203 switch (loadfw_status
) {
204 case FW_STATUS_LOAD_IMEM
:
205 /* Polling IMEM code done. */
207 cpustatus
= rtl_read_byte(rtlpriv
, TCR
);
208 if (cpustatus
& IMEM_CODE_DONE
)
211 } while (pollingcnt
--);
213 if (!(cpustatus
& IMEM_CHK_RPT
) || (pollingcnt
<= 0)) {
214 pr_err("FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\n",
216 goto status_check_fail
;
220 case FW_STATUS_LOAD_EMEM
:
221 /* Check Put Code OK and Turn On CPU */
222 /* Polling EMEM code done. */
224 cpustatus
= rtl_read_byte(rtlpriv
, TCR
);
225 if (cpustatus
& EMEM_CODE_DONE
)
228 } while (pollingcnt
--);
230 if (!(cpustatus
& EMEM_CHK_RPT
) || (pollingcnt
<= 0)) {
231 pr_err("FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\n",
233 goto status_check_fail
;
237 rtstatus
= _rtl92s_firmware_enable_cpu(hw
);
239 pr_err("Enable CPU fail!\n");
240 goto status_check_fail
;
244 case FW_STATUS_LOAD_DMEM
:
245 /* Polling DMEM code done */
247 cpustatus
= rtl_read_byte(rtlpriv
, TCR
);
248 if (cpustatus
& DMEM_CODE_DONE
)
251 } while (pollingcnt
--);
253 if (!(cpustatus
& DMEM_CODE_DONE
) || (pollingcnt
<= 0)) {
254 pr_err("Polling DMEM code done fail ! cpustatus(%#x)\n",
256 goto status_check_fail
;
259 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
260 "DMEM code download success, cpustatus(%#x)\n",
263 /* Prevent Delay too much and being scheduled out */
264 /* Polling Load Firmware ready */
267 cpustatus
= rtl_read_byte(rtlpriv
, TCR
);
268 if (cpustatus
& FWRDY
)
271 } while (pollingcnt
--);
273 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
274 "Polling Load Firmware ready, cpustatus(%x)\n",
277 if (((cpustatus
& LOAD_FW_READY
) != LOAD_FW_READY
) ||
279 pr_err("Polling Load Firmware ready fail ! cpustatus(%x)\n",
281 goto status_check_fail
;
284 /* If right here, we can set TCR/RCR to desired value */
285 /* and config MAC lookback mode to normal mode */
286 tmpu4b
= rtl_read_dword(rtlpriv
, TCR
);
287 rtl_write_dword(rtlpriv
, TCR
, (tmpu4b
& (~TCR_ICV
)));
289 tmpu4b
= rtl_read_dword(rtlpriv
, RCR
);
290 rtl_write_dword(rtlpriv
, RCR
, (tmpu4b
| RCR_APPFCS
|
291 RCR_APP_ICV
| RCR_APP_MIC
));
293 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
294 "Current RCR settings(%#x)\n", tmpu4b
);
296 /* Set to normal mode. */
297 rtl_write_byte(rtlpriv
, LBKMD_SEL
, LBK_NORMAL
);
301 pr_err("Unknown status check!\n");
307 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
308 "loadfw_status(%d), rtstatus(%x)\n",
309 loadfw_status
, rtstatus
);
313 int rtl92s_download_fw(struct ieee80211_hw
*hw
)
315 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
316 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
317 struct rt_firmware
*firmware
= NULL
;
318 struct fw_hdr
*pfwheader
;
319 struct fw_priv
*pfw_priv
= NULL
;
320 u8
*puc_mappedfile
= NULL
;
321 u32 ul_filelength
= 0;
322 u8 fwhdr_size
= RT_8192S_FIRMWARE_HDR_SIZE
;
323 u8 fwstatus
= FW_STATUS_INIT
;
324 bool rtstatus
= true;
326 if (rtlpriv
->max_fw_size
== 0 || !rtlhal
->pfirmware
)
329 firmware
= (struct rt_firmware
*)rtlhal
->pfirmware
;
330 firmware
->fwstatus
= FW_STATUS_INIT
;
332 puc_mappedfile
= firmware
->sz_fw_tmpbuffer
;
334 /* 1. Retrieve FW header. */
335 firmware
->pfwheader
= (struct fw_hdr
*) puc_mappedfile
;
336 pfwheader
= firmware
->pfwheader
;
337 firmware
->firmwareversion
= byte(pfwheader
->version
, 0);
338 firmware
->pfwheader
->fwpriv
.hci_sel
= 1;/* pcie */
340 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
341 "signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n",
342 pfwheader
->signature
,
343 pfwheader
->version
, pfwheader
->dmem_size
,
344 pfwheader
->img_imem_size
, pfwheader
->img_sram_size
);
346 /* 2. Retrieve IMEM image. */
347 if ((pfwheader
->img_imem_size
== 0) || (pfwheader
->img_imem_size
>
348 sizeof(firmware
->fw_imem
))) {
349 pr_err("memory for data image is less than IMEM required\n");
352 puc_mappedfile
+= fwhdr_size
;
354 memcpy(firmware
->fw_imem
, puc_mappedfile
,
355 pfwheader
->img_imem_size
);
356 firmware
->fw_imem_len
= pfwheader
->img_imem_size
;
359 /* 3. Retriecve EMEM image. */
360 if (pfwheader
->img_sram_size
> sizeof(firmware
->fw_emem
)) {
361 pr_err("memory for data image is less than EMEM required\n");
364 puc_mappedfile
+= firmware
->fw_imem_len
;
366 memcpy(firmware
->fw_emem
, puc_mappedfile
,
367 pfwheader
->img_sram_size
);
368 firmware
->fw_emem_len
= pfwheader
->img_sram_size
;
371 /* 4. download fw now */
372 fwstatus
= _rtl92s_firmware_get_nextstatus(firmware
->fwstatus
);
373 while (fwstatus
!= FW_STATUS_READY
) {
374 /* Image buffer redirection. */
376 case FW_STATUS_LOAD_IMEM
:
377 puc_mappedfile
= firmware
->fw_imem
;
378 ul_filelength
= firmware
->fw_imem_len
;
380 case FW_STATUS_LOAD_EMEM
:
381 puc_mappedfile
= firmware
->fw_emem
;
382 ul_filelength
= firmware
->fw_emem_len
;
384 case FW_STATUS_LOAD_DMEM
:
385 /* Partial update the content of header private. */
386 pfwheader
= firmware
->pfwheader
;
387 pfw_priv
= &pfwheader
->fwpriv
;
388 _rtl92s_firmwareheader_priveupdate(hw
, pfw_priv
);
389 puc_mappedfile
= (u8
*)(firmware
->pfwheader
) +
390 RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE
;
391 ul_filelength
= fwhdr_size
-
392 RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE
;
395 pr_err("Unexpected Download step!!\n");
399 /* <2> Download image file */
400 rtstatus
= _rtl92s_firmware_downloadcode(hw
, puc_mappedfile
,
408 /* <3> Check whether load FW process is ready */
409 rtstatus
= _rtl92s_firmware_checkready(hw
, fwstatus
);
411 pr_err("rtl8192se: firmware fail!\n");
415 fwstatus
= _rtl92s_firmware_get_nextstatus(firmware
->fwstatus
);
423 static u32
_rtl92s_fill_h2c_cmd(struct sk_buff
*skb
, u32 h2cbufferlen
,
424 u32 cmd_num
, u32
*pelement_id
, u32
*pcmd_len
,
425 u8
**pcmb_buffer
, u8
*cmd_start_seq
)
427 u32 totallen
= 0, len
= 0, tx_desclen
= 0;
428 u32 pre_continueoffset
= 0;
433 /* 8 - Byte alignment */
434 len
= H2C_TX_CMD_HDR_LEN
+ N_BYTE_ALIGMENT(pcmd_len
[i
], 8);
436 /* Buffer length is not enough */
437 if (h2cbufferlen
< totallen
+ len
+ tx_desclen
)
441 ph2c_buffer
= skb_put(skb
, (u32
)len
);
442 memset((ph2c_buffer
+ totallen
+ tx_desclen
), 0, len
);
445 le32p_replace_bits((__le32
*)(ph2c_buffer
+ totallen
+
446 tx_desclen
), pcmd_len
[i
],
450 le32p_replace_bits((__le32
*)(ph2c_buffer
+ totallen
+
451 tx_desclen
), pelement_id
[i
],
455 *cmd_start_seq
= *cmd_start_seq
% 0x80;
456 le32p_replace_bits((__le32
*)(ph2c_buffer
+ totallen
+
457 tx_desclen
), *cmd_start_seq
,
462 memcpy((ph2c_buffer
+ totallen
+ tx_desclen
+
463 H2C_TX_CMD_HDR_LEN
), pcmb_buffer
[i
], pcmd_len
[i
]);
466 /* set the continue in prevoius cmd. */
468 le32p_replace_bits((__le32
*)(ph2c_buffer
+
472 pre_continueoffset
= totallen
;
475 } while (++i
< cmd_num
);
480 static u32
_rtl92s_get_h2c_cmdlen(u32 h2cbufferlen
, u32 cmd_num
, u32
*pcmd_len
)
482 u32 totallen
= 0, len
= 0, tx_desclen
= 0;
486 /* 8 - Byte alignment */
487 len
= H2C_TX_CMD_HDR_LEN
+ N_BYTE_ALIGMENT(pcmd_len
[i
], 8);
489 /* Buffer length is not enough */
490 if (h2cbufferlen
< totallen
+ len
+ tx_desclen
)
494 } while (++i
< cmd_num
);
496 return totallen
+ tx_desclen
;
499 static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw
*hw
, u8 h2c_cmd
,
502 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
503 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
504 struct rtl_tcb_desc
*cb_desc
;
511 case FW_H2C_SETPWRMODE
:
512 element_id
= H2C_SETPWRMODE_CMD
;
513 cmd_len
= sizeof(struct h2c_set_pwrmode_parm
);
515 case FW_H2C_JOINBSSRPT
:
516 element_id
= H2C_JOINBSSRPT_CMD
;
517 cmd_len
= sizeof(struct h2c_joinbss_rpt_parm
);
519 case FW_H2C_WOWLAN_UPDATE_GTK
:
520 element_id
= H2C_WOWLAN_UPDATE_GTK_CMD
;
521 cmd_len
= sizeof(struct h2c_wpa_two_way_parm
);
523 case FW_H2C_WOWLAN_UPDATE_IV
:
524 element_id
= H2C_WOWLAN_UPDATE_IV_CMD
;
525 cmd_len
= sizeof(unsigned long long);
527 case FW_H2C_WOWLAN_OFFLOAD
:
528 element_id
= H2C_WOWLAN_FW_OFFLOAD
;
529 cmd_len
= sizeof(u8
);
535 len
= _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE
, 1, &cmd_len
);
536 skb
= dev_alloc_skb(len
);
539 cb_desc
= (struct rtl_tcb_desc
*)(skb
->cb
);
540 cb_desc
->queue_index
= TXCMD_QUEUE
;
541 cb_desc
->cmd_or_init
= DESC_PACKET_TYPE_NORMAL
;
542 cb_desc
->last_inipkt
= false;
544 _rtl92s_fill_h2c_cmd(skb
, MAX_TRANSMIT_BUFFER_SIZE
, 1, &element_id
,
545 &cmd_len
, &pcmd_buffer
, &rtlhal
->h2c_txcmd_seq
);
546 _rtl92s_cmd_send_packet(hw
, skb
, false);
547 rtlpriv
->cfg
->ops
->tx_polling(hw
, TXCMD_QUEUE
);
552 void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw
*hw
, u8 mode
)
554 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
555 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
556 struct h2c_set_pwrmode_parm pwrmode
;
557 u16 max_wakeup_period
= 0;
560 pwrmode
.flag_low_traffic_en
= 0;
561 pwrmode
.flag_lpnav_en
= 0;
562 pwrmode
.flag_rf_low_snr_en
= 0;
563 pwrmode
.flag_dps_en
= 0;
564 pwrmode
.bcn_rx_en
= 0;
566 le16p_replace_bits((__le16
*)(((u8
*)(&pwrmode
) + 8)),
567 mac
->vif
->bss_conf
.beacon_int
, GENMASK(15, 0));
569 pwrmode
.awake_bcn_itvl
= ppsc
->reg_max_lps_awakeintvl
;
570 pwrmode
.smart_ps
= 1;
571 pwrmode
.bcn_pass_period
= 10;
573 /* Set beacon pass count */
574 if (pwrmode
.mode
== FW_PS_MIN_MODE
)
575 max_wakeup_period
= mac
->vif
->bss_conf
.beacon_int
;
576 else if (pwrmode
.mode
== FW_PS_MAX_MODE
)
577 max_wakeup_period
= mac
->vif
->bss_conf
.beacon_int
*
578 mac
->vif
->bss_conf
.dtim_period
;
580 if (max_wakeup_period
>= 500)
581 pwrmode
.bcn_pass_cnt
= 1;
582 else if ((max_wakeup_period
>= 300) && (max_wakeup_period
< 500))
583 pwrmode
.bcn_pass_cnt
= 2;
584 else if ((max_wakeup_period
>= 200) && (max_wakeup_period
< 300))
585 pwrmode
.bcn_pass_cnt
= 3;
586 else if ((max_wakeup_period
>= 20) && (max_wakeup_period
< 200))
587 pwrmode
.bcn_pass_cnt
= 5;
589 pwrmode
.bcn_pass_cnt
= 1;
591 _rtl92s_firmware_set_h2c_cmd(hw
, FW_H2C_SETPWRMODE
, (u8
*)&pwrmode
);
595 void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw
*hw
,
596 u8 mstatus
, u8 ps_qosinfo
)
598 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
599 struct h2c_joinbss_rpt_parm joinbss_rpt
;
601 joinbss_rpt
.opmode
= mstatus
;
602 joinbss_rpt
.ps_qos_info
= ps_qosinfo
;
603 joinbss_rpt
.bssid
[0] = mac
->bssid
[0];
604 joinbss_rpt
.bssid
[1] = mac
->bssid
[1];
605 joinbss_rpt
.bssid
[2] = mac
->bssid
[2];
606 joinbss_rpt
.bssid
[3] = mac
->bssid
[3];
607 joinbss_rpt
.bssid
[4] = mac
->bssid
[4];
608 joinbss_rpt
.bssid
[5] = mac
->bssid
[5];
609 le16p_replace_bits((__le16
*)(((u8
*)(&joinbss_rpt
) + 8)),
610 mac
->vif
->bss_conf
.beacon_int
, GENMASK(15, 0));
611 le16p_replace_bits((__le16
*)(((u8
*)(&joinbss_rpt
) + 10)),
612 mac
->assoc_id
, GENMASK(15, 0));
614 _rtl92s_firmware_set_h2c_cmd(hw
, FW_H2C_JOINBSSRPT
, (u8
*)&joinbss_rpt
);