Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/sparc-2.6
[GitHub/mt8127/android_kernel_alcatel_ttab.git] / drivers / staging / rtl8192e / r819xE_firmware.c
1 /*
2 * Procedure: Init boot code/firmware code/data session
3 *
4 * Description: This routine will intialize firmware. If any error occurs
5 * during the initialization process, the routine shall terminate
6 * immediately and return fail. NIC driver should call
7 * NdisOpenFile only from MiniportInitialize.
8 *
9 * Arguments: The pointer of the adapter
10 *
11 * Returns:
12 * NDIS_STATUS_FAILURE - the following initialization process
13 * should be terminated
14 * NDIS_STATUS_SUCCESS - if firmware initialization process
15 * success
16 */
17
18 #include "r8192E.h"
19 #include "r8192E_hw.h"
20
21 #include <linux/firmware.h>
22
23 /* It should be double word alignment */
24 #define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4 * (v / 4) - 8)
25
26 enum firmware_init_step {
27 FW_INIT_STEP0_BOOT = 0,
28 FW_INIT_STEP1_MAIN = 1,
29 FW_INIT_STEP2_DATA = 2,
30 };
31
32 enum opt_rst_type {
33 OPT_SYSTEM_RESET = 0,
34 OPT_FIRMWARE_RESET = 1,
35 };
36
37 void firmware_init_param(struct net_device *dev)
38 {
39 struct r8192_priv *priv = ieee80211_priv(dev);
40 rt_firmware *pfirmware = priv->pFirmware;
41
42 pfirmware->cmdpacket_frag_thresold =
43 GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE);
44 }
45
46 /*
47 * segment the img and use the ptr and length to remember info on each segment
48 */
49 static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
50 u32 buffer_len)
51 {
52 struct r8192_priv *priv = ieee80211_priv(dev);
53 bool rt_status = true;
54 u16 frag_threshold;
55 u16 frag_length, frag_offset = 0;
56 int i;
57
58 rt_firmware *pfirmware = priv->pFirmware;
59 struct sk_buff *skb;
60 unsigned char *seg_ptr;
61 cb_desc *tcb_desc;
62 u8 bLastIniPkt;
63
64 firmware_init_param(dev);
65
66 /* Fragmentation might be required */
67 frag_threshold = pfirmware->cmdpacket_frag_thresold;
68 do {
69 if ((buffer_len - frag_offset) > frag_threshold) {
70 frag_length = frag_threshold ;
71 bLastIniPkt = 0;
72 } else {
73 frag_length = buffer_len - frag_offset;
74 bLastIniPkt = 1;
75 }
76
77 /*
78 * Allocate skb buffer to contain firmware info and tx
79 * descriptor info add 4 to avoid packet appending overflow.
80 */
81 skb = dev_alloc_skb(frag_length + 4);
82 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
83 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
84 tcb_desc->queue_index = TXCMD_QUEUE;
85 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
86 tcb_desc->bLastIniPkt = bLastIniPkt;
87
88 seg_ptr = skb->data;
89
90 /*
91 * Transform from little endian to big endian and pending zero
92 */
93 for (i = 0; i < frag_length; i += 4) {
94 *seg_ptr++ = ((i+0) < frag_length) ? \
95 code_virtual_address[i+3] : 0;
96
97 *seg_ptr++ = ((i+1) < frag_length) ? \
98 code_virtual_address[i+2] : 0;
99
100 *seg_ptr++ = ((i+2) < frag_length) ? \
101 code_virtual_address[i+1] : 0;
102
103 *seg_ptr++ = ((i+3) < frag_length) ? \
104 code_virtual_address[i+0] : 0;
105 }
106 tcb_desc->txbuf_size = (u16)i;
107 skb_put(skb, i);
108 priv->ieee80211->softmac_hard_start_xmit(skb, dev);
109
110 code_virtual_address += frag_length;
111 frag_offset += frag_length;
112
113 } while (frag_offset < buffer_len);
114
115 return rt_status;
116 }
117
118 /*
119 * Procedure: Check whether main code is download OK. If OK, turn on CPU
120 *
121 * Description: CPU register locates in different page against general
122 * register. Switch to CPU register in the begin and switch
123 * back before return
124 *
125 * Arguments: The pointer of the adapter
126 *
127 * Returns:
128 * NDIS_STATUS_FAILURE - the following initialization process should be
129 * terminated
130 * NDIS_STATUS_SUCCESS - if firmware initialization process success
131 */
132 static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
133 {
134 unsigned long timeout;
135 bool rt_status = true;
136 u32 CPU_status = 0;
137
138 /* Check whether put code OK */
139 timeout = jiffies + msecs_to_jiffies(20);
140 while (time_before(jiffies, timeout)) {
141 CPU_status = read_nic_dword(dev, CPU_GEN);
142
143 if (CPU_status & CPU_GEN_PUT_CODE_OK)
144 break;
145 msleep(2);
146 }
147
148 if (!(CPU_status & CPU_GEN_PUT_CODE_OK)) {
149 RT_TRACE(COMP_ERR, "Download Firmware: Put code fail!\n");
150 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
151 } else {
152 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
153 }
154
155 /* Turn On CPU */
156 CPU_status = read_nic_dword(dev, CPU_GEN);
157 write_nic_byte(dev, CPU_GEN,
158 (u8)((CPU_status | CPU_GEN_PWR_STB_CPU) & 0xff));
159 mdelay(1);
160
161 /* Check whether CPU boot OK */
162 timeout = jiffies + msecs_to_jiffies(20);
163 while (time_before(jiffies, timeout)) {
164 CPU_status = read_nic_dword(dev, CPU_GEN);
165
166 if (CPU_status & CPU_GEN_BOOT_RDY)
167 break;
168 msleep(2);
169 }
170
171 if (!(CPU_status & CPU_GEN_BOOT_RDY))
172 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
173 else
174 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
175
176 return rt_status;
177
178 CPUCheckMainCodeOKAndTurnOnCPU_Fail:
179 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
180 rt_status = FALSE;
181 return rt_status;
182 }
183
184 static bool CPUcheck_firmware_ready(struct net_device *dev)
185 {
186 unsigned long timeout;
187 bool rt_status = true;
188 u32 CPU_status = 0;
189
190 /* Check Firmware Ready */
191 timeout = jiffies + msecs_to_jiffies(20);
192 while (time_before(jiffies, timeout)) {
193 CPU_status = read_nic_dword(dev, CPU_GEN);
194
195 if (CPU_status & CPU_GEN_FIRM_RDY)
196 break;
197 msleep(2);
198 }
199
200 if (!(CPU_status & CPU_GEN_FIRM_RDY))
201 goto CPUCheckFirmwareReady_Fail;
202 else
203 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
204
205 return rt_status;
206
207 CPUCheckFirmwareReady_Fail:
208 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
209 rt_status = false;
210 return rt_status;
211
212 }
213
214 bool init_firmware(struct net_device *dev)
215 {
216 struct r8192_priv *priv = ieee80211_priv(dev);
217 bool rt_status = true;
218 u32 file_length = 0;
219 u8 *mapped_file = NULL;
220 u32 init_step = 0;
221 enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
222 enum firmware_init_step starting_state = FW_INIT_STEP0_BOOT;
223
224 rt_firmware *pfirmware = priv->pFirmware;
225 const struct firmware *fw_entry;
226 const char *fw_name[3] = { "RTL8192E/boot.img",
227 "RTL8192E/main.img",
228 "RTL8192E/data.img"};
229 int rc;
230
231 RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n");
232
233 if (pfirmware->firmware_status == FW_STATUS_0_INIT) {
234 /* it is called by reset */
235 rst_opt = OPT_SYSTEM_RESET;
236 starting_state = FW_INIT_STEP0_BOOT;
237 /* TODO: system reset */
238
239 } else if (pfirmware->firmware_status == FW_STATUS_5_READY) {
240 /* it is called by Initialize */
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 /*
249 * Download boot, main, and data image for System reset.
250 * Download data image for firmware reseta
251 */
252 for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; \
253 init_step++) {
254 /*
255 * Open Image file, and map file to contineous memory if open file success.
256 * or read image file from array. Default load from IMG file
257 */
258 if (rst_opt == OPT_SYSTEM_RESET) {
259 if (pfirmware->firmware_buf_size[init_step] == 0) {
260 rc = request_firmware(&fw_entry,
261 fw_name[init_step], &priv->pdev->dev);
262
263 if (rc < 0) {
264 RT_TRACE(COMP_FIRMWARE, "request firmware fail!\n");
265 goto download_firmware_fail;
266 }
267
268 if (fw_entry->size > sizeof(pfirmware->firmware_buf[init_step])) {
269 RT_TRACE(COMP_FIRMWARE, \
270 "img file size exceed the container buffer fail!\n");
271 goto download_firmware_fail;
272 }
273
274 if (init_step != FW_INIT_STEP1_MAIN) {
275 memcpy(pfirmware->firmware_buf[init_step],
276 fw_entry->data, fw_entry->size);
277 pfirmware->firmware_buf_size[init_step] = fw_entry->size;
278
279 } else {
280 memset(pfirmware->firmware_buf[init_step], 0, 128);
281 memcpy(&pfirmware->firmware_buf[init_step][128], fw_entry->data,
282 fw_entry->size);
283 pfirmware->firmware_buf_size[init_step] = fw_entry->size+128;
284 }
285
286 if (rst_opt == OPT_SYSTEM_RESET)
287 release_firmware(fw_entry);
288 }
289 mapped_file = pfirmware->firmware_buf[init_step];
290 file_length = pfirmware->firmware_buf_size[init_step];
291
292 } else if (rst_opt == OPT_FIRMWARE_RESET) {
293 /* we only need to download data.img here */
294 mapped_file = pfirmware->firmware_buf[init_step];
295 file_length = pfirmware->firmware_buf_size[init_step];
296 }
297
298 /* Download image file */
299 /* The firmware download process is just as following,
300 * 1. that is each packet will be segmented and inserted to the
301 * wait queue.
302 * 2. each packet segment will be put in the skb_buff packet.
303 * 3. each skb_buff packet data content will already include
304 * the firmware info and Tx descriptor info
305 */
306 rt_status = fw_download_code(dev, mapped_file, file_length);
307 if (rt_status != TRUE)
308 goto download_firmware_fail;
309
310 switch (init_step) {
311 case FW_INIT_STEP0_BOOT:
312 /* Download boot
313 * initialize command descriptor.
314 * will set polling bit when firmware code is also
315 * configured
316 */
317 pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
318 /* mdelay(1000); */
319 /*
320 * To initialize IMEM, CPU move code from 0x80000080,
321 * hence, we send 0x80 byte packet
322 */
323 break;
324
325 case FW_INIT_STEP1_MAIN:
326 /* Download firmware code.
327 * Wait until Boot Ready and Turn on CPU */
328 pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE;
329
330 /* Check Put Code OK and Turn On CPU */
331 rt_status = CPUcheck_maincodeok_turnonCPU(dev);
332 if (rt_status != TRUE) {
333 RT_TRACE(COMP_FIRMWARE,
334 "CPUcheck_maincodeok_turnonCPU fail!\n");
335 goto download_firmware_fail;
336 }
337
338 pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU;
339 break;
340
341 case FW_INIT_STEP2_DATA:
342 /* download initial data code */
343 pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
344 mdelay(1);
345
346 rt_status = CPUcheck_firmware_ready(dev);
347 if (rt_status != TRUE) {
348 RT_TRACE(COMP_FIRMWARE,
349 "CPUcheck_firmware_ready fail(%d)!\n",
350 rt_status);
351 goto download_firmware_fail;
352 }
353
354 /* wait until data code is initialized ready.*/
355 pfirmware->firmware_status = FW_STATUS_5_READY;
356 break;
357 }
358 }
359
360 RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
361 return rt_status;
362
363 download_firmware_fail:
364 RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
365 rt_status = false;
366 return rt_status;
367 }
368
369 MODULE_FIRMWARE("RTL8192E/boot.img");
370 MODULE_FIRMWARE("RTL8192E/main.img");
371 MODULE_FIRMWARE("RTL8192E/data.img");