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, 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 51 static 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 95 static 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 /* Swap endian - firmware is packaged in invalid endiannes*/ 122 for (i = padding; i < blob->size; i += 4) { 123 u32 *data = (u32 *)(blob->data + i); 124 *data = swab32p(data); 125 } 126 out: 127 release_firmware(fw); 128 return ret; 129 } 130 131 bool 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 194 download_firmware_fail: 195 netdev_err(dev, "%s: Failed to initialize firmware.\n", __func__); 196 return false; 197 } 198