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