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