rtl8xxxu_8723a.c 12 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405
  1. /*
  2. * RTL8XXXU mac80211 USB driver - 8723a specific subdriver
  3. *
  4. * Copyright (c) 2014 - 2017 Jes Sorensen <Jes.Sorensen@gmail.com>
  5. *
  6. * Portions, notably calibration code:
  7. * Copyright(c) 2007 - 2011 Realtek Corporation. All rights reserved.
  8. *
  9. * This driver was written as a replacement for the vendor provided
  10. * rtl8723au driver. As the Realtek 8xxx chips are very similar in
  11. * their programming interface, I have started adding support for
  12. * additional 8xxx chips like the 8192cu, 8188cus, etc.
  13. *
  14. * This program is free software; you can redistribute it and/or modify it
  15. * under the terms of version 2 of the GNU General Public License as
  16. * published by the Free Software Foundation.
  17. *
  18. * This program is distributed in the hope that it will be useful, but WITHOUT
  19. * ANY WARRANTY; without even the implied warranty of MERCHANTABILITY or
  20. * FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License for
  21. * more details.
  22. */
  23. #include <linux/init.h>
  24. #include <linux/kernel.h>
  25. #include <linux/sched.h>
  26. #include <linux/errno.h>
  27. #include <linux/slab.h>
  28. #include <linux/module.h>
  29. #include <linux/spinlock.h>
  30. #include <linux/list.h>
  31. #include <linux/usb.h>
  32. #include <linux/netdevice.h>
  33. #include <linux/etherdevice.h>
  34. #include <linux/ethtool.h>
  35. #include <linux/wireless.h>
  36. #include <linux/firmware.h>
  37. #include <linux/moduleparam.h>
  38. #include <net/mac80211.h>
  39. #include "rtl8xxxu.h"
  40. #include "rtl8xxxu_regs.h"
  41. static struct rtl8xxxu_power_base rtl8723a_power_base = {
  42. .reg_0e00 = 0x0a0c0c0c,
  43. .reg_0e04 = 0x02040608,
  44. .reg_0e08 = 0x00000000,
  45. .reg_086c = 0x00000000,
  46. .reg_0e10 = 0x0a0c0d0e,
  47. .reg_0e14 = 0x02040608,
  48. .reg_0e18 = 0x0a0c0d0e,
  49. .reg_0e1c = 0x02040608,
  50. .reg_0830 = 0x0a0c0c0c,
  51. .reg_0834 = 0x02040608,
  52. .reg_0838 = 0x00000000,
  53. .reg_086c_2 = 0x00000000,
  54. .reg_083c = 0x0a0c0d0e,
  55. .reg_0848 = 0x02040608,
  56. .reg_084c = 0x0a0c0d0e,
  57. .reg_0868 = 0x02040608,
  58. };
  59. static struct rtl8xxxu_rfregval rtl8723au_radioa_1t_init_table[] = {
  60. {0x00, 0x00030159}, {0x01, 0x00031284},
  61. {0x02, 0x00098000}, {0x03, 0x00039c63},
  62. {0x04, 0x000210e7}, {0x09, 0x0002044f},
  63. {0x0a, 0x0001a3f1}, {0x0b, 0x00014787},
  64. {0x0c, 0x000896fe}, {0x0d, 0x0000e02c},
  65. {0x0e, 0x00039ce7}, {0x0f, 0x00000451},
  66. {0x19, 0x00000000}, {0x1a, 0x00030355},
  67. {0x1b, 0x00060a00}, {0x1c, 0x000fc378},
  68. {0x1d, 0x000a1250}, {0x1e, 0x0000024f},
  69. {0x1f, 0x00000000}, {0x20, 0x0000b614},
  70. {0x21, 0x0006c000}, {0x22, 0x00000000},
  71. {0x23, 0x00001558}, {0x24, 0x00000060},
  72. {0x25, 0x00000483}, {0x26, 0x0004f000},
  73. {0x27, 0x000ec7d9}, {0x28, 0x00057730},
  74. {0x29, 0x00004783}, {0x2a, 0x00000001},
  75. {0x2b, 0x00021334}, {0x2a, 0x00000000},
  76. {0x2b, 0x00000054}, {0x2a, 0x00000001},
  77. {0x2b, 0x00000808}, {0x2b, 0x00053333},
  78. {0x2c, 0x0000000c}, {0x2a, 0x00000002},
  79. {0x2b, 0x00000808}, {0x2b, 0x0005b333},
  80. {0x2c, 0x0000000d}, {0x2a, 0x00000003},
  81. {0x2b, 0x00000808}, {0x2b, 0x00063333},
  82. {0x2c, 0x0000000d}, {0x2a, 0x00000004},
  83. {0x2b, 0x00000808}, {0x2b, 0x0006b333},
  84. {0x2c, 0x0000000d}, {0x2a, 0x00000005},
  85. {0x2b, 0x00000808}, {0x2b, 0x00073333},
  86. {0x2c, 0x0000000d}, {0x2a, 0x00000006},
  87. {0x2b, 0x00000709}, {0x2b, 0x0005b333},
  88. {0x2c, 0x0000000d}, {0x2a, 0x00000007},
  89. {0x2b, 0x00000709}, {0x2b, 0x00063333},
  90. {0x2c, 0x0000000d}, {0x2a, 0x00000008},
  91. {0x2b, 0x0000060a}, {0x2b, 0x0004b333},
  92. {0x2c, 0x0000000d}, {0x2a, 0x00000009},
  93. {0x2b, 0x0000060a}, {0x2b, 0x00053333},
  94. {0x2c, 0x0000000d}, {0x2a, 0x0000000a},
  95. {0x2b, 0x0000060a}, {0x2b, 0x0005b333},
  96. {0x2c, 0x0000000d}, {0x2a, 0x0000000b},
  97. {0x2b, 0x0000060a}, {0x2b, 0x00063333},
  98. {0x2c, 0x0000000d}, {0x2a, 0x0000000c},
  99. {0x2b, 0x0000060a}, {0x2b, 0x0006b333},
  100. {0x2c, 0x0000000d}, {0x2a, 0x0000000d},
  101. {0x2b, 0x0000060a}, {0x2b, 0x00073333},
  102. {0x2c, 0x0000000d}, {0x2a, 0x0000000e},
  103. {0x2b, 0x0000050b}, {0x2b, 0x00066666},
  104. {0x2c, 0x0000001a}, {0x2a, 0x000e0000},
  105. {0x10, 0x0004000f}, {0x11, 0x000e31fc},
  106. {0x10, 0x0006000f}, {0x11, 0x000ff9f8},
  107. {0x10, 0x0002000f}, {0x11, 0x000203f9},
  108. {0x10, 0x0003000f}, {0x11, 0x000ff500},
  109. {0x10, 0x00000000}, {0x11, 0x00000000},
  110. {0x10, 0x0008000f}, {0x11, 0x0003f100},
  111. {0x10, 0x0009000f}, {0x11, 0x00023100},
  112. {0x12, 0x00032000}, {0x12, 0x00071000},
  113. {0x12, 0x000b0000}, {0x12, 0x000fc000},
  114. {0x13, 0x000287b3}, {0x13, 0x000244b7},
  115. {0x13, 0x000204ab}, {0x13, 0x0001c49f},
  116. {0x13, 0x00018493}, {0x13, 0x0001429b},
  117. {0x13, 0x00010299}, {0x13, 0x0000c29c},
  118. {0x13, 0x000081a0}, {0x13, 0x000040ac},
  119. {0x13, 0x00000020}, {0x14, 0x0001944c},
  120. {0x14, 0x00059444}, {0x14, 0x0009944c},
  121. {0x14, 0x000d9444}, {0x15, 0x0000f474},
  122. {0x15, 0x0004f477}, {0x15, 0x0008f455},
  123. {0x15, 0x000cf455}, {0x16, 0x00000339},
  124. {0x16, 0x00040339}, {0x16, 0x00080339},
  125. {0x16, 0x000c0366}, {0x00, 0x00010159},
  126. {0x18, 0x0000f401}, {0xfe, 0x00000000},
  127. {0xfe, 0x00000000}, {0x1f, 0x00000003},
  128. {0xfe, 0x00000000}, {0xfe, 0x00000000},
  129. {0x1e, 0x00000247}, {0x1f, 0x00000000},
  130. {0x00, 0x00030159},
  131. {0xff, 0xffffffff}
  132. };
  133. static int rtl8723au_parse_efuse(struct rtl8xxxu_priv *priv)
  134. {
  135. struct rtl8723au_efuse *efuse = &priv->efuse_wifi.efuse8723;
  136. if (efuse->rtl_id != cpu_to_le16(0x8129))
  137. return -EINVAL;
  138. ether_addr_copy(priv->mac_addr, efuse->mac_addr);
  139. memcpy(priv->cck_tx_power_index_A,
  140. efuse->cck_tx_power_index_A,
  141. sizeof(efuse->cck_tx_power_index_A));
  142. memcpy(priv->cck_tx_power_index_B,
  143. efuse->cck_tx_power_index_B,
  144. sizeof(efuse->cck_tx_power_index_B));
  145. memcpy(priv->ht40_1s_tx_power_index_A,
  146. efuse->ht40_1s_tx_power_index_A,
  147. sizeof(efuse->ht40_1s_tx_power_index_A));
  148. memcpy(priv->ht40_1s_tx_power_index_B,
  149. efuse->ht40_1s_tx_power_index_B,
  150. sizeof(efuse->ht40_1s_tx_power_index_B));
  151. memcpy(priv->ht20_tx_power_index_diff,
  152. efuse->ht20_tx_power_index_diff,
  153. sizeof(efuse->ht20_tx_power_index_diff));
  154. memcpy(priv->ofdm_tx_power_index_diff,
  155. efuse->ofdm_tx_power_index_diff,
  156. sizeof(efuse->ofdm_tx_power_index_diff));
  157. memcpy(priv->ht40_max_power_offset,
  158. efuse->ht40_max_power_offset,
  159. sizeof(efuse->ht40_max_power_offset));
  160. memcpy(priv->ht20_max_power_offset,
  161. efuse->ht20_max_power_offset,
  162. sizeof(efuse->ht20_max_power_offset));
  163. if (priv->efuse_wifi.efuse8723.version >= 0x01) {
  164. priv->has_xtalk = 1;
  165. priv->xtalk = priv->efuse_wifi.efuse8723.xtal_k & 0x3f;
  166. }
  167. priv->power_base = &rtl8723a_power_base;
  168. dev_info(&priv->udev->dev, "Vendor: %.7s\n",
  169. efuse->vendor_name);
  170. dev_info(&priv->udev->dev, "Product: %.41s\n",
  171. efuse->device_name);
  172. return 0;
  173. }
  174. static int rtl8723au_load_firmware(struct rtl8xxxu_priv *priv)
  175. {
  176. char *fw_name;
  177. int ret;
  178. switch (priv->chip_cut) {
  179. case 0:
  180. fw_name = "rtlwifi/rtl8723aufw_A.bin";
  181. break;
  182. case 1:
  183. if (priv->enable_bluetooth)
  184. fw_name = "rtlwifi/rtl8723aufw_B.bin";
  185. else
  186. fw_name = "rtlwifi/rtl8723aufw_B_NoBT.bin";
  187. break;
  188. default:
  189. return -EINVAL;
  190. }
  191. ret = rtl8xxxu_load_firmware(priv, fw_name);
  192. return ret;
  193. }
  194. static int rtl8723au_init_phy_rf(struct rtl8xxxu_priv *priv)
  195. {
  196. int ret;
  197. ret = rtl8xxxu_init_phy_rf(priv, rtl8723au_radioa_1t_init_table, RF_A);
  198. /* Reduce 80M spur */
  199. rtl8xxxu_write32(priv, REG_AFE_XTAL_CTRL, 0x0381808d);
  200. rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83);
  201. rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff82);
  202. rtl8xxxu_write32(priv, REG_AFE_PLL_CTRL, 0xf0ffff83);
  203. return ret;
  204. }
  205. static int rtl8723a_emu_to_active(struct rtl8xxxu_priv *priv)
  206. {
  207. u8 val8;
  208. u32 val32;
  209. int count, ret = 0;
  210. /* 0x20[0] = 1 enable LDOA12 MACRO block for all interface*/
  211. val8 = rtl8xxxu_read8(priv, REG_LDOA15_CTRL);
  212. val8 |= LDOA15_ENABLE;
  213. rtl8xxxu_write8(priv, REG_LDOA15_CTRL, val8);
  214. /* 0x67[0] = 0 to disable BT_GPS_SEL pins*/
  215. val8 = rtl8xxxu_read8(priv, 0x0067);
  216. val8 &= ~BIT(4);
  217. rtl8xxxu_write8(priv, 0x0067, val8);
  218. mdelay(1);
  219. /* 0x00[5] = 0 release analog Ips to digital, 1:isolation */
  220. val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL);
  221. val8 &= ~SYS_ISO_ANALOG_IPS;
  222. rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8);
  223. /* disable SW LPS 0x04[10]= 0 */
  224. val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
  225. val8 &= ~BIT(2);
  226. rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
  227. /* wait till 0x04[17] = 1 power ready*/
  228. for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
  229. val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
  230. if (val32 & BIT(17))
  231. break;
  232. udelay(10);
  233. }
  234. if (!count) {
  235. ret = -EBUSY;
  236. goto exit;
  237. }
  238. /* We should be able to optimize the following three entries into one */
  239. /* release WLON reset 0x04[16]= 1*/
  240. val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 2);
  241. val8 |= BIT(0);
  242. rtl8xxxu_write8(priv, REG_APS_FSMCO + 2, val8);
  243. /* disable HWPDN 0x04[15]= 0*/
  244. val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
  245. val8 &= ~BIT(7);
  246. rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
  247. /* disable WL suspend*/
  248. val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 1);
  249. val8 &= ~(BIT(3) | BIT(4));
  250. rtl8xxxu_write8(priv, REG_APS_FSMCO + 1, val8);
  251. /* set, then poll until 0 */
  252. val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
  253. val32 |= APS_FSMCO_MAC_ENABLE;
  254. rtl8xxxu_write32(priv, REG_APS_FSMCO, val32);
  255. for (count = RTL8XXXU_MAX_REG_POLL; count; count--) {
  256. val32 = rtl8xxxu_read32(priv, REG_APS_FSMCO);
  257. if ((val32 & APS_FSMCO_MAC_ENABLE) == 0) {
  258. ret = 0;
  259. break;
  260. }
  261. udelay(10);
  262. }
  263. if (!count) {
  264. ret = -EBUSY;
  265. goto exit;
  266. }
  267. /* 0x4C[23] = 0x4E[7] = 1, switch DPDT_SEL_P output from WL BB */
  268. /*
  269. * Note: Vendor driver actually clears this bit, despite the
  270. * documentation claims it's being set!
  271. */
  272. val8 = rtl8xxxu_read8(priv, REG_LEDCFG2);
  273. val8 |= LEDCFG2_DPDT_SELECT;
  274. val8 &= ~LEDCFG2_DPDT_SELECT;
  275. rtl8xxxu_write8(priv, REG_LEDCFG2, val8);
  276. exit:
  277. return ret;
  278. }
  279. static int rtl8723au_power_on(struct rtl8xxxu_priv *priv)
  280. {
  281. u8 val8;
  282. u16 val16;
  283. u32 val32;
  284. int ret;
  285. /*
  286. * RSV_CTRL 0x001C[7:0] = 0x00, unlock ISO/CLK/Power control register
  287. */
  288. rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0);
  289. rtl8xxxu_disabled_to_emu(priv);
  290. ret = rtl8723a_emu_to_active(priv);
  291. if (ret)
  292. goto exit;
  293. /*
  294. * 0x0004[19] = 1, reset 8051
  295. */
  296. val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO + 2);
  297. val8 |= BIT(3);
  298. rtl8xxxu_write8(priv, REG_APS_FSMCO + 2, val8);
  299. /*
  300. * Enable MAC DMA/WMAC/SCHEDULE/SEC block
  301. * Set CR bit10 to enable 32k calibration.
  302. */
  303. val16 = rtl8xxxu_read16(priv, REG_CR);
  304. val16 |= (CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE |
  305. CR_TXDMA_ENABLE | CR_RXDMA_ENABLE |
  306. CR_PROTOCOL_ENABLE | CR_SCHEDULE_ENABLE |
  307. CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE |
  308. CR_SECURITY_ENABLE | CR_CALTIMER_ENABLE);
  309. rtl8xxxu_write16(priv, REG_CR, val16);
  310. /* For EFuse PG */
  311. val32 = rtl8xxxu_read32(priv, REG_EFUSE_CTRL);
  312. val32 &= ~(BIT(28) | BIT(29) | BIT(30));
  313. val32 |= (0x06 << 28);
  314. rtl8xxxu_write32(priv, REG_EFUSE_CTRL, val32);
  315. exit:
  316. return ret;
  317. }
  318. struct rtl8xxxu_fileops rtl8723au_fops = {
  319. .parse_efuse = rtl8723au_parse_efuse,
  320. .load_firmware = rtl8723au_load_firmware,
  321. .power_on = rtl8723au_power_on,
  322. .power_off = rtl8xxxu_power_off,
  323. .reset_8051 = rtl8xxxu_reset_8051,
  324. .llt_init = rtl8xxxu_init_llt_table,
  325. .init_phy_bb = rtl8xxxu_gen1_init_phy_bb,
  326. .init_phy_rf = rtl8723au_init_phy_rf,
  327. .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate,
  328. .config_channel = rtl8xxxu_gen1_config_channel,
  329. .parse_rx_desc = rtl8xxxu_parse_rxdesc16,
  330. .init_aggregation = rtl8xxxu_gen1_init_aggregation,
  331. .enable_rf = rtl8xxxu_gen1_enable_rf,
  332. .disable_rf = rtl8xxxu_gen1_disable_rf,
  333. .usb_quirks = rtl8xxxu_gen1_usb_quirks,
  334. .set_tx_power = rtl8xxxu_gen1_set_tx_power,
  335. .update_rate_mask = rtl8xxxu_update_rate_mask,
  336. .report_connect = rtl8xxxu_gen1_report_connect,
  337. .fill_txdesc = rtl8xxxu_fill_txdesc_v1,
  338. .writeN_block_size = 1024,
  339. .rx_agg_buf_size = 16000,
  340. .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
  341. .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16),
  342. .adda_1t_init = 0x0b1b25a0,
  343. .adda_1t_path_on = 0x0bdb25a0,
  344. .adda_2t_path_on_a = 0x04db25a4,
  345. .adda_2t_path_on_b = 0x0b1b25a4,
  346. .trxff_boundary = 0x27ff,
  347. .pbp_rx = PBP_PAGE_SIZE_128,
  348. .pbp_tx = PBP_PAGE_SIZE_128,
  349. .mactable = rtl8xxxu_gen1_mac_init_table,
  350. .total_page_num = TX_TOTAL_PAGE_NUM,
  351. .page_num_hi = TX_PAGE_NUM_HI_PQ,
  352. .page_num_lo = TX_PAGE_NUM_LO_PQ,
  353. .page_num_norm = TX_PAGE_NUM_NORM_PQ,
  354. };