1 /******************************************************************************
3 * Copyright(c) 2009-2014 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 *****************************************************************************/
29 #include "fw_common.h"
30 #include <linux/module.h>
32 void rtl8723_enable_fw_download(struct ieee80211_hw
*hw
, bool enable
)
34 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
38 tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
39 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1,
42 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
);
43 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, tmp
| 0x01);
45 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
+ 2);
46 rtl_write_byte(rtlpriv
, REG_MCUFWDL
+ 2, tmp
& 0xf7);
48 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
);
49 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, tmp
& 0xfe);
51 rtl_write_byte(rtlpriv
, REG_MCUFWDL
+ 1, 0x00);
54 EXPORT_SYMBOL_GPL(rtl8723_enable_fw_download
);
56 void rtl8723_fw_block_write(struct ieee80211_hw
*hw
,
57 const u8
*buffer
, u32 size
)
59 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
60 u32 blocksize
= sizeof(u32
);
61 u8
*bufferptr
= (u8
*)buffer
;
62 u32
*pu4byteptr
= (u32
*)buffer
;
63 u32 i
, offset
, blockcount
, remainsize
;
65 blockcount
= size
/ blocksize
;
66 remainsize
= size
% blocksize
;
68 for (i
= 0; i
< blockcount
; i
++) {
69 offset
= i
* blocksize
;
70 rtl_write_dword(rtlpriv
, (FW_8192C_START_ADDRESS
+ offset
),
74 offset
= blockcount
* blocksize
;
76 for (i
= 0; i
< remainsize
; i
++) {
77 rtl_write_byte(rtlpriv
,
78 (FW_8192C_START_ADDRESS
+ offset
+ i
),
83 EXPORT_SYMBOL_GPL(rtl8723_fw_block_write
);
85 void rtl8723_fw_page_write(struct ieee80211_hw
*hw
,
86 u32 page
, const u8
*buffer
, u32 size
)
88 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
90 u8 u8page
= (u8
) (page
& 0x07);
92 value8
= (rtl_read_byte(rtlpriv
, REG_MCUFWDL
+ 2) & 0xF8) | u8page
;
94 rtl_write_byte(rtlpriv
, (REG_MCUFWDL
+ 2), value8
);
95 rtl8723_fw_block_write(hw
, buffer
, size
);
97 EXPORT_SYMBOL_GPL(rtl8723_fw_page_write
);
99 void rtl8723_fill_dummy(u8
*pfwbuf
, u32
*pfwlen
)
102 u8 remain
= (u8
) (fwlen
% 4);
104 remain
= (remain
== 0) ? 0 : (4 - remain
);
113 EXPORT_SYMBOL(rtl8723_fill_dummy
);
115 void rtl8723_write_fw(struct ieee80211_hw
*hw
,
116 enum version_8723e version
,
117 u8
*buffer
, u32 size
, u8 max_page
)
119 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
120 u8
*bufferptr
= buffer
;
121 u32 page_nums
, remain_size
;
124 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
, "FW size is %d bytes,\n", size
);
126 rtl8723_fill_dummy(bufferptr
, &size
);
128 page_nums
= size
/ FW_8192C_PAGE_SIZE
;
129 remain_size
= size
% FW_8192C_PAGE_SIZE
;
131 if (page_nums
> max_page
) {
132 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_EMERG
,
133 "Page numbers should not greater than %d\n", max_page
);
135 for (page
= 0; page
< page_nums
; page
++) {
136 offset
= page
* FW_8192C_PAGE_SIZE
;
137 rtl8723_fw_page_write(hw
, page
, (bufferptr
+ offset
),
142 offset
= page_nums
* FW_8192C_PAGE_SIZE
;
144 rtl8723_fw_page_write(hw
, page
, (bufferptr
+ offset
),
147 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
, "FW write done.\n");
149 EXPORT_SYMBOL_GPL(rtl8723_write_fw
);
151 void rtl8723ae_firmware_selfreset(struct ieee80211_hw
*hw
)
155 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
157 rtl_write_byte(rtlpriv
, REG_HMETFR
+ 3, 0x20);
158 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
160 while (u1b_tmp
& BIT(2)) {
165 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
168 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
169 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1,
173 EXPORT_SYMBOL_GPL(rtl8723ae_firmware_selfreset
);
175 void rtl8723be_firmware_selfreset(struct ieee80211_hw
*hw
)
178 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
180 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_RSV_CTRL
+ 1);
181 rtl_write_byte(rtlpriv
, REG_RSV_CTRL
+ 1, (u1b_tmp
& (~BIT(0))));
183 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
184 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1, (u1b_tmp
& (~BIT(2))));
187 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_RSV_CTRL
+ 1);
188 rtl_write_byte(rtlpriv
, REG_RSV_CTRL
+ 1, (u1b_tmp
| BIT(0)));
190 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
191 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1, (u1b_tmp
| BIT(2)));
193 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
194 " _8051Reset8723be(): 8051 reset success .\n");
196 EXPORT_SYMBOL_GPL(rtl8723be_firmware_selfreset
);
198 int rtl8723_fw_free_to_go(struct ieee80211_hw
*hw
, bool is_8723be
,
201 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
207 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
208 } while ((counter
++ < max_count
) &&
209 (!(value32
& FWDL_CHKSUM_RPT
)));
211 if (counter
>= max_count
) {
212 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_EMERG
,
213 "chksum report fail ! REG_MCUFWDL:0x%08x .\n",
217 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
218 "Checksum report OK ! REG_MCUFWDL:0x%08x .\n", value32
);
220 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
) | MCUFWDL_RDY
;
221 value32
&= ~WINTINI_RDY
;
222 rtl_write_dword(rtlpriv
, REG_MCUFWDL
, value32
);
225 rtl8723be_firmware_selfreset(hw
);
229 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
230 if (value32
& WINTINI_RDY
) {
231 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
232 "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n",
238 mdelay(FW_8192C_POLLING_DELAY
);
240 } while (counter
++ < max_count
);
242 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_EMERG
,
243 "Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n",
249 EXPORT_SYMBOL_GPL(rtl8723_fw_free_to_go
);
251 int rtl8723_download_fw(struct ieee80211_hw
*hw
,
252 bool is_8723be
, int max_count
)
254 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
255 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
256 struct rtlwifi_firmware_header
*pfwheader
;
260 enum version_8723e version
= rtlhal
->version
;
263 if (!rtlhal
->pfirmware
)
266 pfwheader
= (struct rtlwifi_firmware_header
*)rtlhal
->pfirmware
;
267 pfwdata
= rtlhal
->pfirmware
;
268 fwsize
= rtlhal
->fwsize
;
274 if (rtlpriv
->cfg
->ops
->is_fw_header(pfwheader
)) {
275 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
,
276 "Firmware Version(%d), Signature(%#x), Size(%d)\n",
277 pfwheader
->version
, pfwheader
->signature
,
278 (int)sizeof(struct rtlwifi_firmware_header
));
280 pfwdata
= pfwdata
+ sizeof(struct rtlwifi_firmware_header
);
281 fwsize
= fwsize
- sizeof(struct rtlwifi_firmware_header
);
284 if (rtl_read_byte(rtlpriv
, REG_MCUFWDL
)&BIT(7)) {
286 rtl8723be_firmware_selfreset(hw
);
288 rtl8723ae_firmware_selfreset(hw
);
289 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, 0x00);
291 rtl8723_enable_fw_download(hw
, true);
292 rtl8723_write_fw(hw
, version
, pfwdata
, fwsize
, max_page
);
293 rtl8723_enable_fw_download(hw
, false);
295 err
= rtl8723_fw_free_to_go(hw
, is_8723be
, max_count
);
297 RT_TRACE(rtlpriv
, COMP_ERR
, DBG_EMERG
,
298 "Firmware is not ready to run!\n");
300 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
301 "Firmware is ready to run!\n");
305 EXPORT_SYMBOL_GPL(rtl8723_download_fw
);
307 bool rtl8723_cmd_send_packet(struct ieee80211_hw
*hw
,
310 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
311 struct rtl_pci
*rtlpci
= rtl_pcidev(rtl_pcipriv(hw
));
312 struct rtl8192_tx_ring
*ring
;
313 struct rtl_tx_desc
*pdesc
;
314 struct sk_buff
*pskb
= NULL
;
318 ring
= &rtlpci
->tx_ring
[BEACON_QUEUE
];
320 pskb
= __skb_dequeue(&ring
->queue
);
322 spin_lock_irqsave(&rtlpriv
->locks
.irq_th_lock
, flags
);
324 pdesc
= &ring
->desc
[0];
325 own
= (u8
) rtlpriv
->cfg
->ops
->get_desc((u8
*)pdesc
, true, HW_DESC_OWN
);
327 rtlpriv
->cfg
->ops
->fill_tx_cmddesc(hw
, (u8
*)pdesc
, 1, 1, skb
);
329 __skb_queue_tail(&ring
->queue
, skb
);
331 spin_unlock_irqrestore(&rtlpriv
->locks
.irq_th_lock
, flags
);
333 rtlpriv
->cfg
->ops
->tx_polling(hw
, BEACON_QUEUE
);
337 EXPORT_SYMBOL_GPL(rtl8723_cmd_send_packet
);