]> Pileus Git - ~andy/linux/blob - drivers/staging/rtl8192e/r819xE_firmware.c
Merge git://git.kernel.org/pub/scm/linux/kernel/git/davem/net-2.6
[~andy/linux] / drivers / staging / rtl8192e / r819xE_firmware.c
1 /*
2  * Procedure: Init boot code/firmware code/data session
3  *
4  * Description: This routine will initialize firmware. If any error occurs
5  *              during the initialization process, the routine shall terminate
6  *              immediately and return fail.
7  */
8
9 #include "r8192E.h"
10 #include "r8192E_hw.h"
11
12 #include <linux/firmware.h>
13
14 /* It should be double word alignment */
15 #define GET_COMMAND_PACKET_FRAG_THRESHOLD(v) (4 * (v / 4) - 8)
16
17 enum firmware_init_step {
18         FW_INIT_STEP0_BOOT = 0,
19         FW_INIT_STEP1_MAIN = 1,
20         FW_INIT_STEP2_DATA = 2,
21 };
22
23 enum opt_rst_type {
24         OPT_SYSTEM_RESET = 0,
25         OPT_FIRMWARE_RESET = 1,
26 };
27
28 void firmware_init_param(struct net_device *dev)
29 {
30         struct r8192_priv *priv = ieee80211_priv(dev);
31         rt_firmware *pfirmware = priv->pFirmware;
32
33         pfirmware->cmdpacket_frag_thresold =
34                 GET_COMMAND_PACKET_FRAG_THRESHOLD(MAX_TRANSMIT_BUFFER_SIZE);
35 }
36
37 /*
38  * segment the img and use the ptr and length to remember info on each segment
39  */
40 static bool fw_download_code(struct net_device *dev, u8 *code_virtual_address,
41                              u32 buffer_len)
42 {
43         struct r8192_priv *priv = ieee80211_priv(dev);
44         bool rt_status = true;
45         u16 frag_threshold;
46         u16 frag_length, frag_offset = 0;
47         int i;
48
49         rt_firmware *pfirmware = priv->pFirmware;
50         struct sk_buff *skb;
51         unsigned char *seg_ptr;
52         cb_desc *tcb_desc;
53         u8 bLastIniPkt;
54
55         firmware_init_param(dev);
56
57         /* Fragmentation might be required */
58         frag_threshold = pfirmware->cmdpacket_frag_thresold;
59         do {
60                 if ((buffer_len - frag_offset) > frag_threshold) {
61                         frag_length = frag_threshold ;
62                         bLastIniPkt = 0;
63                 } else {
64                         frag_length = buffer_len - frag_offset;
65                         bLastIniPkt = 1;
66                 }
67
68                 /*
69                  * Allocate skb buffer to contain firmware info and tx
70                  * descriptor info add 4 to avoid packet appending overflow.
71                  */
72                 skb  = dev_alloc_skb(frag_length + 4);
73                 memcpy((unsigned char *)(skb->cb), &dev, sizeof(dev));
74                 tcb_desc = (cb_desc *)(skb->cb + MAX_DEV_ADDR_SIZE);
75                 tcb_desc->queue_index = TXCMD_QUEUE;
76                 tcb_desc->bCmdOrInit = DESC_PACKET_TYPE_INIT;
77                 tcb_desc->bLastIniPkt = bLastIniPkt;
78
79                 seg_ptr = skb->data;
80
81                 /*
82                  * Transform from little endian to big endian and pending zero
83                  */
84                 for (i = 0; i < frag_length; i += 4) {
85                         *seg_ptr++ = ((i+0) < frag_length) ?
86                                         code_virtual_address[i+3] : 0;
87
88                         *seg_ptr++ = ((i+1) < frag_length) ?
89                                         code_virtual_address[i+2] : 0;
90
91                         *seg_ptr++ = ((i+2) < frag_length) ?
92                                         code_virtual_address[i+1] : 0;
93
94                         *seg_ptr++ = ((i+3) < frag_length) ?
95                                         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  * Check whether main code is download OK. If OK, turn on CPU
111  *
112  * 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 static bool CPUcheck_maincodeok_turnonCPU(struct net_device *dev)
117 {
118         unsigned long timeout;
119         bool rt_status = true;
120         u32 CPU_status = 0;
121
122         /* Check whether put code OK */
123         timeout = jiffies + msecs_to_jiffies(20);
124         while (time_before(jiffies, timeout)) {
125                 CPU_status = read_nic_dword(dev, CPU_GEN);
126
127                 if (CPU_status & CPU_GEN_PUT_CODE_OK)
128                         break;
129                 msleep(2);
130         }
131
132         if (!(CPU_status & CPU_GEN_PUT_CODE_OK)) {
133                 RT_TRACE(COMP_ERR, "Download Firmware: Put code fail!\n");
134                 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
135         } else {
136                 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Put code ok!\n");
137         }
138
139         /* Turn On CPU */
140         CPU_status = read_nic_dword(dev, CPU_GEN);
141         write_nic_byte(dev, CPU_GEN,
142                        (u8)((CPU_status | CPU_GEN_PWR_STB_CPU) & 0xff));
143         mdelay(1);
144
145         /* Check whether CPU boot OK */
146         timeout = jiffies + msecs_to_jiffies(20);
147         while (time_before(jiffies, timeout)) {
148                 CPU_status = read_nic_dword(dev, CPU_GEN);
149
150                 if (CPU_status & CPU_GEN_BOOT_RDY)
151                         break;
152                 msleep(2);
153         }
154
155         if (!(CPU_status & CPU_GEN_BOOT_RDY))
156                 goto CPUCheckMainCodeOKAndTurnOnCPU_Fail;
157         else
158                 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Boot ready!\n");
159
160         return rt_status;
161
162 CPUCheckMainCodeOKAndTurnOnCPU_Fail:
163         RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
164         rt_status = FALSE;
165         return rt_status;
166 }
167
168 static bool CPUcheck_firmware_ready(struct net_device *dev)
169 {
170         unsigned long timeout;
171         bool rt_status = true;
172         u32 CPU_status = 0;
173
174         /* Check Firmware Ready */
175         timeout = jiffies + msecs_to_jiffies(20);
176         while (time_before(jiffies, timeout)) {
177                 CPU_status = read_nic_dword(dev, CPU_GEN);
178
179                 if (CPU_status & CPU_GEN_FIRM_RDY)
180                         break;
181                 msleep(2);
182         }
183
184         if (!(CPU_status & CPU_GEN_FIRM_RDY))
185                 goto CPUCheckFirmwareReady_Fail;
186         else
187                 RT_TRACE(COMP_FIRMWARE, "Download Firmware: Firmware ready!\n");
188
189         return rt_status;
190
191 CPUCheckFirmwareReady_Fail:
192         RT_TRACE(COMP_ERR, "ERR in %s()\n", __func__);
193         rt_status = false;
194         return rt_status;
195
196 }
197
198 bool init_firmware(struct net_device *dev)
199 {
200         struct r8192_priv *priv = ieee80211_priv(dev);
201         bool rt_status = true;
202         u32 file_length = 0;
203         u8 *mapped_file = NULL;
204         u32 init_step = 0;
205         enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
206         enum firmware_init_step starting_state = FW_INIT_STEP0_BOOT;
207
208         rt_firmware *pfirmware = priv->pFirmware;
209         const struct firmware *fw_entry;
210         const char *fw_name[3] = { "RTL8192E/boot.img",
211                                    "RTL8192E/main.img",
212                                    "RTL8192E/data.img"};
213         int rc;
214
215         RT_TRACE(COMP_FIRMWARE, " PlatformInitFirmware()==>\n");
216
217         if (pfirmware->firmware_status == FW_STATUS_0_INIT) {
218                 /* it is called by reset */
219                 rst_opt = OPT_SYSTEM_RESET;
220                 starting_state = FW_INIT_STEP0_BOOT;
221                 /* TODO: system reset */
222
223         } else if (pfirmware->firmware_status == FW_STATUS_5_READY) {
224                 /* it is called by Initialize */
225                 rst_opt = OPT_FIRMWARE_RESET;
226                 starting_state = FW_INIT_STEP2_DATA;
227         } else {
228                 RT_TRACE(COMP_FIRMWARE,
229                         "PlatformInitFirmware: undefined firmware state\n");
230         }
231
232         /*
233          * Download boot, main, and data image for System reset.
234          * Download data image for firmware reseta
235          */
236         for (init_step = starting_state; init_step <= FW_INIT_STEP2_DATA;
237                         init_step++) {
238                 /*
239                  * Open Image file, and map file to contineous memory if open file success.
240                  * or read image file from array. Default load from IMG file
241                  */
242                 if (rst_opt == OPT_SYSTEM_RESET) {
243                         if (pfirmware->firmware_buf_size[init_step] == 0) {
244                                 rc = request_firmware(&fw_entry,
245                                         fw_name[init_step], &priv->pdev->dev);
246
247                                 if (rc < 0) {
248                                         RT_TRACE(COMP_FIRMWARE, "request firmware fail!\n");
249                                         goto download_firmware_fail;
250                                 }
251
252                                 if (fw_entry->size > sizeof(pfirmware->firmware_buf[init_step])) {
253                                         RT_TRACE(COMP_FIRMWARE,
254                                                 "img file size exceed the container buffer fail!\n");
255                                         goto download_firmware_fail;
256                                 }
257
258                                 if (init_step != FW_INIT_STEP1_MAIN) {
259                                         memcpy(pfirmware->firmware_buf[init_step],
260                                                         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,
266                                                                         fw_entry->size);
267                                         pfirmware->firmware_buf_size[init_step] = fw_entry->size+128;
268                                 }
269
270                                 if (rst_opt == OPT_SYSTEM_RESET)
271                                         release_firmware(fw_entry);
272                         }
273                         mapped_file = pfirmware->firmware_buf[init_step];
274                         file_length = pfirmware->firmware_buf_size[init_step];
275
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
353 MODULE_FIRMWARE("RTL8192E/boot.img");
354 MODULE_FIRMWARE("RTL8192E/main.img");
355 MODULE_FIRMWARE("RTL8192E/data.img");