1 // SPDX-License-Identifier: GPL-2.0
2 /* Copyright(c) 2009-2014 Realtek Corporation.*/
9 #include <linux/module.h>
11 void rtl8723_enable_fw_download(struct ieee80211_hw
*hw
, bool enable
)
13 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
17 tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
18 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1,
21 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
);
22 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, tmp
| 0x01);
24 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
+ 2);
25 rtl_write_byte(rtlpriv
, REG_MCUFWDL
+ 2, tmp
& 0xf7);
27 tmp
= rtl_read_byte(rtlpriv
, REG_MCUFWDL
);
28 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, tmp
& 0xfe);
30 rtl_write_byte(rtlpriv
, REG_MCUFWDL
+ 1, 0x00);
33 EXPORT_SYMBOL_GPL(rtl8723_enable_fw_download
);
35 void rtl8723_write_fw(struct ieee80211_hw
*hw
,
36 enum version_8723e version
,
37 u8
*buffer
, u32 size
, u8 max_page
)
39 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
40 u8
*bufferptr
= buffer
;
41 u32 page_nums
, remain_size
;
44 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
, "FW size is %d bytes,\n", size
);
46 rtl_fill_dummy(bufferptr
, &size
);
48 page_nums
= size
/ FW_8192C_PAGE_SIZE
;
49 remain_size
= size
% FW_8192C_PAGE_SIZE
;
51 if (page_nums
> max_page
) {
52 pr_err("Page numbers should not greater than %d\n",
55 for (page
= 0; page
< page_nums
; page
++) {
56 offset
= page
* FW_8192C_PAGE_SIZE
;
57 rtl_fw_page_write(hw
, page
, (bufferptr
+ offset
),
62 offset
= page_nums
* FW_8192C_PAGE_SIZE
;
64 rtl_fw_page_write(hw
, page
, (bufferptr
+ offset
), remain_size
);
66 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
, "FW write done.\n");
68 EXPORT_SYMBOL_GPL(rtl8723_write_fw
);
70 void rtl8723ae_firmware_selfreset(struct ieee80211_hw
*hw
)
74 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
76 rtl_write_byte(rtlpriv
, REG_HMETFR
+ 3, 0x20);
77 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
79 while (u1b_tmp
& BIT(2)) {
84 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
87 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
88 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1,
92 EXPORT_SYMBOL_GPL(rtl8723ae_firmware_selfreset
);
94 void rtl8723be_firmware_selfreset(struct ieee80211_hw
*hw
)
97 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
99 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_RSV_CTRL
+ 1);
100 rtl_write_byte(rtlpriv
, REG_RSV_CTRL
+ 1, (u1b_tmp
& (~BIT(0))));
102 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
103 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1, (u1b_tmp
& (~BIT(2))));
106 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_RSV_CTRL
+ 1);
107 rtl_write_byte(rtlpriv
, REG_RSV_CTRL
+ 1, (u1b_tmp
| BIT(0)));
109 u1b_tmp
= rtl_read_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1);
110 rtl_write_byte(rtlpriv
, REG_SYS_FUNC_EN
+ 1, (u1b_tmp
| BIT(2)));
112 RT_TRACE(rtlpriv
, COMP_INIT
, DBG_LOUD
,
113 " _8051Reset8723be(): 8051 reset success .\n");
115 EXPORT_SYMBOL_GPL(rtl8723be_firmware_selfreset
);
117 int rtl8723_fw_free_to_go(struct ieee80211_hw
*hw
, bool is_8723be
,
120 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
126 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
127 } while ((counter
++ < max_count
) &&
128 (!(value32
& FWDL_CHKSUM_RPT
)));
130 if (counter
>= max_count
) {
131 pr_err("chksum report fail ! REG_MCUFWDL:0x%08x .\n",
135 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
) | MCUFWDL_RDY
;
136 value32
&= ~WINTINI_RDY
;
137 rtl_write_dword(rtlpriv
, REG_MCUFWDL
, value32
);
140 rtl8723be_firmware_selfreset(hw
);
144 value32
= rtl_read_dword(rtlpriv
, REG_MCUFWDL
);
145 if (value32
& WINTINI_RDY
) {
146 RT_TRACE(rtlpriv
, COMP_FW
, DBG_TRACE
,
147 "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n",
153 mdelay(FW_8192C_POLLING_DELAY
);
155 } while (counter
++ < max_count
);
157 pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n",
163 EXPORT_SYMBOL_GPL(rtl8723_fw_free_to_go
);
165 int rtl8723_download_fw(struct ieee80211_hw
*hw
,
166 bool is_8723be
, int max_count
)
168 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
169 struct rtl_hal
*rtlhal
= rtl_hal(rtl_priv(hw
));
170 struct rtlwifi_firmware_header
*pfwheader
;
174 enum version_8723e version
= rtlhal
->version
;
177 if (rtlpriv
->max_fw_size
== 0 || !rtlhal
->pfirmware
)
180 pfwheader
= (struct rtlwifi_firmware_header
*)rtlhal
->pfirmware
;
181 rtlhal
->fw_version
= le16_to_cpu(pfwheader
->version
);
182 rtlhal
->fw_subversion
= pfwheader
->subversion
;
183 pfwdata
= rtlhal
->pfirmware
;
184 fwsize
= rtlhal
->fwsize
;
190 if (rtlpriv
->cfg
->ops
->is_fw_header(pfwheader
)) {
191 RT_TRACE(rtlpriv
, COMP_FW
, DBG_LOUD
,
192 "Firmware Version(%d), Signature(%#x), Size(%d)\n",
193 pfwheader
->version
, pfwheader
->signature
,
194 (int)sizeof(struct rtlwifi_firmware_header
));
196 pfwdata
= pfwdata
+ sizeof(struct rtlwifi_firmware_header
);
197 fwsize
= fwsize
- sizeof(struct rtlwifi_firmware_header
);
200 if (rtl_read_byte(rtlpriv
, REG_MCUFWDL
)&BIT(7)) {
202 rtl8723be_firmware_selfreset(hw
);
204 rtl8723ae_firmware_selfreset(hw
);
205 rtl_write_byte(rtlpriv
, REG_MCUFWDL
, 0x00);
207 rtl8723_enable_fw_download(hw
, true);
208 rtl8723_write_fw(hw
, version
, pfwdata
, fwsize
, max_page
);
209 rtl8723_enable_fw_download(hw
, false);
211 err
= rtl8723_fw_free_to_go(hw
, is_8723be
, max_count
);
213 pr_err("Firmware is not ready to run!\n");
216 EXPORT_SYMBOL_GPL(rtl8723_download_fw
);
218 bool rtl8723_cmd_send_packet(struct ieee80211_hw
*hw
,
221 struct rtl_priv
*rtlpriv
= rtl_priv(hw
);
222 struct rtl_pci
*rtlpci
= rtl_pcidev(rtl_pcipriv(hw
));
223 struct rtl8192_tx_ring
*ring
;
224 struct rtl_tx_desc
*pdesc
;
225 struct sk_buff
*pskb
= NULL
;
228 ring
= &rtlpci
->tx_ring
[BEACON_QUEUE
];
230 pskb
= __skb_dequeue(&ring
->queue
);
232 spin_lock_irqsave(&rtlpriv
->locks
.irq_th_lock
, flags
);
234 pdesc
= &ring
->desc
[0];
235 rtlpriv
->cfg
->ops
->fill_tx_cmddesc(hw
, (u8
*)pdesc
, 1, 1, skb
);
237 __skb_queue_tail(&ring
->queue
, skb
);
239 spin_unlock_irqrestore(&rtlpriv
->locks
.irq_th_lock
, flags
);
241 rtlpriv
->cfg
->ops
->tx_polling(hw
, BEACON_QUEUE
);
245 EXPORT_SYMBOL_GPL(rtl8723_cmd_send_packet
);