1 /****************************************************************************** 2 * 3 * Copyright(c) 2009-2014 Realtek Corporation. 4 * 5 * This program is free software; you can redistribute it and/or modify it 6 * under the terms of version 2 of the GNU General Public License as 7 * published by the Free Software Foundation. 8 * 9 * This program is distributed in the hope that it will be useful, but WITHOUT 10 * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or 11 * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for 12 * more details. 13 * 14 * The full GNU General Public License is included in this distribution in the 15 * file called LICENSE. 16 * 17 * Contact Information: 18 * wlanfae <wlanfae@realtek.com> 19 * Realtek Corporation, No. 2, Innovation Road II, Hsinchu Science Park, 20 * Hsinchu 300, Taiwan. 21 * 22 * Larry Finger <Larry.Finger@lwfinger.net> 23 * 24 *****************************************************************************/ 25 26 #include "../wifi.h" 27 #include "../pci.h" 28 #include "../base.h" 29 #include "../efuse.h" 30 #include "fw_common.h" 31 #include <linux/module.h> 32 33 void rtl8723_enable_fw_download(struct ieee80211_hw *hw, bool enable) 34 { 35 struct rtl_priv *rtlpriv = rtl_priv(hw); 36 u8 tmp; 37 38 if (enable) { 39 tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 40 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 41 tmp | 0x04); 42 43 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); 44 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp | 0x01); 45 46 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL + 2); 47 rtl_write_byte(rtlpriv, REG_MCUFWDL + 2, tmp & 0xf7); 48 } else { 49 tmp = rtl_read_byte(rtlpriv, REG_MCUFWDL); 50 rtl_write_byte(rtlpriv, REG_MCUFWDL, tmp & 0xfe); 51 52 rtl_write_byte(rtlpriv, REG_MCUFWDL + 1, 0x00); 53 } 54 } 55 EXPORT_SYMBOL_GPL(rtl8723_enable_fw_download); 56 57 void rtl8723_write_fw(struct ieee80211_hw *hw, 58 enum version_8723e version, 59 u8 *buffer, u32 size, u8 max_page) 60 { 61 struct rtl_priv *rtlpriv = rtl_priv(hw); 62 u8 *bufferptr = buffer; 63 u32 page_nums, remain_size; 64 u32 page, offset; 65 66 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW size is %d bytes,\n", size); 67 68 rtl_fill_dummy(bufferptr, &size); 69 70 page_nums = size / FW_8192C_PAGE_SIZE; 71 remain_size = size % FW_8192C_PAGE_SIZE; 72 73 if (page_nums > max_page) { 74 pr_err("Page numbers should not greater than %d\n", 75 max_page); 76 } 77 for (page = 0; page < page_nums; page++) { 78 offset = page * FW_8192C_PAGE_SIZE; 79 rtl_fw_page_write(hw, page, (bufferptr + offset), 80 FW_8192C_PAGE_SIZE); 81 } 82 83 if (remain_size) { 84 offset = page_nums * FW_8192C_PAGE_SIZE; 85 page = page_nums; 86 rtl_fw_page_write(hw, page, (bufferptr + offset), remain_size); 87 } 88 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, "FW write done.\n"); 89 } 90 EXPORT_SYMBOL_GPL(rtl8723_write_fw); 91 92 void rtl8723ae_firmware_selfreset(struct ieee80211_hw *hw) 93 { 94 u8 u1b_tmp; 95 u8 delay = 100; 96 struct rtl_priv *rtlpriv = rtl_priv(hw); 97 98 rtl_write_byte(rtlpriv, REG_HMETFR + 3, 0x20); 99 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 100 101 while (u1b_tmp & BIT(2)) { 102 delay--; 103 if (delay == 0) 104 break; 105 udelay(50); 106 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 107 } 108 if (delay == 0) { 109 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 110 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, 111 u1b_tmp&(~BIT(2))); 112 } 113 } 114 EXPORT_SYMBOL_GPL(rtl8723ae_firmware_selfreset); 115 116 void rtl8723be_firmware_selfreset(struct ieee80211_hw *hw) 117 { 118 u8 u1b_tmp; 119 struct rtl_priv *rtlpriv = rtl_priv(hw); 120 121 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); 122 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp & (~BIT(0)))); 123 124 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 125 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp & (~BIT(2)))); 126 udelay(50); 127 128 u1b_tmp = rtl_read_byte(rtlpriv, REG_RSV_CTRL + 1); 129 rtl_write_byte(rtlpriv, REG_RSV_CTRL + 1, (u1b_tmp | BIT(0))); 130 131 u1b_tmp = rtl_read_byte(rtlpriv, REG_SYS_FUNC_EN + 1); 132 rtl_write_byte(rtlpriv, REG_SYS_FUNC_EN + 1, (u1b_tmp | BIT(2))); 133 134 RT_TRACE(rtlpriv, COMP_INIT, DBG_LOUD, 135 " _8051Reset8723be(): 8051 reset success .\n"); 136 } 137 EXPORT_SYMBOL_GPL(rtl8723be_firmware_selfreset); 138 139 int rtl8723_fw_free_to_go(struct ieee80211_hw *hw, bool is_8723be, 140 int max_count) 141 { 142 struct rtl_priv *rtlpriv = rtl_priv(hw); 143 int err = -EIO; 144 u32 counter = 0; 145 u32 value32; 146 147 do { 148 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 149 } while ((counter++ < max_count) && 150 (!(value32 & FWDL_CHKSUM_RPT))); 151 152 if (counter >= max_count) { 153 pr_err("chksum report fail ! REG_MCUFWDL:0x%08x .\n", 154 value32); 155 goto exit; 156 } 157 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL) | MCUFWDL_RDY; 158 value32 &= ~WINTINI_RDY; 159 rtl_write_dword(rtlpriv, REG_MCUFWDL, value32); 160 161 if (is_8723be) 162 rtl8723be_firmware_selfreset(hw); 163 counter = 0; 164 165 do { 166 value32 = rtl_read_dword(rtlpriv, REG_MCUFWDL); 167 if (value32 & WINTINI_RDY) { 168 RT_TRACE(rtlpriv, COMP_FW, DBG_TRACE, 169 "Polling FW ready success!! REG_MCUFWDL:0x%08x .\n", 170 value32); 171 err = 0; 172 goto exit; 173 } 174 175 mdelay(FW_8192C_POLLING_DELAY); 176 177 } while (counter++ < max_count); 178 179 pr_err("Polling FW ready fail!! REG_MCUFWDL:0x%08x .\n", 180 value32); 181 182 exit: 183 return err; 184 } 185 EXPORT_SYMBOL_GPL(rtl8723_fw_free_to_go); 186 187 int rtl8723_download_fw(struct ieee80211_hw *hw, 188 bool is_8723be, int max_count) 189 { 190 struct rtl_priv *rtlpriv = rtl_priv(hw); 191 struct rtl_hal *rtlhal = rtl_hal(rtl_priv(hw)); 192 struct rtlwifi_firmware_header *pfwheader; 193 u8 *pfwdata; 194 u32 fwsize; 195 int err; 196 enum version_8723e version = rtlhal->version; 197 int max_page; 198 199 if (rtlpriv->max_fw_size == 0 || !rtlhal->pfirmware) 200 return 1; 201 202 pfwheader = (struct rtlwifi_firmware_header *)rtlhal->pfirmware; 203 rtlhal->fw_version = le16_to_cpu(pfwheader->version); 204 rtlhal->fw_subversion = pfwheader->subversion; 205 pfwdata = rtlhal->pfirmware; 206 fwsize = rtlhal->fwsize; 207 208 if (!is_8723be) 209 max_page = 6; 210 else 211 max_page = 8; 212 if (rtlpriv->cfg->ops->is_fw_header(pfwheader)) { 213 RT_TRACE(rtlpriv, COMP_FW, DBG_LOUD, 214 "Firmware Version(%d), Signature(%#x), Size(%d)\n", 215 pfwheader->version, pfwheader->signature, 216 (int)sizeof(struct rtlwifi_firmware_header)); 217 218 pfwdata = pfwdata + sizeof(struct rtlwifi_firmware_header); 219 fwsize = fwsize - sizeof(struct rtlwifi_firmware_header); 220 } 221 222 if (rtl_read_byte(rtlpriv, REG_MCUFWDL)&BIT(7)) { 223 if (is_8723be) 224 rtl8723be_firmware_selfreset(hw); 225 else 226 rtl8723ae_firmware_selfreset(hw); 227 rtl_write_byte(rtlpriv, REG_MCUFWDL, 0x00); 228 } 229 rtl8723_enable_fw_download(hw, true); 230 rtl8723_write_fw(hw, version, pfwdata, fwsize, max_page); 231 rtl8723_enable_fw_download(hw, false); 232 233 err = rtl8723_fw_free_to_go(hw, is_8723be, max_count); 234 if (err) 235 pr_err("Firmware is not ready to run!\n"); 236 return 0; 237 } 238 EXPORT_SYMBOL_GPL(rtl8723_download_fw); 239 240 bool rtl8723_cmd_send_packet(struct ieee80211_hw *hw, 241 struct sk_buff *skb) 242 { 243 struct rtl_priv *rtlpriv = rtl_priv(hw); 244 struct rtl_pci *rtlpci = rtl_pcidev(rtl_pcipriv(hw)); 245 struct rtl8192_tx_ring *ring; 246 struct rtl_tx_desc *pdesc; 247 struct sk_buff *pskb = NULL; 248 u8 own; 249 unsigned long flags; 250 251 ring = &rtlpci->tx_ring[BEACON_QUEUE]; 252 253 pskb = __skb_dequeue(&ring->queue); 254 kfree_skb(pskb); 255 spin_lock_irqsave(&rtlpriv->locks.irq_th_lock, flags); 256 257 pdesc = &ring->desc[0]; 258 own = (u8)rtlpriv->cfg->ops->get_desc(hw, (u8 *)pdesc, true, 259 HW_DESC_OWN); 260 261 rtlpriv->cfg->ops->fill_tx_cmddesc(hw, (u8 *)pdesc, 1, 1, skb); 262 263 __skb_queue_tail(&ring->queue, skb); 264 265 spin_unlock_irqrestore(&rtlpriv->locks.irq_th_lock, flags); 266 267 rtlpriv->cfg->ops->tx_polling(hw, BEACON_QUEUE); 268 269 return true; 270 } 271 EXPORT_SYMBOL_GPL(rtl8723_cmd_send_packet); 272