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