1 // SPDX-License-Identifier: GPL-2.0
3 * Copyright(c) 2008 - 2010 Realtek Corporation. All rights reserved.
5 * Contact Information: wlanfae <wlanfae@realtek.com>
9 #include "r8192E_hwimg.h"
10 #include "r8192E_firmware.h"
11 #include "r8192E_cmdpkt.h"
12 #include <linux/firmware.h>
14 static bool _rtl92e_wait_for_fw(struct net_device *dev, u32 mask, u32 timeout)
16 unsigned long deadline = jiffies + msecs_to_jiffies(timeout);
18 while (time_before(jiffies, deadline)) {
19 if (rtl92e_readl(dev, CPU_GEN) & mask)
26 static bool _rtl92e_fw_boot_cpu(struct net_device *dev)
30 if (!_rtl92e_wait_for_fw(dev, CPU_GEN_PUT_CODE_OK, 200)) {
31 netdev_err(dev, "Firmware download failed.\n");
34 netdev_dbg(dev, "Download Firmware: Put code ok!\n");
36 CPU_status = rtl92e_readl(dev, CPU_GEN);
37 rtl92e_writeb(dev, CPU_GEN, (CPU_status | CPU_GEN_PWR_STB_CPU) & 0xff);
40 if (!_rtl92e_wait_for_fw(dev, CPU_GEN_BOOT_RDY, 200)) {
41 netdev_err(dev, "Firmware boot failed.\n");
45 netdev_dbg(dev, "Download Firmware: Boot ready!\n");
50 static bool _rtl92e_fw_check_ready(struct net_device *dev,
53 struct r8192_priv *priv = rtllib_priv(dev);
54 struct rt_firmware *pfirmware = priv->pFirmware;
55 bool rt_status = true;
57 switch (load_fw_status) {
58 case FW_INIT_STEP0_BOOT:
59 pfirmware->status = FW_STATUS_1_MOVE_BOOT_CODE;
62 case FW_INIT_STEP1_MAIN:
63 pfirmware->status = FW_STATUS_2_MOVE_MAIN_CODE;
65 rt_status = _rtl92e_fw_boot_cpu(dev);
67 pfirmware->status = FW_STATUS_3_TURNON_CPU;
69 netdev_dbg(dev, "_rtl92e_fw_boot_cpu fail!\n");
73 case FW_INIT_STEP2_DATA:
74 pfirmware->status = FW_STATUS_4_MOVE_DATA_CODE;
77 rt_status = _rtl92e_wait_for_fw(dev, CPU_GEN_FIRM_RDY, 20);
79 pfirmware->status = FW_STATUS_5_READY;
81 RT_TRACE(COMP_FIRMWARE,
82 "_rtl92e_is_fw_ready fail(%d)!\n",
87 netdev_dbg(dev, "Unknown firmware status");
94 static bool _rtl92e_fw_prepare(struct net_device *dev, struct rt_fw_blob *blob,
95 const char *name, u8 padding)
97 const struct firmware *fw;
101 rc = reject_firmware(&fw, name, &dev->dev);
105 if (round_up(fw->size, 4) > MAX_FW_SIZE - padding) {
106 netdev_err(dev, "Firmware image %s too big for the device.\n",
113 memset(blob->data, 0, padding);
115 memset(blob->data + padding + fw->size, 0, 4);
116 memcpy(blob->data + padding, fw->data, fw->size);
118 blob->size = round_up(fw->size, 4) + padding;
120 /* Swap endian - firmware is packaged in invalid endiannes*/
121 for (i = padding; i < blob->size; i += 4) {
122 u32 *data = (u32 *)(blob->data + i);
123 *data = swab32p(data);
126 release_firmware(fw);
130 bool rtl92e_init_fw(struct net_device *dev)
132 struct r8192_priv *priv = rtllib_priv(dev);
133 bool rt_status = true;
136 u8 *mapped_file = NULL;
138 enum opt_rst_type rst_opt = OPT_SYSTEM_RESET;
139 enum firmware_init_step starting_state = FW_INIT_STEP0_BOOT;
141 struct rt_firmware *pfirmware = priv->pFirmware;
143 netdev_dbg(dev, " PlatformInitFirmware()==>\n");
145 if (pfirmware->status == FW_STATUS_0_INIT) {
146 rst_opt = OPT_SYSTEM_RESET;
147 starting_state = FW_INIT_STEP0_BOOT;
149 } else if (pfirmware->status == FW_STATUS_5_READY) {
150 rst_opt = OPT_FIRMWARE_RESET;
151 starting_state = FW_INIT_STEP2_DATA;
153 RT_TRACE(COMP_FIRMWARE,
154 "PlatformInitFirmware: undefined firmware state\n");
157 for (i = starting_state; i <= FW_INIT_STEP2_DATA; i++) {
158 if (rst_opt == OPT_SYSTEM_RESET) {
159 if (pfirmware->blobs[i].size == 0) {
160 const char *fw_name[3] = {
161 RTL8192E_BOOT_IMG_FW,
162 RTL8192E_MAIN_IMG_FW,
167 if (i == FW_INIT_STEP1_MAIN)
170 if (!_rtl92e_fw_prepare(dev,
171 &pfirmware->blobs[i],
174 goto download_firmware_fail;
178 mapped_file = pfirmware->blobs[i].data;
179 file_length = pfirmware->blobs[i].size;
181 rt_status = rtl92e_send_cmd_pkt(dev, DESC_PACKET_TYPE_INIT,
182 mapped_file, file_length);
184 goto download_firmware_fail;
186 if (!_rtl92e_fw_check_ready(dev, i))
187 goto download_firmware_fail;
190 netdev_dbg(dev, "Firmware Download Success\n");
193 download_firmware_fail:
194 netdev_err(dev, "%s: Failed to initialize firmware.\n", __func__);