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