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