upload tizen1.0 source
[kernel/linux-2.6.36.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");