dab67c12ccc2807802efe17669c63549e7b2bba6
[deliverable/linux.git] / drivers / staging / rtl8192e / rtl8192e / r8192E_firmware.c
1 /******************************************************************************
2 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3 *
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
7 * more details.
8 *
9 * The full GNU General Public License is included in this distribution in the
10 * file called LICENSE.
11 *
12 * Contact Information:
13 * wlanfae <wlanfae@realtek.com>
14 ******************************************************************************/
15
16 #include "rtl_core.h"
17 #include "r8192E_hw.h"
18 #include "r8192E_hwimg.h"
19 #include "r8192E_firmware.h"
20 #include <linux/firmware.h>
21
22 void rtl92e_init_fw_param(struct net_device *dev)
23 {
24 struct r8192_priv *priv = rtllib_priv(dev);
25 struct rt_firmware *pfirmware = priv->pFirmware;
26
27 pfirmware->cmdpacket_frag_thresold = GET_COMMAND_PACKET_FRAG_THRESHOLD(
28 MAX_TRANSMIT_BUFFER_SIZE);
29 }
30
31 static bool _rtl92e_fw_download_code(struct net_device *dev,
32 u8 *code_virtual_address, u32 buffer_len)
33 {
34 struct r8192_priv *priv = rtllib_priv(dev);
35 u16 frag_threshold;
36 u16 frag_length, frag_offset = 0;
37 int i;
38
39 struct rt_firmware *pfirmware = priv->pFirmware;
40 struct sk_buff *skb;
41 unsigned char *seg_ptr;
42 struct cb_desc *tcb_desc;
43 u8 bLastIniPkt;
44
45 rtl92e_init_fw_param(dev);
46 frag_threshold = pfirmware->cmdpacket_frag_thresold;
47 do {
48 if ((buffer_len - frag_offset) > frag_threshold) {
49 frag_length = frag_threshold;
50 bLastIniPkt = 0;
51
52 } else {
53 frag_length = buffer_len - frag_offset;
54 bLastIniPkt = 1;
55
56 }
57
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;
64
65 seg_ptr = skb->data;
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;
75 }
76 tcb_desc->txbuf_size = (u16)i;
77 skb_put(skb, i);
78
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);
86 } else {
87 priv->rtllib->softmac_hard_start_xmit(skb, dev);
88 }
89
90 code_virtual_address += frag_length;
91 frag_offset += frag_length;
92
93 } while (frag_offset < buffer_len);
94
95 rtl92e_writeb(dev, TPPoll, TPPoll_CQ);
96
97 return true;
98 }
99
100 static bool _rtl92e_fw_boot_cpu(struct net_device *dev)
101 {
102 bool rt_status = true;
103 u32 CPU_status = 0;
104 unsigned long timeout;
105
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)
110 break;
111 mdelay(2);
112 }
113
114 if (!(CPU_status&CPU_GEN_PUT_CODE_OK)) {
115 netdev_err(dev, "Firmware download failed.\n");
116 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
117 } else {
118 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
119 }
120
121 CPU_status = rtl92e_readl(dev, CPU_GEN);
122 rtl92e_writeb(dev, CPU_GEN,
123 (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
124 mdelay(1);
125
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)
130 break;
131 mdelay(2);
132 }
133
134 if (!(CPU_status&CPU_GEN_BOOT_RDY)) {
135 netdev_err(dev, "Firmware boot failed.\n");
136 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
137 }
138
139 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
140
141 return rt_status;
142
143 CPUCheckMainCodeOKAndTurnOnCPU_Fail:
144 rt_status = false;
145 return rt_status;
146 }
147
148 static bool _rtl92e_is_fw_ready(struct net_device *dev)
149 {
150
151 bool rt_status = true;
152 u32 CPU_status = 0;
153 unsigned long timeout;
154
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)
159 break;
160 mdelay(2);
161 }
162
163 if (!(CPU_status&CPU_GEN_FIRM_RDY))
164 goto CPUCheckFirmwareReady_Fail;
165 else
166 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
167
168 return rt_status;
169
170 CPUCheckFirmwareReady_Fail:
171 rt_status = false;
172 return rt_status;
173
174 }
175
176 static bool _rtl92e_fw_check_ready(struct net_device *dev,
177 u8 load_fw_status)
178 {
179 struct r8192_priv *priv = rtllib_priv(dev);
180 struct rt_firmware *pfirmware = priv->pFirmware;
181 bool rt_status = true;
182
183 switch (load_fw_status) {
184 case FW_INIT_STEP0_BOOT:
185 pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
186 break;
187
188 case FW_INIT_STEP1_MAIN:
189 pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE;
190
191 rt_status = _rtl92e_fw_boot_cpu(dev);
192 if (rt_status)
193 pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU;
194 else
195 RT_TRACE(COMP_FIRMWARE, "_rtl92e_fw_boot_cpu fail!\n");
196
197 break;
198
199 case FW_INIT_STEP2_DATA:
200 pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
201 mdelay(1);
202
203 rt_status = _rtl92e_is_fw_ready(dev);
204 if (rt_status)
205 pfirmware->firmware_status = FW_STATUS_5_READY;
206 else
207 RT_TRACE(COMP_FIRMWARE,
208 "_rtl92e_is_fw_ready fail(%d)!\n",
209 rt_status);
210
211 break;
212 default:
213 rt_status = false;
214 RT_TRACE(COMP_FIRMWARE, "Unknown firmware status");
215 break;
216 }
217
218 return rt_status;
219 }
220
221 bool rtl92e_init_fw(struct net_device *dev)
222 {
223 struct r8192_priv *priv = rtllib_priv(dev);
224 bool rt_status = true;
225
226 u32 file_length = 0;
227 u8 *mapped_file = NULL;
228 u8 i = 0;
229 enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
230 enum firmware_init_step starting_state = FW_INIT_STEP0_BOOT;
231
232 struct rt_firmware *pfirmware = priv->pFirmware;
233
234 RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n");
235
236 if (pfirmware->firmware_status == FW_STATUS_0_INIT) {
237 rst_opt = OPT_SYSTEM_RESET;
238 starting_state = FW_INIT_STEP0_BOOT;
239
240 } else if (pfirmware->firmware_status == FW_STATUS_5_READY) {
241 rst_opt = OPT_FIRMWARE_RESET;
242 starting_state = FW_INIT_STEP2_DATA;
243 } else {
244 RT_TRACE(COMP_FIRMWARE,
245 "PlatformInitFirmware: undefined firmware state\n");
246 }
247
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,
254 RTL8192E_DATA_IMG_FW
255 };
256 const struct firmware *fw_entry;
257 int rc;
258
259 rc = request_firmware(&fw_entry,
260 fw_name[i],
261 &priv->pdev->dev);
262 if (rc < 0) {
263 RT_TRACE(COMP_FIRMWARE,
264 "request firmware fail!\n");
265 goto download_firmware_fail;
266 }
267 if (fw_entry->size >
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;
273 }
274
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] =
279 fw_entry->size;
280
281 } else {
282 memset(pfirmware->firmware_buf[i],
283 0, 128);
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;
288 }
289
290 if (rst_opt == OPT_SYSTEM_RESET)
291 release_firmware(fw_entry);
292 }
293 }
294
295 mapped_file = pfirmware->firmware_buf[i];
296 file_length = pfirmware->firmware_buf_size[i];
297
298 rt_status = _rtl92e_fw_download_code(dev, mapped_file,
299 file_length);
300 if (!rt_status)
301 goto download_firmware_fail;
302
303 if (!_rtl92e_fw_check_ready(dev, i))
304 goto download_firmware_fail;
305 }
306
307 RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
308 return rt_status;
309
310 download_firmware_fail:
311 netdev_err(dev, "%s: Failed to initialize firmware.\n", __func__);
312 rt_status = false;
313 return rt_status;
314
315 }
This page took 0.036241 seconds and 4 git commands to generate.