1 /******************************************************************************
3 * Copyright(c) 2009-2012 Realtek Corporation.
5 * This program is free software; you can redistribute it and/or modify it
6 * under the terms of version 2 of the GNU General Public License as
7 * published by the Free Software Foundation.
9 * This program is distributed in the hope that it will be useful, but WITHOUT
10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
14 * The full GNU General Public License is included in this distribution in the
15 * file called LICENSE.
17 * Contact Information:
18 * wlanfae <wlanfae@realtek.com>
19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park,
20 * Hsinchu 300, Taiwan.
22 * Larry Finger <Larry.Finger@lwfinger.net>
24 *****************************************************************************/
33 static void _rtl92s_fw_set_rqpn(struct ieee80211_hw
*hw
)
35 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
37 rtl_write_dword(rtlpriv
, RQPN
, 0xffffffff);
38 rtl_write_dword(rtlpriv
, RQPN
+ 4, 0xffffffff);
39 rtl_write_byte(rtlpriv
, RQPN
+ 8, 0xff);
40 rtl_write_byte(rtlpriv
, RQPN
+ 0xB, 0x80);
43 static bool _rtl92s_firmware_enable_cpu(struct ieee80211_hw
*hw
)
45 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
48 u8 tmpu1b
, cpustatus
= 0;
50 _rtl92s_fw_set_rqpn(hw
);
53 tmpu1b
= rtl_read_byte(rtlpriv
, SYS_CLKR
);
55 rtl_write_byte(rtlpriv
, SYS_CLKR
, (tmpu1b
| SYS_CPU_CLKSEL
));
57 tmpu2b
= rtl_read_word(rtlpriv
, REG_SYS_FUNC_EN
);
58 rtl_write_word(rtlpriv
, REG_SYS_FUNC_EN
, (tmpu2b
| FEN_CPUEN
));
60 /* Polling IMEM Ready after CPU has refilled. */
62 cpustatus
= rtl_read_byte(rtlpriv
, TCR
);
63 if (cpustatus
& IMEM_RDY
) {
64 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
65 "IMEM Ready after CPU has refilled\n");
70 } while (ichecktime
--);
72 if (!(cpustatus
& IMEM_RDY
))
78 static enum fw_status
_rtl92s_firmware_get_nextstatus(
79 enum fw_status fw_currentstatus
)
81 enum fw_status next_fwstatus
= 0;
83 switch (fw_currentstatus
) {
85 next_fwstatus
= FW_STATUS_LOAD_IMEM
;
87 case FW_STATUS_LOAD_IMEM
:
88 next_fwstatus
= FW_STATUS_LOAD_EMEM
;
90 case FW_STATUS_LOAD_EMEM
:
91 next_fwstatus
= FW_STATUS_LOAD_DMEM
;
93 case FW_STATUS_LOAD_DMEM
:
94 next_fwstatus
= FW_STATUS_READY
;
100 return next_fwstatus
;
103 static u8
_rtl92s_firmware_header_map_rftype(struct ieee80211_hw
*hw
)
105 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
106 struct rtl_phy
*rtlphy
= &(rtlpriv
->phy
);
108 switch (rtlphy
->rf_type
) {
116 pr_err("Unknown RF type(%x)\n", rtlphy
->rf_type
);
122 static void _rtl92s_firmwareheader_priveupdate(struct ieee80211_hw
*hw
,
123 struct fw_priv
*pfw_priv
)
125 /* Update RF types for RATR settings. */
126 pfw_priv
->rf_config
= _rtl92s_firmware_header_map_rftype(hw
);
131 static bool _rtl92s_cmd_send_packet(struct ieee80211_hw
*hw
,
132 struct sk_buff
*skb
, u8 last
)
134 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
135 struct rtl_pci
*rtlpci
= rtl_pcidev(rtl_pcipriv(hw
));
136 struct rtl8192_tx_ring
*ring
;
137 struct rtl_tx_desc
*pdesc
;
141 ring
= &rtlpci
->tx_ring
[TXCMD_QUEUE
];
143 spin_lock_irqsave(&rtlpriv
->locks
.irq_th_lock
, flags
);
145 idx
= (ring
->idx
+ skb_queue_len(&ring
->queue
)) % ring
->entries
;
146 pdesc
= &ring
->desc
[idx
];
147 rtlpriv
->cfg
->ops
->fill_tx_cmddesc(hw
, (u8
*)pdesc
, 1, 1, skb
);
148 __skb_queue_tail(&ring
->queue
, skb
);
150 spin_unlock_irqrestore(&rtlpriv
->locks
.irq_th_lock
, flags
);
155 static bool _rtl92s_firmware_downloadcode(struct ieee80211_hw
*hw
,
156 u8
*code_virtual_address
, u32 buffer_len
)
158 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
160 struct rtl_tcb_desc
*tcb_desc
;
161 unsigned char *seg_ptr
;
162 u16 frag_threshold
= MAX_FIRMWARE_CODE_SIZE
;
163 u16 frag_length
, frag_offset
= 0;
164 u16 extra_descoffset
= 0;
167 _rtl92s_fw_set_rqpn(hw
);
169 if (buffer_len
>= MAX_FIRMWARE_CODE_SIZE
) {
170 pr_err("Size over FIRMWARE_CODE_SIZE!\n");
174 extra_descoffset
= 0;
177 if ((buffer_len
- frag_offset
) > frag_threshold
) {
178 frag_length
= frag_threshold
+ extra_descoffset
;
180 frag_length
= (u16
)(buffer_len
- frag_offset
+
185 /* Allocate skb buffer to contain firmware */
186 /* info and tx descriptor info. */
187 skb
= dev_alloc_skb(frag_length
);
190 skb_reserve(skb
, extra_descoffset
);
191 seg_ptr
= skb_put_data(skb
,
192 code_virtual_address
+ frag_offset
,
193 (u32
)(frag_length
- extra_descoffset
));
195 tcb_desc
= (struct rtl_tcb_desc
*)(skb
->cb
);
196 tcb_desc
->queue_index
= TXCMD_QUEUE
;
197 tcb_desc
->cmd_or_init
= DESC_PACKET_TYPE_INIT
;
198 tcb_desc
->last_inipkt
= last_inipkt
;
200 _rtl92s_cmd_send_packet(hw
, skb
, last_inipkt
);
202 frag_offset
+= (frag_length
- extra_descoffset
);
204 } while (frag_offset
< buffer_len
);
206 rtl_write_byte(rtlpriv
, TP_POLL
, TPPOLL_CQ
);
211 static bool _rtl92s_firmware_checkready(struct ieee80211_hw
*hw
,
214 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
215 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
216 struct rt_firmware
*firmware
= (struct rt_firmware
*)rtlhal
->pfirmware
;
219 short pollingcnt
= 1000;
220 bool rtstatus
= true;
222 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
223 "LoadStaus(%d)\n", loadfw_status
);
225 firmware
->fwstatus
= (enum fw_status
)loadfw_status
;
227 switch (loadfw_status
) {
228 case FW_STATUS_LOAD_IMEM
:
229 /* Polling IMEM code done. */
231 cpustatus
= rtl_read_byte(rtlpriv
, TCR
);
232 if (cpustatus
& IMEM_CODE_DONE
)
235 } while (pollingcnt
--);
237 if (!(cpustatus
& IMEM_CHK_RPT
) || (pollingcnt
<= 0)) {
238 pr_err("FW_STATUS_LOAD_IMEM FAIL CPU, Status=%x\n",
240 goto status_check_fail
;
244 case FW_STATUS_LOAD_EMEM
:
245 /* Check Put Code OK and Turn On CPU */
246 /* Polling EMEM code done. */
248 cpustatus
= rtl_read_byte(rtlpriv
, TCR
);
249 if (cpustatus
& EMEM_CODE_DONE
)
252 } while (pollingcnt
--);
254 if (!(cpustatus
& EMEM_CHK_RPT
) || (pollingcnt
<= 0)) {
255 pr_err("FW_STATUS_LOAD_EMEM FAIL CPU, Status=%x\n",
257 goto status_check_fail
;
261 rtstatus
= _rtl92s_firmware_enable_cpu(hw
);
263 pr_err("Enable CPU fail!\n");
264 goto status_check_fail
;
268 case FW_STATUS_LOAD_DMEM
:
269 /* Polling DMEM code done */
271 cpustatus
= rtl_read_byte(rtlpriv
, TCR
);
272 if (cpustatus
& DMEM_CODE_DONE
)
275 } while (pollingcnt
--);
277 if (!(cpustatus
& DMEM_CODE_DONE
) || (pollingcnt
<= 0)) {
278 pr_err("Polling DMEM code done fail ! cpustatus(%#x)\n",
280 goto status_check_fail
;
283 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
284 "DMEM code download success, cpustatus(%#x)\n",
287 /* Prevent Delay too much and being scheduled out */
288 /* Polling Load Firmware ready */
291 cpustatus
= rtl_read_byte(rtlpriv
, TCR
);
292 if (cpustatus
& FWRDY
)
295 } while (pollingcnt
--);
297 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
298 "Polling Load Firmware ready, cpustatus(%x)\n",
301 if (((cpustatus
& LOAD_FW_READY
) != LOAD_FW_READY
) ||
303 pr_err("Polling Load Firmware ready fail ! cpustatus(%x)\n",
305 goto status_check_fail
;
308 /* If right here, we can set TCR/RCR to desired value */
309 /* and config MAC lookback mode to normal mode */
310 tmpu4b
= rtl_read_dword(rtlpriv
, TCR
);
311 rtl_write_dword(rtlpriv
, TCR
, (tmpu4b
& (~TCR_ICV
)));
313 tmpu4b
= rtl_read_dword(rtlpriv
, RCR
);
314 rtl_write_dword(rtlpriv
, RCR
, (tmpu4b
| RCR_APPFCS
|
315 RCR_APP_ICV
| RCR_APP_MIC
));
317 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
318 "Current RCR settings(%#x)\n", tmpu4b
);
320 /* Set to normal mode. */
321 rtl_write_byte(rtlpriv
, LBKMD_SEL
, LBK_NORMAL
);
325 pr_err("Unknown status check!\n");
331 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
332 "loadfw_status(%d), rtstatus(%x)\n",
333 loadfw_status
, rtstatus
);
337 int rtl92s_download_fw(struct ieee80211_hw
*hw
)
339 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
340 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
341 struct rt_firmware
*firmware
= NULL
;
342 struct fw_hdr
*pfwheader
;
343 struct fw_priv
*pfw_priv
= NULL
;
344 u8
*puc_mappedfile
= NULL
;
345 u32 ul_filelength
= 0;
346 u8 fwhdr_size
= RT_8192S_FIRMWARE_HDR_SIZE
;
347 u8 fwstatus
= FW_STATUS_INIT
;
348 bool rtstatus
= true;
350 if (rtlpriv
->max_fw_size
== 0 || !rtlhal
->pfirmware
)
353 firmware
= (struct rt_firmware
*)rtlhal
->pfirmware
;
354 firmware
->fwstatus
= FW_STATUS_INIT
;
356 puc_mappedfile
= firmware
->sz_fw_tmpbuffer
;
358 /* 1. Retrieve FW header. */
359 firmware
->pfwheader
= (struct fw_hdr
*) puc_mappedfile
;
360 pfwheader
= firmware
->pfwheader
;
361 firmware
->firmwareversion
= byte(pfwheader
->version
, 0);
362 firmware
->pfwheader
->fwpriv
.hci_sel
= 1;/* pcie */
364 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
365 "signature:%x, version:%x, size:%x, imemsize:%x, sram size:%x\n",
366 pfwheader
->signature
,
367 pfwheader
->version
, pfwheader
->dmem_size
,
368 pfwheader
->img_imem_size
, pfwheader
->img_sram_size
);
370 /* 2. Retrieve IMEM image. */
371 if ((pfwheader
->img_imem_size
== 0) || (pfwheader
->img_imem_size
>
372 sizeof(firmware
->fw_imem
))) {
373 pr_err("memory for data image is less than IMEM required\n");
376 puc_mappedfile
+= fwhdr_size
;
378 memcpy(firmware
->fw_imem
, puc_mappedfile
,
379 pfwheader
->img_imem_size
);
380 firmware
->fw_imem_len
= pfwheader
->img_imem_size
;
383 /* 3. Retriecve EMEM image. */
384 if (pfwheader
->img_sram_size
> sizeof(firmware
->fw_emem
)) {
385 pr_err("memory for data image is less than EMEM required\n");
388 puc_mappedfile
+= firmware
->fw_imem_len
;
390 memcpy(firmware
->fw_emem
, puc_mappedfile
,
391 pfwheader
->img_sram_size
);
392 firmware
->fw_emem_len
= pfwheader
->img_sram_size
;
395 /* 4. download fw now */
396 fwstatus
= _rtl92s_firmware_get_nextstatus(firmware
->fwstatus
);
397 while (fwstatus
!= FW_STATUS_READY
) {
398 /* Image buffer redirection. */
400 case FW_STATUS_LOAD_IMEM
:
401 puc_mappedfile
= firmware
->fw_imem
;
402 ul_filelength
= firmware
->fw_imem_len
;
404 case FW_STATUS_LOAD_EMEM
:
405 puc_mappedfile
= firmware
->fw_emem
;
406 ul_filelength
= firmware
->fw_emem_len
;
408 case FW_STATUS_LOAD_DMEM
:
409 /* Partial update the content of header private. */
410 pfwheader
= firmware
->pfwheader
;
411 pfw_priv
= &pfwheader
->fwpriv
;
412 _rtl92s_firmwareheader_priveupdate(hw
, pfw_priv
);
413 puc_mappedfile
= (u8
*)(firmware
->pfwheader
) +
414 RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE
;
415 ul_filelength
= fwhdr_size
-
416 RT_8192S_FIRMWARE_HDR_EXCLUDE_PRI_SIZE
;
419 pr_err("Unexpected Download step!!\n");
423 /* <2> Download image file */
424 rtstatus
= _rtl92s_firmware_downloadcode(hw
, puc_mappedfile
,
432 /* <3> Check whether load FW process is ready */
433 rtstatus
= _rtl92s_firmware_checkready(hw
, fwstatus
);
435 pr_err("rtl8192se: firmware fail!\n");
439 fwstatus
= _rtl92s_firmware_get_nextstatus(firmware
->fwstatus
);
447 static u32
_rtl92s_fill_h2c_cmd(struct sk_buff
*skb
, u32 h2cbufferlen
,
448 u32 cmd_num
, u32
*pelement_id
, u32
*pcmd_len
,
449 u8
**pcmb_buffer
, u8
*cmd_start_seq
)
451 u32 totallen
= 0, len
= 0, tx_desclen
= 0;
452 u32 pre_continueoffset
= 0;
457 /* 8 - Byte alignment */
458 len
= H2C_TX_CMD_HDR_LEN
+ N_BYTE_ALIGMENT(pcmd_len
[i
], 8);
460 /* Buffer length is not enough */
461 if (h2cbufferlen
< totallen
+ len
+ tx_desclen
)
465 ph2c_buffer
= skb_put(skb
, (u32
)len
);
466 memset((ph2c_buffer
+ totallen
+ tx_desclen
), 0, len
);
469 SET_BITS_TO_LE_4BYTE((ph2c_buffer
+ totallen
+ tx_desclen
),
473 SET_BITS_TO_LE_4BYTE((ph2c_buffer
+ totallen
+ tx_desclen
),
474 16, 8, pelement_id
[i
]);
477 *cmd_start_seq
= *cmd_start_seq
% 0x80;
478 SET_BITS_TO_LE_4BYTE((ph2c_buffer
+ totallen
+ tx_desclen
),
479 24, 7, *cmd_start_seq
);
483 memcpy((ph2c_buffer
+ totallen
+ tx_desclen
+
484 H2C_TX_CMD_HDR_LEN
), pcmb_buffer
[i
], pcmd_len
[i
]);
487 /* set the continue in prevoius cmd. */
489 SET_BITS_TO_LE_4BYTE((ph2c_buffer
+ pre_continueoffset
),
492 pre_continueoffset
= totallen
;
495 } while (++i
< cmd_num
);
500 static u32
_rtl92s_get_h2c_cmdlen(u32 h2cbufferlen
, u32 cmd_num
, u32
*pcmd_len
)
502 u32 totallen
= 0, len
= 0, tx_desclen
= 0;
506 /* 8 - Byte alignment */
507 len
= H2C_TX_CMD_HDR_LEN
+ N_BYTE_ALIGMENT(pcmd_len
[i
], 8);
509 /* Buffer length is not enough */
510 if (h2cbufferlen
< totallen
+ len
+ tx_desclen
)
514 } while (++i
< cmd_num
);
516 return totallen
+ tx_desclen
;
519 static bool _rtl92s_firmware_set_h2c_cmd(struct ieee80211_hw
*hw
, u8 h2c_cmd
,
522 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
523 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
524 struct rtl_tcb_desc
*cb_desc
;
531 case FW_H2C_SETPWRMODE
:
532 element_id
= H2C_SETPWRMODE_CMD
;
533 cmd_len
= sizeof(struct h2c_set_pwrmode_parm
);
535 case FW_H2C_JOINBSSRPT
:
536 element_id
= H2C_JOINBSSRPT_CMD
;
537 cmd_len
= sizeof(struct h2c_joinbss_rpt_parm
);
539 case FW_H2C_WOWLAN_UPDATE_GTK
:
540 element_id
= H2C_WOWLAN_UPDATE_GTK_CMD
;
541 cmd_len
= sizeof(struct h2c_wpa_two_way_parm
);
543 case FW_H2C_WOWLAN_UPDATE_IV
:
544 element_id
= H2C_WOWLAN_UPDATE_IV_CMD
;
545 cmd_len
= sizeof(unsigned long long);
547 case FW_H2C_WOWLAN_OFFLOAD
:
548 element_id
= H2C_WOWLAN_FW_OFFLOAD
;
549 cmd_len
= sizeof(u8
);
555 len
= _rtl92s_get_h2c_cmdlen(MAX_TRANSMIT_BUFFER_SIZE
, 1, &cmd_len
);
556 skb
= dev_alloc_skb(len
);
559 cb_desc
= (struct rtl_tcb_desc
*)(skb
->cb
);
560 cb_desc
->queue_index
= TXCMD_QUEUE
;
561 cb_desc
->cmd_or_init
= DESC_PACKET_TYPE_NORMAL
;
562 cb_desc
->last_inipkt
= false;
564 _rtl92s_fill_h2c_cmd(skb
, MAX_TRANSMIT_BUFFER_SIZE
, 1, &element_id
,
565 &cmd_len
, &pcmd_buffer
, &rtlhal
->h2c_txcmd_seq
);
566 _rtl92s_cmd_send_packet(hw
, skb
, false);
567 rtlpriv
->cfg
->ops
->tx_polling(hw
, TXCMD_QUEUE
);
572 void rtl92s_set_fw_pwrmode_cmd(struct ieee80211_hw
*hw
, u8 Mode
)
574 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
575 struct rtl_ps_ctl
*ppsc
= rtl_psc(rtl_priv(hw
));
576 struct h2c_set_pwrmode_parm pwrmode
;
577 u16 max_wakeup_period
= 0;
580 pwrmode
.flag_low_traffic_en
= 0;
581 pwrmode
.flag_lpnav_en
= 0;
582 pwrmode
.flag_rf_low_snr_en
= 0;
583 pwrmode
.flag_dps_en
= 0;
584 pwrmode
.bcn_rx_en
= 0;
586 SET_BITS_TO_LE_2BYTE((u8
*)(&pwrmode
) + 8, 0, 16,
587 mac
->vif
->bss_conf
.beacon_int
);
589 pwrmode
.awake_bcn_itvl
= ppsc
->reg_max_lps_awakeintvl
;
590 pwrmode
.smart_ps
= 1;
591 pwrmode
.bcn_pass_period
= 10;
593 /* Set beacon pass count */
594 if (pwrmode
.mode
== FW_PS_MIN_MODE
)
595 max_wakeup_period
= mac
->vif
->bss_conf
.beacon_int
;
596 else if (pwrmode
.mode
== FW_PS_MAX_MODE
)
597 max_wakeup_period
= mac
->vif
->bss_conf
.beacon_int
*
598 mac
->vif
->bss_conf
.dtim_period
;
600 if (max_wakeup_period
>= 500)
601 pwrmode
.bcn_pass_cnt
= 1;
602 else if ((max_wakeup_period
>= 300) && (max_wakeup_period
< 500))
603 pwrmode
.bcn_pass_cnt
= 2;
604 else if ((max_wakeup_period
>= 200) && (max_wakeup_period
< 300))
605 pwrmode
.bcn_pass_cnt
= 3;
606 else if ((max_wakeup_period
>= 20) && (max_wakeup_period
< 200))
607 pwrmode
.bcn_pass_cnt
= 5;
609 pwrmode
.bcn_pass_cnt
= 1;
611 _rtl92s_firmware_set_h2c_cmd(hw
, FW_H2C_SETPWRMODE
, (u8
*)&pwrmode
);
615 void rtl92s_set_fw_joinbss_report_cmd(struct ieee80211_hw
*hw
,
616 u8 mstatus
, u8 ps_qosinfo
)
618 struct rtl_mac
*mac
= rtl_mac(rtl_priv(hw
));
619 struct h2c_joinbss_rpt_parm joinbss_rpt
;
621 joinbss_rpt
.opmode
= mstatus
;
622 joinbss_rpt
.ps_qos_info
= ps_qosinfo
;
623 joinbss_rpt
.bssid
[0] = mac
->bssid
[0];
624 joinbss_rpt
.bssid
[1] = mac
->bssid
[1];
625 joinbss_rpt
.bssid
[2] = mac
->bssid
[2];
626 joinbss_rpt
.bssid
[3] = mac
->bssid
[3];
627 joinbss_rpt
.bssid
[4] = mac
->bssid
[4];
628 joinbss_rpt
.bssid
[5] = mac
->bssid
[5];
629 SET_BITS_TO_LE_2BYTE((u8
*)(&joinbss_rpt
) + 8, 0, 16,
630 mac
->vif
->bss_conf
.beacon_int
);
631 SET_BITS_TO_LE_2BYTE((u8
*)(&joinbss_rpt
) + 10, 0, 16, mac
->assoc_id
);
633 _rtl92s_firmware_set_h2c_cmd(hw
, FW_H2C_JOINBSSRPT
, (u8
*)&joinbss_rpt
);