rtl8225.c 32 KB

1234567891011121314151617181920212223242526272829303132333435363738394041424344454647484950515253545556575859606162636465666768697071727374757677787980818283848586878889909192939495969798991001011021031041051061071081091101111121131141151161171181191201211221231241251261271281291301311321331341351361371381391401411421431441451461471481491501511521531541551561571581591601611621631641651661671681691701711721731741751761771781791801811821831841851861871881891901911921931941951961971981992002012022032042052062072082092102112122132142152162172182192202212222232242252262272282292302312322332342352362372382392402412422432442452462472482492502512522532542552562572582592602612622632642652662672682692702712722732742752762772782792802812822832842852862872882892902912922932942952962972982993003013023033043053063073083093103113123133143153163173183193203213223233243253263273283293303313323333343353363373383393403413423433443453463473483493503513523533543553563573583593603613623633643653663673683693703713723733743753763773783793803813823833843853863873883893903913923933943953963973983994004014024034044054064074084094104114124134144154164174184194204214224234244254264274284294304314324334344354364374384394404414424434444454464474484494504514524534544554564574584594604614624634644654664674684694704714724734744754764774784794804814824834844854864874884894904914924934944954964974984995005015025035045055065075085095105115125135145155165175185195205215225235245255265275285295305315325335345355365375385395405415425435445455465475485495505515525535545555565575585595605615625635645655665675685695705715725735745755765775785795805815825835845855865875885895905915925935945955965975985996006016026036046056066076086096106116126136146156166176186196206216226236246256266276286296306316326336346356366376386396406416426436446456466476486496506516526536546556566576586596606616626636646656666676686696706716726736746756766776786796806816826836846856866876886896906916926936946956966976986997007017027037047057067077087097107117127137147157167177187197207217227237247257267277287297307317327337347357367377387397407417427437447457467477487497507517527537547557567577587597607617627637647657667677687697707717727737747757767777787797807817827837847857867877887897907917927937947957967977987998008018028038048058068078088098108118128138148158168178188198208218228238248258268278288298308318328338348358368378388398408418428438448458468478488498508518528538548558568578588598608618628638648658668678688698708718728738748758768778788798808818828838848858868878888898908918928938948958968978988999009019029039049059069079089099109119129139149159169179189199209219229239249259269279289299309319329339349359369379389399409419429439449459469479489499509519529539549559569579589599609619629639649659669679689699709719729739749759769779789799809819829839849859869879889899909919929939949959969979989991000100110021003100410051006100710081009101010111012101310141015101610171018101910201021102210231024102510261027102810291030103110321033103410351036103710381039104010411042104310441045104610471048104910501051105210531054
  1. /*
  2. * Radio tuning for RTL8225 on RTL8187
  3. *
  4. * Copyright 2007 Michael Wu <flamingice@sourmilk.net>
  5. * Copyright 2007 Andrea Merello <andrea.merello@gmail.com>
  6. *
  7. * Based on the r8187 driver, which is:
  8. * Copyright 2005 Andrea Merello <andrea.merello@gmail.com>, et al.
  9. *
  10. * Magic delays, register offsets, and phy value tables below are
  11. * taken from the original r8187 driver sources. Thanks to Realtek
  12. * for their support!
  13. *
  14. * This program is free software; you can redistribute it and/or modify
  15. * it under the terms of the GNU General Public License version 2 as
  16. * published by the Free Software Foundation.
  17. */
  18. #include <linux/usb.h>
  19. #include <net/mac80211.h>
  20. #include "rtl8187.h"
  21. #include "rtl8225.h"
  22. u8 rtl818x_ioread8_idx(struct rtl8187_priv *priv,
  23. u8 *addr, u8 idx)
  24. {
  25. u8 val;
  26. mutex_lock(&priv->io_mutex);
  27. usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
  28. RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
  29. (unsigned long)addr, idx & 0x03,
  30. &priv->io_dmabuf->bits8, sizeof(val), HZ / 2);
  31. val = priv->io_dmabuf->bits8;
  32. mutex_unlock(&priv->io_mutex);
  33. return val;
  34. }
  35. u16 rtl818x_ioread16_idx(struct rtl8187_priv *priv,
  36. __le16 *addr, u8 idx)
  37. {
  38. __le16 val;
  39. mutex_lock(&priv->io_mutex);
  40. usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
  41. RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
  42. (unsigned long)addr, idx & 0x03,
  43. &priv->io_dmabuf->bits16, sizeof(val), HZ / 2);
  44. val = priv->io_dmabuf->bits16;
  45. mutex_unlock(&priv->io_mutex);
  46. return le16_to_cpu(val);
  47. }
  48. u32 rtl818x_ioread32_idx(struct rtl8187_priv *priv,
  49. __le32 *addr, u8 idx)
  50. {
  51. __le32 val;
  52. mutex_lock(&priv->io_mutex);
  53. usb_control_msg(priv->udev, usb_rcvctrlpipe(priv->udev, 0),
  54. RTL8187_REQ_GET_REG, RTL8187_REQT_READ,
  55. (unsigned long)addr, idx & 0x03,
  56. &priv->io_dmabuf->bits32, sizeof(val), HZ / 2);
  57. val = priv->io_dmabuf->bits32;
  58. mutex_unlock(&priv->io_mutex);
  59. return le32_to_cpu(val);
  60. }
  61. void rtl818x_iowrite8_idx(struct rtl8187_priv *priv,
  62. u8 *addr, u8 val, u8 idx)
  63. {
  64. mutex_lock(&priv->io_mutex);
  65. priv->io_dmabuf->bits8 = val;
  66. usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
  67. RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
  68. (unsigned long)addr, idx & 0x03,
  69. &priv->io_dmabuf->bits8, sizeof(val), HZ / 2);
  70. mutex_unlock(&priv->io_mutex);
  71. }
  72. void rtl818x_iowrite16_idx(struct rtl8187_priv *priv,
  73. __le16 *addr, u16 val, u8 idx)
  74. {
  75. mutex_lock(&priv->io_mutex);
  76. priv->io_dmabuf->bits16 = cpu_to_le16(val);
  77. usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
  78. RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
  79. (unsigned long)addr, idx & 0x03,
  80. &priv->io_dmabuf->bits16, sizeof(val), HZ / 2);
  81. mutex_unlock(&priv->io_mutex);
  82. }
  83. void rtl818x_iowrite32_idx(struct rtl8187_priv *priv,
  84. __le32 *addr, u32 val, u8 idx)
  85. {
  86. mutex_lock(&priv->io_mutex);
  87. priv->io_dmabuf->bits32 = cpu_to_le32(val);
  88. usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
  89. RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
  90. (unsigned long)addr, idx & 0x03,
  91. &priv->io_dmabuf->bits32, sizeof(val), HZ / 2);
  92. mutex_unlock(&priv->io_mutex);
  93. }
  94. static void rtl8225_write_bitbang(struct ieee80211_hw *dev, u8 addr, u16 data)
  95. {
  96. struct rtl8187_priv *priv = dev->priv;
  97. u16 reg80, reg84, reg82;
  98. u32 bangdata;
  99. int i;
  100. bangdata = (data << 4) | (addr & 0xf);
  101. reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput) & 0xfff3;
  102. reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
  103. rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x7);
  104. reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
  105. rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x7);
  106. udelay(10);
  107. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
  108. udelay(2);
  109. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
  110. udelay(10);
  111. for (i = 15; i >= 0; i--) {
  112. u16 reg = reg80 | (bangdata & (1 << i)) >> i;
  113. if (i & 1)
  114. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
  115. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
  116. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg | (1 << 1));
  117. if (!(i & 1))
  118. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
  119. }
  120. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
  121. udelay(10);
  122. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
  123. rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
  124. }
  125. static void rtl8225_write_8051(struct ieee80211_hw *dev, u8 addr, __le16 data)
  126. {
  127. struct rtl8187_priv *priv = dev->priv;
  128. u16 reg80, reg82, reg84;
  129. reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
  130. reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
  131. reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
  132. reg80 &= ~(0x3 << 2);
  133. reg84 &= ~0xF;
  134. rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x0007);
  135. rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x0007);
  136. udelay(10);
  137. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
  138. udelay(2);
  139. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
  140. udelay(10);
  141. mutex_lock(&priv->io_mutex);
  142. priv->io_dmabuf->bits16 = data;
  143. usb_control_msg(priv->udev, usb_sndctrlpipe(priv->udev, 0),
  144. RTL8187_REQ_SET_REG, RTL8187_REQT_WRITE,
  145. addr, 0x8225, &priv->io_dmabuf->bits16, sizeof(data),
  146. HZ / 2);
  147. mutex_unlock(&priv->io_mutex);
  148. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
  149. udelay(10);
  150. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
  151. rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
  152. }
  153. static void rtl8225_write(struct ieee80211_hw *dev, u8 addr, u16 data)
  154. {
  155. struct rtl8187_priv *priv = dev->priv;
  156. if (priv->asic_rev)
  157. rtl8225_write_8051(dev, addr, cpu_to_le16(data));
  158. else
  159. rtl8225_write_bitbang(dev, addr, data);
  160. }
  161. static u16 rtl8225_read(struct ieee80211_hw *dev, u8 addr)
  162. {
  163. struct rtl8187_priv *priv = dev->priv;
  164. u16 reg80, reg82, reg84, out;
  165. int i;
  166. reg80 = rtl818x_ioread16(priv, &priv->map->RFPinsOutput);
  167. reg82 = rtl818x_ioread16(priv, &priv->map->RFPinsEnable);
  168. reg84 = rtl818x_ioread16(priv, &priv->map->RFPinsSelect);
  169. reg80 &= ~0xF;
  170. rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82 | 0x000F);
  171. rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84 | 0x000F);
  172. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80 | (1 << 2));
  173. udelay(4);
  174. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg80);
  175. udelay(5);
  176. for (i = 4; i >= 0; i--) {
  177. u16 reg = reg80 | ((addr >> i) & 1);
  178. if (!(i & 1)) {
  179. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
  180. udelay(1);
  181. }
  182. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
  183. reg | (1 << 1));
  184. udelay(2);
  185. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
  186. reg | (1 << 1));
  187. udelay(2);
  188. if (i & 1) {
  189. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, reg);
  190. udelay(1);
  191. }
  192. }
  193. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
  194. reg80 | (1 << 3) | (1 << 1));
  195. udelay(2);
  196. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
  197. reg80 | (1 << 3));
  198. udelay(2);
  199. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
  200. reg80 | (1 << 3));
  201. udelay(2);
  202. out = 0;
  203. for (i = 11; i >= 0; i--) {
  204. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
  205. reg80 | (1 << 3));
  206. udelay(1);
  207. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
  208. reg80 | (1 << 3) | (1 << 1));
  209. udelay(2);
  210. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
  211. reg80 | (1 << 3) | (1 << 1));
  212. udelay(2);
  213. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
  214. reg80 | (1 << 3) | (1 << 1));
  215. udelay(2);
  216. if (rtl818x_ioread16(priv, &priv->map->RFPinsInput) & (1 << 1))
  217. out |= 1 << i;
  218. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
  219. reg80 | (1 << 3));
  220. udelay(2);
  221. }
  222. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput,
  223. reg80 | (1 << 3) | (1 << 2));
  224. udelay(2);
  225. rtl818x_iowrite16(priv, &priv->map->RFPinsEnable, reg82);
  226. rtl818x_iowrite16(priv, &priv->map->RFPinsSelect, reg84);
  227. rtl818x_iowrite16(priv, &priv->map->RFPinsOutput, 0x03A0);
  228. return out;
  229. }
  230. static const u16 rtl8225bcd_rxgain[] = {
  231. 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
  232. 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
  233. 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
  234. 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
  235. 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
  236. 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
  237. 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
  238. 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
  239. 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
  240. 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
  241. 0x07aa, 0x07ab, 0x07ac, 0x07ad, 0x07b0, 0x07b1, 0x07b2, 0x07b3,
  242. 0x07b4, 0x07b5, 0x07b8, 0x07b9, 0x07ba, 0x07bb, 0x07bb
  243. };
  244. static const u8 rtl8225_agc[] = {
  245. 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e, 0x9e,
  246. 0x9d, 0x9c, 0x9b, 0x9a, 0x99, 0x98, 0x97, 0x96,
  247. 0x95, 0x94, 0x93, 0x92, 0x91, 0x90, 0x8f, 0x8e,
  248. 0x8d, 0x8c, 0x8b, 0x8a, 0x89, 0x88, 0x87, 0x86,
  249. 0x85, 0x84, 0x83, 0x82, 0x81, 0x80, 0x3f, 0x3e,
  250. 0x3d, 0x3c, 0x3b, 0x3a, 0x39, 0x38, 0x37, 0x36,
  251. 0x35, 0x34, 0x33, 0x32, 0x31, 0x30, 0x2f, 0x2e,
  252. 0x2d, 0x2c, 0x2b, 0x2a, 0x29, 0x28, 0x27, 0x26,
  253. 0x25, 0x24, 0x23, 0x22, 0x21, 0x20, 0x1f, 0x1e,
  254. 0x1d, 0x1c, 0x1b, 0x1a, 0x19, 0x18, 0x17, 0x16,
  255. 0x15, 0x14, 0x13, 0x12, 0x11, 0x10, 0x0f, 0x0e,
  256. 0x0d, 0x0c, 0x0b, 0x0a, 0x09, 0x08, 0x07, 0x06,
  257. 0x05, 0x04, 0x03, 0x02, 0x01, 0x01, 0x01, 0x01,
  258. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  259. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  260. 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01
  261. };
  262. static const u8 rtl8225_gain[] = {
  263. 0x23, 0x88, 0x7c, 0xa5, /* -82dBm */
  264. 0x23, 0x88, 0x7c, 0xb5, /* -82dBm */
  265. 0x23, 0x88, 0x7c, 0xc5, /* -82dBm */
  266. 0x33, 0x80, 0x79, 0xc5, /* -78dBm */
  267. 0x43, 0x78, 0x76, 0xc5, /* -74dBm */
  268. 0x53, 0x60, 0x73, 0xc5, /* -70dBm */
  269. 0x63, 0x58, 0x70, 0xc5, /* -66dBm */
  270. };
  271. static const u8 rtl8225_threshold[] = {
  272. 0x8d, 0x8d, 0x8d, 0x8d, 0x9d, 0xad, 0xbd
  273. };
  274. static const u8 rtl8225_tx_gain_cck_ofdm[] = {
  275. 0x02, 0x06, 0x0e, 0x1e, 0x3e, 0x7e
  276. };
  277. static const u8 rtl8225_tx_power_cck[] = {
  278. 0x18, 0x17, 0x15, 0x11, 0x0c, 0x08, 0x04, 0x02,
  279. 0x1b, 0x1a, 0x17, 0x13, 0x0e, 0x09, 0x04, 0x02,
  280. 0x1f, 0x1e, 0x1a, 0x15, 0x10, 0x0a, 0x05, 0x02,
  281. 0x22, 0x21, 0x1d, 0x18, 0x11, 0x0b, 0x06, 0x02,
  282. 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03,
  283. 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03
  284. };
  285. static const u8 rtl8225_tx_power_cck_ch14[] = {
  286. 0x18, 0x17, 0x15, 0x0c, 0x00, 0x00, 0x00, 0x00,
  287. 0x1b, 0x1a, 0x17, 0x0e, 0x00, 0x00, 0x00, 0x00,
  288. 0x1f, 0x1e, 0x1a, 0x0f, 0x00, 0x00, 0x00, 0x00,
  289. 0x22, 0x21, 0x1d, 0x11, 0x00, 0x00, 0x00, 0x00,
  290. 0x26, 0x25, 0x21, 0x13, 0x00, 0x00, 0x00, 0x00,
  291. 0x2b, 0x2a, 0x25, 0x15, 0x00, 0x00, 0x00, 0x00
  292. };
  293. static const u8 rtl8225_tx_power_ofdm[] = {
  294. 0x80, 0x90, 0xa2, 0xb5, 0xcb, 0xe4
  295. };
  296. static const u32 rtl8225_chan[] = {
  297. 0x085c, 0x08dc, 0x095c, 0x09dc, 0x0a5c, 0x0adc, 0x0b5c,
  298. 0x0bdc, 0x0c5c, 0x0cdc, 0x0d5c, 0x0ddc, 0x0e5c, 0x0f72
  299. };
  300. static void rtl8225_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
  301. {
  302. struct rtl8187_priv *priv = dev->priv;
  303. u8 cck_power, ofdm_power;
  304. const u8 *tmp;
  305. u32 reg;
  306. int i;
  307. cck_power = priv->channels[channel - 1].hw_value & 0xF;
  308. ofdm_power = priv->channels[channel - 1].hw_value >> 4;
  309. cck_power = min(cck_power, (u8)11);
  310. if (ofdm_power > (u8)15)
  311. ofdm_power = 25;
  312. else
  313. ofdm_power += 10;
  314. rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
  315. rtl8225_tx_gain_cck_ofdm[cck_power / 6] >> 1);
  316. if (channel == 14)
  317. tmp = &rtl8225_tx_power_cck_ch14[(cck_power % 6) * 8];
  318. else
  319. tmp = &rtl8225_tx_power_cck[(cck_power % 6) * 8];
  320. for (i = 0; i < 8; i++)
  321. rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
  322. msleep(1); // FIXME: optional?
  323. /* anaparam2 on */
  324. rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
  325. reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
  326. rtl818x_iowrite8(priv, &priv->map->CONFIG3,
  327. reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
  328. rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
  329. RTL8187_RTL8225_ANAPARAM2_ON);
  330. rtl818x_iowrite8(priv, &priv->map->CONFIG3,
  331. reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
  332. rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
  333. rtl8225_write_phy_ofdm(dev, 2, 0x42);
  334. rtl8225_write_phy_ofdm(dev, 6, 0x00);
  335. rtl8225_write_phy_ofdm(dev, 8, 0x00);
  336. rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
  337. rtl8225_tx_gain_cck_ofdm[ofdm_power / 6] >> 1);
  338. tmp = &rtl8225_tx_power_ofdm[ofdm_power % 6];
  339. rtl8225_write_phy_ofdm(dev, 5, *tmp);
  340. rtl8225_write_phy_ofdm(dev, 7, *tmp);
  341. msleep(1);
  342. }
  343. static void rtl8225_rf_init(struct ieee80211_hw *dev)
  344. {
  345. struct rtl8187_priv *priv = dev->priv;
  346. int i;
  347. rtl8225_write(dev, 0x0, 0x067);
  348. rtl8225_write(dev, 0x1, 0xFE0);
  349. rtl8225_write(dev, 0x2, 0x44D);
  350. rtl8225_write(dev, 0x3, 0x441);
  351. rtl8225_write(dev, 0x4, 0x486);
  352. rtl8225_write(dev, 0x5, 0xBC0);
  353. rtl8225_write(dev, 0x6, 0xAE6);
  354. rtl8225_write(dev, 0x7, 0x82A);
  355. rtl8225_write(dev, 0x8, 0x01F);
  356. rtl8225_write(dev, 0x9, 0x334);
  357. rtl8225_write(dev, 0xA, 0xFD4);
  358. rtl8225_write(dev, 0xB, 0x391);
  359. rtl8225_write(dev, 0xC, 0x050);
  360. rtl8225_write(dev, 0xD, 0x6DB);
  361. rtl8225_write(dev, 0xE, 0x029);
  362. rtl8225_write(dev, 0xF, 0x914); msleep(100);
  363. rtl8225_write(dev, 0x2, 0xC4D); msleep(200);
  364. rtl8225_write(dev, 0x2, 0x44D); msleep(200);
  365. if (!(rtl8225_read(dev, 6) & (1 << 7))) {
  366. rtl8225_write(dev, 0x02, 0x0c4d);
  367. msleep(200);
  368. rtl8225_write(dev, 0x02, 0x044d);
  369. msleep(100);
  370. if (!(rtl8225_read(dev, 6) & (1 << 7)))
  371. wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n",
  372. rtl8225_read(dev, 6));
  373. }
  374. rtl8225_write(dev, 0x0, 0x127);
  375. for (i = 0; i < ARRAY_SIZE(rtl8225bcd_rxgain); i++) {
  376. rtl8225_write(dev, 0x1, i + 1);
  377. rtl8225_write(dev, 0x2, rtl8225bcd_rxgain[i]);
  378. }
  379. rtl8225_write(dev, 0x0, 0x027);
  380. rtl8225_write(dev, 0x0, 0x22F);
  381. for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
  382. rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
  383. rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
  384. }
  385. msleep(1);
  386. rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
  387. rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
  388. rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
  389. rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
  390. rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
  391. rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
  392. rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
  393. rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
  394. rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
  395. rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
  396. rtl8225_write_phy_ofdm(dev, 0x0a, 0x09);
  397. rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
  398. rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
  399. rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
  400. rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
  401. rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
  402. rtl8225_write_phy_ofdm(dev, 0x11, 0x06);
  403. rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
  404. rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
  405. rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
  406. rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
  407. rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
  408. rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
  409. rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
  410. rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
  411. rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
  412. rtl8225_write_phy_ofdm(dev, 0x1b, 0x76);
  413. rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
  414. rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
  415. rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
  416. rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
  417. rtl8225_write_phy_ofdm(dev, 0x21, 0x27);
  418. rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
  419. rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
  420. rtl8225_write_phy_ofdm(dev, 0x25, 0x20);
  421. rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
  422. rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
  423. rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
  424. rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
  425. rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
  426. rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
  427. rtl8225_write_phy_cck(dev, 0x00, 0x98);
  428. rtl8225_write_phy_cck(dev, 0x03, 0x20);
  429. rtl8225_write_phy_cck(dev, 0x04, 0x7e);
  430. rtl8225_write_phy_cck(dev, 0x05, 0x12);
  431. rtl8225_write_phy_cck(dev, 0x06, 0xfc);
  432. rtl8225_write_phy_cck(dev, 0x07, 0x78);
  433. rtl8225_write_phy_cck(dev, 0x08, 0x2e);
  434. rtl8225_write_phy_cck(dev, 0x10, 0x9b);
  435. rtl8225_write_phy_cck(dev, 0x11, 0x88);
  436. rtl8225_write_phy_cck(dev, 0x12, 0x47);
  437. rtl8225_write_phy_cck(dev, 0x13, 0xd0);
  438. rtl8225_write_phy_cck(dev, 0x19, 0x00);
  439. rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
  440. rtl8225_write_phy_cck(dev, 0x1b, 0x08);
  441. rtl8225_write_phy_cck(dev, 0x40, 0x86);
  442. rtl8225_write_phy_cck(dev, 0x41, 0x8d);
  443. rtl8225_write_phy_cck(dev, 0x42, 0x15);
  444. rtl8225_write_phy_cck(dev, 0x43, 0x18);
  445. rtl8225_write_phy_cck(dev, 0x44, 0x1f);
  446. rtl8225_write_phy_cck(dev, 0x45, 0x1e);
  447. rtl8225_write_phy_cck(dev, 0x46, 0x1a);
  448. rtl8225_write_phy_cck(dev, 0x47, 0x15);
  449. rtl8225_write_phy_cck(dev, 0x48, 0x10);
  450. rtl8225_write_phy_cck(dev, 0x49, 0x0a);
  451. rtl8225_write_phy_cck(dev, 0x4a, 0x05);
  452. rtl8225_write_phy_cck(dev, 0x4b, 0x02);
  453. rtl8225_write_phy_cck(dev, 0x4c, 0x05);
  454. rtl818x_iowrite8(priv, &priv->map->TESTR, 0x0D);
  455. rtl8225_rf_set_tx_power(dev, 1);
  456. /* RX antenna default to A */
  457. rtl8225_write_phy_cck(dev, 0x10, 0x9b); /* B: 0xDB */
  458. rtl8225_write_phy_ofdm(dev, 0x26, 0x90); /* B: 0x10 */
  459. rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
  460. msleep(1);
  461. rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
  462. /* set sensitivity */
  463. rtl8225_write(dev, 0x0c, 0x50);
  464. rtl8225_write_phy_ofdm(dev, 0x0d, rtl8225_gain[2 * 4]);
  465. rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225_gain[2 * 4 + 2]);
  466. rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225_gain[2 * 4 + 3]);
  467. rtl8225_write_phy_ofdm(dev, 0x23, rtl8225_gain[2 * 4 + 1]);
  468. rtl8225_write_phy_cck(dev, 0x41, rtl8225_threshold[2]);
  469. }
  470. static const u8 rtl8225z2_agc[] = {
  471. 0x5e, 0x5e, 0x5e, 0x5e, 0x5d, 0x5b, 0x59, 0x57, 0x55, 0x53, 0x51, 0x4f,
  472. 0x4d, 0x4b, 0x49, 0x47, 0x45, 0x43, 0x41, 0x3f, 0x3d, 0x3b, 0x39, 0x37,
  473. 0x35, 0x33, 0x31, 0x2f, 0x2d, 0x2b, 0x29, 0x27, 0x25, 0x23, 0x21, 0x1f,
  474. 0x1d, 0x1b, 0x19, 0x17, 0x15, 0x13, 0x11, 0x0f, 0x0d, 0x0b, 0x09, 0x07,
  475. 0x05, 0x03, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01, 0x01,
  476. 0x01, 0x01, 0x01, 0x01, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19, 0x19,
  477. 0x19, 0x20, 0x21, 0x22, 0x23, 0x24, 0x25, 0x26, 0x26, 0x27, 0x27, 0x28,
  478. 0x28, 0x29, 0x2a, 0x2a, 0x2a, 0x2b, 0x2b, 0x2b, 0x2c, 0x2c, 0x2c, 0x2d,
  479. 0x2d, 0x2d, 0x2d, 0x2e, 0x2e, 0x2e, 0x2e, 0x2f, 0x2f, 0x2f, 0x30, 0x30,
  480. 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31,
  481. 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31, 0x31
  482. };
  483. static const u8 rtl8225z2_ofdm[] = {
  484. 0x10, 0x0d, 0x01, 0x00, 0x14, 0xfb, 0xfb, 0x60,
  485. 0x00, 0x60, 0x00, 0x00, 0x00, 0x5c, 0x00, 0x00,
  486. 0x40, 0x00, 0x40, 0x00, 0x00, 0x00, 0xa8, 0x26,
  487. 0x32, 0x33, 0x07, 0xa5, 0x6f, 0x55, 0xc8, 0xb3,
  488. 0x0a, 0xe1, 0x2C, 0x8a, 0x86, 0x83, 0x34, 0x0f,
  489. 0x4f, 0x24, 0x6f, 0xc2, 0x6b, 0x40, 0x80, 0x00,
  490. 0xc0, 0xc1, 0x58, 0xf1, 0x00, 0xe4, 0x90, 0x3e,
  491. 0x6d, 0x3c, 0xfb, 0x07
  492. };
  493. static const u8 rtl8225z2_tx_power_cck_ch14[] = {
  494. 0x36, 0x35, 0x2e, 0x1b, 0x00, 0x00, 0x00, 0x00,
  495. 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
  496. 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00,
  497. 0x30, 0x2f, 0x29, 0x15, 0x00, 0x00, 0x00, 0x00
  498. };
  499. static const u8 rtl8225z2_tx_power_cck[] = {
  500. 0x36, 0x35, 0x2e, 0x25, 0x1c, 0x12, 0x09, 0x04,
  501. 0x30, 0x2f, 0x29, 0x21, 0x19, 0x10, 0x08, 0x03,
  502. 0x2b, 0x2a, 0x25, 0x1e, 0x16, 0x0e, 0x07, 0x03,
  503. 0x26, 0x25, 0x21, 0x1b, 0x14, 0x0d, 0x06, 0x03
  504. };
  505. static const u8 rtl8225z2_tx_power_ofdm[] = {
  506. 0x42, 0x00, 0x40, 0x00, 0x40
  507. };
  508. static const u8 rtl8225z2_tx_gain_cck_ofdm[] = {
  509. 0x00, 0x01, 0x02, 0x03, 0x04, 0x05,
  510. 0x06, 0x07, 0x08, 0x09, 0x0a, 0x0b,
  511. 0x0c, 0x0d, 0x0e, 0x0f, 0x10, 0x11,
  512. 0x12, 0x13, 0x14, 0x15, 0x16, 0x17,
  513. 0x18, 0x19, 0x1a, 0x1b, 0x1c, 0x1d,
  514. 0x1e, 0x1f, 0x20, 0x21, 0x22, 0x23
  515. };
  516. static void rtl8225z2_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
  517. {
  518. struct rtl8187_priv *priv = dev->priv;
  519. u8 cck_power, ofdm_power;
  520. const u8 *tmp;
  521. u32 reg;
  522. int i;
  523. cck_power = priv->channels[channel - 1].hw_value & 0xF;
  524. ofdm_power = priv->channels[channel - 1].hw_value >> 4;
  525. cck_power = min(cck_power, (u8)15);
  526. cck_power += priv->txpwr_base & 0xF;
  527. cck_power = min(cck_power, (u8)35);
  528. if (ofdm_power > (u8)15)
  529. ofdm_power = 25;
  530. else
  531. ofdm_power += 10;
  532. ofdm_power += priv->txpwr_base >> 4;
  533. ofdm_power = min(ofdm_power, (u8)35);
  534. if (channel == 14)
  535. tmp = rtl8225z2_tx_power_cck_ch14;
  536. else
  537. tmp = rtl8225z2_tx_power_cck;
  538. for (i = 0; i < 8; i++)
  539. rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
  540. rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
  541. rtl8225z2_tx_gain_cck_ofdm[cck_power]);
  542. msleep(1);
  543. /* anaparam2 on */
  544. rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_CONFIG);
  545. reg = rtl818x_ioread8(priv, &priv->map->CONFIG3);
  546. rtl818x_iowrite8(priv, &priv->map->CONFIG3,
  547. reg | RTL818X_CONFIG3_ANAPARAM_WRITE);
  548. rtl818x_iowrite32(priv, &priv->map->ANAPARAM2,
  549. RTL8187_RTL8225_ANAPARAM2_ON);
  550. rtl818x_iowrite8(priv, &priv->map->CONFIG3,
  551. reg & ~RTL818X_CONFIG3_ANAPARAM_WRITE);
  552. rtl818x_iowrite8(priv, &priv->map->EEPROM_CMD, RTL818X_EEPROM_CMD_NORMAL);
  553. rtl8225_write_phy_ofdm(dev, 2, 0x42);
  554. rtl8225_write_phy_ofdm(dev, 5, 0x00);
  555. rtl8225_write_phy_ofdm(dev, 6, 0x40);
  556. rtl8225_write_phy_ofdm(dev, 7, 0x00);
  557. rtl8225_write_phy_ofdm(dev, 8, 0x40);
  558. rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
  559. rtl8225z2_tx_gain_cck_ofdm[ofdm_power]);
  560. msleep(1);
  561. }
  562. static void rtl8225z2_b_rf_set_tx_power(struct ieee80211_hw *dev, int channel)
  563. {
  564. struct rtl8187_priv *priv = dev->priv;
  565. u8 cck_power, ofdm_power;
  566. const u8 *tmp;
  567. int i;
  568. cck_power = priv->channels[channel - 1].hw_value & 0xF;
  569. ofdm_power = priv->channels[channel - 1].hw_value >> 4;
  570. if (cck_power > 15)
  571. cck_power = (priv->hw_rev == RTL8187BvB) ? 15 : 22;
  572. else
  573. cck_power += (priv->hw_rev == RTL8187BvB) ? 0 : 7;
  574. cck_power += priv->txpwr_base & 0xF;
  575. cck_power = min(cck_power, (u8)35);
  576. if (ofdm_power > 15)
  577. ofdm_power = (priv->hw_rev == RTL8187BvB) ? 17 : 25;
  578. else
  579. ofdm_power += (priv->hw_rev == RTL8187BvB) ? 2 : 10;
  580. ofdm_power += (priv->txpwr_base >> 4) & 0xF;
  581. ofdm_power = min(ofdm_power, (u8)35);
  582. if (channel == 14)
  583. tmp = rtl8225z2_tx_power_cck_ch14;
  584. else
  585. tmp = rtl8225z2_tx_power_cck;
  586. if (priv->hw_rev == RTL8187BvB) {
  587. if (cck_power <= 6)
  588. ; /* do nothing */
  589. else if (cck_power <= 11)
  590. tmp += 8;
  591. else
  592. tmp += 16;
  593. } else {
  594. if (cck_power <= 5)
  595. ; /* do nothing */
  596. else if (cck_power <= 11)
  597. tmp += 8;
  598. else if (cck_power <= 17)
  599. tmp += 16;
  600. else
  601. tmp += 24;
  602. }
  603. for (i = 0; i < 8; i++)
  604. rtl8225_write_phy_cck(dev, 0x44 + i, *tmp++);
  605. rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK,
  606. rtl8225z2_tx_gain_cck_ofdm[cck_power] << 1);
  607. msleep(1);
  608. rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM,
  609. rtl8225z2_tx_gain_cck_ofdm[ofdm_power] << 1);
  610. if (priv->hw_rev == RTL8187BvB) {
  611. if (ofdm_power <= 11) {
  612. rtl8225_write_phy_ofdm(dev, 0x87, 0x60);
  613. rtl8225_write_phy_ofdm(dev, 0x89, 0x60);
  614. } else {
  615. rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
  616. rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
  617. }
  618. } else {
  619. if (ofdm_power <= 11) {
  620. rtl8225_write_phy_ofdm(dev, 0x87, 0x5c);
  621. rtl8225_write_phy_ofdm(dev, 0x89, 0x5c);
  622. } else if (ofdm_power <= 17) {
  623. rtl8225_write_phy_ofdm(dev, 0x87, 0x54);
  624. rtl8225_write_phy_ofdm(dev, 0x89, 0x54);
  625. } else {
  626. rtl8225_write_phy_ofdm(dev, 0x87, 0x50);
  627. rtl8225_write_phy_ofdm(dev, 0x89, 0x50);
  628. }
  629. }
  630. msleep(1);
  631. }
  632. static const u16 rtl8225z2_rxgain[] = {
  633. 0x0400, 0x0401, 0x0402, 0x0403, 0x0404, 0x0405, 0x0408, 0x0409,
  634. 0x040a, 0x040b, 0x0502, 0x0503, 0x0504, 0x0505, 0x0540, 0x0541,
  635. 0x0542, 0x0543, 0x0544, 0x0545, 0x0580, 0x0581, 0x0582, 0x0583,
  636. 0x0584, 0x0585, 0x0588, 0x0589, 0x058a, 0x058b, 0x0643, 0x0644,
  637. 0x0645, 0x0680, 0x0681, 0x0682, 0x0683, 0x0684, 0x0685, 0x0688,
  638. 0x0689, 0x068a, 0x068b, 0x068c, 0x0742, 0x0743, 0x0744, 0x0745,
  639. 0x0780, 0x0781, 0x0782, 0x0783, 0x0784, 0x0785, 0x0788, 0x0789,
  640. 0x078a, 0x078b, 0x078c, 0x078d, 0x0790, 0x0791, 0x0792, 0x0793,
  641. 0x0794, 0x0795, 0x0798, 0x0799, 0x079a, 0x079b, 0x079c, 0x079d,
  642. 0x07a0, 0x07a1, 0x07a2, 0x07a3, 0x07a4, 0x07a5, 0x07a8, 0x07a9,
  643. 0x03aa, 0x03ab, 0x03ac, 0x03ad, 0x03b0, 0x03b1, 0x03b2, 0x03b3,
  644. 0x03b4, 0x03b5, 0x03b8, 0x03b9, 0x03ba, 0x03bb, 0x03bb
  645. };
  646. static const u8 rtl8225z2_gain_bg[] = {
  647. 0x23, 0x15, 0xa5, /* -82-1dBm */
  648. 0x23, 0x15, 0xb5, /* -82-2dBm */
  649. 0x23, 0x15, 0xc5, /* -82-3dBm */
  650. 0x33, 0x15, 0xc5, /* -78dBm */
  651. 0x43, 0x15, 0xc5, /* -74dBm */
  652. 0x53, 0x15, 0xc5, /* -70dBm */
  653. 0x63, 0x15, 0xc5 /* -66dBm */
  654. };
  655. static void rtl8225z2_rf_init(struct ieee80211_hw *dev)
  656. {
  657. struct rtl8187_priv *priv = dev->priv;
  658. int i;
  659. rtl8225_write(dev, 0x0, 0x2BF);
  660. rtl8225_write(dev, 0x1, 0xEE0);
  661. rtl8225_write(dev, 0x2, 0x44D);
  662. rtl8225_write(dev, 0x3, 0x441);
  663. rtl8225_write(dev, 0x4, 0x8C3);
  664. rtl8225_write(dev, 0x5, 0xC72);
  665. rtl8225_write(dev, 0x6, 0x0E6);
  666. rtl8225_write(dev, 0x7, 0x82A);
  667. rtl8225_write(dev, 0x8, 0x03F);
  668. rtl8225_write(dev, 0x9, 0x335);
  669. rtl8225_write(dev, 0xa, 0x9D4);
  670. rtl8225_write(dev, 0xb, 0x7BB);
  671. rtl8225_write(dev, 0xc, 0x850);
  672. rtl8225_write(dev, 0xd, 0xCDF);
  673. rtl8225_write(dev, 0xe, 0x02B);
  674. rtl8225_write(dev, 0xf, 0x114);
  675. msleep(100);
  676. rtl8225_write(dev, 0x0, 0x1B7);
  677. for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
  678. rtl8225_write(dev, 0x1, i + 1);
  679. rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
  680. }
  681. rtl8225_write(dev, 0x3, 0x080);
  682. rtl8225_write(dev, 0x5, 0x004);
  683. rtl8225_write(dev, 0x0, 0x0B7);
  684. rtl8225_write(dev, 0x2, 0xc4D);
  685. msleep(200);
  686. rtl8225_write(dev, 0x2, 0x44D);
  687. msleep(100);
  688. if (!(rtl8225_read(dev, 6) & (1 << 7))) {
  689. rtl8225_write(dev, 0x02, 0x0C4D);
  690. msleep(200);
  691. rtl8225_write(dev, 0x02, 0x044D);
  692. msleep(100);
  693. if (!(rtl8225_read(dev, 6) & (1 << 7)))
  694. wiphy_warn(dev->wiphy, "RF Calibration Failed! %x\n",
  695. rtl8225_read(dev, 6));
  696. }
  697. msleep(200);
  698. rtl8225_write(dev, 0x0, 0x2BF);
  699. for (i = 0; i < ARRAY_SIZE(rtl8225_agc); i++) {
  700. rtl8225_write_phy_ofdm(dev, 0xB, rtl8225_agc[i]);
  701. rtl8225_write_phy_ofdm(dev, 0xA, 0x80 + i);
  702. }
  703. msleep(1);
  704. rtl8225_write_phy_ofdm(dev, 0x00, 0x01);
  705. rtl8225_write_phy_ofdm(dev, 0x01, 0x02);
  706. rtl8225_write_phy_ofdm(dev, 0x02, 0x42);
  707. rtl8225_write_phy_ofdm(dev, 0x03, 0x00);
  708. rtl8225_write_phy_ofdm(dev, 0x04, 0x00);
  709. rtl8225_write_phy_ofdm(dev, 0x05, 0x00);
  710. rtl8225_write_phy_ofdm(dev, 0x06, 0x40);
  711. rtl8225_write_phy_ofdm(dev, 0x07, 0x00);
  712. rtl8225_write_phy_ofdm(dev, 0x08, 0x40);
  713. rtl8225_write_phy_ofdm(dev, 0x09, 0xfe);
  714. rtl8225_write_phy_ofdm(dev, 0x0a, 0x08);
  715. rtl8225_write_phy_ofdm(dev, 0x0b, 0x80);
  716. rtl8225_write_phy_ofdm(dev, 0x0c, 0x01);
  717. rtl8225_write_phy_ofdm(dev, 0x0d, 0x43);
  718. rtl8225_write_phy_ofdm(dev, 0x0e, 0xd3);
  719. rtl8225_write_phy_ofdm(dev, 0x0f, 0x38);
  720. rtl8225_write_phy_ofdm(dev, 0x10, 0x84);
  721. rtl8225_write_phy_ofdm(dev, 0x11, 0x07);
  722. rtl8225_write_phy_ofdm(dev, 0x12, 0x20);
  723. rtl8225_write_phy_ofdm(dev, 0x13, 0x20);
  724. rtl8225_write_phy_ofdm(dev, 0x14, 0x00);
  725. rtl8225_write_phy_ofdm(dev, 0x15, 0x40);
  726. rtl8225_write_phy_ofdm(dev, 0x16, 0x00);
  727. rtl8225_write_phy_ofdm(dev, 0x17, 0x40);
  728. rtl8225_write_phy_ofdm(dev, 0x18, 0xef);
  729. rtl8225_write_phy_ofdm(dev, 0x19, 0x19);
  730. rtl8225_write_phy_ofdm(dev, 0x1a, 0x20);
  731. rtl8225_write_phy_ofdm(dev, 0x1b, 0x15);
  732. rtl8225_write_phy_ofdm(dev, 0x1c, 0x04);
  733. rtl8225_write_phy_ofdm(dev, 0x1d, 0xc5);
  734. rtl8225_write_phy_ofdm(dev, 0x1e, 0x95);
  735. rtl8225_write_phy_ofdm(dev, 0x1f, 0x75);
  736. rtl8225_write_phy_ofdm(dev, 0x20, 0x1f);
  737. rtl8225_write_phy_ofdm(dev, 0x21, 0x17);
  738. rtl8225_write_phy_ofdm(dev, 0x22, 0x16);
  739. rtl8225_write_phy_ofdm(dev, 0x23, 0x80);
  740. rtl8225_write_phy_ofdm(dev, 0x24, 0x46);
  741. rtl8225_write_phy_ofdm(dev, 0x25, 0x00);
  742. rtl8225_write_phy_ofdm(dev, 0x26, 0x90);
  743. rtl8225_write_phy_ofdm(dev, 0x27, 0x88);
  744. rtl8225_write_phy_ofdm(dev, 0x0b, rtl8225z2_gain_bg[4 * 3]);
  745. rtl8225_write_phy_ofdm(dev, 0x1b, rtl8225z2_gain_bg[4 * 3 + 1]);
  746. rtl8225_write_phy_ofdm(dev, 0x1d, rtl8225z2_gain_bg[4 * 3 + 2]);
  747. rtl8225_write_phy_ofdm(dev, 0x21, 0x37);
  748. rtl8225_write_phy_cck(dev, 0x00, 0x98);
  749. rtl8225_write_phy_cck(dev, 0x03, 0x20);
  750. rtl8225_write_phy_cck(dev, 0x04, 0x7e);
  751. rtl8225_write_phy_cck(dev, 0x05, 0x12);
  752. rtl8225_write_phy_cck(dev, 0x06, 0xfc);
  753. rtl8225_write_phy_cck(dev, 0x07, 0x78);
  754. rtl8225_write_phy_cck(dev, 0x08, 0x2e);
  755. rtl8225_write_phy_cck(dev, 0x10, 0x9b);
  756. rtl8225_write_phy_cck(dev, 0x11, 0x88);
  757. rtl8225_write_phy_cck(dev, 0x12, 0x47);
  758. rtl8225_write_phy_cck(dev, 0x13, 0xd0);
  759. rtl8225_write_phy_cck(dev, 0x19, 0x00);
  760. rtl8225_write_phy_cck(dev, 0x1a, 0xa0);
  761. rtl8225_write_phy_cck(dev, 0x1b, 0x08);
  762. rtl8225_write_phy_cck(dev, 0x40, 0x86);
  763. rtl8225_write_phy_cck(dev, 0x41, 0x8d);
  764. rtl8225_write_phy_cck(dev, 0x42, 0x15);
  765. rtl8225_write_phy_cck(dev, 0x43, 0x18);
  766. rtl8225_write_phy_cck(dev, 0x44, 0x36);
  767. rtl8225_write_phy_cck(dev, 0x45, 0x35);
  768. rtl8225_write_phy_cck(dev, 0x46, 0x2e);
  769. rtl8225_write_phy_cck(dev, 0x47, 0x25);
  770. rtl8225_write_phy_cck(dev, 0x48, 0x1c);
  771. rtl8225_write_phy_cck(dev, 0x49, 0x12);
  772. rtl8225_write_phy_cck(dev, 0x4a, 0x09);
  773. rtl8225_write_phy_cck(dev, 0x4b, 0x04);
  774. rtl8225_write_phy_cck(dev, 0x4c, 0x05);
  775. rtl818x_iowrite8(priv, (u8 *)0xFF5B, 0x0D); msleep(1);
  776. rtl8225z2_rf_set_tx_power(dev, 1);
  777. /* RX antenna default to A */
  778. rtl8225_write_phy_cck(dev, 0x10, 0x9b); /* B: 0xDB */
  779. rtl8225_write_phy_ofdm(dev, 0x26, 0x90); /* B: 0x10 */
  780. rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03); /* B: 0x00 */
  781. msleep(1);
  782. rtl818x_iowrite32(priv, (__le32 *)0xFF94, 0x3dc00002);
  783. }
  784. static void rtl8225z2_b_rf_init(struct ieee80211_hw *dev)
  785. {
  786. struct rtl8187_priv *priv = dev->priv;
  787. int i;
  788. rtl8225_write(dev, 0x0, 0x0B7);
  789. rtl8225_write(dev, 0x1, 0xEE0);
  790. rtl8225_write(dev, 0x2, 0x44D);
  791. rtl8225_write(dev, 0x3, 0x441);
  792. rtl8225_write(dev, 0x4, 0x8C3);
  793. rtl8225_write(dev, 0x5, 0xC72);
  794. rtl8225_write(dev, 0x6, 0x0E6);
  795. rtl8225_write(dev, 0x7, 0x82A);
  796. rtl8225_write(dev, 0x8, 0x03F);
  797. rtl8225_write(dev, 0x9, 0x335);
  798. rtl8225_write(dev, 0xa, 0x9D4);
  799. rtl8225_write(dev, 0xb, 0x7BB);
  800. rtl8225_write(dev, 0xc, 0x850);
  801. rtl8225_write(dev, 0xd, 0xCDF);
  802. rtl8225_write(dev, 0xe, 0x02B);
  803. rtl8225_write(dev, 0xf, 0x114);
  804. rtl8225_write(dev, 0x0, 0x1B7);
  805. for (i = 0; i < ARRAY_SIZE(rtl8225z2_rxgain); i++) {
  806. rtl8225_write(dev, 0x1, i + 1);
  807. rtl8225_write(dev, 0x2, rtl8225z2_rxgain[i]);
  808. }
  809. rtl8225_write(dev, 0x3, 0x080);
  810. rtl8225_write(dev, 0x5, 0x004);
  811. rtl8225_write(dev, 0x0, 0x0B7);
  812. rtl8225_write(dev, 0x2, 0xC4D);
  813. rtl8225_write(dev, 0x2, 0x44D);
  814. rtl8225_write(dev, 0x0, 0x2BF);
  815. rtl818x_iowrite8(priv, &priv->map->TX_GAIN_CCK, 0x03);
  816. rtl818x_iowrite8(priv, &priv->map->TX_GAIN_OFDM, 0x07);
  817. rtl818x_iowrite8(priv, &priv->map->TX_ANTENNA, 0x03);
  818. rtl8225_write_phy_ofdm(dev, 0x80, 0x12);
  819. for (i = 0; i < ARRAY_SIZE(rtl8225z2_agc); i++) {
  820. rtl8225_write_phy_ofdm(dev, 0xF, rtl8225z2_agc[i]);
  821. rtl8225_write_phy_ofdm(dev, 0xE, 0x80 + i);
  822. rtl8225_write_phy_ofdm(dev, 0xE, 0);
  823. }
  824. rtl8225_write_phy_ofdm(dev, 0x80, 0x10);
  825. for (i = 0; i < ARRAY_SIZE(rtl8225z2_ofdm); i++)
  826. rtl8225_write_phy_ofdm(dev, i, rtl8225z2_ofdm[i]);
  827. rtl8225_write_phy_ofdm(dev, 0x97, 0x46);
  828. rtl8225_write_phy_ofdm(dev, 0xa4, 0xb6);
  829. rtl8225_write_phy_ofdm(dev, 0x85, 0xfc);
  830. rtl8225_write_phy_cck(dev, 0xc1, 0x88);
  831. }
  832. static void rtl8225_rf_stop(struct ieee80211_hw *dev)
  833. {
  834. rtl8225_write(dev, 0x4, 0x1f);
  835. }
  836. static void rtl8225_rf_set_channel(struct ieee80211_hw *dev,
  837. struct ieee80211_conf *conf)
  838. {
  839. struct rtl8187_priv *priv = dev->priv;
  840. int chan =
  841. ieee80211_frequency_to_channel(conf->chandef.chan->center_freq);
  842. if (priv->rf->init == rtl8225_rf_init)
  843. rtl8225_rf_set_tx_power(dev, chan);
  844. else if (priv->rf->init == rtl8225z2_rf_init)
  845. rtl8225z2_rf_set_tx_power(dev, chan);
  846. else
  847. rtl8225z2_b_rf_set_tx_power(dev, chan);
  848. rtl8225_write(dev, 0x7, rtl8225_chan[chan - 1]);
  849. msleep(10);
  850. }
  851. static const struct rtl818x_rf_ops rtl8225_ops = {
  852. .name = "rtl8225",
  853. .init = rtl8225_rf_init,
  854. .stop = rtl8225_rf_stop,
  855. .set_chan = rtl8225_rf_set_channel
  856. };
  857. static const struct rtl818x_rf_ops rtl8225z2_ops = {
  858. .name = "rtl8225z2",
  859. .init = rtl8225z2_rf_init,
  860. .stop = rtl8225_rf_stop,
  861. .set_chan = rtl8225_rf_set_channel
  862. };
  863. static const struct rtl818x_rf_ops rtl8225z2_b_ops = {
  864. .name = "rtl8225z2",
  865. .init = rtl8225z2_b_rf_init,
  866. .stop = rtl8225_rf_stop,
  867. .set_chan = rtl8225_rf_set_channel
  868. };
  869. const struct rtl818x_rf_ops * rtl8187_detect_rf(struct ieee80211_hw *dev)
  870. {
  871. u16 reg8, reg9;
  872. struct rtl8187_priv *priv = dev->priv;
  873. if (!priv->is_rtl8187b) {
  874. rtl8225_write(dev, 0, 0x1B7);
  875. reg8 = rtl8225_read(dev, 8);
  876. reg9 = rtl8225_read(dev, 9);
  877. rtl8225_write(dev, 0, 0x0B7);
  878. if (reg8 != 0x588 || reg9 != 0x700)
  879. return &rtl8225_ops;
  880. return &rtl8225z2_ops;
  881. } else
  882. return &rtl8225z2_b_ops;
  883. }