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 *****************************************************************************/
30 #include "fw_common.h"
31 #include <linux/module.h>
33 void rtl8723_enable_fw_download(struct ieee80211_hw
*hw
, bool enable
)
35 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
39 tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
40 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1,
43 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
);
44 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, tmp
| 0x01);
46 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
+ 2);
47 rtl_write_byte(rtlpriv
, REG_MCUFWDL
+ 2, tmp
& 0xf7);
49 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
);
50 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, tmp
& 0xfe);
52 rtl_write_byte(rtlpriv
, REG_MCUFWDL
+ 1, 0x00);
55 EXPORT_SYMBOL_GPL(rtl8723_enable_fw_download
);
57 void rtl8723_write_fw(struct ieee80211_hw
*hw
,
58 enum version_8723e version
,
59 u8
*buffer
, u32 size
, u8 max_page
)
61 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
62 u8
*bufferptr
= buffer
;
63 u32 page_nums
, remain_size
;
66 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
, "FW size is %d bytes,\n", size
);
68 rtl_fill_dummy(bufferptr
, &size
);
70 page_nums
= size
/ FW_8192C_PAGE_SIZE
;
71 remain_size
= size
% FW_8192C_PAGE_SIZE
;
73 if (page_nums
> max_page
) {
74 pr_err("Page numbers should not greater than %d\n",
77 for (page
= 0; page
< page_nums
; page
++) {
78 offset
= page
* FW_8192C_PAGE_SIZE
;
79 rtl_fw_page_write(hw
, page
, (bufferptr
+ offset
),
84 offset
= page_nums
* FW_8192C_PAGE_SIZE
;
86 rtl_fw_page_write(hw
, page
, (bufferptr
+ offset
), remain_size
);
88 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
, "FW write done.\n");
90 EXPORT_SYMBOL_GPL(rtl8723_write_fw
);
92 void rtl8723ae_firmware_selfreset(struct ieee80211_hw
*hw
)
96 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
98 rtl_write_byte(rtlpriv
, REG_HMETFR
+ 3, 0x20);
99 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
101 while (u1b_tmp
& BIT(2)) {
106 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
109 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
110 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1,
114 EXPORT_SYMBOL_GPL(rtl8723ae_firmware_selfreset
);
116 void rtl8723be_firmware_selfreset(struct ieee80211_hw
*hw
)
119 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
121 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_RSV_CTRL
+ 1);
122 rtl_write_byte(rtlpriv
, REG_RSV_CTRL
+ 1, (u1b_tmp
& (~BIT(0))));
124 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
125 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1, (u1b_tmp
& (~BIT(2))));
128 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_RSV_CTRL
+ 1);
129 rtl_write_byte(rtlpriv
, REG_RSV_CTRL
+ 1, (u1b_tmp
| BIT(0)));
131 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
132 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1, (u1b_tmp
| BIT(2)));
134 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
135 " _8051Reset8723be(): 8051 reset success .\n");
137 EXPORT_SYMBOL_GPL(rtl8723be_firmware_selfreset
);
139 int rtl8723_fw_free_to_go(struct ieee80211_hw
*hw
, bool is_8723be
,
142 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
148 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
149 } while ((counter
++ < max_count
) &&
150 (!(value32
& FWDL_CHKSUM_RPT
)));
152 if (counter
>= max_count
) {
153 pr_err("chksum report fail ! REG_MCUFWDL:0x%08x .\n",
157 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
) | MCUFWDL_RDY
;
158 value32
&= ~WINTINI_RDY
;
159 rtl_write_dword(rtlpriv
, REG_MCUFWDL
, value32
);
162 rtl8723be_firmware_selfreset(hw
);
166 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
167 if (value32
& WINTINI_RDY
) {
168 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
169 "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n",
175 mdelay(FW_8192C_POLLING_DELAY
);
177 } while (counter
++ < max_count
);
179 pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n",
185 EXPORT_SYMBOL_GPL(rtl8723_fw_free_to_go
);
187 int rtl8723_download_fw(struct ieee80211_hw
*hw
,
188 bool is_8723be
, int max_count
)
190 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
191 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
192 struct rtlwifi_firmware_header
*pfwheader
;
196 enum version_8723e version
= rtlhal
->version
;
199 if (rtlpriv
->max_fw_size
== 0 || !rtlhal
->pfirmware
)
202 pfwheader
= (struct rtlwifi_firmware_header
*)rtlhal
->pfirmware
;
203 rtlhal
->fw_version
= le16_to_cpu(pfwheader
->version
);
204 rtlhal
->fw_subversion
= pfwheader
->subversion
;
205 pfwdata
= rtlhal
->pfirmware
;
206 fwsize
= rtlhal
->fwsize
;
212 if (rtlpriv
->cfg
->ops
->is_fw_header(pfwheader
)) {
213 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
,
214 "Firmware Version(%d), Signature(%#x), Size(%d)\n",
215 pfwheader
->version
, pfwheader
->signature
,
216 (int)sizeof(struct rtlwifi_firmware_header
));
218 pfwdata
= pfwdata
+ sizeof(struct rtlwifi_firmware_header
);
219 fwsize
= fwsize
- sizeof(struct rtlwifi_firmware_header
);
222 if (rtl_read_byte(rtlpriv
, REG_MCUFWDL
)&BIT(7)) {
224 rtl8723be_firmware_selfreset(hw
);
226 rtl8723ae_firmware_selfreset(hw
);
227 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, 0x00);
229 rtl8723_enable_fw_download(hw
, true);
230 rtl8723_write_fw(hw
, version
, pfwdata
, fwsize
, max_page
);
231 rtl8723_enable_fw_download(hw
, false);
233 err
= rtl8723_fw_free_to_go(hw
, is_8723be
, max_count
);
235 pr_err("Firmware is not ready to run!\n");
238 EXPORT_SYMBOL_GPL(rtl8723_download_fw
);
240 bool rtl8723_cmd_send_packet(struct ieee80211_hw
*hw
,
243 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
244 struct rtl_pci
*rtlpci
= rtl_pcidev(rtl_pcipriv(hw
));
245 struct rtl8192_tx_ring
*ring
;
246 struct rtl_tx_desc
*pdesc
;
247 struct sk_buff
*pskb
= NULL
;
251 ring
= &rtlpci
->tx_ring
[BEACON_QUEUE
];
253 pskb
= __skb_dequeue(&ring
->queue
);
255 spin_lock_irqsave(&rtlpriv
->locks
.irq_th_lock
, flags
);
257 pdesc
= &ring
->desc
[0];
258 own
= (u8
)rtlpriv
->cfg
->ops
->get_desc(hw
, (u8
*)pdesc
, true,
261 rtlpriv
->cfg
->ops
->fill_tx_cmddesc(hw
, (u8
*)pdesc
, 1, 1, skb
);
263 __skb_queue_tail(&ring
->queue
, skb
);
265 spin_unlock_irqrestore(&rtlpriv
->locks
.irq_th_lock
, flags
);
267 rtlpriv
->cfg
->ops
->tx_polling(hw
, BEACON_QUEUE
);
271 EXPORT_SYMBOL_GPL(rtl8723_cmd_send_packet
);