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