rtl8xxxu_8192c.c 19 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589
  1. /*
  2. * RTL8XXXU mac80211 USB driver - 8188c/8188r/8192c 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. #ifdef CONFIG_RTL8XXXU_UNTESTED
  42. static struct rtl8xxxu_power_base rtl8192c_power_base = {
  43. .reg_0e00 = 0x07090c0c,
  44. .reg_0e04 = 0x01020405,
  45. .reg_0e08 = 0x00000000,
  46. .reg_086c = 0x00000000,
  47. .reg_0e10 = 0x0b0c0c0e,
  48. .reg_0e14 = 0x01030506,
  49. .reg_0e18 = 0x0b0c0d0e,
  50. .reg_0e1c = 0x01030509,
  51. .reg_0830 = 0x07090c0c,
  52. .reg_0834 = 0x01020405,
  53. .reg_0838 = 0x00000000,
  54. .reg_086c_2 = 0x00000000,
  55. .reg_083c = 0x0b0c0d0e,
  56. .reg_0848 = 0x01030509,
  57. .reg_084c = 0x0b0c0d0e,
  58. .reg_0868 = 0x01030509,
  59. };
  60. static struct rtl8xxxu_power_base rtl8188r_power_base = {
  61. .reg_0e00 = 0x06080808,
  62. .reg_0e04 = 0x00040406,
  63. .reg_0e08 = 0x00000000,
  64. .reg_086c = 0x00000000,
  65. .reg_0e10 = 0x04060608,
  66. .reg_0e14 = 0x00020204,
  67. .reg_0e18 = 0x04060608,
  68. .reg_0e1c = 0x00020204,
  69. .reg_0830 = 0x06080808,
  70. .reg_0834 = 0x00040406,
  71. .reg_0838 = 0x00000000,
  72. .reg_086c_2 = 0x00000000,
  73. .reg_083c = 0x04060608,
  74. .reg_0848 = 0x00020204,
  75. .reg_084c = 0x04060608,
  76. .reg_0868 = 0x00020204,
  77. };
  78. static struct rtl8xxxu_rfregval rtl8192cu_radioa_2t_init_table[] = {
  79. {0x00, 0x00030159}, {0x01, 0x00031284},
  80. {0x02, 0x00098000}, {0x03, 0x00018c63},
  81. {0x04, 0x000210e7}, {0x09, 0x0002044f},
  82. {0x0a, 0x0001adb1}, {0x0b, 0x00054867},
  83. {0x0c, 0x0008992e}, {0x0d, 0x0000e52c},
  84. {0x0e, 0x00039ce7}, {0x0f, 0x00000451},
  85. {0x19, 0x00000000}, {0x1a, 0x00010255},
  86. {0x1b, 0x00060a00}, {0x1c, 0x000fc378},
  87. {0x1d, 0x000a1250}, {0x1e, 0x0004445f},
  88. {0x1f, 0x00080001}, {0x20, 0x0000b614},
  89. {0x21, 0x0006c000}, {0x22, 0x00000000},
  90. {0x23, 0x00001558}, {0x24, 0x00000060},
  91. {0x25, 0x00000483}, {0x26, 0x0004f000},
  92. {0x27, 0x000ec7d9}, {0x28, 0x000577c0},
  93. {0x29, 0x00004783}, {0x2a, 0x00000001},
  94. {0x2b, 0x00021334}, {0x2a, 0x00000000},
  95. {0x2b, 0x00000054}, {0x2a, 0x00000001},
  96. {0x2b, 0x00000808}, {0x2b, 0x00053333},
  97. {0x2c, 0x0000000c}, {0x2a, 0x00000002},
  98. {0x2b, 0x00000808}, {0x2b, 0x0005b333},
  99. {0x2c, 0x0000000d}, {0x2a, 0x00000003},
  100. {0x2b, 0x00000808}, {0x2b, 0x00063333},
  101. {0x2c, 0x0000000d}, {0x2a, 0x00000004},
  102. {0x2b, 0x00000808}, {0x2b, 0x0006b333},
  103. {0x2c, 0x0000000d}, {0x2a, 0x00000005},
  104. {0x2b, 0x00000808}, {0x2b, 0x00073333},
  105. {0x2c, 0x0000000d}, {0x2a, 0x00000006},
  106. {0x2b, 0x00000709}, {0x2b, 0x0005b333},
  107. {0x2c, 0x0000000d}, {0x2a, 0x00000007},
  108. {0x2b, 0x00000709}, {0x2b, 0x00063333},
  109. {0x2c, 0x0000000d}, {0x2a, 0x00000008},
  110. {0x2b, 0x0000060a}, {0x2b, 0x0004b333},
  111. {0x2c, 0x0000000d}, {0x2a, 0x00000009},
  112. {0x2b, 0x0000060a}, {0x2b, 0x00053333},
  113. {0x2c, 0x0000000d}, {0x2a, 0x0000000a},
  114. {0x2b, 0x0000060a}, {0x2b, 0x0005b333},
  115. {0x2c, 0x0000000d}, {0x2a, 0x0000000b},
  116. {0x2b, 0x0000060a}, {0x2b, 0x00063333},
  117. {0x2c, 0x0000000d}, {0x2a, 0x0000000c},
  118. {0x2b, 0x0000060a}, {0x2b, 0x0006b333},
  119. {0x2c, 0x0000000d}, {0x2a, 0x0000000d},
  120. {0x2b, 0x0000060a}, {0x2b, 0x00073333},
  121. {0x2c, 0x0000000d}, {0x2a, 0x0000000e},
  122. {0x2b, 0x0000050b}, {0x2b, 0x00066666},
  123. {0x2c, 0x0000001a}, {0x2a, 0x000e0000},
  124. {0x10, 0x0004000f}, {0x11, 0x000e31fc},
  125. {0x10, 0x0006000f}, {0x11, 0x000ff9f8},
  126. {0x10, 0x0002000f}, {0x11, 0x000203f9},
  127. {0x10, 0x0003000f}, {0x11, 0x000ff500},
  128. {0x10, 0x00000000}, {0x11, 0x00000000},
  129. {0x10, 0x0008000f}, {0x11, 0x0003f100},
  130. {0x10, 0x0009000f}, {0x11, 0x00023100},
  131. {0x12, 0x00032000}, {0x12, 0x00071000},
  132. {0x12, 0x000b0000}, {0x12, 0x000fc000},
  133. {0x13, 0x000287b3}, {0x13, 0x000244b7},
  134. {0x13, 0x000204ab}, {0x13, 0x0001c49f},
  135. {0x13, 0x00018493}, {0x13, 0x0001429b},
  136. {0x13, 0x00010299}, {0x13, 0x0000c29c},
  137. {0x13, 0x000081a0}, {0x13, 0x000040ac},
  138. {0x13, 0x00000020}, {0x14, 0x0001944c},
  139. {0x14, 0x00059444}, {0x14, 0x0009944c},
  140. {0x14, 0x000d9444}, {0x15, 0x0000f424},
  141. {0x15, 0x0004f424}, {0x15, 0x0008f424},
  142. {0x15, 0x000cf424}, {0x16, 0x000e0330},
  143. {0x16, 0x000a0330}, {0x16, 0x00060330},
  144. {0x16, 0x00020330}, {0x00, 0x00010159},
  145. {0x18, 0x0000f401}, {0xfe, 0x00000000},
  146. {0xfe, 0x00000000}, {0x1f, 0x00080003},
  147. {0xfe, 0x00000000}, {0xfe, 0x00000000},
  148. {0x1e, 0x00044457}, {0x1f, 0x00080000},
  149. {0x00, 0x00030159},
  150. {0xff, 0xffffffff}
  151. };
  152. static struct rtl8xxxu_rfregval rtl8192cu_radiob_2t_init_table[] = {
  153. {0x00, 0x00030159}, {0x01, 0x00031284},
  154. {0x02, 0x00098000}, {0x03, 0x00018c63},
  155. {0x04, 0x000210e7}, {0x09, 0x0002044f},
  156. {0x0a, 0x0001adb1}, {0x0b, 0x00054867},
  157. {0x0c, 0x0008992e}, {0x0d, 0x0000e52c},
  158. {0x0e, 0x00039ce7}, {0x0f, 0x00000451},
  159. {0x12, 0x00032000}, {0x12, 0x00071000},
  160. {0x12, 0x000b0000}, {0x12, 0x000fc000},
  161. {0x13, 0x000287af}, {0x13, 0x000244b7},
  162. {0x13, 0x000204ab}, {0x13, 0x0001c49f},
  163. {0x13, 0x00018493}, {0x13, 0x00014297},
  164. {0x13, 0x00010295}, {0x13, 0x0000c298},
  165. {0x13, 0x0000819c}, {0x13, 0x000040a8},
  166. {0x13, 0x0000001c}, {0x14, 0x0001944c},
  167. {0x14, 0x00059444}, {0x14, 0x0009944c},
  168. {0x14, 0x000d9444}, {0x15, 0x0000f424},
  169. {0x15, 0x0004f424}, {0x15, 0x0008f424},
  170. {0x15, 0x000cf424}, {0x16, 0x000e0330},
  171. {0x16, 0x000a0330}, {0x16, 0x00060330},
  172. {0x16, 0x00020330},
  173. {0xff, 0xffffffff}
  174. };
  175. static struct rtl8xxxu_rfregval rtl8192cu_radioa_1t_init_table[] = {
  176. {0x00, 0x00030159}, {0x01, 0x00031284},
  177. {0x02, 0x00098000}, {0x03, 0x00018c63},
  178. {0x04, 0x000210e7}, {0x09, 0x0002044f},
  179. {0x0a, 0x0001adb1}, {0x0b, 0x00054867},
  180. {0x0c, 0x0008992e}, {0x0d, 0x0000e52c},
  181. {0x0e, 0x00039ce7}, {0x0f, 0x00000451},
  182. {0x19, 0x00000000}, {0x1a, 0x00010255},
  183. {0x1b, 0x00060a00}, {0x1c, 0x000fc378},
  184. {0x1d, 0x000a1250}, {0x1e, 0x0004445f},
  185. {0x1f, 0x00080001}, {0x20, 0x0000b614},
  186. {0x21, 0x0006c000}, {0x22, 0x00000000},
  187. {0x23, 0x00001558}, {0x24, 0x00000060},
  188. {0x25, 0x00000483}, {0x26, 0x0004f000},
  189. {0x27, 0x000ec7d9}, {0x28, 0x000577c0},
  190. {0x29, 0x00004783}, {0x2a, 0x00000001},
  191. {0x2b, 0x00021334}, {0x2a, 0x00000000},
  192. {0x2b, 0x00000054}, {0x2a, 0x00000001},
  193. {0x2b, 0x00000808}, {0x2b, 0x00053333},
  194. {0x2c, 0x0000000c}, {0x2a, 0x00000002},
  195. {0x2b, 0x00000808}, {0x2b, 0x0005b333},
  196. {0x2c, 0x0000000d}, {0x2a, 0x00000003},
  197. {0x2b, 0x00000808}, {0x2b, 0x00063333},
  198. {0x2c, 0x0000000d}, {0x2a, 0x00000004},
  199. {0x2b, 0x00000808}, {0x2b, 0x0006b333},
  200. {0x2c, 0x0000000d}, {0x2a, 0x00000005},
  201. {0x2b, 0x00000808}, {0x2b, 0x00073333},
  202. {0x2c, 0x0000000d}, {0x2a, 0x00000006},
  203. {0x2b, 0x00000709}, {0x2b, 0x0005b333},
  204. {0x2c, 0x0000000d}, {0x2a, 0x00000007},
  205. {0x2b, 0x00000709}, {0x2b, 0x00063333},
  206. {0x2c, 0x0000000d}, {0x2a, 0x00000008},
  207. {0x2b, 0x0000060a}, {0x2b, 0x0004b333},
  208. {0x2c, 0x0000000d}, {0x2a, 0x00000009},
  209. {0x2b, 0x0000060a}, {0x2b, 0x00053333},
  210. {0x2c, 0x0000000d}, {0x2a, 0x0000000a},
  211. {0x2b, 0x0000060a}, {0x2b, 0x0005b333},
  212. {0x2c, 0x0000000d}, {0x2a, 0x0000000b},
  213. {0x2b, 0x0000060a}, {0x2b, 0x00063333},
  214. {0x2c, 0x0000000d}, {0x2a, 0x0000000c},
  215. {0x2b, 0x0000060a}, {0x2b, 0x0006b333},
  216. {0x2c, 0x0000000d}, {0x2a, 0x0000000d},
  217. {0x2b, 0x0000060a}, {0x2b, 0x00073333},
  218. {0x2c, 0x0000000d}, {0x2a, 0x0000000e},
  219. {0x2b, 0x0000050b}, {0x2b, 0x00066666},
  220. {0x2c, 0x0000001a}, {0x2a, 0x000e0000},
  221. {0x10, 0x0004000f}, {0x11, 0x000e31fc},
  222. {0x10, 0x0006000f}, {0x11, 0x000ff9f8},
  223. {0x10, 0x0002000f}, {0x11, 0x000203f9},
  224. {0x10, 0x0003000f}, {0x11, 0x000ff500},
  225. {0x10, 0x00000000}, {0x11, 0x00000000},
  226. {0x10, 0x0008000f}, {0x11, 0x0003f100},
  227. {0x10, 0x0009000f}, {0x11, 0x00023100},
  228. {0x12, 0x00032000}, {0x12, 0x00071000},
  229. {0x12, 0x000b0000}, {0x12, 0x000fc000},
  230. {0x13, 0x000287b3}, {0x13, 0x000244b7},
  231. {0x13, 0x000204ab}, {0x13, 0x0001c49f},
  232. {0x13, 0x00018493}, {0x13, 0x0001429b},
  233. {0x13, 0x00010299}, {0x13, 0x0000c29c},
  234. {0x13, 0x000081a0}, {0x13, 0x000040ac},
  235. {0x13, 0x00000020}, {0x14, 0x0001944c},
  236. {0x14, 0x00059444}, {0x14, 0x0009944c},
  237. {0x14, 0x000d9444}, {0x15, 0x0000f405},
  238. {0x15, 0x0004f405}, {0x15, 0x0008f405},
  239. {0x15, 0x000cf405}, {0x16, 0x000e0330},
  240. {0x16, 0x000a0330}, {0x16, 0x00060330},
  241. {0x16, 0x00020330}, {0x00, 0x00010159},
  242. {0x18, 0x0000f401}, {0xfe, 0x00000000},
  243. {0xfe, 0x00000000}, {0x1f, 0x00080003},
  244. {0xfe, 0x00000000}, {0xfe, 0x00000000},
  245. {0x1e, 0x00044457}, {0x1f, 0x00080000},
  246. {0x00, 0x00030159},
  247. {0xff, 0xffffffff}
  248. };
  249. static struct rtl8xxxu_rfregval rtl8188ru_radioa_1t_highpa_table[] = {
  250. {0x00, 0x00030159}, {0x01, 0x00031284},
  251. {0x02, 0x00098000}, {0x03, 0x00018c63},
  252. {0x04, 0x000210e7}, {0x09, 0x0002044f},
  253. {0x0a, 0x0001adb0}, {0x0b, 0x00054867},
  254. {0x0c, 0x0008992e}, {0x0d, 0x0000e529},
  255. {0x0e, 0x00039ce7}, {0x0f, 0x00000451},
  256. {0x19, 0x00000000}, {0x1a, 0x00000255},
  257. {0x1b, 0x00060a00}, {0x1c, 0x000fc378},
  258. {0x1d, 0x000a1250}, {0x1e, 0x0004445f},
  259. {0x1f, 0x00080001}, {0x20, 0x0000b614},
  260. {0x21, 0x0006c000}, {0x22, 0x0000083c},
  261. {0x23, 0x00001558}, {0x24, 0x00000060},
  262. {0x25, 0x00000483}, {0x26, 0x0004f000},
  263. {0x27, 0x000ec7d9}, {0x28, 0x000977c0},
  264. {0x29, 0x00004783}, {0x2a, 0x00000001},
  265. {0x2b, 0x00021334}, {0x2a, 0x00000000},
  266. {0x2b, 0x00000054}, {0x2a, 0x00000001},
  267. {0x2b, 0x00000808}, {0x2b, 0x00053333},
  268. {0x2c, 0x0000000c}, {0x2a, 0x00000002},
  269. {0x2b, 0x00000808}, {0x2b, 0x0005b333},
  270. {0x2c, 0x0000000d}, {0x2a, 0x00000003},
  271. {0x2b, 0x00000808}, {0x2b, 0x00063333},
  272. {0x2c, 0x0000000d}, {0x2a, 0x00000004},
  273. {0x2b, 0x00000808}, {0x2b, 0x0006b333},
  274. {0x2c, 0x0000000d}, {0x2a, 0x00000005},
  275. {0x2b, 0x00000808}, {0x2b, 0x00073333},
  276. {0x2c, 0x0000000d}, {0x2a, 0x00000006},
  277. {0x2b, 0x00000709}, {0x2b, 0x0005b333},
  278. {0x2c, 0x0000000d}, {0x2a, 0x00000007},
  279. {0x2b, 0x00000709}, {0x2b, 0x00063333},
  280. {0x2c, 0x0000000d}, {0x2a, 0x00000008},
  281. {0x2b, 0x0000060a}, {0x2b, 0x0004b333},
  282. {0x2c, 0x0000000d}, {0x2a, 0x00000009},
  283. {0x2b, 0x0000060a}, {0x2b, 0x00053333},
  284. {0x2c, 0x0000000d}, {0x2a, 0x0000000a},
  285. {0x2b, 0x0000060a}, {0x2b, 0x0005b333},
  286. {0x2c, 0x0000000d}, {0x2a, 0x0000000b},
  287. {0x2b, 0x0000060a}, {0x2b, 0x00063333},
  288. {0x2c, 0x0000000d}, {0x2a, 0x0000000c},
  289. {0x2b, 0x0000060a}, {0x2b, 0x0006b333},
  290. {0x2c, 0x0000000d}, {0x2a, 0x0000000d},
  291. {0x2b, 0x0000060a}, {0x2b, 0x00073333},
  292. {0x2c, 0x0000000d}, {0x2a, 0x0000000e},
  293. {0x2b, 0x0000050b}, {0x2b, 0x00066666},
  294. {0x2c, 0x0000001a}, {0x2a, 0x000e0000},
  295. {0x10, 0x0004000f}, {0x11, 0x000e31fc},
  296. {0x10, 0x0006000f}, {0x11, 0x000ff9f8},
  297. {0x10, 0x0002000f}, {0x11, 0x000203f9},
  298. {0x10, 0x0003000f}, {0x11, 0x000ff500},
  299. {0x10, 0x00000000}, {0x11, 0x00000000},
  300. {0x10, 0x0008000f}, {0x11, 0x0003f100},
  301. {0x10, 0x0009000f}, {0x11, 0x00023100},
  302. {0x12, 0x000d8000}, {0x12, 0x00090000},
  303. {0x12, 0x00051000}, {0x12, 0x00012000},
  304. {0x13, 0x00028fb4}, {0x13, 0x00024fa8},
  305. {0x13, 0x000207a4}, {0x13, 0x0001c3b0},
  306. {0x13, 0x000183a4}, {0x13, 0x00014398},
  307. {0x13, 0x000101a4}, {0x13, 0x0000c198},
  308. {0x13, 0x000080a4}, {0x13, 0x00004098},
  309. {0x13, 0x00000000}, {0x14, 0x0001944c},
  310. {0x14, 0x00059444}, {0x14, 0x0009944c},
  311. {0x14, 0x000d9444}, {0x15, 0x0000f405},
  312. {0x15, 0x0004f405}, {0x15, 0x0008f405},
  313. {0x15, 0x000cf405}, {0x16, 0x000e0330},
  314. {0x16, 0x000a0330}, {0x16, 0x00060330},
  315. {0x16, 0x00020330}, {0x00, 0x00010159},
  316. {0x18, 0x0000f401}, {0xfe, 0x00000000},
  317. {0xfe, 0x00000000}, {0x1f, 0x00080003},
  318. {0xfe, 0x00000000}, {0xfe, 0x00000000},
  319. {0x1e, 0x00044457}, {0x1f, 0x00080000},
  320. {0x00, 0x00030159},
  321. {0xff, 0xffffffff}
  322. };
  323. static int rtl8192cu_load_firmware(struct rtl8xxxu_priv *priv)
  324. {
  325. char *fw_name;
  326. int ret;
  327. if (!priv->vendor_umc)
  328. fw_name = "rtlwifi/rtl8192cufw_TMSC.bin";
  329. else if (priv->chip_cut || priv->rtl_chip == RTL8192C)
  330. fw_name = "rtlwifi/rtl8192cufw_B.bin";
  331. else
  332. fw_name = "rtlwifi/rtl8192cufw_A.bin";
  333. ret = rtl8xxxu_load_firmware(priv, fw_name);
  334. return ret;
  335. }
  336. static int rtl8192cu_parse_efuse(struct rtl8xxxu_priv *priv)
  337. {
  338. struct rtl8192cu_efuse *efuse = &priv->efuse_wifi.efuse8192;
  339. int i;
  340. if (efuse->rtl_id != cpu_to_le16(0x8129))
  341. return -EINVAL;
  342. ether_addr_copy(priv->mac_addr, efuse->mac_addr);
  343. memcpy(priv->cck_tx_power_index_A,
  344. efuse->cck_tx_power_index_A,
  345. sizeof(efuse->cck_tx_power_index_A));
  346. memcpy(priv->cck_tx_power_index_B,
  347. efuse->cck_tx_power_index_B,
  348. sizeof(efuse->cck_tx_power_index_B));
  349. memcpy(priv->ht40_1s_tx_power_index_A,
  350. efuse->ht40_1s_tx_power_index_A,
  351. sizeof(efuse->ht40_1s_tx_power_index_A));
  352. memcpy(priv->ht40_1s_tx_power_index_B,
  353. efuse->ht40_1s_tx_power_index_B,
  354. sizeof(efuse->ht40_1s_tx_power_index_B));
  355. memcpy(priv->ht40_2s_tx_power_index_diff,
  356. efuse->ht40_2s_tx_power_index_diff,
  357. sizeof(efuse->ht40_2s_tx_power_index_diff));
  358. memcpy(priv->ht20_tx_power_index_diff,
  359. efuse->ht20_tx_power_index_diff,
  360. sizeof(efuse->ht20_tx_power_index_diff));
  361. memcpy(priv->ofdm_tx_power_index_diff,
  362. efuse->ofdm_tx_power_index_diff,
  363. sizeof(efuse->ofdm_tx_power_index_diff));
  364. memcpy(priv->ht40_max_power_offset,
  365. efuse->ht40_max_power_offset,
  366. sizeof(efuse->ht40_max_power_offset));
  367. memcpy(priv->ht20_max_power_offset,
  368. efuse->ht20_max_power_offset,
  369. sizeof(efuse->ht20_max_power_offset));
  370. dev_info(&priv->udev->dev, "Vendor: %.7s\n",
  371. efuse->vendor_name);
  372. dev_info(&priv->udev->dev, "Product: %.20s\n",
  373. efuse->device_name);
  374. priv->power_base = &rtl8192c_power_base;
  375. if (efuse->rf_regulatory & 0x20) {
  376. sprintf(priv->chip_name, "8188RU");
  377. priv->rtl_chip = RTL8188R;
  378. priv->hi_pa = 1;
  379. priv->no_pape = 1;
  380. priv->power_base = &rtl8188r_power_base;
  381. }
  382. if (rtl8xxxu_debug & RTL8XXXU_DEBUG_EFUSE) {
  383. unsigned char *raw = priv->efuse_wifi.raw;
  384. dev_info(&priv->udev->dev,
  385. "%s: dumping efuse (0x%02zx bytes):\n",
  386. __func__, sizeof(struct rtl8192cu_efuse));
  387. for (i = 0; i < sizeof(struct rtl8192cu_efuse); i += 8)
  388. dev_info(&priv->udev->dev, "%02x: %8ph\n", i, &raw[i]);
  389. }
  390. return 0;
  391. }
  392. static int rtl8192cu_init_phy_rf(struct rtl8xxxu_priv *priv)
  393. {
  394. struct rtl8xxxu_rfregval *rftable;
  395. int ret;
  396. if (priv->rtl_chip == RTL8188R) {
  397. rftable = rtl8188ru_radioa_1t_highpa_table;
  398. ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A);
  399. } else if (priv->rf_paths == 1) {
  400. rftable = rtl8192cu_radioa_1t_init_table;
  401. ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A);
  402. } else {
  403. rftable = rtl8192cu_radioa_2t_init_table;
  404. ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_A);
  405. if (ret)
  406. goto exit;
  407. rftable = rtl8192cu_radiob_2t_init_table;
  408. ret = rtl8xxxu_init_phy_rf(priv, rftable, RF_B);
  409. }
  410. exit:
  411. return ret;
  412. }
  413. static int rtl8192cu_power_on(struct rtl8xxxu_priv *priv)
  414. {
  415. u8 val8;
  416. u16 val16;
  417. u32 val32;
  418. int i;
  419. for (i = 100; i; i--) {
  420. val8 = rtl8xxxu_read8(priv, REG_APS_FSMCO);
  421. if (val8 & APS_FSMCO_PFM_ALDN)
  422. break;
  423. }
  424. if (!i) {
  425. pr_info("%s: Poll failed\n", __func__);
  426. return -ENODEV;
  427. }
  428. /*
  429. * RSV_CTRL 0x001C[7:0] = 0x00, unlock ISO/CLK/Power control register
  430. */
  431. rtl8xxxu_write8(priv, REG_RSV_CTRL, 0x0);
  432. rtl8xxxu_write8(priv, REG_SPS0_CTRL, 0x2b);
  433. udelay(100);
  434. val8 = rtl8xxxu_read8(priv, REG_LDOV12D_CTRL);
  435. if (!(val8 & LDOV12D_ENABLE)) {
  436. pr_info("%s: Enabling LDOV12D (%02x)\n", __func__, val8);
  437. val8 |= LDOV12D_ENABLE;
  438. rtl8xxxu_write8(priv, REG_LDOV12D_CTRL, val8);
  439. udelay(100);
  440. val8 = rtl8xxxu_read8(priv, REG_SYS_ISO_CTRL);
  441. val8 &= ~SYS_ISO_MD2PP;
  442. rtl8xxxu_write8(priv, REG_SYS_ISO_CTRL, val8);
  443. }
  444. /*
  445. * Auto enable WLAN
  446. */
  447. val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO);
  448. val16 |= APS_FSMCO_MAC_ENABLE;
  449. rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
  450. for (i = 1000; i; i--) {
  451. val16 = rtl8xxxu_read16(priv, REG_APS_FSMCO);
  452. if (!(val16 & APS_FSMCO_MAC_ENABLE))
  453. break;
  454. }
  455. if (!i) {
  456. pr_info("%s: FSMCO_MAC_ENABLE poll failed\n", __func__);
  457. return -EBUSY;
  458. }
  459. /*
  460. * Enable radio, GPIO, LED
  461. */
  462. val16 = APS_FSMCO_HW_SUSPEND | APS_FSMCO_ENABLE_POWERDOWN |
  463. APS_FSMCO_PFM_ALDN;
  464. rtl8xxxu_write16(priv, REG_APS_FSMCO, val16);
  465. /*
  466. * Release RF digital isolation
  467. */
  468. val16 = rtl8xxxu_read16(priv, REG_SYS_ISO_CTRL);
  469. val16 &= ~SYS_ISO_DIOR;
  470. rtl8xxxu_write16(priv, REG_SYS_ISO_CTRL, val16);
  471. val8 = rtl8xxxu_read8(priv, REG_APSD_CTRL);
  472. val8 &= ~APSD_CTRL_OFF;
  473. rtl8xxxu_write8(priv, REG_APSD_CTRL, val8);
  474. for (i = 200; i; i--) {
  475. val8 = rtl8xxxu_read8(priv, REG_APSD_CTRL);
  476. if (!(val8 & APSD_CTRL_OFF_STATUS))
  477. break;
  478. }
  479. if (!i) {
  480. pr_info("%s: APSD_CTRL poll failed\n", __func__);
  481. return -EBUSY;
  482. }
  483. /*
  484. * Enable MAC DMA/WMAC/SCHEDULE/SEC block
  485. */
  486. val16 = rtl8xxxu_read16(priv, REG_CR);
  487. val16 |= CR_HCI_TXDMA_ENABLE | CR_HCI_RXDMA_ENABLE |
  488. CR_TXDMA_ENABLE | CR_RXDMA_ENABLE | CR_PROTOCOL_ENABLE |
  489. CR_SCHEDULE_ENABLE | CR_MAC_TX_ENABLE | CR_MAC_RX_ENABLE;
  490. rtl8xxxu_write16(priv, REG_CR, val16);
  491. rtl8xxxu_write8(priv, 0xfe10, 0x19);
  492. /*
  493. * Workaround for 8188RU LNA power leakage problem.
  494. */
  495. if (priv->rtl_chip == RTL8188R) {
  496. val32 = rtl8xxxu_read32(priv, REG_FPGA0_XCD_RF_PARM);
  497. val32 &= ~BIT(1);
  498. rtl8xxxu_write32(priv, REG_FPGA0_XCD_RF_PARM, val32);
  499. }
  500. return 0;
  501. }
  502. struct rtl8xxxu_fileops rtl8192cu_fops = {
  503. .parse_efuse = rtl8192cu_parse_efuse,
  504. .load_firmware = rtl8192cu_load_firmware,
  505. .power_on = rtl8192cu_power_on,
  506. .power_off = rtl8xxxu_power_off,
  507. .reset_8051 = rtl8xxxu_reset_8051,
  508. .llt_init = rtl8xxxu_init_llt_table,
  509. .init_phy_bb = rtl8xxxu_gen1_init_phy_bb,
  510. .init_phy_rf = rtl8192cu_init_phy_rf,
  511. .phy_iq_calibrate = rtl8xxxu_gen1_phy_iq_calibrate,
  512. .config_channel = rtl8xxxu_gen1_config_channel,
  513. .parse_rx_desc = rtl8xxxu_parse_rxdesc16,
  514. .init_aggregation = rtl8xxxu_gen1_init_aggregation,
  515. .enable_rf = rtl8xxxu_gen1_enable_rf,
  516. .disable_rf = rtl8xxxu_gen1_disable_rf,
  517. .usb_quirks = rtl8xxxu_gen1_usb_quirks,
  518. .set_tx_power = rtl8xxxu_gen1_set_tx_power,
  519. .update_rate_mask = rtl8xxxu_update_rate_mask,
  520. .report_connect = rtl8xxxu_gen1_report_connect,
  521. .fill_txdesc = rtl8xxxu_fill_txdesc_v1,
  522. .writeN_block_size = 128,
  523. .rx_agg_buf_size = 16000,
  524. .tx_desc_size = sizeof(struct rtl8xxxu_txdesc32),
  525. .rx_desc_size = sizeof(struct rtl8xxxu_rxdesc16),
  526. .adda_1t_init = 0x0b1b25a0,
  527. .adda_1t_path_on = 0x0bdb25a0,
  528. .adda_2t_path_on_a = 0x04db25a4,
  529. .adda_2t_path_on_b = 0x0b1b25a4,
  530. .trxff_boundary = 0x27ff,
  531. .pbp_rx = PBP_PAGE_SIZE_128,
  532. .pbp_tx = PBP_PAGE_SIZE_128,
  533. .mactable = rtl8xxxu_gen1_mac_init_table,
  534. .total_page_num = TX_TOTAL_PAGE_NUM,
  535. .page_num_hi = TX_PAGE_NUM_HI_PQ,
  536. .page_num_lo = TX_PAGE_NUM_LO_PQ,
  537. .page_num_norm = TX_PAGE_NUM_NORM_PQ,
  538. };
  539. #endif