phy_ht.c 32 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101102103104105106107108109110111112113114115116117118119120121122123124125126127128129130131132133134135136137138139140141142143144145146147148149150151152153154155156157158159160161162163164165166167168169170171172173174175176177178179180181182183184185186187188189190191192193194195196197198199200201202203204205206207208209210211212213214215216217218219220221222223224225226227228229230231232233234235236237238239240241242243244245246247248249250251252253254255256257258259260261262263264265266267268269270271272273274275276277278279280281282283284285286287288289290291292293294295296297298299300301302303304305306307308309310311312313314315316317318319320321322323324325326327328329330331332333334335336337338339340341342343344345346347348349350351352353354355356357358359360361362363364365366367368369370371372373374375376377378379380381382383384385386387388389390391392393394395396397398399400401402403404405406407408409410411412413414415416417418419420421422423424425426427428429430431432433434435436437438439440441442443444445446447448449450451452453454455456457458459460461462463464465466467468469470471472473474475476477478479480481482483484485486487488489490491492493494495496497498499500501502503504505506507508509510511512513514515516517518519520521522523524525526527528529530531532533534535536537538539540541542543544545546547548549550551552553554555556557558559560561562563564565566567568569570571572573574575576577578579580581582583584585586587588589590591592593594595596597598599600601602603604605606607608609610611612613614615616617618619620621622623624625626627628629630631632633634635636637638639640641642643644645646647648649650651652653654655656657658659660661662663664665666667668669670671672673674675676677678679680681682683684685686687688689690691692693694695696697698699700701702703704705706707708709710711712713714715716717718719720721722723724725726727728729730731732733734735736737738739740741742743744745746747748749750751752753754755756757758759760761762763764765766767768769770771772773774775776777778779780781782783784785786787788789790791792793794795796797798799800801802803804805806807808809810811812813814815816817818819820821822823824825826827828829830831832833834835836837838839840841842843844845846847848849850851852853854855856857858859860861862863864865866867868869870871872873874875876877878879880881882883884885886887888889890891892893894895896897898899900901902903904905906907908909910911912913914915916917918919920921922923924925926927928929930931932933934935936937938939940941942943944945946947948949950951952953954955956957958959960961962963964965966967968969970971972973974975976977978979980981982983984985986987988989990991992993994995996997998999100010011002100310041005100610071008100910101011101210131014101510161017101810191020102110221023102410251026102710281029103010311032103310341035103610371038103910401041104210431044104510461047104810491050105110521053105410551056105710581059106010611062106310641065106610671068106910701071107210731074107510761077107810791080108110821083108410851086108710881089109010911092109310941095109610971098109911001101110211031104110511061107110811091110111111121113111411151116111711181119112011211122112311241125112611271128112911301131113211331134113511361137
  1. // SPDX-License-Identifier: GPL-2.0-or-later
  2. /*
  3. Broadcom B43 wireless driver
  4. IEEE 802.11n HT-PHY support
  5. Copyright (c) 2011 Rafał Miłecki <zajec5@gmail.com>
  6. */
  7. #include <linux/slab.h>
  8. #include "b43.h"
  9. #include "phy_ht.h"
  10. #include "tables_phy_ht.h"
  11. #include "radio_2059.h"
  12. #include "main.h"
  13. /* Force values to keep compatibility with wl */
  14. enum ht_rssi_type {
  15. HT_RSSI_W1 = 0,
  16. HT_RSSI_W2 = 1,
  17. HT_RSSI_NB = 2,
  18. HT_RSSI_IQ = 3,
  19. HT_RSSI_TSSI_2G = 4,
  20. HT_RSSI_TSSI_5G = 5,
  21. HT_RSSI_TBD = 6,
  22. };
  23. /**************************************************
  24. * Radio 2059.
  25. **************************************************/
  26. static void b43_radio_2059_channel_setup(struct b43_wldev *dev,
  27. const struct b43_phy_ht_channeltab_e_radio2059 *e)
  28. {
  29. static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, };
  30. u16 r;
  31. int core;
  32. b43_radio_write(dev, 0x16, e->radio_syn16);
  33. b43_radio_write(dev, 0x17, e->radio_syn17);
  34. b43_radio_write(dev, 0x22, e->radio_syn22);
  35. b43_radio_write(dev, 0x25, e->radio_syn25);
  36. b43_radio_write(dev, 0x27, e->radio_syn27);
  37. b43_radio_write(dev, 0x28, e->radio_syn28);
  38. b43_radio_write(dev, 0x29, e->radio_syn29);
  39. b43_radio_write(dev, 0x2c, e->radio_syn2c);
  40. b43_radio_write(dev, 0x2d, e->radio_syn2d);
  41. b43_radio_write(dev, 0x37, e->radio_syn37);
  42. b43_radio_write(dev, 0x41, e->radio_syn41);
  43. b43_radio_write(dev, 0x43, e->radio_syn43);
  44. b43_radio_write(dev, 0x47, e->radio_syn47);
  45. for (core = 0; core < 3; core++) {
  46. r = routing[core];
  47. b43_radio_write(dev, r | 0x4a, e->radio_rxtx4a);
  48. b43_radio_write(dev, r | 0x58, e->radio_rxtx58);
  49. b43_radio_write(dev, r | 0x5a, e->radio_rxtx5a);
  50. b43_radio_write(dev, r | 0x6a, e->radio_rxtx6a);
  51. b43_radio_write(dev, r | 0x6d, e->radio_rxtx6d);
  52. b43_radio_write(dev, r | 0x6e, e->radio_rxtx6e);
  53. b43_radio_write(dev, r | 0x92, e->radio_rxtx92);
  54. b43_radio_write(dev, r | 0x98, e->radio_rxtx98);
  55. }
  56. udelay(50);
  57. /* Calibration */
  58. b43_radio_mask(dev, R2059_RFPLL_MISC_EN, ~0x1);
  59. b43_radio_mask(dev, R2059_RFPLL_MISC_CAL_RESETN, ~0x4);
  60. b43_radio_set(dev, R2059_RFPLL_MISC_CAL_RESETN, 0x4);
  61. b43_radio_set(dev, R2059_RFPLL_MISC_EN, 0x1);
  62. udelay(300);
  63. }
  64. /* Calibrate resistors in LPF of PLL? */
  65. static void b43_radio_2059_rcal(struct b43_wldev *dev)
  66. {
  67. /* Enable */
  68. b43_radio_set(dev, R2059_C3 | R2059_RCAL_CONFIG, 0x1);
  69. usleep_range(10, 20);
  70. b43_radio_set(dev, R2059_C3 | 0x0BF, 0x1);
  71. b43_radio_maskset(dev, R2059_C3 | 0x19B, 0x3, 0x2);
  72. /* Start */
  73. b43_radio_set(dev, R2059_C3 | R2059_RCAL_CONFIG, 0x2);
  74. usleep_range(100, 200);
  75. /* Stop */
  76. b43_radio_mask(dev, R2059_C3 | R2059_RCAL_CONFIG, ~0x2);
  77. if (!b43_radio_wait_value(dev, R2059_C3 | R2059_RCAL_STATUS, 1, 1, 100,
  78. 1000000))
  79. b43err(dev->wl, "Radio 0x2059 rcal timeout\n");
  80. /* Disable */
  81. b43_radio_mask(dev, R2059_C3 | R2059_RCAL_CONFIG, ~0x1);
  82. b43_radio_set(dev, 0xa, 0x60);
  83. }
  84. /* Calibrate the internal RC oscillator? */
  85. static void b43_radio_2057_rccal(struct b43_wldev *dev)
  86. {
  87. static const u16 radio_values[3][2] = {
  88. { 0x61, 0xE9 }, { 0x69, 0xD5 }, { 0x73, 0x99 },
  89. };
  90. int i;
  91. for (i = 0; i < 3; i++) {
  92. b43_radio_write(dev, R2059_RCCAL_MASTER, radio_values[i][0]);
  93. b43_radio_write(dev, R2059_RCCAL_X1, 0x6E);
  94. b43_radio_write(dev, R2059_RCCAL_TRC0, radio_values[i][1]);
  95. /* Start */
  96. b43_radio_write(dev, R2059_RCCAL_START_R1_Q1_P1, 0x55);
  97. /* Wait */
  98. if (!b43_radio_wait_value(dev, R2059_RCCAL_DONE_OSCCAP, 2, 2,
  99. 500, 5000000))
  100. b43err(dev->wl, "Radio 0x2059 rccal timeout\n");
  101. /* Stop */
  102. b43_radio_write(dev, R2059_RCCAL_START_R1_Q1_P1, 0x15);
  103. }
  104. b43_radio_mask(dev, R2059_RCCAL_MASTER, ~0x1);
  105. }
  106. static void b43_radio_2059_init_pre(struct b43_wldev *dev)
  107. {
  108. b43_phy_mask(dev, B43_PHY_HT_RF_CTL_CMD, ~B43_PHY_HT_RF_CTL_CMD_CHIP0_PU);
  109. b43_phy_set(dev, B43_PHY_HT_RF_CTL_CMD, B43_PHY_HT_RF_CTL_CMD_FORCE);
  110. b43_phy_mask(dev, B43_PHY_HT_RF_CTL_CMD, ~B43_PHY_HT_RF_CTL_CMD_FORCE);
  111. b43_phy_set(dev, B43_PHY_HT_RF_CTL_CMD, B43_PHY_HT_RF_CTL_CMD_CHIP0_PU);
  112. }
  113. static void b43_radio_2059_init(struct b43_wldev *dev)
  114. {
  115. static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3 };
  116. int i;
  117. /* Prepare (reset?) radio */
  118. b43_radio_2059_init_pre(dev);
  119. r2059_upload_inittabs(dev);
  120. for (i = 0; i < ARRAY_SIZE(routing); i++)
  121. b43_radio_set(dev, routing[i] | 0x146, 0x3);
  122. /* Post init starts below */
  123. b43_radio_set(dev, R2059_RFPLL_MISC_CAL_RESETN, 0x0078);
  124. b43_radio_set(dev, R2059_XTAL_CONFIG2, 0x0080);
  125. msleep(2);
  126. b43_radio_mask(dev, R2059_RFPLL_MISC_CAL_RESETN, ~0x0078);
  127. b43_radio_mask(dev, R2059_XTAL_CONFIG2, ~0x0080);
  128. if (1) { /* FIXME */
  129. b43_radio_2059_rcal(dev);
  130. b43_radio_2057_rccal(dev);
  131. }
  132. b43_radio_mask(dev, R2059_RFPLL_MASTER, ~0x0008);
  133. }
  134. /**************************************************
  135. * RF
  136. **************************************************/
  137. static void b43_phy_ht_force_rf_sequence(struct b43_wldev *dev, u16 rf_seq)
  138. {
  139. u8 i;
  140. u16 save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE);
  141. b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE, 0x3);
  142. b43_phy_set(dev, B43_PHY_HT_RF_SEQ_TRIG, rf_seq);
  143. for (i = 0; i < 200; i++) {
  144. if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & rf_seq)) {
  145. i = 0;
  146. break;
  147. }
  148. msleep(1);
  149. }
  150. if (i)
  151. b43err(dev->wl, "Forcing RF sequence timeout\n");
  152. b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode);
  153. }
  154. static void b43_phy_ht_pa_override(struct b43_wldev *dev, bool enable)
  155. {
  156. struct b43_phy_ht *htphy = dev->phy.ht;
  157. static const u16 regs[3] = { B43_PHY_HT_RF_CTL_INT_C1,
  158. B43_PHY_HT_RF_CTL_INT_C2,
  159. B43_PHY_HT_RF_CTL_INT_C3 };
  160. int i;
  161. if (enable) {
  162. for (i = 0; i < 3; i++)
  163. b43_phy_write(dev, regs[i], htphy->rf_ctl_int_save[i]);
  164. } else {
  165. for (i = 0; i < 3; i++)
  166. htphy->rf_ctl_int_save[i] = b43_phy_read(dev, regs[i]);
  167. /* TODO: Does 5GHz band use different value (not 0x0400)? */
  168. for (i = 0; i < 3; i++)
  169. b43_phy_write(dev, regs[i], 0x0400);
  170. }
  171. }
  172. /**************************************************
  173. * Various PHY ops
  174. **************************************************/
  175. static u16 b43_phy_ht_classifier(struct b43_wldev *dev, u16 mask, u16 val)
  176. {
  177. u16 tmp;
  178. u16 allowed = B43_PHY_HT_CLASS_CTL_CCK_EN |
  179. B43_PHY_HT_CLASS_CTL_OFDM_EN |
  180. B43_PHY_HT_CLASS_CTL_WAITED_EN;
  181. tmp = b43_phy_read(dev, B43_PHY_HT_CLASS_CTL);
  182. tmp &= allowed;
  183. tmp &= ~mask;
  184. tmp |= (val & mask);
  185. b43_phy_maskset(dev, B43_PHY_HT_CLASS_CTL, ~allowed, tmp);
  186. return tmp;
  187. }
  188. static void b43_phy_ht_reset_cca(struct b43_wldev *dev)
  189. {
  190. u16 bbcfg;
  191. b43_phy_force_clock(dev, true);
  192. bbcfg = b43_phy_read(dev, B43_PHY_HT_BBCFG);
  193. b43_phy_write(dev, B43_PHY_HT_BBCFG, bbcfg | B43_PHY_HT_BBCFG_RSTCCA);
  194. udelay(1);
  195. b43_phy_write(dev, B43_PHY_HT_BBCFG, bbcfg & ~B43_PHY_HT_BBCFG_RSTCCA);
  196. b43_phy_force_clock(dev, false);
  197. b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX);
  198. }
  199. static void b43_phy_ht_zero_extg(struct b43_wldev *dev)
  200. {
  201. u8 i, j;
  202. static const u16 base[] = { 0x40, 0x60, 0x80 };
  203. for (i = 0; i < ARRAY_SIZE(base); i++) {
  204. for (j = 0; j < 4; j++)
  205. b43_phy_write(dev, B43_PHY_EXTG(base[i] + j), 0);
  206. }
  207. for (i = 0; i < ARRAY_SIZE(base); i++)
  208. b43_phy_write(dev, B43_PHY_EXTG(base[i] + 0xc), 0);
  209. }
  210. /* Some unknown AFE (Analog Frondned) op */
  211. static void b43_phy_ht_afe_unk1(struct b43_wldev *dev)
  212. {
  213. u8 i;
  214. static const u16 ctl_regs[3][2] = {
  215. { B43_PHY_HT_AFE_C1_OVER, B43_PHY_HT_AFE_C1 },
  216. { B43_PHY_HT_AFE_C2_OVER, B43_PHY_HT_AFE_C2 },
  217. { B43_PHY_HT_AFE_C3_OVER, B43_PHY_HT_AFE_C3},
  218. };
  219. for (i = 0; i < 3; i++) {
  220. /* TODO: verify masks&sets */
  221. b43_phy_set(dev, ctl_regs[i][1], 0x4);
  222. b43_phy_set(dev, ctl_regs[i][0], 0x4);
  223. b43_phy_mask(dev, ctl_regs[i][1], ~0x1);
  224. b43_phy_set(dev, ctl_regs[i][0], 0x1);
  225. b43_httab_write(dev, B43_HTTAB16(8, 5 + (i * 0x10)), 0);
  226. b43_phy_mask(dev, ctl_regs[i][0], ~0x4);
  227. }
  228. }
  229. static void b43_phy_ht_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
  230. {
  231. clip_st[0] = b43_phy_read(dev, B43_PHY_HT_C1_CLIP1THRES);
  232. clip_st[1] = b43_phy_read(dev, B43_PHY_HT_C2_CLIP1THRES);
  233. clip_st[2] = b43_phy_read(dev, B43_PHY_HT_C3_CLIP1THRES);
  234. }
  235. static void b43_phy_ht_bphy_init(struct b43_wldev *dev)
  236. {
  237. unsigned int i;
  238. u16 val;
  239. val = 0x1E1F;
  240. for (i = 0; i < 16; i++) {
  241. b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
  242. val -= 0x202;
  243. }
  244. val = 0x3E3F;
  245. for (i = 0; i < 16; i++) {
  246. b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val);
  247. val -= 0x202;
  248. }
  249. b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
  250. }
  251. static void b43_phy_ht_bphy_reset(struct b43_wldev *dev, bool reset)
  252. {
  253. u16 tmp;
  254. tmp = b43_read16(dev, B43_MMIO_PSM_PHY_HDR);
  255. b43_write16(dev, B43_MMIO_PSM_PHY_HDR,
  256. tmp | B43_PSM_HDR_MAC_PHY_FORCE_CLK);
  257. /* Put BPHY in or take it out of the reset */
  258. if (reset)
  259. b43_phy_set(dev, B43_PHY_B_BBCFG,
  260. B43_PHY_B_BBCFG_RSTCCA | B43_PHY_B_BBCFG_RSTRX);
  261. else
  262. b43_phy_mask(dev, B43_PHY_B_BBCFG,
  263. 0xffff & ~(B43_PHY_B_BBCFG_RSTCCA |
  264. B43_PHY_B_BBCFG_RSTRX));
  265. b43_write16(dev, B43_MMIO_PSM_PHY_HDR, tmp);
  266. }
  267. /**************************************************
  268. * Samples
  269. **************************************************/
  270. static void b43_phy_ht_stop_playback(struct b43_wldev *dev)
  271. {
  272. struct b43_phy_ht *phy_ht = dev->phy.ht;
  273. u16 tmp;
  274. int i;
  275. tmp = b43_phy_read(dev, B43_PHY_HT_SAMP_STAT);
  276. if (tmp & 0x1)
  277. b43_phy_set(dev, B43_PHY_HT_SAMP_CMD, B43_PHY_HT_SAMP_CMD_STOP);
  278. else if (tmp & 0x2)
  279. b43_phy_mask(dev, B43_PHY_HT_IQLOCAL_CMDGCTL, 0x7FFF);
  280. b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0x0004);
  281. for (i = 0; i < 3; i++) {
  282. if (phy_ht->bb_mult_save[i] >= 0) {
  283. b43_httab_write(dev, B43_HTTAB16(13, 0x63 + i * 4),
  284. phy_ht->bb_mult_save[i]);
  285. b43_httab_write(dev, B43_HTTAB16(13, 0x67 + i * 4),
  286. phy_ht->bb_mult_save[i]);
  287. }
  288. }
  289. }
  290. static u16 b43_phy_ht_load_samples(struct b43_wldev *dev)
  291. {
  292. int i;
  293. u16 len = 20 << 3;
  294. b43_phy_write(dev, B43_PHY_HT_TABLE_ADDR, 0x4400);
  295. for (i = 0; i < len; i++) {
  296. b43_phy_write(dev, B43_PHY_HT_TABLE_DATAHI, 0);
  297. b43_phy_write(dev, B43_PHY_HT_TABLE_DATALO, 0);
  298. }
  299. return len;
  300. }
  301. static void b43_phy_ht_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
  302. u16 wait)
  303. {
  304. struct b43_phy_ht *phy_ht = dev->phy.ht;
  305. u16 save_seq_mode;
  306. int i;
  307. for (i = 0; i < 3; i++) {
  308. if (phy_ht->bb_mult_save[i] < 0)
  309. phy_ht->bb_mult_save[i] = b43_httab_read(dev, B43_HTTAB16(13, 0x63 + i * 4));
  310. }
  311. b43_phy_write(dev, B43_PHY_HT_SAMP_DEP_CNT, samps - 1);
  312. if (loops != 0xFFFF)
  313. loops--;
  314. b43_phy_write(dev, B43_PHY_HT_SAMP_LOOP_CNT, loops);
  315. b43_phy_write(dev, B43_PHY_HT_SAMP_WAIT_CNT, wait);
  316. save_seq_mode = b43_phy_read(dev, B43_PHY_HT_RF_SEQ_MODE);
  317. b43_phy_set(dev, B43_PHY_HT_RF_SEQ_MODE,
  318. B43_PHY_HT_RF_SEQ_MODE_CA_OVER);
  319. /* TODO: find out mask bits! Do we need more function arguments? */
  320. b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0);
  321. b43_phy_mask(dev, B43_PHY_HT_SAMP_CMD, ~0);
  322. b43_phy_mask(dev, B43_PHY_HT_IQLOCAL_CMDGCTL, ~0);
  323. b43_phy_set(dev, B43_PHY_HT_SAMP_CMD, 0x1);
  324. for (i = 0; i < 100; i++) {
  325. if (!(b43_phy_read(dev, B43_PHY_HT_RF_SEQ_STATUS) & 1)) {
  326. i = 0;
  327. break;
  328. }
  329. udelay(10);
  330. }
  331. if (i)
  332. b43err(dev->wl, "run samples timeout\n");
  333. b43_phy_write(dev, B43_PHY_HT_RF_SEQ_MODE, save_seq_mode);
  334. }
  335. static void b43_phy_ht_tx_tone(struct b43_wldev *dev)
  336. {
  337. u16 samp;
  338. samp = b43_phy_ht_load_samples(dev);
  339. b43_phy_ht_run_samples(dev, samp, 0xFFFF, 0);
  340. }
  341. /**************************************************
  342. * RSSI
  343. **************************************************/
  344. static void b43_phy_ht_rssi_select(struct b43_wldev *dev, u8 core_sel,
  345. enum ht_rssi_type rssi_type)
  346. {
  347. static const u16 ctl_regs[3][2] = {
  348. { B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER, },
  349. { B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER, },
  350. { B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER, },
  351. };
  352. static const u16 radio_r[] = { R2059_C1, R2059_C2, R2059_C3, };
  353. int core;
  354. if (core_sel == 0) {
  355. b43err(dev->wl, "RSSI selection for core off not implemented yet\n");
  356. } else {
  357. for (core = 0; core < 3; core++) {
  358. /* Check if caller requested a one specific core */
  359. if ((core_sel == 1 && core != 0) ||
  360. (core_sel == 2 && core != 1) ||
  361. (core_sel == 3 && core != 2))
  362. continue;
  363. switch (rssi_type) {
  364. case HT_RSSI_TSSI_2G:
  365. b43_phy_set(dev, ctl_regs[core][0], 0x3 << 8);
  366. b43_phy_set(dev, ctl_regs[core][0], 0x3 << 10);
  367. b43_phy_set(dev, ctl_regs[core][1], 0x1 << 9);
  368. b43_phy_set(dev, ctl_regs[core][1], 0x1 << 10);
  369. b43_radio_set(dev, R2059_C3 | 0xbf, 0x1);
  370. b43_radio_write(dev, radio_r[core] | 0x159,
  371. 0x11);
  372. break;
  373. default:
  374. b43err(dev->wl, "RSSI selection for type %d not implemented yet\n",
  375. rssi_type);
  376. }
  377. }
  378. }
  379. }
  380. static void b43_phy_ht_poll_rssi(struct b43_wldev *dev, enum ht_rssi_type type,
  381. s32 *buf, u8 nsamp)
  382. {
  383. u16 phy_regs_values[12];
  384. static const u16 phy_regs_to_save[] = {
  385. B43_PHY_HT_AFE_C1, B43_PHY_HT_AFE_C1_OVER,
  386. 0x848, 0x841,
  387. B43_PHY_HT_AFE_C2, B43_PHY_HT_AFE_C2_OVER,
  388. 0x868, 0x861,
  389. B43_PHY_HT_AFE_C3, B43_PHY_HT_AFE_C3_OVER,
  390. 0x888, 0x881,
  391. };
  392. u16 tmp[3];
  393. int i;
  394. for (i = 0; i < 12; i++)
  395. phy_regs_values[i] = b43_phy_read(dev, phy_regs_to_save[i]);
  396. b43_phy_ht_rssi_select(dev, 5, type);
  397. for (i = 0; i < 6; i++)
  398. buf[i] = 0;
  399. for (i = 0; i < nsamp; i++) {
  400. tmp[0] = b43_phy_read(dev, B43_PHY_HT_RSSI_C1);
  401. tmp[1] = b43_phy_read(dev, B43_PHY_HT_RSSI_C2);
  402. tmp[2] = b43_phy_read(dev, B43_PHY_HT_RSSI_C3);
  403. buf[0] += ((s8)((tmp[0] & 0x3F) << 2)) >> 2;
  404. buf[1] += ((s8)(((tmp[0] >> 8) & 0x3F) << 2)) >> 2;
  405. buf[2] += ((s8)((tmp[1] & 0x3F) << 2)) >> 2;
  406. buf[3] += ((s8)(((tmp[1] >> 8) & 0x3F) << 2)) >> 2;
  407. buf[4] += ((s8)((tmp[2] & 0x3F) << 2)) >> 2;
  408. buf[5] += ((s8)(((tmp[2] >> 8) & 0x3F) << 2)) >> 2;
  409. }
  410. for (i = 0; i < 12; i++)
  411. b43_phy_write(dev, phy_regs_to_save[i], phy_regs_values[i]);
  412. }
  413. /**************************************************
  414. * Tx/Rx
  415. **************************************************/
  416. static void b43_phy_ht_tx_power_fix(struct b43_wldev *dev)
  417. {
  418. int i;
  419. for (i = 0; i < 3; i++) {
  420. u16 mask;
  421. u32 tmp = b43_httab_read(dev, B43_HTTAB32(26, 0xE8));
  422. if (0) /* FIXME */
  423. mask = 0x2 << (i * 4);
  424. else
  425. mask = 0;
  426. b43_phy_mask(dev, B43_PHY_EXTG(0x108), mask);
  427. b43_httab_write(dev, B43_HTTAB16(7, 0x110 + i), tmp >> 16);
  428. b43_httab_write(dev, B43_HTTAB8(13, 0x63 + (i * 4)),
  429. tmp & 0xFF);
  430. b43_httab_write(dev, B43_HTTAB8(13, 0x73 + (i * 4)),
  431. tmp & 0xFF);
  432. }
  433. }
  434. static void b43_phy_ht_tx_power_ctl(struct b43_wldev *dev, bool enable)
  435. {
  436. struct b43_phy_ht *phy_ht = dev->phy.ht;
  437. u16 en_bits = B43_PHY_HT_TXPCTL_CMD_C1_COEFF |
  438. B43_PHY_HT_TXPCTL_CMD_C1_HWPCTLEN |
  439. B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN;
  440. static const u16 cmd_regs[3] = { B43_PHY_HT_TXPCTL_CMD_C1,
  441. B43_PHY_HT_TXPCTL_CMD_C2,
  442. B43_PHY_HT_TXPCTL_CMD_C3 };
  443. static const u16 status_regs[3] = { B43_PHY_HT_TX_PCTL_STATUS_C1,
  444. B43_PHY_HT_TX_PCTL_STATUS_C2,
  445. B43_PHY_HT_TX_PCTL_STATUS_C3 };
  446. int i;
  447. if (!enable) {
  448. if (b43_phy_read(dev, B43_PHY_HT_TXPCTL_CMD_C1) & en_bits) {
  449. /* We disable enabled TX pwr ctl, save it's state */
  450. for (i = 0; i < 3; i++)
  451. phy_ht->tx_pwr_idx[i] =
  452. b43_phy_read(dev, status_regs[i]);
  453. }
  454. b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0xffff & ~en_bits);
  455. } else {
  456. b43_phy_set(dev, B43_PHY_HT_TXPCTL_CMD_C1, en_bits);
  457. if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) {
  458. for (i = 0; i < 3; i++)
  459. b43_phy_write(dev, cmd_regs[i], 0x32);
  460. }
  461. for (i = 0; i < 3; i++)
  462. if (phy_ht->tx_pwr_idx[i] <=
  463. B43_PHY_HT_TXPCTL_CMD_C1_INIT)
  464. b43_phy_write(dev, cmd_regs[i],
  465. phy_ht->tx_pwr_idx[i]);
  466. }
  467. phy_ht->tx_pwr_ctl = enable;
  468. }
  469. static void b43_phy_ht_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
  470. {
  471. struct b43_phy_ht *phy_ht = dev->phy.ht;
  472. static const u16 base[] = { 0x840, 0x860, 0x880 };
  473. u16 save_regs[3][3];
  474. s32 rssi_buf[6];
  475. int core;
  476. for (core = 0; core < 3; core++) {
  477. save_regs[core][1] = b43_phy_read(dev, base[core] + 6);
  478. save_regs[core][2] = b43_phy_read(dev, base[core] + 7);
  479. save_regs[core][0] = b43_phy_read(dev, base[core] + 0);
  480. b43_phy_write(dev, base[core] + 6, 0);
  481. b43_phy_mask(dev, base[core] + 7, ~0xF); /* 0xF? Or just 0x6? */
  482. b43_phy_set(dev, base[core] + 0, 0x0400);
  483. b43_phy_set(dev, base[core] + 0, 0x1000);
  484. }
  485. b43_phy_ht_tx_tone(dev);
  486. udelay(20);
  487. b43_phy_ht_poll_rssi(dev, HT_RSSI_TSSI_2G, rssi_buf, 1);
  488. b43_phy_ht_stop_playback(dev);
  489. b43_phy_ht_reset_cca(dev);
  490. phy_ht->idle_tssi[0] = rssi_buf[0] & 0xff;
  491. phy_ht->idle_tssi[1] = rssi_buf[2] & 0xff;
  492. phy_ht->idle_tssi[2] = rssi_buf[4] & 0xff;
  493. for (core = 0; core < 3; core++) {
  494. b43_phy_write(dev, base[core] + 0, save_regs[core][0]);
  495. b43_phy_write(dev, base[core] + 6, save_regs[core][1]);
  496. b43_phy_write(dev, base[core] + 7, save_regs[core][2]);
  497. }
  498. }
  499. static void b43_phy_ht_tssi_setup(struct b43_wldev *dev)
  500. {
  501. static const u16 routing[] = { R2059_C1, R2059_C2, R2059_C3, };
  502. int core;
  503. /* 0x159 is probably TX_SSI_MUX or TSSIG (by comparing to N-PHY) */
  504. for (core = 0; core < 3; core++) {
  505. b43_radio_set(dev, 0x8bf, 0x1);
  506. b43_radio_write(dev, routing[core] | 0x0159, 0x0011);
  507. }
  508. }
  509. static void b43_phy_ht_tx_power_ctl_setup(struct b43_wldev *dev)
  510. {
  511. struct b43_phy_ht *phy_ht = dev->phy.ht;
  512. struct ssb_sprom *sprom = dev->dev->bus_sprom;
  513. u8 *idle = phy_ht->idle_tssi;
  514. u8 target[3];
  515. s16 a1[3], b0[3], b1[3];
  516. u16 freq = dev->phy.chandef->chan->center_freq;
  517. int i, c;
  518. if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
  519. for (c = 0; c < 3; c++) {
  520. target[c] = sprom->core_pwr_info[c].maxpwr_2g;
  521. a1[c] = sprom->core_pwr_info[c].pa_2g[0];
  522. b0[c] = sprom->core_pwr_info[c].pa_2g[1];
  523. b1[c] = sprom->core_pwr_info[c].pa_2g[2];
  524. }
  525. } else if (freq >= 4900 && freq < 5100) {
  526. for (c = 0; c < 3; c++) {
  527. target[c] = sprom->core_pwr_info[c].maxpwr_5gl;
  528. a1[c] = sprom->core_pwr_info[c].pa_5gl[0];
  529. b0[c] = sprom->core_pwr_info[c].pa_5gl[1];
  530. b1[c] = sprom->core_pwr_info[c].pa_5gl[2];
  531. }
  532. } else if (freq >= 5100 && freq < 5500) {
  533. for (c = 0; c < 3; c++) {
  534. target[c] = sprom->core_pwr_info[c].maxpwr_5g;
  535. a1[c] = sprom->core_pwr_info[c].pa_5g[0];
  536. b0[c] = sprom->core_pwr_info[c].pa_5g[1];
  537. b1[c] = sprom->core_pwr_info[c].pa_5g[2];
  538. }
  539. } else if (freq >= 5500) {
  540. for (c = 0; c < 3; c++) {
  541. target[c] = sprom->core_pwr_info[c].maxpwr_5gh;
  542. a1[c] = sprom->core_pwr_info[c].pa_5gh[0];
  543. b0[c] = sprom->core_pwr_info[c].pa_5gh[1];
  544. b1[c] = sprom->core_pwr_info[c].pa_5gh[2];
  545. }
  546. } else {
  547. target[0] = target[1] = target[2] = 52;
  548. a1[0] = a1[1] = a1[2] = -424;
  549. b0[0] = b0[1] = b0[2] = 5612;
  550. b1[0] = b1[1] = b1[2] = -1393;
  551. }
  552. b43_phy_set(dev, B43_PHY_HT_TSSIMODE, B43_PHY_HT_TSSIMODE_EN);
  553. b43_phy_mask(dev, B43_PHY_HT_TXPCTL_CMD_C1,
  554. ~B43_PHY_HT_TXPCTL_CMD_C1_PCTLEN & 0xFFFF);
  555. /* TODO: Does it depend on sprom->fem.ghz2.tssipos? */
  556. b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI, 0x4000);
  557. b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1,
  558. ~B43_PHY_HT_TXPCTL_CMD_C1_INIT, 0x19);
  559. b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C2,
  560. ~B43_PHY_HT_TXPCTL_CMD_C2_INIT, 0x19);
  561. b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C3,
  562. ~B43_PHY_HT_TXPCTL_CMD_C3_INIT, 0x19);
  563. b43_phy_set(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI,
  564. B43_PHY_HT_TXPCTL_IDLE_TSSI_BINF);
  565. b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI,
  566. ~B43_PHY_HT_TXPCTL_IDLE_TSSI_C1,
  567. idle[0] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C1_SHIFT);
  568. b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI,
  569. ~B43_PHY_HT_TXPCTL_IDLE_TSSI_C2,
  570. idle[1] << B43_PHY_HT_TXPCTL_IDLE_TSSI_C2_SHIFT);
  571. b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_IDLE_TSSI2,
  572. ~B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3,
  573. idle[2] << B43_PHY_HT_TXPCTL_IDLE_TSSI2_C3_SHIFT);
  574. b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_TSSID,
  575. 0xf0);
  576. b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_N, ~B43_PHY_HT_TXPCTL_N_NPTIL2,
  577. 0x3 << B43_PHY_HT_TXPCTL_N_NPTIL2_SHIFT);
  578. #if 0
  579. /* TODO: what to mask/set? */
  580. b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x800, 0)
  581. b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_CMD_C1, 0x400, 0)
  582. #endif
  583. b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR,
  584. ~B43_PHY_HT_TXPCTL_TARG_PWR_C1,
  585. target[0] << B43_PHY_HT_TXPCTL_TARG_PWR_C1_SHIFT);
  586. b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR,
  587. ~B43_PHY_HT_TXPCTL_TARG_PWR_C2 & 0xFFFF,
  588. target[1] << B43_PHY_HT_TXPCTL_TARG_PWR_C2_SHIFT);
  589. b43_phy_maskset(dev, B43_PHY_HT_TXPCTL_TARG_PWR2,
  590. ~B43_PHY_HT_TXPCTL_TARG_PWR2_C3,
  591. target[2] << B43_PHY_HT_TXPCTL_TARG_PWR2_C3_SHIFT);
  592. for (c = 0; c < 3; c++) {
  593. s32 num, den, pwr;
  594. u32 regval[64];
  595. for (i = 0; i < 64; i++) {
  596. num = 8 * (16 * b0[c] + b1[c] * i);
  597. den = 32768 + a1[c] * i;
  598. pwr = max((4 * num + den / 2) / den, -8);
  599. regval[i] = pwr;
  600. }
  601. b43_httab_write_bulk(dev, B43_HTTAB16(26 + c, 0), 64, regval);
  602. }
  603. }
  604. /**************************************************
  605. * Channel switching ops.
  606. **************************************************/
  607. static void b43_phy_ht_spur_avoid(struct b43_wldev *dev,
  608. struct ieee80211_channel *new_channel)
  609. {
  610. struct bcma_device *core = dev->dev->bdev;
  611. int spuravoid = 0;
  612. /* Check for 13 and 14 is just a guess, we don't have enough logs. */
  613. if (new_channel->hw_value == 13 || new_channel->hw_value == 14)
  614. spuravoid = 1;
  615. bcma_core_pll_ctl(core, B43_BCMA_CLKCTLST_PHY_PLL_REQ, 0, false);
  616. bcma_pmu_spuravoid_pllupdate(&core->bus->drv_cc, spuravoid);
  617. bcma_core_pll_ctl(core,
  618. B43_BCMA_CLKCTLST_80211_PLL_REQ |
  619. B43_BCMA_CLKCTLST_PHY_PLL_REQ,
  620. B43_BCMA_CLKCTLST_80211_PLL_ST |
  621. B43_BCMA_CLKCTLST_PHY_PLL_ST, false);
  622. b43_mac_switch_freq(dev, spuravoid);
  623. b43_wireless_core_phy_pll_reset(dev);
  624. if (spuravoid)
  625. b43_phy_set(dev, B43_PHY_HT_BBCFG, B43_PHY_HT_BBCFG_RSTRX);
  626. else
  627. b43_phy_mask(dev, B43_PHY_HT_BBCFG,
  628. ~B43_PHY_HT_BBCFG_RSTRX & 0xFFFF);
  629. b43_phy_ht_reset_cca(dev);
  630. }
  631. static void b43_phy_ht_channel_setup(struct b43_wldev *dev,
  632. const struct b43_phy_ht_channeltab_e_phy *e,
  633. struct ieee80211_channel *new_channel)
  634. {
  635. if (new_channel->band == NL80211_BAND_5GHZ) {
  636. /* Switch to 2 GHz for a moment to access B-PHY regs */
  637. b43_phy_mask(dev, B43_PHY_HT_BANDCTL, ~B43_PHY_HT_BANDCTL_5GHZ);
  638. b43_phy_ht_bphy_reset(dev, true);
  639. /* Switch to 5 GHz */
  640. b43_phy_set(dev, B43_PHY_HT_BANDCTL, B43_PHY_HT_BANDCTL_5GHZ);
  641. } else {
  642. /* Switch to 2 GHz */
  643. b43_phy_mask(dev, B43_PHY_HT_BANDCTL, ~B43_PHY_HT_BANDCTL_5GHZ);
  644. b43_phy_ht_bphy_reset(dev, false);
  645. }
  646. b43_phy_write(dev, B43_PHY_HT_BW1, e->bw1);
  647. b43_phy_write(dev, B43_PHY_HT_BW2, e->bw2);
  648. b43_phy_write(dev, B43_PHY_HT_BW3, e->bw3);
  649. b43_phy_write(dev, B43_PHY_HT_BW4, e->bw4);
  650. b43_phy_write(dev, B43_PHY_HT_BW5, e->bw5);
  651. b43_phy_write(dev, B43_PHY_HT_BW6, e->bw6);
  652. if (new_channel->hw_value == 14) {
  653. b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN, 0);
  654. b43_phy_set(dev, B43_PHY_HT_TEST, 0x0800);
  655. } else {
  656. b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_OFDM_EN,
  657. B43_PHY_HT_CLASS_CTL_OFDM_EN);
  658. if (new_channel->band == NL80211_BAND_2GHZ)
  659. b43_phy_mask(dev, B43_PHY_HT_TEST, ~0x840);
  660. }
  661. if (1) /* TODO: On N it's for early devices only, what about HT? */
  662. b43_phy_ht_tx_power_fix(dev);
  663. b43_phy_ht_spur_avoid(dev, new_channel);
  664. b43_phy_write(dev, 0x017e, 0x3830);
  665. }
  666. static int b43_phy_ht_set_channel(struct b43_wldev *dev,
  667. struct ieee80211_channel *channel,
  668. enum nl80211_channel_type channel_type)
  669. {
  670. struct b43_phy *phy = &dev->phy;
  671. const struct b43_phy_ht_channeltab_e_radio2059 *chent_r2059 = NULL;
  672. if (phy->radio_ver == 0x2059) {
  673. chent_r2059 = b43_phy_ht_get_channeltab_e_r2059(dev,
  674. channel->center_freq);
  675. if (!chent_r2059)
  676. return -ESRCH;
  677. } else {
  678. return -ESRCH;
  679. }
  680. /* TODO: In case of N-PHY some bandwidth switching goes here */
  681. if (phy->radio_ver == 0x2059) {
  682. b43_radio_2059_channel_setup(dev, chent_r2059);
  683. b43_phy_ht_channel_setup(dev, &(chent_r2059->phy_regs),
  684. channel);
  685. } else {
  686. return -ESRCH;
  687. }
  688. return 0;
  689. }
  690. /**************************************************
  691. * Basic PHY ops.
  692. **************************************************/
  693. static int b43_phy_ht_op_allocate(struct b43_wldev *dev)
  694. {
  695. struct b43_phy_ht *phy_ht;
  696. phy_ht = kzalloc(sizeof(*phy_ht), GFP_KERNEL);
  697. if (!phy_ht)
  698. return -ENOMEM;
  699. dev->phy.ht = phy_ht;
  700. return 0;
  701. }
  702. static void b43_phy_ht_op_prepare_structs(struct b43_wldev *dev)
  703. {
  704. struct b43_phy *phy = &dev->phy;
  705. struct b43_phy_ht *phy_ht = phy->ht;
  706. int i;
  707. memset(phy_ht, 0, sizeof(*phy_ht));
  708. phy_ht->tx_pwr_ctl = true;
  709. for (i = 0; i < 3; i++)
  710. phy_ht->tx_pwr_idx[i] = B43_PHY_HT_TXPCTL_CMD_C1_INIT + 1;
  711. for (i = 0; i < 3; i++)
  712. phy_ht->bb_mult_save[i] = -1;
  713. }
  714. static int b43_phy_ht_op_init(struct b43_wldev *dev)
  715. {
  716. struct b43_phy_ht *phy_ht = dev->phy.ht;
  717. u16 tmp;
  718. u16 clip_state[3];
  719. bool saved_tx_pwr_ctl;
  720. if (dev->dev->bus_type != B43_BUS_BCMA) {
  721. b43err(dev->wl, "HT-PHY is supported only on BCMA bus!\n");
  722. return -EOPNOTSUPP;
  723. }
  724. b43_phy_ht_tables_init(dev);
  725. b43_phy_mask(dev, 0x0be, ~0x2);
  726. b43_phy_set(dev, 0x23f, 0x7ff);
  727. b43_phy_set(dev, 0x240, 0x7ff);
  728. b43_phy_set(dev, 0x241, 0x7ff);
  729. b43_phy_ht_zero_extg(dev);
  730. b43_phy_mask(dev, B43_PHY_EXTG(0), ~0x3);
  731. b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0);
  732. b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0);
  733. b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0);
  734. b43_phy_write(dev, B43_PHY_EXTG(0x103), 0x20);
  735. b43_phy_write(dev, B43_PHY_EXTG(0x101), 0x20);
  736. b43_phy_write(dev, 0x20d, 0xb8);
  737. b43_phy_write(dev, B43_PHY_EXTG(0x14f), 0xc8);
  738. b43_phy_write(dev, 0x70, 0x50);
  739. b43_phy_write(dev, 0x1ff, 0x30);
  740. if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ)
  741. b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN, 0);
  742. else
  743. b43_phy_ht_classifier(dev, B43_PHY_HT_CLASS_CTL_CCK_EN,
  744. B43_PHY_HT_CLASS_CTL_CCK_EN);
  745. b43_phy_set(dev, 0xb1, 0x91);
  746. b43_phy_write(dev, 0x32f, 0x0003);
  747. b43_phy_write(dev, 0x077, 0x0010);
  748. b43_phy_write(dev, 0x0b4, 0x0258);
  749. b43_phy_mask(dev, 0x17e, ~0x4000);
  750. b43_phy_write(dev, 0x0b9, 0x0072);
  751. b43_httab_write_few(dev, B43_HTTAB16(7, 0x14e), 2, 0x010f, 0x010f);
  752. b43_httab_write_few(dev, B43_HTTAB16(7, 0x15e), 2, 0x010f, 0x010f);
  753. b43_httab_write_few(dev, B43_HTTAB16(7, 0x16e), 2, 0x010f, 0x010f);
  754. b43_phy_ht_afe_unk1(dev);
  755. b43_httab_write_few(dev, B43_HTTAB16(7, 0x130), 9, 0x777, 0x111, 0x111,
  756. 0x777, 0x111, 0x111, 0x777, 0x111, 0x111);
  757. b43_httab_write(dev, B43_HTTAB16(7, 0x120), 0x0777);
  758. b43_httab_write(dev, B43_HTTAB16(7, 0x124), 0x0777);
  759. b43_httab_write(dev, B43_HTTAB16(8, 0x00), 0x02);
  760. b43_httab_write(dev, B43_HTTAB16(8, 0x10), 0x02);
  761. b43_httab_write(dev, B43_HTTAB16(8, 0x20), 0x02);
  762. b43_httab_write_few(dev, B43_HTTAB16(8, 0x08), 4,
  763. 0x8e, 0x96, 0x96, 0x96);
  764. b43_httab_write_few(dev, B43_HTTAB16(8, 0x18), 4,
  765. 0x8f, 0x9f, 0x9f, 0x9f);
  766. b43_httab_write_few(dev, B43_HTTAB16(8, 0x28), 4,
  767. 0x8f, 0x9f, 0x9f, 0x9f);
  768. b43_httab_write_few(dev, B43_HTTAB16(8, 0x0c), 4, 0x2, 0x2, 0x2, 0x2);
  769. b43_httab_write_few(dev, B43_HTTAB16(8, 0x1c), 4, 0x2, 0x2, 0x2, 0x2);
  770. b43_httab_write_few(dev, B43_HTTAB16(8, 0x2c), 4, 0x2, 0x2, 0x2, 0x2);
  771. b43_phy_maskset(dev, 0x0280, 0xff00, 0x3e);
  772. b43_phy_maskset(dev, 0x0283, 0xff00, 0x3e);
  773. b43_phy_maskset(dev, B43_PHY_OFDM(0x0141), 0xff00, 0x46);
  774. b43_phy_maskset(dev, 0x0283, 0xff00, 0x40);
  775. b43_httab_write_few(dev, B43_HTTAB16(00, 0x8), 4,
  776. 0x09, 0x0e, 0x13, 0x18);
  777. b43_httab_write_few(dev, B43_HTTAB16(01, 0x8), 4,
  778. 0x09, 0x0e, 0x13, 0x18);
  779. /* TODO: Did wl mean 2 instead of 40? */
  780. b43_httab_write_few(dev, B43_HTTAB16(40, 0x8), 4,
  781. 0x09, 0x0e, 0x13, 0x18);
  782. b43_phy_maskset(dev, B43_PHY_OFDM(0x24), 0x3f, 0xd);
  783. b43_phy_maskset(dev, B43_PHY_OFDM(0x64), 0x3f, 0xd);
  784. b43_phy_maskset(dev, B43_PHY_OFDM(0xa4), 0x3f, 0xd);
  785. b43_phy_set(dev, B43_PHY_EXTG(0x060), 0x1);
  786. b43_phy_set(dev, B43_PHY_EXTG(0x064), 0x1);
  787. b43_phy_set(dev, B43_PHY_EXTG(0x080), 0x1);
  788. b43_phy_set(dev, B43_PHY_EXTG(0x084), 0x1);
  789. /* Copy some tables entries */
  790. tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x144));
  791. b43_httab_write(dev, B43_HTTAB16(7, 0x14a), tmp);
  792. tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x154));
  793. b43_httab_write(dev, B43_HTTAB16(7, 0x15a), tmp);
  794. tmp = b43_httab_read(dev, B43_HTTAB16(7, 0x164));
  795. b43_httab_write(dev, B43_HTTAB16(7, 0x16a), tmp);
  796. /* Reset CCA */
  797. b43_phy_force_clock(dev, true);
  798. tmp = b43_phy_read(dev, B43_PHY_HT_BBCFG);
  799. b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp | B43_PHY_HT_BBCFG_RSTCCA);
  800. b43_phy_write(dev, B43_PHY_HT_BBCFG, tmp & ~B43_PHY_HT_BBCFG_RSTCCA);
  801. b43_phy_force_clock(dev, false);
  802. b43_mac_phy_clock_set(dev, true);
  803. b43_phy_ht_pa_override(dev, false);
  804. b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RX2TX);
  805. b43_phy_ht_force_rf_sequence(dev, B43_PHY_HT_RF_SEQ_TRIG_RST2RX);
  806. b43_phy_ht_pa_override(dev, true);
  807. /* TODO: Should we restore it? Or store it in global PHY info? */
  808. b43_phy_ht_classifier(dev, 0, 0);
  809. b43_phy_ht_read_clip_detection(dev, clip_state);
  810. if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
  811. b43_phy_ht_bphy_init(dev);
  812. b43_httab_write_bulk(dev, B43_HTTAB32(0x1a, 0xc0),
  813. B43_HTTAB_1A_C0_LATE_SIZE, b43_httab_0x1a_0xc0_late);
  814. saved_tx_pwr_ctl = phy_ht->tx_pwr_ctl;
  815. b43_phy_ht_tx_power_fix(dev);
  816. b43_phy_ht_tx_power_ctl(dev, false);
  817. b43_phy_ht_tx_power_ctl_idle_tssi(dev);
  818. b43_phy_ht_tx_power_ctl_setup(dev);
  819. b43_phy_ht_tssi_setup(dev);
  820. b43_phy_ht_tx_power_ctl(dev, saved_tx_pwr_ctl);
  821. return 0;
  822. }
  823. static void b43_phy_ht_op_free(struct b43_wldev *dev)
  824. {
  825. struct b43_phy *phy = &dev->phy;
  826. struct b43_phy_ht *phy_ht = phy->ht;
  827. kfree(phy_ht);
  828. phy->ht = NULL;
  829. }
  830. /* https://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
  831. static void b43_phy_ht_op_software_rfkill(struct b43_wldev *dev,
  832. bool blocked)
  833. {
  834. if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
  835. b43err(dev->wl, "MAC not suspended\n");
  836. if (blocked) {
  837. b43_phy_mask(dev, B43_PHY_HT_RF_CTL_CMD,
  838. ~B43_PHY_HT_RF_CTL_CMD_CHIP0_PU);
  839. } else {
  840. if (dev->phy.radio_ver == 0x2059)
  841. b43_radio_2059_init(dev);
  842. else
  843. B43_WARN_ON(1);
  844. b43_switch_channel(dev, dev->phy.channel);
  845. }
  846. }
  847. static void b43_phy_ht_op_switch_analog(struct b43_wldev *dev, bool on)
  848. {
  849. if (on) {
  850. b43_phy_write(dev, B43_PHY_HT_AFE_C1, 0x00cd);
  851. b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0x0000);
  852. b43_phy_write(dev, B43_PHY_HT_AFE_C2, 0x00cd);
  853. b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0x0000);
  854. b43_phy_write(dev, B43_PHY_HT_AFE_C3, 0x00cd);
  855. b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0x0000);
  856. } else {
  857. b43_phy_write(dev, B43_PHY_HT_AFE_C1_OVER, 0x07ff);
  858. b43_phy_write(dev, B43_PHY_HT_AFE_C1, 0x00fd);
  859. b43_phy_write(dev, B43_PHY_HT_AFE_C2_OVER, 0x07ff);
  860. b43_phy_write(dev, B43_PHY_HT_AFE_C2, 0x00fd);
  861. b43_phy_write(dev, B43_PHY_HT_AFE_C3_OVER, 0x07ff);
  862. b43_phy_write(dev, B43_PHY_HT_AFE_C3, 0x00fd);
  863. }
  864. }
  865. static int b43_phy_ht_op_switch_channel(struct b43_wldev *dev,
  866. unsigned int new_channel)
  867. {
  868. struct ieee80211_channel *channel = dev->wl->hw->conf.chandef.chan;
  869. enum nl80211_channel_type channel_type =
  870. cfg80211_get_chandef_type(&dev->wl->hw->conf.chandef);
  871. if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ) {
  872. if ((new_channel < 1) || (new_channel > 14))
  873. return -EINVAL;
  874. } else {
  875. return -EINVAL;
  876. }
  877. return b43_phy_ht_set_channel(dev, channel, channel_type);
  878. }
  879. static unsigned int b43_phy_ht_op_get_default_chan(struct b43_wldev *dev)
  880. {
  881. if (b43_current_band(dev->wl) == NL80211_BAND_2GHZ)
  882. return 11;
  883. return 36;
  884. }
  885. /**************************************************
  886. * R/W ops.
  887. **************************************************/
  888. static void b43_phy_ht_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
  889. u16 set)
  890. {
  891. b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg);
  892. b43_write16(dev, B43_MMIO_PHY_DATA,
  893. (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
  894. }
  895. static u16 b43_phy_ht_op_radio_read(struct b43_wldev *dev, u16 reg)
  896. {
  897. /* HT-PHY needs 0x200 for read access */
  898. reg |= 0x200;
  899. b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
  900. return b43_read16(dev, B43_MMIO_RADIO24_DATA);
  901. }
  902. static void b43_phy_ht_op_radio_write(struct b43_wldev *dev, u16 reg,
  903. u16 value)
  904. {
  905. b43_write16f(dev, B43_MMIO_RADIO24_CONTROL, reg);
  906. b43_write16(dev, B43_MMIO_RADIO24_DATA, value);
  907. }
  908. static enum b43_txpwr_result
  909. b43_phy_ht_op_recalc_txpower(struct b43_wldev *dev, bool ignore_tssi)
  910. {
  911. return B43_TXPWR_RES_DONE;
  912. }
  913. static void b43_phy_ht_op_adjust_txpower(struct b43_wldev *dev)
  914. {
  915. }
  916. /**************************************************
  917. * PHY ops struct.
  918. **************************************************/
  919. const struct b43_phy_operations b43_phyops_ht = {
  920. .allocate = b43_phy_ht_op_allocate,
  921. .free = b43_phy_ht_op_free,
  922. .prepare_structs = b43_phy_ht_op_prepare_structs,
  923. .init = b43_phy_ht_op_init,
  924. .phy_maskset = b43_phy_ht_op_maskset,
  925. .radio_read = b43_phy_ht_op_radio_read,
  926. .radio_write = b43_phy_ht_op_radio_write,
  927. .software_rfkill = b43_phy_ht_op_software_rfkill,
  928. .switch_analog = b43_phy_ht_op_switch_analog,
  929. .switch_channel = b43_phy_ht_op_switch_channel,
  930. .get_default_chan = b43_phy_ht_op_get_default_chan,
  931. .recalc_txpower = b43_phy_ht_op_recalc_txpower,
  932. .adjust_txpower = b43_phy_ht_op_adjust_txpower,
  933. };