fw_common.c (6565B)
1// SPDX-License-Identifier: GPL-2.0 2/* Copyright(c) 2009-2014 Realtek Corporation.*/ 3 4#include "../wifi.h" 5#include "../pci.h" 6#include "../base.h" 7#include "../efuse.h" 8#include "fw_common.h" 9#include <linux/module.h> 10 11void rtl8723_enable_fw_download(struct ieee80211_hw *hw, bool enable) 12{ 13 struct rtl_priv *rtlpriv = rtl_priv(hw); 14 u8 tmp; 15 16 if (enable) { 17 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 18 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 19 tmp | 0x04); 20 21 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); 22 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); 23 24 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); 25 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); 26 } else { 27 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); 28 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); 29 30 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00); 31 } 32} 33EXPORT_SYMBOL_GPL(rtl8723_enable_fw_download); 34 35void rtl8723_write_fw(struct ieee80211_hw *hw, 36 enum version_8723e version, 37 u8 *buffer, u32 size, u8 max_page) 38{ 39 struct rtl_priv *rtlpriv = rtl_priv(hw); 40 u8 *bufferptr = buffer; 41 u32 page_nums, remain_size; 42 u32 page, offset; 43 44 rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size); 45 46 rtl_fill_dummy(bufferptr, &size); 47 48 page_nums = size / FW_8192C_PAGE_SIZE; 49 remain_size = size % FW_8192C_PAGE_SIZE; 50 51 if (page_nums > max_page) { 52 pr_err("Page numbers should not greater than %d\n", 53 max_page); 54 } 55 for (page = 0; page < page_nums; page++) { 56 offset = page * FW_8192C_PAGE_SIZE; 57 rtl_fw_page_write(hw, page, (bufferptr + offset), 58 FW_8192C_PAGE_SIZE); 59 } 60 61 if (remain_size) { 62 offset = page_nums * FW_8192C_PAGE_SIZE; 63 page = page_nums; 64 rtl_fw_page_write(hw, page, (bufferptr + offset), remain_size); 65 } 66 rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, "FW write done.\n"); 67} 68EXPORT_SYMBOL_GPL(rtl8723_write_fw); 69 70void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw) 71{ 72 u8 u1b_tmp; 73 u8 delay = 100; 74 struct rtl_priv *rtlpriv = rtl_priv(hw); 75 76 rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20); 77 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 78 79 while (u1b_tmp & BIT(2)) { 80 delay--; 81 if (delay == 0) 82 break; 83 udelay(50); 84 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 85 } 86 if (delay == 0) { 87 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 88 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 89 u1b_tmp&(~BIT(2))); 90 } 91} 92EXPORT_SYMBOL_GPL(rtl8723ae_firmware_selfreset); 93 94void rtl8723be_firmware_selfreset(struct ieee80211_hw *hw) 95{ 96 u8 u1b_tmp; 97 struct rtl_priv *rtlpriv = rtl_priv(hw); 98 99 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); 100 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); 101 102 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 103 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); 104 udelay(50); 105 106 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); 107 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0))); 108 109 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 110 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2))); 111 112 rtl_dbg(rtlpriv, COMP_INIT, DBG_LOUD, 113 "_8051Reset8723be(): 8051 reset success .\n"); 114} 115EXPORT_SYMBOL_GPL(rtl8723be_firmware_selfreset); 116 117int rtl8723_fw_free_to_go(struct ieee80211_hw *hw, bool is_8723be, 118 int max_count) 119{ 120 struct rtl_priv *rtlpriv = rtl_priv(hw); 121 int err = -EIO; 122 u32 counter = 0; 123 u32 value32; 124 125 do { 126 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 127 } while ((counter++ < max_count) && 128 (!(value32 & FWDL_CHKSUM_RPT))); 129 130 if (counter >= max_count) { 131 pr_err("chksum report fail ! REG_MCUFWDL:0x%08x .\n", 132 value32); 133 goto exit; 134 } 135 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL) | MCUFWDL_RDY; 136 value32 &= ~WINTINI_RDY; 137 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); 138 139 if (is_8723be) 140 rtl8723be_firmware_selfreset(hw); 141 counter = 0; 142 143 do { 144 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 145 if (value32 & WINTINI_RDY) { 146 rtl_dbg(rtlpriv, COMP_FW, DBG_TRACE, 147 "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n", 148 value32); 149 err = 0; 150 goto exit; 151 } 152 153 mdelay(FW_8192C_POLLING_DELAY); 154 155 } while (counter++ < max_count); 156 157 pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", 158 value32); 159 160exit: 161 return err; 162} 163EXPORT_SYMBOL_GPL(rtl8723_fw_free_to_go); 164 165int rtl8723_download_fw(struct ieee80211_hw *hw, 166 bool is_8723be, int max_count) 167{ 168 struct rtl_priv *rtlpriv = rtl_priv(hw); 169 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 170 struct rtlwifi_firmware_header *pfwheader; 171 u8 *pfwdata; 172 u32 fwsize; 173 int err; 174 enum version_8723e version = rtlhal->version; 175 int max_page; 176 177 if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware) 178 return 1; 179 180 pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware; 181 rtlhal->fw_version = le16_to_cpu(pfwheader->version); 182 rtlhal->fw_subversion = pfwheader->subversion; 183 pfwdata = rtlhal->pfirmware; 184 fwsize = rtlhal->fwsize; 185 186 if (!is_8723be) 187 max_page = 6; 188 else 189 max_page = 8; 190 if (rtlpriv->cfg->ops->is_fw_header(pfwheader)) { 191 rtl_dbg(rtlpriv, COMP_FW, DBG_LOUD, 192 "Firmware Version(%d), Signature(%#x), Size(%d)\n", 193 pfwheader->version, pfwheader->signature, 194 (int)sizeof(struct rtlwifi_firmware_header)); 195 196 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); 197 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); 198 } 199 200 if (rtl_read_byte(rtlpriv, REG_MCUFWDL)&BIT(7)) { 201 if (is_8723be) 202 rtl8723be_firmware_selfreset(hw); 203 else 204 rtl8723ae_firmware_selfreset(hw); 205 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); 206 } 207 rtl8723_enable_fw_download(hw, true); 208 rtl8723_write_fw(hw, version, pfwdata, fwsize, max_page); 209 rtl8723_enable_fw_download(hw, false); 210 211 err = rtl8723_fw_free_to_go(hw, is_8723be, max_count); 212 if (err) 213 pr_err("Firmware is not ready to run!\n"); 214 return 0; 215} 216EXPORT_SYMBOL_GPL(rtl8723_download_fw); 217 218bool rtl8723_cmd_send_packet(struct ieee80211_hw *hw, 219 struct sk_buff *skb) 220{ 221 struct rtl_priv *rtlpriv = rtl_priv(hw); 222 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 223 struct rtl8192_tx_ring *ring; 224 struct rtl_tx_desc *pdesc; 225 struct sk_buff *pskb = NULL; 226 unsigned long flags; 227 228 ring = &rtlpci->tx_ring[BEACON_QUEUE]; 229 230 pskb = __skb_dequeue(&ring->queue); 231 kfree_skb(pskb); 232 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); 233 234 pdesc = &ring->desc[0]; 235 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); 236 237 __skb_queue_tail(&ring->queue, skb); 238 239 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); 240 241 rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); 242 243 return true; 244} 245EXPORT_SYMBOL_GPL(rtl8723_cmd_send_packet);