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