1 /******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
4 * This program is distributed in the hope that it will be useful, but WITHOUT
5 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
9 * The full GNU General Public License is included in this distribution in the
10 * file called LICENSE.
12 * Contact Information:
13 * wlanfae <wlanfae@realtek.com>
14 ******************************************************************************/
17 #include "r8192E_hw.h"
18 #include "r8192E_hwimg.h"
19 #include "r8192E_firmware.h"
20 #include <linux/firmware.h>
22 void rtl92e_init_fw_param(struct net_device
*dev
)
24 struct r8192_priv
*priv
= rtllib_priv(dev
);
25 struct rt_firmware
*pfirmware
= priv
->pFirmware
;
27 pfirmware
->cmdpacket_frag_thresold
= GET_COMMAND_PACKET_FRAG_THRESHOLD(
28 MAX_TRANSMIT_BUFFER_SIZE
);
31 static bool _rtl92e_fw_download_code(struct net_device
*dev
,
32 u8
*code_virtual_address
, u32 buffer_len
)
34 struct r8192_priv
*priv
= rtllib_priv(dev
);
36 u16 frag_length
, frag_offset
= 0;
39 struct rt_firmware
*pfirmware
= priv
->pFirmware
;
41 unsigned char *seg_ptr
;
42 struct cb_desc
*tcb_desc
;
45 rtl92e_init_fw_param(dev
);
46 frag_threshold
= pfirmware
->cmdpacket_frag_thresold
;
48 if ((buffer_len
- frag_offset
) > frag_threshold
) {
49 frag_length
= frag_threshold
;
53 frag_length
= buffer_len
- frag_offset
;
58 skb
= dev_alloc_skb(frag_length
+ 4);
59 memcpy((unsigned char *)(skb
->cb
), &dev
, sizeof(dev
));
60 tcb_desc
= (struct cb_desc
*)(skb
->cb
+ MAX_DEV_ADDR_SIZE
);
61 tcb_desc
->queue_index
= TXCMD_QUEUE
;
62 tcb_desc
->bCmdOrInit
= DESC_PACKET_TYPE_INIT
;
63 tcb_desc
->bLastIniPkt
= bLastIniPkt
;
66 for (i
= 0; i
< frag_length
; i
+= 4) {
67 *seg_ptr
++ = ((i
+0) < frag_length
) ?
68 code_virtual_address
[i
+3] : 0;
69 *seg_ptr
++ = ((i
+1) < frag_length
) ?
70 code_virtual_address
[i
+2] : 0;
71 *seg_ptr
++ = ((i
+2) < frag_length
) ?
72 code_virtual_address
[i
+1] : 0;
73 *seg_ptr
++ = ((i
+3) < frag_length
) ?
74 code_virtual_address
[i
+0] : 0;
76 tcb_desc
->txbuf_size
= (u16
)i
;
79 if (!priv
->rtllib
->check_nic_enough_desc(dev
, tcb_desc
->queue_index
) ||
80 (!skb_queue_empty(&priv
->rtllib
->skb_waitQ
[tcb_desc
->queue_index
])) ||
81 (priv
->rtllib
->queue_stop
)) {
82 RT_TRACE(COMP_FIRMWARE
,
83 "===================> tx full!\n");
84 skb_queue_tail(&priv
->rtllib
->skb_waitQ
85 [tcb_desc
->queue_index
], skb
);
87 priv
->rtllib
->softmac_hard_start_xmit(skb
, dev
);
90 code_virtual_address
+= frag_length
;
91 frag_offset
+= frag_length
;
93 } while (frag_offset
< buffer_len
);
95 rtl92e_writeb(dev
, TPPoll
, TPPoll_CQ
);
100 static bool _rtl92e_fw_boot_cpu(struct net_device
*dev
)
102 bool rt_status
= true;
104 unsigned long timeout
;
106 timeout
= jiffies
+ msecs_to_jiffies(200);
107 while (time_before(jiffies
, timeout
)) {
108 CPU_status
= rtl92e_readl(dev
, CPU_GEN
);
109 if (CPU_status
& CPU_GEN_PUT_CODE_OK
)
114 if (!(CPU_status
&CPU_GEN_PUT_CODE_OK
)) {
115 netdev_err(dev
, "Firmware download failed.\n");
116 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail
;
118 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Put code ok!\n");
121 CPU_status
= rtl92e_readl(dev
, CPU_GEN
);
122 rtl92e_writeb(dev
, CPU_GEN
,
123 (u8
)((CPU_status
|CPU_GEN_PWR_STB_CPU
)&0xff));
126 timeout
= jiffies
+ msecs_to_jiffies(200);
127 while (time_before(jiffies
, timeout
)) {
128 CPU_status
= rtl92e_readl(dev
, CPU_GEN
);
129 if (CPU_status
&CPU_GEN_BOOT_RDY
)
134 if (!(CPU_status
&CPU_GEN_BOOT_RDY
)) {
135 netdev_err(dev
, "Firmware boot failed.\n");
136 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail
;
139 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Boot ready!\n");
143 CPUCheckMainCodeOKAndTurnOnCPU_Fail
:
148 static bool _rtl92e_is_fw_ready(struct net_device
*dev
)
151 bool rt_status
= true;
153 unsigned long timeout
;
155 timeout
= jiffies
+ msecs_to_jiffies(20);
156 while (time_before(jiffies
, timeout
)) {
157 CPU_status
= rtl92e_readl(dev
, CPU_GEN
);
158 if (CPU_status
&CPU_GEN_FIRM_RDY
)
163 if (!(CPU_status
&CPU_GEN_FIRM_RDY
))
164 goto CPUCheckFirmwareReady_Fail
;
166 RT_TRACE(COMP_FIRMWARE
, "Download Firmware: Firmware ready!\n");
170 CPUCheckFirmwareReady_Fail
:
176 static bool _rtl92e_fw_check_ready(struct net_device
*dev
,
179 struct r8192_priv
*priv
= rtllib_priv(dev
);
180 struct rt_firmware
*pfirmware
= priv
->pFirmware
;
181 bool rt_status
= true;
183 switch (load_fw_status
) {
184 case FW_INIT_STEP0_BOOT
:
185 pfirmware
->firmware_status
= FW_STATUS_1_MOVE_BOOT_CODE
;
188 case FW_INIT_STEP1_MAIN
:
189 pfirmware
->firmware_status
= FW_STATUS_2_MOVE_MAIN_CODE
;
191 rt_status
= _rtl92e_fw_boot_cpu(dev
);
193 pfirmware
->firmware_status
= FW_STATUS_3_TURNON_CPU
;
195 RT_TRACE(COMP_FIRMWARE
, "_rtl92e_fw_boot_cpu fail!\n");
199 case FW_INIT_STEP2_DATA
:
200 pfirmware
->firmware_status
= FW_STATUS_4_MOVE_DATA_CODE
;
203 rt_status
= _rtl92e_is_fw_ready(dev
);
205 pfirmware
->firmware_status
= FW_STATUS_5_READY
;
207 RT_TRACE(COMP_FIRMWARE
,
208 "_rtl92e_is_fw_ready fail(%d)!\n",
214 RT_TRACE(COMP_FIRMWARE
, "Unknown firmware status");
221 bool rtl92e_init_fw(struct net_device
*dev
)
223 struct r8192_priv
*priv
= rtllib_priv(dev
);
224 bool rt_status
= true;
227 u8
*mapped_file
= NULL
;
229 enum opt_rst_type rst_opt
= OPT_SYSTEM_RESET
;
230 enum firmware_init_step starting_state
= FW_INIT_STEP0_BOOT
;
232 struct rt_firmware
*pfirmware
= priv
->pFirmware
;
234 RT_TRACE(COMP_FIRMWARE
, " PlatformInitFirmware()==>\n");
236 if (pfirmware
->firmware_status
== FW_STATUS_0_INIT
) {
237 rst_opt
= OPT_SYSTEM_RESET
;
238 starting_state
= FW_INIT_STEP0_BOOT
;
240 } else if (pfirmware
->firmware_status
== FW_STATUS_5_READY
) {
241 rst_opt
= OPT_FIRMWARE_RESET
;
242 starting_state
= FW_INIT_STEP2_DATA
;
244 RT_TRACE(COMP_FIRMWARE
,
245 "PlatformInitFirmware: undefined firmware state\n");
248 for (i
= starting_state
; i
<= FW_INIT_STEP2_DATA
; i
++) {
249 if (rst_opt
== OPT_SYSTEM_RESET
) {
250 if (pfirmware
->firmware_buf_size
[i
] == 0) {
251 const char *fw_name
[3] = {
252 RTL8192E_BOOT_IMG_FW
,
253 RTL8192E_MAIN_IMG_FW
,
256 const struct firmware
*fw_entry
;
259 rc
= request_firmware(&fw_entry
,
263 RT_TRACE(COMP_FIRMWARE
,
264 "request firmware fail!\n");
265 goto download_firmware_fail
;
268 sizeof(pfirmware
->firmware_buf
[i
])) {
269 RT_TRACE(COMP_FIRMWARE
,
270 "img file size exceed the container struct buffer fail!\n");
271 release_firmware(fw_entry
);
272 goto download_firmware_fail
;
275 if (i
!= FW_INIT_STEP1_MAIN
) {
276 memcpy(pfirmware
->firmware_buf
[i
],
277 fw_entry
->data
, fw_entry
->size
);
278 pfirmware
->firmware_buf_size
[i
] =
282 memset(pfirmware
->firmware_buf
[i
],
284 memcpy(&pfirmware
->firmware_buf
[i
][128],
285 fw_entry
->data
, fw_entry
->size
);
286 pfirmware
->firmware_buf_size
[i
] =
287 fw_entry
->size
+ 128;
290 if (rst_opt
== OPT_SYSTEM_RESET
)
291 release_firmware(fw_entry
);
295 mapped_file
= pfirmware
->firmware_buf
[i
];
296 file_length
= pfirmware
->firmware_buf_size
[i
];
298 rt_status
= _rtl92e_fw_download_code(dev
, mapped_file
,
301 goto download_firmware_fail
;
303 if (!_rtl92e_fw_check_ready(dev
, i
))
304 goto download_firmware_fail
;
307 RT_TRACE(COMP_FIRMWARE
, "Firmware Download Success\n");
310 download_firmware_fail
:
311 netdev_err(dev
, "%s: Failed to initialize firmware.\n", __func__
);