These changes are the raw update to linux-4.4.6-rt14. Kernel sources
[kvmfornfv.git] / kernel / drivers / staging / rtl8192e / rtl8192e / r8192E_firmware.c
1 /******************************************************************************
2  * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
3  *
4  * This program is distributed in the hope that it will be useful, but WITHOUT
5  * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
6  * FITNESS FOR A PARTICULAR PURPOSE.  See the GNU General Public License for
7  * more details.
8  *
9  * The full GNU General Public License is included in this distribution in the
10  * file called LICENSE.
11  *
12  * Contact Information:
13  * wlanfae <wlanfae@realtek.com>
14 ******************************************************************************/
15
16 #include "rtl_core.h"
17 #include "r8192E_hw.h"
18 #include "r8192E_hwimg.h"
19 #include "r8192E_firmware.h"
20 #include "r8192E_cmdpkt.h"
21 #include <linux/firmware.h>
22
23 static bool _rtl92e_wait_for_fw(struct net_device *dev, u32 mask, u32 timeout)
24 {
25         unsigned long deadline = jiffies + msecs_to_jiffies(timeout);
26
27         while (time_before(jiffies, deadline)) {
28                 if (rtl92e_readl(dev, CPU_GEN) & mask)
29                         return true;
30                 mdelay(2);
31         }
32         return false;
33 }
34
35 static bool _rtl92e_fw_boot_cpu(struct net_device *dev)
36 {
37         u32             CPU_status = 0;
38
39         if (!_rtl92e_wait_for_fw(dev, CPU_GEN_PUT_CODE_OK, 200)) {
40                 netdev_err(dev, "Firmware download failed.\n");
41                 return false;
42         }
43         netdev_dbg(dev, "Download Firmware: Put code ok!\n");
44
45         CPU_status = rtl92e_readl(dev, CPU_GEN);
46         rtl92e_writeb(dev, CPU_GEN,
47                       (u8)((CPU_status|CPU_GEN_PWR_STB_CPU)&0xff));
48         mdelay(1);
49
50         if (!_rtl92e_wait_for_fw(dev, CPU_GEN_BOOT_RDY, 200)) {
51                 netdev_err(dev, "Firmware boot failed.\n");
52                 return false;
53         }
54
55         netdev_dbg(dev, "Download Firmware: Boot ready!\n");
56
57         return true;
58 }
59
60 static bool _rtl92e_fw_check_ready(struct net_device *dev,
61                                    u8 load_fw_status)
62 {
63         struct r8192_priv *priv = rtllib_priv(dev);
64         struct rt_firmware *pfirmware = priv->pFirmware;
65         bool rt_status  = true;
66
67         switch (load_fw_status) {
68         case FW_INIT_STEP0_BOOT:
69                 pfirmware->status = FW_STATUS_1_MOVE_BOOT_CODE;
70                 break;
71
72         case FW_INIT_STEP1_MAIN:
73                 pfirmware->status = FW_STATUS_2_MOVE_MAIN_CODE;
74
75                 rt_status = _rtl92e_fw_boot_cpu(dev);
76                 if (rt_status)
77                         pfirmware->status = FW_STATUS_3_TURNON_CPU;
78                 else
79                         netdev_dbg(dev, "_rtl92e_fw_boot_cpu fail!\n");
80
81                 break;
82
83         case FW_INIT_STEP2_DATA:
84                 pfirmware->status = FW_STATUS_4_MOVE_DATA_CODE;
85                 mdelay(1);
86
87                 rt_status = _rtl92e_wait_for_fw(dev, CPU_GEN_FIRM_RDY, 20);
88                 if (rt_status)
89                         pfirmware->status = FW_STATUS_5_READY;
90                 else
91                         RT_TRACE(COMP_FIRMWARE,
92                                  "_rtl92e_is_fw_ready fail(%d)!\n",
93                                  rt_status);
94                 break;
95         default:
96                 rt_status = false;
97                 netdev_dbg(dev, "Unknown firmware status");
98                 break;
99         }
100
101         return rt_status;
102 }
103
104 static bool _rtl92e_fw_prepare(struct net_device *dev, struct rt_fw_blob *blob,
105                                const char *name, u8 padding)
106 {
107         const struct firmware *fw;
108         int rc, i;
109         bool ret = true;
110
111         rc = request_firmware(&fw, name, &dev->dev);
112         if (rc < 0)
113                 return false;
114
115         if (round_up(fw->size, 4) > MAX_FW_SIZE - padding) {
116                 netdev_err(dev, "Firmware image %s too big for the device.\n",
117                            name);
118                 ret = false;
119                 goto out;
120         }
121
122         if (padding)
123                 memset(blob->data, 0, padding);
124         if (fw->size % 4)
125                 memset(blob->data + padding + fw->size, 0, 4);
126         memcpy(blob->data + padding, fw->data, fw->size);
127
128         blob->size = round_up(fw->size, 4) + padding;
129
130         /* Swap endian - firmware is packaged in invalid endiannes*/
131         for (i = padding; i < blob->size; i += 4) {
132                 u32 *data = (u32 *)(blob->data + i);
133                 *data = swab32p(data);
134         }
135 out:
136         release_firmware(fw);
137         return ret;
138 }
139
140 bool rtl92e_init_fw(struct net_device *dev)
141 {
142         struct r8192_priv *priv = rtllib_priv(dev);
143         bool                    rt_status = true;
144
145         u32     file_length = 0;
146         u8      *mapped_file = NULL;
147         u8      i = 0;
148         enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
149         enum firmware_init_step starting_state = FW_INIT_STEP0_BOOT;
150
151         struct rt_firmware *pfirmware = priv->pFirmware;
152
153         netdev_dbg(dev, " PlatformInitFirmware()==>\n");
154
155         if (pfirmware->status == FW_STATUS_0_INIT) {
156                 rst_opt = OPT_SYSTEM_RESET;
157                 starting_state = FW_INIT_STEP0_BOOT;
158
159         } else if (pfirmware->status == FW_STATUS_5_READY) {
160                 rst_opt = OPT_FIRMWARE_RESET;
161                 starting_state = FW_INIT_STEP2_DATA;
162         } else {
163                 RT_TRACE(COMP_FIRMWARE,
164                          "PlatformInitFirmware: undefined firmware state\n");
165         }
166
167         for (i = starting_state; i <= FW_INIT_STEP2_DATA; i++) {
168                 if (rst_opt == OPT_SYSTEM_RESET) {
169                         if (pfirmware->blobs[i].size == 0) {
170                                 const char *fw_name[3] = {
171                                         RTL8192E_BOOT_IMG_FW,
172                                         RTL8192E_MAIN_IMG_FW,
173                                         RTL8192E_DATA_IMG_FW
174                                 };
175                                 int pad = 0;
176
177                                 if (i == FW_INIT_STEP1_MAIN)
178                                         pad = 128;
179
180                                 if (!_rtl92e_fw_prepare(dev,
181                                                         &pfirmware->blobs[i],
182                                                         fw_name[i],
183                                                         pad))
184                                         goto download_firmware_fail;
185                         }
186                 }
187
188                 mapped_file = pfirmware->blobs[i].data;
189                 file_length = pfirmware->blobs[i].size;
190
191                 rt_status = rtl92e_send_cmd_pkt(dev, DESC_PACKET_TYPE_INIT,
192                                                 mapped_file, file_length);
193                 if (!rt_status)
194                         goto download_firmware_fail;
195
196                 if (!_rtl92e_fw_check_ready(dev, i))
197                         goto download_firmware_fail;
198         }
199
200         netdev_dbg(dev, "Firmware Download Success\n");
201         return rt_status;
202
203 download_firmware_fail:
204         netdev_err(dev, "%s: Failed to initialize firmware.\n", __func__);
205         rt_status = false;
206         return rt_status;
207
208 }