0001
0002
0003
0004
0005
0006
0007
0008
0009
0010
0011
0012
0013
0014
0015
0016 #define _HAL_INIT_C_
0017
0018 #include <linux/usb.h>
0019 #include <linux/device.h>
0020 #include <linux/usb/ch9.h>
0021 #include <linux/firmware.h>
0022 #include <linux/module.h>
0023
0024 #include "osdep_service.h"
0025 #include "drv_types.h"
0026 #include "usb_osintf.h"
0027
0028 #define FWBUFF_ALIGN_SZ 512
0029 #define MAX_DUMP_FWSZ (48 * 1024)
0030
0031 static void rtl871x_load_fw_fail(struct _adapter *adapter)
0032 {
0033 struct usb_device *udev = adapter->dvobjpriv.pusbdev;
0034 struct device *dev = &udev->dev;
0035 struct device *parent = dev->parent;
0036
0037 complete(&adapter->rtl8712_fw_ready);
0038
0039 dev_err(&udev->dev, "r8712u: Firmware request failed\n");
0040
0041 if (parent)
0042 device_lock(parent);
0043
0044 device_release_driver(dev);
0045
0046 if (parent)
0047 device_unlock(parent);
0048 }
0049
0050 static void rtl871x_load_fw_cb(const struct firmware *firmware, void *context)
0051 {
0052 struct _adapter *adapter = context;
0053
0054 if (!firmware) {
0055 rtl871x_load_fw_fail(adapter);
0056 return;
0057 }
0058 adapter->fw = firmware;
0059
0060 register_netdev(adapter->pnetdev);
0061 complete(&adapter->rtl8712_fw_ready);
0062 }
0063
0064 static const char firmware_file[] = "rtlwifi/rtl8712u.bin";
0065
0066 int rtl871x_load_fw(struct _adapter *padapter)
0067 {
0068 struct device *dev = &padapter->dvobjpriv.pusbdev->dev;
0069 int rc;
0070
0071 init_completion(&padapter->rtl8712_fw_ready);
0072 dev_info(dev, "r8712u: Loading firmware from \"%s\"\n", firmware_file);
0073 rc = request_firmware_nowait(THIS_MODULE, 1, firmware_file, dev,
0074 GFP_KERNEL, padapter, rtl871x_load_fw_cb);
0075 if (rc)
0076 dev_err(dev, "r8712u: Firmware request error %d\n", rc);
0077 return rc;
0078 }
0079 MODULE_FIRMWARE("rtlwifi/rtl8712u.bin");
0080
0081 static u32 rtl871x_open_fw(struct _adapter *adapter, const u8 **mappedfw)
0082 {
0083 if (adapter->fw->size > 200000) {
0084 dev_err(&adapter->pnetdev->dev, "r8712u: Bad fw->size of %zu\n",
0085 adapter->fw->size);
0086 return 0;
0087 }
0088 *mappedfw = adapter->fw->data;
0089 return adapter->fw->size;
0090 }
0091
0092 static void fill_fwpriv(struct _adapter *adapter, struct fw_priv *fwpriv)
0093 {
0094 struct dvobj_priv *dvobj = &adapter->dvobjpriv;
0095 struct registry_priv *regpriv = &adapter->registrypriv;
0096
0097 memset(fwpriv, 0, sizeof(struct fw_priv));
0098
0099 fwpriv->hci_sel = RTL8712_HCI_TYPE_72USB;
0100 fwpriv->usb_ep_num = (u8)dvobj->nr_endpoint;
0101 fwpriv->bw_40MHz_en = regpriv->cbw40_enable;
0102 switch (regpriv->rf_config) {
0103 case RTL8712_RF_1T1R:
0104 fwpriv->rf_config = RTL8712_RFC_1T1R;
0105 break;
0106 case RTL8712_RF_2T2R:
0107 fwpriv->rf_config = RTL8712_RFC_2T2R;
0108 break;
0109 case RTL8712_RF_1T2R:
0110 default:
0111 fwpriv->rf_config = RTL8712_RFC_1T2R;
0112 }
0113 fwpriv->mp_mode = (regpriv->mp_mode == 1);
0114
0115 fwpriv->vcs_type = regpriv->vrtl_carrier_sense;
0116 fwpriv->vcs_mode = regpriv->vcs_type;
0117
0118 fwpriv->turbo_mode = (regpriv->wifi_test != 1);
0119 fwpriv->low_power_mode = regpriv->low_power;
0120 }
0121
0122 static void update_fwhdr(struct fw_hdr *pfwhdr, const u8 *pmappedfw)
0123 {
0124 pfwhdr->signature = le16_to_cpu(*(__le16 *)pmappedfw);
0125 pfwhdr->version = le16_to_cpu(*(__le16 *)(pmappedfw + 2));
0126
0127 pfwhdr->dmem_size = le32_to_cpu(*(__le32 *)(pmappedfw + 4));
0128
0129 pfwhdr->img_IMEM_size = le32_to_cpu(*(__le32 *)(pmappedfw + 8));
0130
0131 pfwhdr->img_SRAM_size = le32_to_cpu(*(__le32 *)(pmappedfw + 12));
0132
0133 pfwhdr->fw_priv_sz = le32_to_cpu(*(__le32 *)(pmappedfw + 16));
0134 }
0135
0136 static u8 chk_fwhdr(struct fw_hdr *pfwhdr, u32 ulfilelength)
0137 {
0138 u32 fwhdrsz, fw_sz;
0139
0140
0141 if ((pfwhdr->signature != 0x8712) && (pfwhdr->signature != 0x8192))
0142 return _FAIL;
0143
0144 if (pfwhdr->fw_priv_sz != sizeof(struct fw_priv))
0145 return _FAIL;
0146
0147 fwhdrsz = offsetof(struct fw_hdr, fwpriv) + pfwhdr->fw_priv_sz;
0148 fw_sz = fwhdrsz + pfwhdr->img_IMEM_size + pfwhdr->img_SRAM_size +
0149 pfwhdr->dmem_size;
0150 if (fw_sz != ulfilelength)
0151 return _FAIL;
0152 return _SUCCESS;
0153 }
0154
0155 static u8 rtl8712_dl_fw(struct _adapter *adapter)
0156 {
0157 sint i;
0158 u8 tmp8, tmp8_a;
0159 u16 tmp16;
0160 u32 maxlen = 0;
0161 uint dump_imem_sz, imem_sz, dump_emem_sz, emem_sz;
0162 struct fw_hdr fwhdr;
0163 u32 ulfilelength;
0164 const u8 *mappedfw = NULL;
0165 u8 *tmpchar = NULL, *payload, *ptr;
0166 struct tx_desc *txdesc;
0167 u32 txdscp_sz = sizeof(struct tx_desc);
0168 u8 ret = _FAIL;
0169
0170 ulfilelength = rtl871x_open_fw(adapter, &mappedfw);
0171 if (mappedfw && (ulfilelength > 0)) {
0172 update_fwhdr(&fwhdr, mappedfw);
0173 if (chk_fwhdr(&fwhdr, ulfilelength) == _FAIL)
0174 return ret;
0175 fill_fwpriv(adapter, &fwhdr.fwpriv);
0176
0177 maxlen = (fwhdr.img_IMEM_size > fwhdr.img_SRAM_size) ?
0178 fwhdr.img_IMEM_size : fwhdr.img_SRAM_size;
0179 maxlen += txdscp_sz;
0180 tmpchar = kmalloc(maxlen + FWBUFF_ALIGN_SZ, GFP_KERNEL);
0181 if (!tmpchar)
0182 return ret;
0183
0184 txdesc = (struct tx_desc *)(tmpchar + FWBUFF_ALIGN_SZ -
0185 ((addr_t)(tmpchar) & (FWBUFF_ALIGN_SZ - 1)));
0186 payload = (u8 *)(txdesc) + txdscp_sz;
0187 ptr = (u8 *)mappedfw + offsetof(struct fw_hdr, fwpriv) +
0188 fwhdr.fw_priv_sz;
0189
0190
0191 imem_sz = fwhdr.img_IMEM_size;
0192 do {
0193 memset(txdesc, 0, TXDESC_SIZE);
0194 if (imem_sz > MAX_DUMP_FWSZ) {
0195 dump_imem_sz = MAX_DUMP_FWSZ;
0196 } else {
0197 dump_imem_sz = imem_sz;
0198 txdesc->txdw0 |= cpu_to_le32(BIT(28));
0199 }
0200 txdesc->txdw0 |= cpu_to_le32(dump_imem_sz &
0201 0x0000ffff);
0202 memcpy(payload, ptr, dump_imem_sz);
0203 r8712_write_mem(adapter, RTL8712_DMA_VOQ,
0204 dump_imem_sz + TXDESC_SIZE,
0205 (u8 *)txdesc);
0206 ptr += dump_imem_sz;
0207 imem_sz -= dump_imem_sz;
0208 } while (imem_sz > 0);
0209 i = 10;
0210 tmp16 = r8712_read16(adapter, TCR);
0211 while (((tmp16 & _IMEM_CODE_DONE) == 0) && (i > 0)) {
0212 usleep_range(10, 1000);
0213 tmp16 = r8712_read16(adapter, TCR);
0214 i--;
0215 }
0216 if (i == 0 || (tmp16 & _IMEM_CHK_RPT) == 0)
0217 goto exit_fail;
0218
0219
0220 emem_sz = fwhdr.img_SRAM_size;
0221 do {
0222 memset(txdesc, 0, TXDESC_SIZE);
0223 if (emem_sz > MAX_DUMP_FWSZ) {
0224 dump_emem_sz = MAX_DUMP_FWSZ;
0225 } else {
0226 dump_emem_sz = emem_sz;
0227 txdesc->txdw0 |= cpu_to_le32(BIT(28));
0228 }
0229 txdesc->txdw0 |= cpu_to_le32(dump_emem_sz &
0230 0x0000ffff);
0231 memcpy(payload, ptr, dump_emem_sz);
0232 r8712_write_mem(adapter, RTL8712_DMA_VOQ,
0233 dump_emem_sz + TXDESC_SIZE,
0234 (u8 *)txdesc);
0235 ptr += dump_emem_sz;
0236 emem_sz -= dump_emem_sz;
0237 } while (emem_sz > 0);
0238 i = 5;
0239 tmp16 = r8712_read16(adapter, TCR);
0240 while (((tmp16 & _EMEM_CODE_DONE) == 0) && (i > 0)) {
0241 usleep_range(10, 1000);
0242 tmp16 = r8712_read16(adapter, TCR);
0243 i--;
0244 }
0245 if (i == 0 || (tmp16 & _EMEM_CHK_RPT) == 0)
0246 goto exit_fail;
0247
0248
0249 tmp8 = r8712_read8(adapter, SYS_CLKR);
0250 r8712_write8(adapter, SYS_CLKR, tmp8 | BIT(2));
0251 tmp8_a = r8712_read8(adapter, SYS_CLKR);
0252 if (tmp8_a != (tmp8 | BIT(2)))
0253 goto exit_fail;
0254
0255 tmp8 = r8712_read8(adapter, SYS_FUNC_EN + 1);
0256 r8712_write8(adapter, SYS_FUNC_EN + 1, tmp8 | BIT(2));
0257 tmp8_a = r8712_read8(adapter, SYS_FUNC_EN + 1);
0258 if (tmp8_a != (tmp8 | BIT(2)))
0259 goto exit_fail;
0260
0261 r8712_read32(adapter, TCR);
0262
0263
0264 i = 100;
0265 tmp16 = r8712_read16(adapter, TCR);
0266 while (((tmp16 & _IMEM_RDY) == 0) && (i > 0)) {
0267 msleep(20);
0268 tmp16 = r8712_read16(adapter, TCR);
0269 i--;
0270 }
0271 if (i == 0) {
0272 r8712_write16(adapter, 0x10250348, 0xc000);
0273 r8712_write16(adapter, 0x10250348, 0xc001);
0274 r8712_write16(adapter, 0x10250348, 0x2000);
0275 r8712_write16(adapter, 0x10250348, 0x2001);
0276 r8712_write16(adapter, 0x10250348, 0x2002);
0277 r8712_write16(adapter, 0x10250348, 0x2003);
0278 goto exit_fail;
0279 }
0280
0281 memset(txdesc, 0, TXDESC_SIZE);
0282 txdesc->txdw0 |= cpu_to_le32(fwhdr.fw_priv_sz & 0x0000ffff);
0283 txdesc->txdw0 |= cpu_to_le32(BIT(28));
0284 memcpy(payload, &fwhdr.fwpriv, fwhdr.fw_priv_sz);
0285 r8712_write_mem(adapter, RTL8712_DMA_VOQ,
0286 fwhdr.fw_priv_sz + TXDESC_SIZE, (u8 *)txdesc);
0287
0288
0289 i = 100;
0290 tmp16 = r8712_read16(adapter, TCR);
0291 while (((tmp16 & _DMEM_CODE_DONE) == 0) && (i > 0)) {
0292 msleep(20);
0293 tmp16 = r8712_read16(adapter, TCR);
0294 i--;
0295 }
0296 if (i == 0)
0297 goto exit_fail;
0298
0299 tmp8 = r8712_read8(adapter, 0x1025000A);
0300 if (tmp8 & BIT(4))
0301
0302
0303 i = 60;
0304 else
0305 i = 30;
0306 tmp16 = r8712_read16(adapter, TCR);
0307 while (((tmp16 & _FWRDY) == 0) && (i > 0)) {
0308 msleep(100);
0309 tmp16 = r8712_read16(adapter, TCR);
0310 i--;
0311 }
0312 if (i == 0)
0313 goto exit_fail;
0314 } else {
0315 goto exit_fail;
0316 }
0317 ret = _SUCCESS;
0318
0319 exit_fail:
0320 kfree(tmpchar);
0321 return ret;
0322 }
0323
0324 uint rtl8712_hal_init(struct _adapter *padapter)
0325 {
0326 u32 val32;
0327 int i;
0328
0329
0330 if (rtl8712_dl_fw(padapter) != _SUCCESS)
0331 return _FAIL;
0332
0333 netdev_info(padapter->pnetdev, "1 RCR=0x%x\n",
0334 r8712_read32(padapter, RCR));
0335 val32 = r8712_read32(padapter, RCR);
0336 r8712_write32(padapter, RCR, (val32 | BIT(26)));
0337
0338
0339 netdev_info(padapter->pnetdev, "2 RCR=0x%x\n",
0340 r8712_read32(padapter, RCR));
0341 val32 = r8712_read32(padapter, RCR);
0342 r8712_write32(padapter, RCR, (val32 | BIT(25)));
0343 val32 = r8712_read32(padapter, 0x10250040);
0344 r8712_write32(padapter, 0x10250040, (val32 & 0x00FFFFFF));
0345
0346 r8712_write8(padapter, 0x102500B5, r8712_read8(padapter, 0x102500B5) |
0347 BIT(0));
0348 r8712_write8(padapter, 0x102500BD, r8712_read8(padapter, 0x102500BD) |
0349 BIT(7));
0350 r8712_write8(padapter, 0x102500D9, 1);
0351
0352
0353 r8712_write8(padapter, 0x1025FE5B, 0x04);
0354
0355 r8712_write8(padapter, 0x1025fe5C, r8712_read8(padapter, 0x1025fe5C)
0356 | BIT(7));
0357 for (i = 0; i < ETH_ALEN; i++)
0358 padapter->eeprompriv.mac_addr[i] = r8712_read8(padapter,
0359 MACID + i);
0360 return _SUCCESS;
0361 }
0362
0363 uint rtl8712_hal_deinit(struct _adapter *padapter)
0364 {
0365 r8712_write8(padapter, RF_CTRL, 0x00);
0366
0367 msleep(20);
0368
0369 r8712_write8(padapter, SYS_CLKR + 1, 0x38);
0370 r8712_write8(padapter, SYS_FUNC_EN + 1, 0x70);
0371 r8712_write8(padapter, PMC_FSM, 0x06);
0372 r8712_write8(padapter, SYS_ISO_CTRL, 0xF9);
0373
0374
0375 r8712_write8(padapter, SYS_ISO_CTRL + 1, 0xe8);
0376 r8712_write8(padapter, AFE_PLL_CTRL, 0x00);
0377 r8712_write8(padapter, LDOA15_CTRL, 0x54);
0378 r8712_write8(padapter, SYS_FUNC_EN + 1, 0x50);
0379 r8712_write8(padapter, LDOV12D_CTRL, 0x24);
0380 r8712_write8(padapter, AFE_MISC, 0x30);
0381
0382 r8712_write8(padapter, SPS0_CTRL, 0x56);
0383 r8712_write8(padapter, SPS0_CTRL + 1, 0x43);
0384 return _SUCCESS;
0385 }
0386
0387 uint rtl871x_hal_init(struct _adapter *padapter)
0388 {
0389 padapter->hw_init_completed = false;
0390 if (!padapter->halpriv.hal_bus_init)
0391 return _FAIL;
0392 if (padapter->halpriv.hal_bus_init(padapter) != _SUCCESS)
0393 return _FAIL;
0394 if (rtl8712_hal_init(padapter) == _SUCCESS) {
0395 padapter->hw_init_completed = true;
0396 } else {
0397 padapter->hw_init_completed = false;
0398 return _FAIL;
0399 }
0400 return _SUCCESS;
0401 }