Merge branch 'for-linus' of git://git.kernel.org/pub/scm/linux/kernel/git/bp/bp
[sfrench/cifs-2.6.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         unsigned long timeout;
126         bool rt_status = true;
127         u32 CPU_status = 0;
128
129         /* Check whether put code OK */
130         timeout = jiffies + msecs_to_jiffies(20);
131         while (time_before(jiffies, timeout)) {
132                 CPU_status = read_nic_dword(dev, CPU_GEN);
133
134                 if (CPU_status & CPU_GEN_PUT_CODE_OK)
135                         break;
136                 msleep(2);
137         }
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         timeout = jiffies + msecs_to_jiffies(20);
154         while (time_before(jiffies, timeout)) {
155                 CPU_status = read_nic_dword(dev, CPU_GEN);
156
157                 if (CPU_status & CPU_GEN_BOOT_RDY)
158                         break;
159                 msleep(2);
160         }
161
162         if (!(CPU_status & CPU_GEN_BOOT_RDY))
163                 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
164         else
165                 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
166
167         return rt_status;
168
169 CPUCheckMainCodeOKAndTurnOnCPU_Fail:
170         RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
171         rt_status = FALSE;
172         return rt_status;
173 }
174
175 static bool CPUcheck_firmware_ready(struct net_device *dev)
176 {
177         unsigned long timeout;
178         bool rt_status = true;
179         u32 CPU_status = 0;
180
181         /* Check Firmware Ready */
182         timeout = jiffies + msecs_to_jiffies(20);
183         while (time_before(jiffies, timeout)) {
184                 CPU_status = read_nic_dword(dev, CPU_GEN);
185
186                 if (CPU_status & CPU_GEN_FIRM_RDY)
187                         break;
188                 msleep(2);
189         }
190
191         if (!(CPU_status & CPU_GEN_FIRM_RDY))
192                 goto CPUCheckFirmwareReady_Fail;
193         else
194                 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
195
196         return rt_status;
197
198 CPUCheckFirmwareReady_Fail:
199         RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
200         rt_status = false;
201         return rt_status;
202
203 }
204
205 bool init_firmware(struct net_device *dev)
206 {
207         struct r8192_priv       *priv = ieee80211_priv(dev);
208         bool                    rt_status = TRUE;
209         u32                     file_length = 0;
210         u8                      *mapped_file = NULL;
211         u32                     init_step = 0;
212         enum opt_rst_type       rst_opt = OPT_SYSTEM_RESET;
213         enum firmware_init_step starting_state = FW_INIT_STEP0_BOOT;
214
215         rt_firmware             *pfirmware = priv->pFirmware;
216         const struct firmware   *fw_entry;
217         const char *fw_name[3] = { "RTL8192E/boot.img",
218                                    "RTL8192E/main.img",
219                                    "RTL8192E/data.img"};
220         int rc;
221
222         RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n");
223
224         if (pfirmware->firmware_status == FW_STATUS_0_INIT) {
225                 /* it is called by reset */
226                 rst_opt = OPT_SYSTEM_RESET;
227                 starting_state = FW_INIT_STEP0_BOOT;
228                 /* TODO: system reset */
229
230         } else if (pfirmware->firmware_status == FW_STATUS_5_READY) {
231                 /* it is called by Initialize */
232                 rst_opt = OPT_FIRMWARE_RESET;
233                 starting_state = FW_INIT_STEP2_DATA;
234         } else {
235                 RT_TRACE(COMP_FIRMWARE,
236                         "PlatformInitFirmware: undefined firmware state\n");
237         }
238
239         /*
240          * Download boot, main, and data image for System reset.
241          * Download data image for firmware reseta
242          */
243         for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA; init_step++) {
244                 /*
245                  * Open Image file, and map file to contineous memory if open file success.
246                  * or read image file from array. Default load from IMG file
247                  */
248                 if (rst_opt == OPT_SYSTEM_RESET) {
249                         if (pfirmware->firmware_buf_size[init_step] == 0) {
250                                 rc = request_firmware(&fw_entry, fw_name[init_step], &priv->pdev->dev);
251                                 if (rc < 0) {
252                                         RT_TRACE(COMP_FIRMWARE, "request firmware fail!\n");
253                                         goto download_firmware_fail;
254                                 }
255
256                                 if (fw_entry->size > sizeof(pfirmware->firmware_buf[init_step])) {
257                                         RT_TRACE(COMP_FIRMWARE, "img file size exceed the container buffer fail!\n");
258                                         goto download_firmware_fail;
259                                 }
260
261                                 if (init_step != FW_INIT_STEP1_MAIN) {
262                                         memcpy(pfirmware->firmware_buf[init_step], fw_entry->data, fw_entry->size);
263                                         pfirmware->firmware_buf_size[init_step] = fw_entry->size;
264
265                                 } else {
266                                         memset(pfirmware->firmware_buf[init_step], 0, 128);
267                                         memcpy(&pfirmware->firmware_buf[init_step][128], fw_entry->data, fw_entry->size);
268                                         pfirmware->firmware_buf_size[init_step] = fw_entry->size+128;
269                                 }
270
271                                 if (rst_opt == OPT_SYSTEM_RESET)
272                                         release_firmware(fw_entry);
273                         }
274                         mapped_file = pfirmware->firmware_buf[init_step];
275                         file_length = pfirmware->firmware_buf_size[init_step];
276                 } else if (rst_opt == OPT_FIRMWARE_RESET) {
277                         /* we only need to download data.img here */
278                         mapped_file = pfirmware->firmware_buf[init_step];
279                         file_length = pfirmware->firmware_buf_size[init_step];
280                 }
281
282                 /* Download image file */
283                 /* The firmware download process is just as following,
284                  * 1. that is each packet will be segmented and inserted to the
285                  *    wait queue.
286                  * 2. each packet segment will be put in the skb_buff packet.
287                  * 3. each skb_buff packet data content will already include
288                  *    the firmware info and Tx descriptor info
289                  */
290                 rt_status = fw_download_code(dev, mapped_file, file_length);
291                 if (rt_status != TRUE)
292                         goto download_firmware_fail;
293
294                 switch (init_step) {
295                 case FW_INIT_STEP0_BOOT:
296                         /* Download boot
297                          * initialize command descriptor.
298                          * will set polling bit when firmware code is also
299                          * configured
300                          */
301                         pfirmware->firmware_status = FW_STATUS_1_MOVE_BOOT_CODE;
302                         /* mdelay(1000); */
303                         /*
304                          * To initialize IMEM, CPU move code  from 0x80000080,
305                          * hence, we send 0x80 byte packet
306                          */
307                         break;
308
309                 case FW_INIT_STEP1_MAIN:
310                         /* Download firmware code.
311                          * Wait until Boot Ready and Turn on CPU */
312                         pfirmware->firmware_status = FW_STATUS_2_MOVE_MAIN_CODE;
313
314                         /* Check Put Code OK and Turn On CPU */
315                         rt_status = CPUcheck_maincodeok_turnonCPU(dev);
316                         if (rt_status != TRUE) {
317                                 RT_TRACE(COMP_FIRMWARE,
318                                         "CPUcheck_maincodeok_turnonCPU fail!\n");
319                                 goto download_firmware_fail;
320                         }
321
322                         pfirmware->firmware_status = FW_STATUS_3_TURNON_CPU;
323                         break;
324
325                 case FW_INIT_STEP2_DATA:
326                         /* download initial data code */
327                         pfirmware->firmware_status = FW_STATUS_4_MOVE_DATA_CODE;
328                         mdelay(1);
329
330                         rt_status = CPUcheck_firmware_ready(dev);
331                         if (rt_status != TRUE) {
332                                 RT_TRACE(COMP_FIRMWARE,
333                                         "CPUcheck_firmware_ready fail(%d)!\n",
334                                         rt_status);
335                                 goto download_firmware_fail;
336                         }
337
338                         /* wait until data code is initialized ready.*/
339                         pfirmware->firmware_status = FW_STATUS_5_READY;
340                         break;
341                 }
342         }
343
344         RT_TRACE(COMP_FIRMWARE, "Firmware Download Success\n");
345         return rt_status;
346
347 download_firmware_fail:
348         RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
349         rt_status = FALSE;
350         return rt_status;
351
352 }