Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
phy_n.c
Go to the documentation of this file.
1 /*
2 
3  Broadcom B43 wireless driver
4  IEEE 802.11n PHY support
5 
6  Copyright (c) 2008 Michael Buesch <[email protected]>
7  Copyright (c) 2010-2011 Rafał Miłecki <[email protected]>
8 
9  This program is free software; you can redistribute it and/or modify
10  it under the terms of the GNU General Public License as published by
11  the Free Software Foundation; either version 2 of the License, or
12  (at your option) any later version.
13 
14  This program is distributed in the hope that it will be useful,
15  but WITHOUT ANY WARRANTY; without even the implied warranty of
16  MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
17  GNU General Public License for more details.
18 
19  You should have received a copy of the GNU General Public License
20  along with this program; see the file COPYING. If not, write to
21  the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
22  Boston, MA 02110-1301, USA.
23 
24 */
25 
26 #include <linux/delay.h>
27 #include <linux/slab.h>
28 #include <linux/types.h>
29 
30 #include "b43.h"
31 #include "phy_n.h"
32 #include "tables_nphy.h"
33 #include "radio_2055.h"
34 #include "radio_2056.h"
35 #include "radio_2057.h"
36 #include "main.h"
37 
38 struct nphy_txgains {
39  u16 txgm[2];
40  u16 pga[2];
41  u16 pad[2];
42  u16 ipa[2];
43 };
44 
51  u16 ncorr[5];
52 };
53 
54 struct nphy_iq_est {
61 };
62 
70 };
71 
80 };
81 
82 static inline bool b43_nphy_ipa(struct b43_wldev *dev)
83 {
84  enum ieee80211_band band = b43_current_band(dev->wl);
85  return ((dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
86  (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ));
87 }
88 
89 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreGetState */
90 static u8 b43_nphy_get_rx_core_state(struct b43_wldev *dev)
91 {
94 }
95 
96 /**************************************************
97  * RF (just without b43_nphy_rf_control_intc_override)
98  **************************************************/
99 
100 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
101 static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
102  enum b43_nphy_rf_sequence seq)
103 {
104  static const u16 trigger[] = {
111  };
112  int i;
113  u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
114 
115  B43_WARN_ON(seq >= ARRAY_SIZE(trigger));
116 
119  b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]);
120  for (i = 0; i < 200; i++) {
121  if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq]))
122  goto ok;
123  msleep(1);
124  }
125  b43err(dev->wl, "RF sequence status timeout\n");
126 ok:
127  b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
128 }
129 
130 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverrideRev7 */
131 static void b43_nphy_rf_control_override_rev7(struct b43_wldev *dev, u16 field,
132  u16 value, u8 core, bool off,
133  u8 override)
134 {
135  const struct nphy_rf_control_override_rev7 *e;
136  u16 en_addrs[3][2] = {
137  { 0x0E7, 0x0EC }, { 0x342, 0x343 }, { 0x346, 0x347 }
138  };
139  u16 en_addr;
140  u16 en_mask = field;
141  u16 val_addr;
142  u8 i;
143 
144  /* Remember: we can get NULL! */
145  e = b43_nphy_get_rf_ctl_over_rev7(dev, field, override);
146 
147  for (i = 0; i < 2; i++) {
148  if (override >= ARRAY_SIZE(en_addrs)) {
149  b43err(dev->wl, "Invalid override value %d\n", override);
150  return;
151  }
152  en_addr = en_addrs[override][i];
153 
154  val_addr = (i == 0) ? e->val_addr_core0 : e->val_addr_core1;
155 
156  if (off) {
157  b43_phy_mask(dev, en_addr, ~en_mask);
158  if (e) /* Do it safer, better than wl */
159  b43_phy_mask(dev, val_addr, ~e->val_mask);
160  } else {
161  if (!core || (core & (1 << i))) {
162  b43_phy_set(dev, en_addr, en_mask);
163  if (e)
164  b43_phy_maskset(dev, val_addr, ~e->val_mask, (value << e->val_shift));
165  }
166  }
167  }
168 }
169 
170 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
171 static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
172  u16 value, u8 core, bool off)
173 {
174  int i;
175  u8 index = fls(field);
176  u8 addr, en_addr, val_addr;
177  /* we expect only one bit set */
178  B43_WARN_ON(field & (~(1 << (index - 1))));
179 
180  if (dev->phy.rev >= 3) {
181  const struct nphy_rf_control_override_rev3 *rf_ctrl;
182  for (i = 0; i < 2; i++) {
183  if (index == 0 || index == 16) {
184  b43err(dev->wl,
185  "Unsupported RF Ctrl Override call\n");
186  return;
187  }
188 
189  rf_ctrl = &tbl_rf_control_override_rev3[index - 1];
190  en_addr = B43_PHY_N((i == 0) ?
191  rf_ctrl->en_addr0 : rf_ctrl->en_addr1);
192  val_addr = B43_PHY_N((i == 0) ?
193  rf_ctrl->val_addr0 : rf_ctrl->val_addr1);
194 
195  if (off) {
196  b43_phy_mask(dev, en_addr, ~(field));
197  b43_phy_mask(dev, val_addr,
198  ~(rf_ctrl->val_mask));
199  } else {
200  if (core == 0 || ((1 << i) & core)) {
201  b43_phy_set(dev, en_addr, field);
202  b43_phy_maskset(dev, val_addr,
203  ~(rf_ctrl->val_mask),
204  (value << rf_ctrl->val_shift));
205  }
206  }
207  }
208  } else {
209  const struct nphy_rf_control_override_rev2 *rf_ctrl;
210  if (off) {
211  b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field));
212  value = 0;
213  } else {
214  b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field);
215  }
216 
217  for (i = 0; i < 2; i++) {
218  if (index <= 1 || index == 16) {
219  b43err(dev->wl,
220  "Unsupported RF Ctrl Override call\n");
221  return;
222  }
223 
224  if (index == 2 || index == 10 ||
225  (index >= 13 && index <= 15)) {
226  core = 1;
227  }
228 
229  rf_ctrl = &tbl_rf_control_override_rev2[index - 2];
230  addr = B43_PHY_N((i == 0) ?
231  rf_ctrl->addr0 : rf_ctrl->addr1);
232 
233  if ((1 << i) & core)
234  b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask),
235  (value << rf_ctrl->shift));
236 
237  b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
240  udelay(1);
241  b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE);
242  }
243  }
244 }
245 
246 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
247 static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
248  u16 value, u8 core)
249 {
250  u8 i, j;
251  u16 reg, tmp, val;
252 
253  B43_WARN_ON(dev->phy.rev < 3);
254  B43_WARN_ON(field > 4);
255 
256  for (i = 0; i < 2; i++) {
257  if ((core == 1 && i == 1) || (core == 2 && !i))
258  continue;
259 
260  reg = (i == 0) ?
262  b43_phy_set(dev, reg, 0x400);
263 
264  switch (field) {
265  case 0:
266  b43_phy_write(dev, reg, 0);
267  b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
268  break;
269  case 1:
270  if (!i) {
272  0xFC3F, (value << 6));
274  0xFFFE, 1);
277  for (j = 0; j < 100; j++) {
279  j = 0;
280  break;
281  }
282  udelay(10);
283  }
284  if (j)
285  b43err(dev->wl,
286  "intc override timeout\n");
288  0xFFFE);
289  } else {
291  0xFC3F, (value << 6));
293  0xFFFE, 1);
296  for (j = 0; j < 100; j++) {
298  j = 0;
299  break;
300  }
301  udelay(10);
302  }
303  if (j)
304  b43err(dev->wl,
305  "intc override timeout\n");
307  0xFFFE);
308  }
309  break;
310  case 2:
311  if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
312  tmp = 0x0020;
313  val = value << 5;
314  } else {
315  tmp = 0x0010;
316  val = value << 4;
317  }
318  b43_phy_maskset(dev, reg, ~tmp, val);
319  break;
320  case 3:
321  if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
322  tmp = 0x0001;
323  val = value;
324  } else {
325  tmp = 0x0004;
326  val = value << 2;
327  }
328  b43_phy_maskset(dev, reg, ~tmp, val);
329  break;
330  case 4:
331  if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
332  tmp = 0x0002;
333  val = value << 1;
334  } else {
335  tmp = 0x0008;
336  val = value << 3;
337  }
338  b43_phy_maskset(dev, reg, ~tmp, val);
339  break;
340  }
341  }
342 }
343 
344 /**************************************************
345  * Various PHY ops
346  **************************************************/
347 
348 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
349 static void b43_nphy_write_clip_detection(struct b43_wldev *dev,
350  const u16 *clip_st)
351 {
352  b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]);
353  b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]);
354 }
355 
356 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
357 static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
358 {
359  clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES);
360  clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES);
361 }
362 
363 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
364 static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
365 {
366  u16 tmp;
367 
368  if (dev->dev->core_rev == 16)
369  b43_mac_suspend(dev);
370 
371  tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
374  tmp &= ~mask;
375  tmp |= (val & mask);
376  b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
377 
378  if (dev->dev->core_rev == 16)
379  b43_mac_enable(dev);
380 
381  return tmp;
382 }
383 
384 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
385 static void b43_nphy_reset_cca(struct b43_wldev *dev)
386 {
387  u16 bbcfg;
388 
389  b43_phy_force_clock(dev, 1);
390  bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
392  udelay(1);
394  b43_phy_force_clock(dev, 0);
395  b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
396 }
397 
398 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
399 static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
400 {
401  struct b43_phy *phy = &dev->phy;
402  struct b43_phy_n *nphy = phy->n;
403 
404  if (enable) {
405  static const u16 clip[] = { 0xFFFF, 0xFFFF };
406  if (nphy->deaf_count++ == 0) {
407  nphy->classifier_state = b43_nphy_classifier(dev, 0, 0);
408  b43_nphy_classifier(dev, 0x7, 0);
409  b43_nphy_read_clip_detection(dev, nphy->clip_state);
410  b43_nphy_write_clip_detection(dev, clip);
411  }
412  b43_nphy_reset_cca(dev);
413  } else {
414  if (--nphy->deaf_count == 0) {
415  b43_nphy_classifier(dev, 0x7, nphy->classifier_state);
416  b43_nphy_write_clip_detection(dev, nphy->clip_state);
417  }
418  }
419 }
420 
421 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
422 static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
423 {
424  struct b43_phy_n *nphy = dev->phy.n;
425 
426  u8 i;
427  s16 tmp;
428  u16 data[4];
429  s16 gain[2];
430  u16 minmax[2];
431  static const u16 lna_gain[4] = { -2, 10, 19, 25 };
432 
433  if (nphy->hang_avoid)
434  b43_nphy_stay_in_carrier_search(dev, 1);
435 
436  if (nphy->gain_boost) {
437  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
438  gain[0] = 6;
439  gain[1] = 6;
440  } else {
441  tmp = 40370 - 315 * dev->phy.channel;
442  gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
443  tmp = 23242 - 224 * dev->phy.channel;
444  gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
445  }
446  } else {
447  gain[0] = 0;
448  gain[1] = 0;
449  }
450 
451  for (i = 0; i < 2; i++) {
452  if (nphy->elna_gain_config) {
453  data[0] = 19 + gain[i];
454  data[1] = 25 + gain[i];
455  data[2] = 25 + gain[i];
456  data[3] = 25 + gain[i];
457  } else {
458  data[0] = lna_gain[0] + gain[i];
459  data[1] = lna_gain[1] + gain[i];
460  data[2] = lna_gain[2] + gain[i];
461  data[3] = lna_gain[3] + gain[i];
462  }
463  b43_ntab_write_bulk(dev, B43_NTAB16(i, 8), 4, data);
464 
465  minmax[i] = 23 + gain[i];
466  }
467 
469  minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT);
471  minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT);
472 
473  if (nphy->hang_avoid)
474  b43_nphy_stay_in_carrier_search(dev, 0);
475 }
476 
477 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */
478 static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
479  u8 *events, u8 *delays, u8 length)
480 {
481  struct b43_phy_n *nphy = dev->phy.n;
482  u8 i;
483  u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F;
484  u16 offset1 = cmd << 4;
485  u16 offset2 = offset1 + 0x80;
486 
487  if (nphy->hang_avoid)
488  b43_nphy_stay_in_carrier_search(dev, true);
489 
490  b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events);
491  b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays);
492 
493  for (i = length; i < 16; i++) {
494  b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end);
495  b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1);
496  }
497 
498  if (nphy->hang_avoid)
499  b43_nphy_stay_in_carrier_search(dev, false);
500 }
501 
502 /**************************************************
503  * Radio 0x2057
504  **************************************************/
505 
506 /* http://bcm-v4.sipsolutions.net/PHY/radio2057_rcal */
507 static u8 b43_radio_2057_rcal(struct b43_wldev *dev)
508 {
509  struct b43_phy *phy = &dev->phy;
510  u16 tmp;
511 
512  if (phy->radio_rev == 5) {
513  b43_phy_mask(dev, 0x342, ~0x2);
514  udelay(10);
516  b43_radio_maskset(dev, 0x1ca, ~0x2, 0x1);
517  }
518 
519  b43_radio_set(dev, R2057_RCAL_CONFIG, 0x1);
520  udelay(10);
521  b43_radio_set(dev, R2057_RCAL_CONFIG, 0x3);
522  if (!b43_radio_wait_value(dev, R2057_RCCAL_N1_1, 1, 1, 100, 1000000)) {
523  b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
524  return 0;
525  }
526  b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x2);
527  tmp = b43_radio_read(dev, R2057_RCAL_STATUS) & 0x3E;
528  b43_radio_mask(dev, R2057_RCAL_CONFIG, ~0x1);
529 
530  if (phy->radio_rev == 5) {
532  b43_radio_mask(dev, 0x1ca, ~0x2);
533  }
534  if (phy->radio_rev <= 4 || phy->radio_rev == 6) {
535  b43_radio_maskset(dev, R2057_TEMPSENSE_CONFIG, ~0x3C, tmp);
537  tmp << 2);
538  }
539 
540  return tmp & 0x3e;
541 }
542 
543 /* http://bcm-v4.sipsolutions.net/PHY/radio2057_rccal */
544 static u16 b43_radio_2057_rccal(struct b43_wldev *dev)
545 {
546  struct b43_phy *phy = &dev->phy;
547  bool special = (phy->radio_rev == 3 || phy->radio_rev == 4 ||
548  phy->radio_rev == 6);
549  u16 tmp;
550 
551  if (special) {
553  b43_radio_write(dev, R2057_RCCAL_TRC0, 0xC0);
554  } else {
555  b43_radio_write(dev, 0x1AE, 0x61);
556  b43_radio_write(dev, R2057_RCCAL_TRC0, 0xE1);
557  }
558  b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
560  if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
561  5000000))
562  b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
564  if (special) {
566  b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
567  } else {
568  b43_radio_write(dev, 0x1AE, 0x69);
569  b43_radio_write(dev, R2057_RCCAL_TRC0, 0xD5);
570  }
571  b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
573  if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
574  5000000))
575  b43dbg(dev->wl, "Radio 0x2057 rccal timeout\n");
577  if (special) {
579  b43_radio_write(dev, R2057_RCCAL_X1, 0x28);
580  b43_radio_write(dev, R2057_RCCAL_TRC0, 0xB0);
581  } else {
582  b43_radio_write(dev, 0x1AE, 0x73);
583  b43_radio_write(dev, R2057_RCCAL_X1, 0x6E);
584  b43_radio_write(dev, R2057_RCCAL_TRC0, 0x99);
585  }
587  if (!b43_radio_wait_value(dev, R2057_RCCAL_DONE_OSCCAP, 1, 1, 500,
588  5000000)) {
589  b43err(dev->wl, "Radio 0x2057 rcal timeout\n");
590  return 0;
591  }
594  return tmp;
595 }
596 
597 static void b43_radio_2057_init_pre(struct b43_wldev *dev)
598 {
600  /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
604 }
605 
606 static void b43_radio_2057_init_post(struct b43_wldev *dev)
607 {
609 
611  b43_radio_set(dev, R2057_XTAL_CONFIG2, 0x80);
612  mdelay(2);
614  b43_radio_mask(dev, R2057_XTAL_CONFIG2, ~0x80);
615 
616  if (dev->phy.n->init_por) {
617  b43_radio_2057_rcal(dev);
618  b43_radio_2057_rccal(dev);
619  }
621 
622  dev->phy.n->init_por = false;
623 }
624 
625 /* http://bcm-v4.sipsolutions.net/802.11/Radio/2057/Init */
626 static void b43_radio_2057_init(struct b43_wldev *dev)
627 {
628  b43_radio_2057_init_pre(dev);
630  b43_radio_2057_init_post(dev);
631 }
632 
633 /**************************************************
634  * Radio 0x2056
635  **************************************************/
636 
637 static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
638  const struct b43_nphy_channeltab_entry_rev3 *e)
639 {
666 
671 
688 
693 
710 }
711 
712 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */
713 static void b43_radio_2056_setup(struct b43_wldev *dev,
714  const struct b43_nphy_channeltab_entry_rev3 *e)
715 {
716  struct ssb_sprom *sprom = dev->dev->bus_sprom;
717  enum ieee80211_band band = b43_current_band(dev->wl);
718  u16 offset;
719  u8 i;
720  u16 bias, cbias;
721  u16 pag_boost, padg_boost, pgag_boost, mixg_boost;
722  u16 paa_boost, pada_boost, pgaa_boost, mixa_boost;
723 
724  B43_WARN_ON(dev->phy.rev < 3);
725 
726  b43_chantab_radio_2056_upload(dev, e);
728 
729  if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
730  b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
733  if (dev->dev->chip_id == 0x4716) {
736  } else {
739  }
740  }
741  if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
742  b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
747  }
748 
749  if (dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) {
750  for (i = 0; i < 2; i++) {
751  offset = i ? B2056_TX1 : B2056_TX0;
752  if (dev->phy.rev >= 5) {
753  b43_radio_write(dev,
754  offset | B2056_TX_PADG_IDAC, 0xcc);
755 
756  if (dev->dev->chip_id == 0x4716) {
757  bias = 0x40;
758  cbias = 0x45;
759  pag_boost = 0x5;
760  pgag_boost = 0x33;
761  mixg_boost = 0x55;
762  } else {
763  bias = 0x25;
764  cbias = 0x20;
765  pag_boost = 0x4;
766  pgag_boost = 0x03;
767  mixg_boost = 0x65;
768  }
769  padg_boost = 0x77;
770 
771  b43_radio_write(dev,
773  bias);
774  b43_radio_write(dev,
775  offset | B2056_TX_INTPAG_IAUX_STAT,
776  bias);
777  b43_radio_write(dev,
778  offset | B2056_TX_INTPAG_CASCBIAS,
779  cbias);
780  b43_radio_write(dev,
782  pag_boost);
783  b43_radio_write(dev,
784  offset | B2056_TX_PGAG_BOOST_TUNE,
785  pgag_boost);
786  b43_radio_write(dev,
787  offset | B2056_TX_PADG_BOOST_TUNE,
788  padg_boost);
789  b43_radio_write(dev,
790  offset | B2056_TX_MIXG_BOOST_TUNE,
791  mixg_boost);
792  } else {
793  bias = dev->phy.is_40mhz ? 0x40 : 0x20;
794  b43_radio_write(dev,
796  bias);
797  b43_radio_write(dev,
798  offset | B2056_TX_INTPAG_IAUX_STAT,
799  bias);
800  b43_radio_write(dev,
801  offset | B2056_TX_INTPAG_CASCBIAS,
802  0x30);
803  }
804  b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
805  }
806  } else if (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ) {
807  u16 freq = dev->phy.channel_freq;
808  if (freq < 5100) {
809  paa_boost = 0xA;
810  pada_boost = 0x77;
811  pgaa_boost = 0xF;
812  mixa_boost = 0xF;
813  } else if (freq < 5340) {
814  paa_boost = 0x8;
815  pada_boost = 0x77;
816  pgaa_boost = 0xFB;
817  mixa_boost = 0xF;
818  } else if (freq < 5650) {
819  paa_boost = 0x0;
820  pada_boost = 0x77;
821  pgaa_boost = 0xB;
822  mixa_boost = 0xF;
823  } else {
824  paa_boost = 0x0;
825  pada_boost = 0x77;
826  if (freq != 5825)
827  pgaa_boost = -(freq - 18) / 36 + 168;
828  else
829  pgaa_boost = 6;
830  mixa_boost = 0xF;
831  }
832 
833  for (i = 0; i < 2; i++) {
834  offset = i ? B2056_TX1 : B2056_TX0;
835 
836  b43_radio_write(dev,
837  offset | B2056_TX_INTPAA_BOOST_TUNE, paa_boost);
838  b43_radio_write(dev,
839  offset | B2056_TX_PADA_BOOST_TUNE, pada_boost);
840  b43_radio_write(dev,
841  offset | B2056_TX_PGAA_BOOST_TUNE, pgaa_boost);
842  b43_radio_write(dev,
843  offset | B2056_TX_MIXA_BOOST_TUNE, mixa_boost);
844  b43_radio_write(dev,
845  offset | B2056_TX_TXSPARE1, 0x30);
846  b43_radio_write(dev,
847  offset | B2056_TX_PA_SPARE2, 0xee);
848  b43_radio_write(dev,
849  offset | B2056_TX_PADA_CASCBIAS, 0x03);
850  b43_radio_write(dev,
851  offset | B2056_TX_INTPAA_IAUX_STAT, 0x50);
852  b43_radio_write(dev,
853  offset | B2056_TX_INTPAA_IMAIN_STAT, 0x50);
854  b43_radio_write(dev,
855  offset | B2056_TX_INTPAA_CASCBIAS, 0x30);
856  }
857  }
858 
859  udelay(50);
860  /* VCO calibration */
866  udelay(300);
867 }
868 
869 static u8 b43_radio_2056_rcal(struct b43_wldev *dev)
870 {
871  struct b43_phy *phy = &dev->phy;
872  u16 mast2, tmp;
873 
874  if (phy->rev != 3)
875  return 0;
876 
877  mast2 = b43_radio_read(dev, B2056_SYN_PLL_MAST2);
878  b43_radio_write(dev, B2056_SYN_PLL_MAST2, mast2 | 0x7);
879 
880  udelay(10);
882  udelay(10);
884 
885  if (!b43_radio_wait_value(dev, B2056_SYN_RCAL_CODE_OUT, 0x80, 0x80, 100,
886  1000000)) {
887  b43err(dev->wl, "Radio recalibration timeout\n");
888  return 0;
889  }
890 
894 
896 
897  return tmp & 0x1f;
898 }
899 
900 static void b43_radio_init2056_pre(struct b43_wldev *dev)
901 {
904  /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
911 }
912 
913 static void b43_radio_init2056_post(struct b43_wldev *dev)
914 {
916  b43_radio_set(dev, B2056_SYN_COM_PU, 0x2);
918  msleep(1);
920  b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC);
922  if (dev->phy.n->init_por)
923  b43_radio_2056_rcal(dev);
924 }
925 
926 /*
927  * Initialize a Broadcom 2056 N-radio
928  * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init
929  */
930 static void b43_radio_init2056(struct b43_wldev *dev)
931 {
932  b43_radio_init2056_pre(dev);
933  b2056_upload_inittabs(dev, 0, 0);
934  b43_radio_init2056_post(dev);
935 
936  dev->phy.n->init_por = false;
937 }
938 
939 /**************************************************
940  * Radio 0x2055
941  **************************************************/
942 
943 static void b43_chantab_radio_upload(struct b43_wldev *dev,
944  const struct b43_nphy_channeltab_entry_rev2 *e)
945 {
950  b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
951 
956  b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
957 
962  b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
963 
968  b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
969 
974  b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
975 
978 }
979 
980 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
981 static void b43_radio_2055_setup(struct b43_wldev *dev,
982  const struct b43_nphy_channeltab_entry_rev2 *e)
983 {
984  B43_WARN_ON(dev->phy.rev >= 3);
985 
986  b43_chantab_radio_upload(dev, e);
987  udelay(50);
988  b43_radio_write(dev, B2055_VCO_CAL10, 0x05);
989  b43_radio_write(dev, B2055_VCO_CAL10, 0x45);
990  b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
991  b43_radio_write(dev, B2055_VCO_CAL10, 0x65);
992  udelay(300);
993 }
994 
995 static void b43_radio_init2055_pre(struct b43_wldev *dev)
996 {
1004 }
1005 
1006 static void b43_radio_init2055_post(struct b43_wldev *dev)
1007 {
1008  struct b43_phy_n *nphy = dev->phy.n;
1009  struct ssb_sprom *sprom = dev->dev->bus_sprom;
1010  bool workaround = false;
1011 
1012  if (sprom->revision < 4)
1013  workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
1014  && dev->dev->board_type == 0x46D
1015  && dev->dev->board_rev >= 0x41);
1016  else
1017  workaround =
1019 
1020  b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
1021  if (workaround) {
1022  b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
1023  b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F);
1024  }
1025  b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C);
1026  b43_radio_write(dev, B2055_CAL_MISC, 0x3C);
1027  b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE);
1028  b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80);
1029  b43_radio_set(dev, B2055_CAL_MISC, 0x1);
1030  msleep(1);
1031  b43_radio_set(dev, B2055_CAL_MISC, 0x40);
1032  if (!b43_radio_wait_value(dev, B2055_CAL_COUT2, 0x80, 0x80, 10, 2000))
1033  b43err(dev->wl, "radio post init timeout\n");
1034  b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
1035  b43_switch_channel(dev, dev->phy.channel);
1040  b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6);
1041  b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6);
1042  if (!nphy->gain_boost) {
1043  b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2);
1044  b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2);
1045  } else {
1046  b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD);
1047  b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD);
1048  }
1049  udelay(2);
1050 }
1051 
1052 /*
1053  * Initialize a Broadcom 2055 N-radio
1054  * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init
1055  */
1056 static void b43_radio_init2055(struct b43_wldev *dev)
1057 {
1058  b43_radio_init2055_pre(dev);
1059  if (b43_status(dev) < B43_STAT_INITIALIZED) {
1060  /* Follow wl, not specs. Do not force uploading all regs */
1061  b2055_upload_inittab(dev, 0, 0);
1062  } else {
1063  bool ghz5 = b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ;
1064  b2055_upload_inittab(dev, ghz5, 0);
1065  }
1066  b43_radio_init2055_post(dev);
1067 }
1068 
1069 /**************************************************
1070  * Samples
1071  **************************************************/
1072 
1073 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */
1074 static int b43_nphy_load_samples(struct b43_wldev *dev,
1075  struct b43_c32 *samples, u16 len) {
1076  struct b43_phy_n *nphy = dev->phy.n;
1077  u16 i;
1078  u32 *data;
1079 
1080  data = kzalloc(len * sizeof(u32), GFP_KERNEL);
1081  if (!data) {
1082  b43err(dev->wl, "allocation for samples loading failed\n");
1083  return -ENOMEM;
1084  }
1085  if (nphy->hang_avoid)
1086  b43_nphy_stay_in_carrier_search(dev, 1);
1087 
1088  for (i = 0; i < len; i++) {
1089  data[i] = (samples[i].i & 0x3FF << 10);
1090  data[i] |= samples[i].q & 0x3FF;
1091  }
1092  b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data);
1093 
1094  kfree(data);
1095  if (nphy->hang_avoid)
1096  b43_nphy_stay_in_carrier_search(dev, 0);
1097  return 0;
1098 }
1099 
1100 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */
1101 static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
1102  bool test)
1103 {
1104  int i;
1105  u16 bw, len, rot, angle;
1106  struct b43_c32 *samples;
1107 
1108 
1109  bw = (dev->phy.is_40mhz) ? 40 : 20;
1110  len = bw << 3;
1111 
1112  if (test) {
1114  bw = 82;
1115  else
1116  bw = 80;
1117 
1118  if (dev->phy.is_40mhz)
1119  bw <<= 1;
1120 
1121  len = bw << 1;
1122  }
1123 
1124  samples = kcalloc(len, sizeof(struct b43_c32), GFP_KERNEL);
1125  if (!samples) {
1126  b43err(dev->wl, "allocation for samples generation failed\n");
1127  return 0;
1128  }
1129  rot = (((freq * 36) / bw) << 16) / 100;
1130  angle = 0;
1131 
1132  for (i = 0; i < len; i++) {
1133  samples[i] = b43_cordic(angle);
1134  angle += rot;
1135  samples[i].q = CORDIC_CONVERT(samples[i].q * max);
1136  samples[i].i = CORDIC_CONVERT(samples[i].i * max);
1137  }
1138 
1139  i = b43_nphy_load_samples(dev, samples, len);
1140  kfree(samples);
1141  return (i < 0) ? 0 : len;
1142 }
1143 
1144 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
1145 static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
1146  u16 wait, bool iqmode, bool dac_test)
1147 {
1148  struct b43_phy_n *nphy = dev->phy.n;
1149  int i;
1150  u16 seq_mode;
1151  u32 tmp;
1152 
1153  if (nphy->hang_avoid)
1154  b43_nphy_stay_in_carrier_search(dev, true);
1155 
1156  if ((nphy->bb_mult_save & 0x80000000) == 0) {
1157  tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
1158  nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
1159  }
1160 
1161  if (!dev->phy.is_40mhz)
1162  tmp = 0x6464;
1163  else
1164  tmp = 0x4747;
1165  b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
1166 
1167  if (nphy->hang_avoid)
1168  b43_nphy_stay_in_carrier_search(dev, false);
1169 
1170  b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1));
1171 
1172  if (loops != 0xFFFF)
1173  b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1));
1174  else
1175  b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops);
1176 
1178 
1179  seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
1180 
1182  if (iqmode) {
1183  b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
1184  b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000);
1185  } else {
1186  if (dac_test)
1188  else
1190  }
1191  for (i = 0; i < 100; i++) {
1192  if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & 1)) {
1193  i = 0;
1194  break;
1195  }
1196  udelay(10);
1197  }
1198  if (i)
1199  b43err(dev->wl, "run samples timeout\n");
1200 
1201  b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
1202 }
1203 
1204 /**************************************************
1205  * RSSI
1206  **************************************************/
1207 
1208 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
1209 static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
1210  s8 offset, u8 core, u8 rail,
1211  enum b43_nphy_rssi_type type)
1212 {
1213  u16 tmp;
1214  bool core1or5 = (core == 1) || (core == 5);
1215  bool core2or5 = (core == 2) || (core == 5);
1216 
1217  offset = clamp_val(offset, -32, 31);
1218  tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
1219 
1220  if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
1222  if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
1224  if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
1226  if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
1228 
1229  if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
1231  if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
1233  if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
1235  if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
1237 
1238  if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
1240  if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
1242  if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
1244  if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
1246 
1247  if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
1249  if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
1251  if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
1253  if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
1255 
1256  if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
1258  if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
1260  if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
1262  if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
1264 
1265  if (core1or5 && (type == B43_NPHY_RSSI_TSSI_I))
1267  if (core2or5 && (type == B43_NPHY_RSSI_TSSI_I))
1269 
1270  if (core1or5 && (type == B43_NPHY_RSSI_TSSI_Q))
1272  if (core2or5 && (type == B43_NPHY_RSSI_TSSI_Q))
1274 }
1275 
1276 static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
1277 {
1278  u8 i;
1279  u16 reg, val;
1280 
1281  if (code == 0) {
1282  b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF);
1283  b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF);
1284  b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF);
1285  b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF);
1286  b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF);
1287  b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF);
1290  } else {
1291  for (i = 0; i < 2; i++) {
1292  if ((code == 1 && i == 1) || (code == 2 && !i))
1293  continue;
1294 
1295  reg = (i == 0) ?
1297  b43_phy_maskset(dev, reg, 0xFDFF, 0x0200);
1298 
1299  if (type < 3) {
1300  reg = (i == 0) ?
1303  b43_phy_maskset(dev, reg, 0xFCFF, 0);
1304 
1305  reg = (i == 0) ?
1308  b43_phy_maskset(dev, reg, 0xFFC3, 0);
1309 
1310  if (type == 0)
1311  val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8;
1312  else if (type == 1)
1313  val = 16;
1314  else
1315  val = 32;
1316  b43_phy_set(dev, reg, val);
1317 
1318  reg = (i == 0) ?
1321  b43_phy_set(dev, reg, 0x0020);
1322  } else {
1323  if (type == 6)
1324  val = 0x0100;
1325  else if (type == 3)
1326  val = 0x0200;
1327  else
1328  val = 0x0300;
1329 
1330  reg = (i == 0) ?
1333 
1334  b43_phy_maskset(dev, reg, 0xFCFF, val);
1335  b43_phy_maskset(dev, reg, 0xF3FF, val << 2);
1336 
1337  if (type != 3 && type != 6) {
1338  enum ieee80211_band band =
1339  b43_current_band(dev->wl);
1340 
1341  if (b43_nphy_ipa(dev))
1342  val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
1343  else
1344  val = 0x11;
1345  reg = (i == 0) ? 0x2000 : 0x3000;
1346  reg |= B2055_PADDRV;
1347  b43_radio_write16(dev, reg, val);
1348 
1349  reg = (i == 0) ?
1352  b43_phy_set(dev, reg, 0x0200);
1353  }
1354  }
1355  }
1356  }
1357 }
1358 
1359 static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
1360 {
1361  u16 val;
1362 
1363  if (type < 3)
1364  val = 0;
1365  else if (type == 6)
1366  val = 1;
1367  else if (type == 3)
1368  val = 2;
1369  else
1370  val = 3;
1371 
1372  val = (val << 12) | (val << 14);
1373  b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
1374  b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
1375 
1376  if (type < 3) {
1378  (type + 1) << 4);
1380  (type + 1) << 4);
1381  }
1382 
1383  if (code == 0) {
1384  b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000);
1385  if (type < 3) {
1390  ~(0x1 << 12 |
1391  0x1 << 5 |
1392  0x1 << 1 |
1393  0x1));
1396  udelay(20);
1397  b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
1398  }
1399  } else {
1400  b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000);
1401  if (type < 3) {
1408  (0x1 << 12 |
1409  0x1 << 5 |
1410  0x1 << 1 |
1411  0x1));
1414  udelay(20);
1415  b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
1416  }
1417  }
1418 }
1419 
1420 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
1421 static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
1422 {
1423  if (dev->phy.rev >= 3)
1424  b43_nphy_rev3_rssi_select(dev, code, type);
1425  else
1426  b43_nphy_rev2_rssi_select(dev, code, type);
1427 }
1428 
1429 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
1430 static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf)
1431 {
1432  int i;
1433  for (i = 0; i < 2; i++) {
1434  if (type == 2) {
1435  if (i == 0) {
1437  0xFC, buf[0]);
1439  0xFC, buf[1]);
1440  } else {
1442  0xFC, buf[2 * i]);
1444  0xFC, buf[2 * i + 1]);
1445  }
1446  } else {
1447  if (i == 0)
1449  0xF3, buf[0] << 2);
1450  else
1452  0xF3, buf[2 * i + 1] << 2);
1453  }
1454  }
1455 }
1456 
1457 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
1458 static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
1459  u8 nsamp)
1460 {
1461  int i;
1462  int out;
1463  u16 save_regs_phy[9];
1464  u16 s[2];
1465 
1466  if (dev->phy.rev >= 3) {
1467  save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
1468  save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
1469  save_regs_phy[2] = b43_phy_read(dev,
1471  save_regs_phy[3] = b43_phy_read(dev,
1473  save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
1474  save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
1475  save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
1476  save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
1477  save_regs_phy[8] = 0;
1478  } else {
1479  save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
1480  save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
1481  save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
1482  save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD);
1483  save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
1484  save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
1485  save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
1486  save_regs_phy[7] = 0;
1487  save_regs_phy[8] = 0;
1488  }
1489 
1490  b43_nphy_rssi_select(dev, 5, type);
1491 
1492  if (dev->phy.rev < 2) {
1493  save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
1495  }
1496 
1497  for (i = 0; i < 4; i++)
1498  buf[i] = 0;
1499 
1500  for (i = 0; i < nsamp; i++) {
1501  if (dev->phy.rev < 2) {
1502  s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT);
1503  s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT);
1504  } else {
1505  s[0] = b43_phy_read(dev, B43_NPHY_RSSI1);
1506  s[1] = b43_phy_read(dev, B43_NPHY_RSSI2);
1507  }
1508 
1509  buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2;
1510  buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2;
1511  buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2;
1512  buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2;
1513  }
1514  out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 |
1515  (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF);
1516 
1517  if (dev->phy.rev < 2)
1518  b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]);
1519 
1520  if (dev->phy.rev >= 3) {
1521  b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
1522  b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
1524  save_regs_phy[2]);
1526  save_regs_phy[3]);
1527  b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]);
1528  b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
1529  b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
1530  b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
1531  } else {
1532  b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
1533  b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
1534  b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]);
1535  b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]);
1536  b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]);
1537  b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]);
1538  b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]);
1539  }
1540 
1541  return out;
1542 }
1543 
1544 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
1545 static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
1546 {
1547  struct b43_phy_n *nphy = dev->phy.n;
1548 
1549  u16 saved_regs_phy_rfctl[2];
1550  u16 saved_regs_phy[13];
1551  u16 regs_to_store[] = {
1559  };
1560 
1561  u16 class;
1562 
1563  u16 clip_state[2];
1564  u16 clip_off[2] = { 0xFFFF, 0xFFFF };
1565 
1566  u8 vcm_final = 0;
1567  s8 offset[4];
1568  s32 results[8][4] = { };
1569  s32 results_min[4] = { };
1570  s32 poll_results[4] = { };
1571 
1572  u16 *rssical_radio_regs = NULL;
1573  u16 *rssical_phy_regs = NULL;
1574 
1575  u16 r; /* routing */
1576  u8 rx_core_state;
1577  u8 core, i, j;
1578 
1579  class = b43_nphy_classifier(dev, 0, 0);
1580  b43_nphy_classifier(dev, 7, 4);
1581  b43_nphy_read_clip_detection(dev, clip_state);
1582  b43_nphy_write_clip_detection(dev, clip_off);
1583 
1584  saved_regs_phy_rfctl[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
1585  saved_regs_phy_rfctl[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
1586  for (i = 0; i < ARRAY_SIZE(regs_to_store); i++)
1587  saved_regs_phy[i] = b43_phy_read(dev, regs_to_store[i]);
1588 
1589  b43_nphy_rf_control_intc_override(dev, 0, 0, 7);
1590  b43_nphy_rf_control_intc_override(dev, 1, 1, 7);
1591  b43_nphy_rf_control_override(dev, 0x1, 0, 0, false);
1592  b43_nphy_rf_control_override(dev, 0x2, 1, 0, false);
1593  b43_nphy_rf_control_override(dev, 0x80, 1, 0, false);
1594  b43_nphy_rf_control_override(dev, 0x40, 1, 0, false);
1595 
1596  if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
1597  b43_nphy_rf_control_override(dev, 0x20, 0, 0, false);
1598  b43_nphy_rf_control_override(dev, 0x10, 1, 0, false);
1599  } else {
1600  b43_nphy_rf_control_override(dev, 0x10, 0, 0, false);
1601  b43_nphy_rf_control_override(dev, 0x20, 1, 0, false);
1602  }
1603 
1604  rx_core_state = b43_nphy_get_rx_core_state(dev);
1605  for (core = 0; core < 2; core++) {
1606  if (!(rx_core_state & (1 << core)))
1607  continue;
1608  r = core ? B2056_RX1 : B2056_RX0;
1609  b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 0, 2);
1610  b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 1, 2);
1611  for (i = 0; i < 8; i++) {
1612  b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, 0xE3,
1613  i << 2);
1614  b43_nphy_poll_rssi(dev, 2, results[i], 8);
1615  }
1616  for (i = 0; i < 4; i += 2) {
1617  s32 curr;
1618  s32 mind = 40;
1619  s32 minpoll = 249;
1620  u8 minvcm = 0;
1621  if (2 * core != i)
1622  continue;
1623  for (j = 0; j < 8; j++) {
1624  curr = results[j][i] * results[j][i] +
1625  results[j][i + 1] * results[j][i];
1626  if (curr < mind) {
1627  mind = curr;
1628  minvcm = j;
1629  }
1630  if (results[j][i] < minpoll)
1631  minpoll = results[j][i];
1632  }
1633  vcm_final = minvcm;
1634  results_min[i] = minpoll;
1635  }
1636  b43_radio_maskset(dev, r | B2056_RX_RSSI_MISC, 0xE3,
1637  vcm_final << 2);
1638  for (i = 0; i < 4; i++) {
1639  if (core != i / 2)
1640  continue;
1641  offset[i] = -results[vcm_final][i];
1642  if (offset[i] < 0)
1643  offset[i] = -((abs(offset[i]) + 4) / 8);
1644  else
1645  offset[i] = (offset[i] + 4) / 8;
1646  if (results_min[i] == 248)
1647  offset[i] = -32;
1648  b43_nphy_scale_offset_rssi(dev, 0, offset[i],
1649  (i / 2 == 0) ? 1 : 2,
1650  (i % 2 == 0) ? 0 : 1,
1651  2);
1652  }
1653  }
1654  for (core = 0; core < 2; core++) {
1655  if (!(rx_core_state & (1 << core)))
1656  continue;
1657  for (i = 0; i < 2; i++) {
1658  b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 0, i);
1659  b43_nphy_scale_offset_rssi(dev, 0, 0, core + 1, 1, i);
1660  b43_nphy_poll_rssi(dev, i, poll_results, 8);
1661  for (j = 0; j < 4; j++) {
1662  if (j / 2 == core) {
1663  offset[j] = 232 - poll_results[j];
1664  if (offset[j] < 0)
1665  offset[j] = -(abs(offset[j] + 4) / 8);
1666  else
1667  offset[j] = (offset[j] + 4) / 8;
1668  b43_nphy_scale_offset_rssi(dev, 0,
1669  offset[2 * core], core + 1, j % 2, i);
1670  }
1671  }
1672  }
1673  }
1674 
1675  b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, saved_regs_phy_rfctl[0]);
1676  b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, saved_regs_phy_rfctl[1]);
1677 
1678  b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
1679 
1683 
1684  b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
1687 
1688  for (i = 0; i < ARRAY_SIZE(regs_to_store); i++)
1689  b43_phy_write(dev, regs_to_store[i], saved_regs_phy[i]);
1690 
1691  /* Store for future configuration */
1692  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
1693  rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
1694  rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
1695  } else {
1696  rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
1697  rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
1698  }
1699  rssical_radio_regs[0] = b43_radio_read(dev, 0x602B);
1700  rssical_radio_regs[0] = b43_radio_read(dev, 0x702B);
1701  rssical_phy_regs[0] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Z);
1702  rssical_phy_regs[1] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z);
1703  rssical_phy_regs[2] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Z);
1704  rssical_phy_regs[3] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z);
1705  rssical_phy_regs[4] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_X);
1706  rssical_phy_regs[5] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_X);
1707  rssical_phy_regs[6] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_X);
1708  rssical_phy_regs[7] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_X);
1709  rssical_phy_regs[8] = b43_phy_read(dev, B43_NPHY_RSSIMC_0I_RSSI_Y);
1710  rssical_phy_regs[9] = b43_phy_read(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y);
1711  rssical_phy_regs[10] = b43_phy_read(dev, B43_NPHY_RSSIMC_1I_RSSI_Y);
1712  rssical_phy_regs[11] = b43_phy_read(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y);
1713 
1714  /* Remember for which channel we store configuration */
1715  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
1716  nphy->rssical_chanspec_2G.center_freq = dev->phy.channel_freq;
1717  else
1718  nphy->rssical_chanspec_5G.center_freq = dev->phy.channel_freq;
1719 
1720  /* End of calibration, restore configuration */
1721  b43_nphy_classifier(dev, 7, class);
1722  b43_nphy_write_clip_detection(dev, clip_state);
1723 }
1724 
1725 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
1726 static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
1727 {
1728  int i, j;
1729  u8 state[4];
1730  u8 code, val;
1731  u16 class, override;
1732  u8 regs_save_radio[2];
1733  u16 regs_save_phy[2];
1734 
1735  s8 offset[4];
1736  u8 core;
1737  u8 rail;
1738 
1739  u16 clip_state[2];
1740  u16 clip_off[2] = { 0xFFFF, 0xFFFF };
1741  s32 results_min[4] = { };
1742  u8 vcm_final[4] = { };
1743  s32 results[4][4] = { };
1744  s32 miniq[4][2] = { };
1745 
1746  if (type == 2) {
1747  code = 0;
1748  val = 6;
1749  } else if (type < 2) {
1750  code = 25;
1751  val = 4;
1752  } else {
1753  B43_WARN_ON(1);
1754  return;
1755  }
1756 
1757  class = b43_nphy_classifier(dev, 0, 0);
1758  b43_nphy_classifier(dev, 7, 4);
1759  b43_nphy_read_clip_detection(dev, clip_state);
1760  b43_nphy_write_clip_detection(dev, clip_off);
1761 
1762  if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
1763  override = 0x140;
1764  else
1765  override = 0x110;
1766 
1767  regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
1768  regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX);
1769  b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override);
1771 
1772  regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
1773  regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX);
1774  b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override);
1776 
1777  state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07;
1778  state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07;
1781  state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07;
1782  state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07;
1783 
1784  b43_nphy_rssi_select(dev, 5, type);
1785  b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type);
1786  b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type);
1787 
1788  for (i = 0; i < 4; i++) {
1789  u8 tmp[4];
1790  for (j = 0; j < 4; j++)
1791  tmp[j] = i;
1792  if (type != 1)
1793  b43_nphy_set_rssi_2055_vcm(dev, type, tmp);
1794  b43_nphy_poll_rssi(dev, type, results[i], 8);
1795  if (type < 2)
1796  for (j = 0; j < 2; j++)
1797  miniq[i][j] = min(results[i][2 * j],
1798  results[i][2 * j + 1]);
1799  }
1800 
1801  for (i = 0; i < 4; i++) {
1802  s32 mind = 40;
1803  u8 minvcm = 0;
1804  s32 minpoll = 249;
1805  s32 curr;
1806  for (j = 0; j < 4; j++) {
1807  if (type == 2)
1808  curr = abs(results[j][i]);
1809  else
1810  curr = abs(miniq[j][i / 2] - code * 8);
1811 
1812  if (curr < mind) {
1813  mind = curr;
1814  minvcm = j;
1815  }
1816 
1817  if (results[j][i] < minpoll)
1818  minpoll = results[j][i];
1819  }
1820  results_min[i] = minpoll;
1821  vcm_final[i] = minvcm;
1822  }
1823 
1824  if (type != 1)
1825  b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final);
1826 
1827  for (i = 0; i < 4; i++) {
1828  offset[i] = (code * 8) - results[vcm_final[i]][i];
1829 
1830  if (offset[i] < 0)
1831  offset[i] = -((abs(offset[i]) + 4) / 8);
1832  else
1833  offset[i] = (offset[i] + 4) / 8;
1834 
1835  if (results_min[i] == 248)
1836  offset[i] = code - 32;
1837 
1838  core = (i / 2) ? 2 : 1;
1839  rail = (i % 2) ? 1 : 0;
1840 
1841  b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail,
1842  type);
1843  }
1844 
1845  b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]);
1846  b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]);
1847 
1848  switch (state[2]) {
1849  case 1:
1850  b43_nphy_rssi_select(dev, 1, 2);
1851  break;
1852  case 4:
1853  b43_nphy_rssi_select(dev, 1, 0);
1854  break;
1855  case 2:
1856  b43_nphy_rssi_select(dev, 1, 1);
1857  break;
1858  default:
1859  b43_nphy_rssi_select(dev, 1, 1);
1860  break;
1861  }
1862 
1863  switch (state[3]) {
1864  case 1:
1865  b43_nphy_rssi_select(dev, 2, 2);
1866  break;
1867  case 4:
1868  b43_nphy_rssi_select(dev, 2, 0);
1869  break;
1870  default:
1871  b43_nphy_rssi_select(dev, 2, 1);
1872  break;
1873  }
1874 
1875  b43_nphy_rssi_select(dev, 0, type);
1876 
1877  b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]);
1878  b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
1879  b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]);
1880  b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
1881 
1882  b43_nphy_classifier(dev, 7, class);
1883  b43_nphy_write_clip_detection(dev, clip_state);
1884  /* Specs don't say about reset here, but it makes wl and b43 dumps
1885  identical, it really seems wl performs this */
1886  b43_nphy_reset_cca(dev);
1887 }
1888 
1889 /*
1890  * RSSI Calibration
1891  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
1892  */
1893 static void b43_nphy_rssi_cal(struct b43_wldev *dev)
1894 {
1895  if (dev->phy.rev >= 3) {
1896  b43_nphy_rev3_rssi_cal(dev);
1897  } else {
1898  b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Z);
1899  b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_X);
1900  b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Y);
1901  }
1902 }
1903 
1904 /**************************************************
1905  * Workarounds
1906  **************************************************/
1907 
1908 static void b43_nphy_gain_ctl_workarounds_rev3plus(struct b43_wldev *dev)
1909 {
1910  struct ssb_sprom *sprom = dev->dev->bus_sprom;
1911 
1912  bool ghz5;
1913  bool ext_lna;
1914  u16 rssi_gain;
1916  u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
1917  u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
1918 
1919  /* Prepare values */
1920  ghz5 = b43_phy_read(dev, B43_NPHY_BANDCTL)
1922  ext_lna = ghz5 ? sprom->boardflags_hi & B43_BFH_EXTLNA_5GHZ :
1923  sprom->boardflags_lo & B43_BFL_EXTLNA;
1924  e = b43_nphy_get_gain_ctl_workaround_ent(dev, ghz5, ext_lna);
1925  if (ghz5 && dev->phy.rev >= 5)
1926  rssi_gain = 0x90;
1927  else
1928  rssi_gain = 0x50;
1929 
1930  b43_phy_set(dev, B43_NPHY_RXCTL, 0x0040);
1931 
1932  /* Set Clip 2 detect */
1937 
1939  0x17);
1941  0x17);
1947  rssi_gain);
1949  rssi_gain);
1951  0x17);
1953  0x17);
1956 
1957  b43_ntab_write_bulk(dev, B43_NTAB8(0, 8), 4, e->lna1_gain);
1958  b43_ntab_write_bulk(dev, B43_NTAB8(1, 8), 4, e->lna1_gain);
1959  b43_ntab_write_bulk(dev, B43_NTAB8(0, 16), 4, e->lna2_gain);
1960  b43_ntab_write_bulk(dev, B43_NTAB8(1, 16), 4, e->lna2_gain);
1961  b43_ntab_write_bulk(dev, B43_NTAB8(0, 32), 10, e->gain_db);
1962  b43_ntab_write_bulk(dev, B43_NTAB8(1, 32), 10, e->gain_db);
1963  b43_ntab_write_bulk(dev, B43_NTAB8(2, 32), 10, e->gain_bits);
1964  b43_ntab_write_bulk(dev, B43_NTAB8(3, 32), 10, e->gain_bits);
1965  b43_ntab_write_bulk(dev, B43_NTAB8(0, 0x40), 6, lpf_gain);
1966  b43_ntab_write_bulk(dev, B43_NTAB8(1, 0x40), 6, lpf_gain);
1967  b43_ntab_write_bulk(dev, B43_NTAB8(2, 0x40), 6, lpf_bits);
1968  b43_ntab_write_bulk(dev, B43_NTAB8(3, 0x40), 6, lpf_bits);
1969 
1971  b43_phy_write(dev, 0x2A7, e->init_gain);
1972  b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2,
1973  e->rfseq_init);
1974 
1975  /* TODO: check defines. Do not match variables names */
1977  b43_phy_write(dev, 0x2A9, e->cliphi_gain);
1979  b43_phy_write(dev, 0x2AB, e->clipmd_gain);
1981  b43_phy_write(dev, 0x2AD, e->cliplo_gain);
1982 
1983  b43_phy_maskset(dev, 0x27D, 0xFF00, e->crsmin);
1984  b43_phy_maskset(dev, 0x280, 0xFF00, e->crsminl);
1985  b43_phy_maskset(dev, 0x283, 0xFF00, e->crsminu);
1992  b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
1993 }
1994 
1995 static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)
1996 {
1997  struct b43_phy_n *nphy = dev->phy.n;
1998 
1999  u8 i, j;
2000  u8 code;
2001  u16 tmp;
2002  u8 rfseq_events[3] = { 6, 8, 7 };
2003  u8 rfseq_delays[3] = { 10, 30, 1 };
2004 
2005  /* Set Clip 2 detect */
2008 
2009  /* Set narrowband clip threshold */
2012 
2013  if (!dev->phy.is_40mhz) {
2014  /* Set dwell lengths */
2019  }
2020 
2021  /* Set wideband clip 2 threshold */
2026 
2027  if (!dev->phy.is_40mhz) {
2036  }
2037 
2038  b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
2039 
2040  if (nphy->gain_boost) {
2041  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ &&
2042  dev->phy.is_40mhz)
2043  code = 4;
2044  else
2045  code = 5;
2046  } else {
2047  code = dev->phy.is_40mhz ? 6 : 7;
2048  }
2049 
2050  /* Set HPVGA2 index */
2055 
2056  b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
2057  /* specs say about 2 loops, but wl does 4 */
2058  for (i = 0; i < 4; i++)
2059  b43_phy_write(dev, B43_NPHY_TABLE_DATALO, (code << 8 | 0x7C));
2060 
2061  b43_nphy_adjust_lna_gain_table(dev);
2062 
2063  if (nphy->elna_gain_config) {
2064  b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808);
2069 
2070  b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08);
2075 
2076  b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
2077  /* specs say about 2 loops, but wl does 4 */
2078  for (i = 0; i < 4; i++)
2080  (code << 8 | 0x74));
2081  }
2082 
2083  if (dev->phy.rev == 2) {
2084  for (i = 0; i < 4; i++) {
2086  (0x0400 * i) + 0x0020);
2087  for (j = 0; j < 21; j++) {
2088  tmp = j * (i < 2 ? 3 : 1);
2089  b43_phy_write(dev,
2090  B43_NPHY_TABLE_DATALO, tmp);
2091  }
2092  }
2093  }
2094 
2095  b43_nphy_set_rf_sequence(dev, 5, rfseq_events, rfseq_delays, 3);
2097  ~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,
2099 
2100  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
2101  b43_phy_maskset(dev, B43_PHY_N(0xC5D), 0xFF80, 4);
2102 }
2103 
2104 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
2105 static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev)
2106 {
2107  if (dev->phy.rev >= 7)
2108  ; /* TODO */
2109  else if (dev->phy.rev >= 3)
2110  b43_nphy_gain_ctl_workarounds_rev3plus(dev);
2111  else
2112  b43_nphy_gain_ctl_workarounds_rev1_2(dev);
2113 }
2114 
2115 /* http://bcm-v4.sipsolutions.net/PHY/N/Read_Lpf_Bw_Ctl */
2116 static u16 b43_nphy_read_lpf_ctl(struct b43_wldev *dev, u16 offset)
2117 {
2118  if (!offset)
2119  offset = (dev->phy.is_40mhz) ? 0x159 : 0x154;
2120  return b43_ntab_read(dev, B43_NTAB16(7, offset)) & 0x7;
2121 }
2122 
2123 static void b43_nphy_workarounds_rev7plus(struct b43_wldev *dev)
2124 {
2125  struct ssb_sprom *sprom = dev->dev->bus_sprom;
2126  struct b43_phy *phy = &dev->phy;
2127 
2128  u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
2129  0x1F };
2130  u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
2131 
2132  u16 ntab7_15e_16e[] = { 0x10f, 0x10f };
2133  u8 ntab7_138_146[] = { 0x11, 0x11 };
2134  u8 ntab7_133[] = { 0x77, 0x11, 0x11 };
2135 
2136  u16 lpf_20, lpf_40, lpf_11b;
2137  u16 bcap_val, bcap_val_11b, bcap_val_11n_20, bcap_val_11n_40;
2138  u16 scap_val, scap_val_11b, scap_val_11n_20, scap_val_11n_40;
2139  bool rccal_ovrd = false;
2140 
2141  u16 rx2tx_lut_20_11b, rx2tx_lut_20_11n, rx2tx_lut_40_11n;
2142  u16 bias, conv, filt;
2143 
2144  u32 tmp32;
2145  u8 core;
2146 
2147  if (phy->rev == 7) {
2148  b43_phy_set(dev, B43_NPHY_FINERX2_CGC, 0x10);
2149  b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0xFF80, 0x0020);
2150  b43_phy_maskset(dev, B43_NPHY_FREQGAIN0, 0x80FF, 0x2700);
2151  b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0xFF80, 0x002E);
2152  b43_phy_maskset(dev, B43_NPHY_FREQGAIN1, 0x80FF, 0x3300);
2153  b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0xFF80, 0x0037);
2154  b43_phy_maskset(dev, B43_NPHY_FREQGAIN2, 0x80FF, 0x3A00);
2155  b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0xFF80, 0x003C);
2156  b43_phy_maskset(dev, B43_NPHY_FREQGAIN3, 0x80FF, 0x3E00);
2157  b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0xFF80, 0x003E);
2158  b43_phy_maskset(dev, B43_NPHY_FREQGAIN4, 0x80FF, 0x3F00);
2159  b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0xFF80, 0x0040);
2160  b43_phy_maskset(dev, B43_NPHY_FREQGAIN5, 0x80FF, 0x4000);
2161  b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0xFF80, 0x0040);
2162  b43_phy_maskset(dev, B43_NPHY_FREQGAIN6, 0x80FF, 0x4000);
2163  b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0xFF80, 0x0040);
2164  b43_phy_maskset(dev, B43_NPHY_FREQGAIN7, 0x80FF, 0x4000);
2165  }
2166  if (phy->rev <= 8) {
2167  b43_phy_write(dev, 0x23F, 0x1B0);
2168  b43_phy_write(dev, 0x240, 0x1B0);
2169  }
2170  if (phy->rev >= 8)
2171  b43_phy_maskset(dev, B43_NPHY_TXTAILCNT, ~0xFF, 0x72);
2172 
2173  b43_ntab_write(dev, B43_NTAB16(8, 0x00), 2);
2174  b43_ntab_write(dev, B43_NTAB16(8, 0x10), 2);
2175  tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
2176  tmp32 &= 0xffffff;
2177  b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
2178  b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x15e), 2, ntab7_15e_16e);
2179  b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x16e), 2, ntab7_15e_16e);
2180 
2181  if (b43_nphy_ipa(dev))
2182  b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
2183  rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
2184 
2185  b43_phy_maskset(dev, 0x299, 0x3FFF, 0x4000);
2186  b43_phy_maskset(dev, 0x29D, 0x3FFF, 0x4000);
2187 
2188  lpf_20 = b43_nphy_read_lpf_ctl(dev, 0x154);
2189  lpf_40 = b43_nphy_read_lpf_ctl(dev, 0x159);
2190  lpf_11b = b43_nphy_read_lpf_ctl(dev, 0x152);
2191  if (b43_nphy_ipa(dev)) {
2192  if ((phy->radio_rev == 5 && phy->is_40mhz) ||
2193  phy->radio_rev == 7 || phy->radio_rev == 8) {
2194  bcap_val = b43_radio_read(dev, 0x16b);
2195  scap_val = b43_radio_read(dev, 0x16a);
2196  scap_val_11b = scap_val;
2197  bcap_val_11b = bcap_val;
2198  if (phy->radio_rev == 5 && phy->is_40mhz) {
2199  scap_val_11n_20 = scap_val;
2200  bcap_val_11n_20 = bcap_val;
2201  scap_val_11n_40 = bcap_val_11n_40 = 0xc;
2202  rccal_ovrd = true;
2203  } else { /* Rev 7/8 */
2204  lpf_20 = 4;
2205  lpf_11b = 1;
2206  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2207  scap_val_11n_20 = 0xc;
2208  bcap_val_11n_20 = 0xc;
2209  scap_val_11n_40 = 0xa;
2210  bcap_val_11n_40 = 0xa;
2211  } else {
2212  scap_val_11n_20 = 0x14;
2213  bcap_val_11n_20 = 0x14;
2214  scap_val_11n_40 = 0xf;
2215  bcap_val_11n_40 = 0xf;
2216  }
2217  rccal_ovrd = true;
2218  }
2219  }
2220  } else {
2221  if (phy->radio_rev == 5) {
2222  lpf_20 = 1;
2223  lpf_40 = 3;
2224  bcap_val = b43_radio_read(dev, 0x16b);
2225  scap_val = b43_radio_read(dev, 0x16a);
2226  scap_val_11b = scap_val;
2227  bcap_val_11b = bcap_val;
2228  scap_val_11n_20 = 0x11;
2229  scap_val_11n_40 = 0x11;
2230  bcap_val_11n_20 = 0x13;
2231  bcap_val_11n_40 = 0x13;
2232  rccal_ovrd = true;
2233  }
2234  }
2235  if (rccal_ovrd) {
2236  rx2tx_lut_20_11b = (bcap_val_11b << 8) |
2237  (scap_val_11b << 3) |
2238  lpf_11b;
2239  rx2tx_lut_20_11n = (bcap_val_11n_20 << 8) |
2240  (scap_val_11n_20 << 3) |
2241  lpf_20;
2242  rx2tx_lut_40_11n = (bcap_val_11n_40 << 8) |
2243  (scap_val_11n_40 << 3) |
2244  lpf_40;
2245  for (core = 0; core < 2; core++) {
2246  b43_ntab_write(dev, B43_NTAB16(7, 0x152 + core * 16),
2247  rx2tx_lut_20_11b);
2248  b43_ntab_write(dev, B43_NTAB16(7, 0x153 + core * 16),
2249  rx2tx_lut_20_11n);
2250  b43_ntab_write(dev, B43_NTAB16(7, 0x154 + core * 16),
2251  rx2tx_lut_20_11n);
2252  b43_ntab_write(dev, B43_NTAB16(7, 0x155 + core * 16),
2253  rx2tx_lut_40_11n);
2254  b43_ntab_write(dev, B43_NTAB16(7, 0x156 + core * 16),
2255  rx2tx_lut_40_11n);
2256  b43_ntab_write(dev, B43_NTAB16(7, 0x157 + core * 16),
2257  rx2tx_lut_40_11n);
2258  b43_ntab_write(dev, B43_NTAB16(7, 0x158 + core * 16),
2259  rx2tx_lut_40_11n);
2260  b43_ntab_write(dev, B43_NTAB16(7, 0x159 + core * 16),
2261  rx2tx_lut_40_11n);
2262  }
2263  b43_nphy_rf_control_override_rev7(dev, 16, 1, 3, false, 2);
2264  }
2265  b43_phy_write(dev, 0x32F, 0x3);
2266  if (phy->radio_rev == 4 || phy->radio_rev == 6)
2267  b43_nphy_rf_control_override_rev7(dev, 4, 1, 3, false, 0);
2268 
2269  if (phy->radio_rev == 3 || phy->radio_rev == 4 || phy->radio_rev == 6) {
2270  if (sprom->revision &&
2272  b43_radio_write(dev, 0x5, 0x05);
2273  b43_radio_write(dev, 0x6, 0x30);
2274  b43_radio_write(dev, 0x7, 0x00);
2275  b43_radio_set(dev, 0x4f, 0x1);
2276  b43_radio_set(dev, 0xd4, 0x1);
2277  bias = 0x1f;
2278  conv = 0x6f;
2279  filt = 0xaa;
2280  } else {
2281  bias = 0x2b;
2282  conv = 0x7f;
2283  filt = 0xee;
2284  }
2285  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2286  for (core = 0; core < 2; core++) {
2287  if (core == 0) {
2288  b43_radio_write(dev, 0x5F, bias);
2289  b43_radio_write(dev, 0x64, conv);
2290  b43_radio_write(dev, 0x66, filt);
2291  } else {
2292  b43_radio_write(dev, 0xE8, bias);
2293  b43_radio_write(dev, 0xE9, conv);
2294  b43_radio_write(dev, 0xEB, filt);
2295  }
2296  }
2297  }
2298  }
2299 
2300  if (b43_nphy_ipa(dev)) {
2301  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2302  if (phy->radio_rev == 3 || phy->radio_rev == 4 ||
2303  phy->radio_rev == 6) {
2304  for (core = 0; core < 2; core++) {
2305  if (core == 0)
2306  b43_radio_write(dev, 0x51,
2307  0x7f);
2308  else
2309  b43_radio_write(dev, 0xd6,
2310  0x7f);
2311  }
2312  }
2313  if (phy->radio_rev == 3) {
2314  for (core = 0; core < 2; core++) {
2315  if (core == 0) {
2316  b43_radio_write(dev, 0x64,
2317  0x13);
2318  b43_radio_write(dev, 0x5F,
2319  0x1F);
2320  b43_radio_write(dev, 0x66,
2321  0xEE);
2322  b43_radio_write(dev, 0x59,
2323  0x8A);
2324  b43_radio_write(dev, 0x80,
2325  0x3E);
2326  } else {
2327  b43_radio_write(dev, 0x69,
2328  0x13);
2329  b43_radio_write(dev, 0xE8,
2330  0x1F);
2331  b43_radio_write(dev, 0xEB,
2332  0xEE);
2333  b43_radio_write(dev, 0xDE,
2334  0x8A);
2335  b43_radio_write(dev, 0x105,
2336  0x3E);
2337  }
2338  }
2339  } else if (phy->radio_rev == 7 || phy->radio_rev == 8) {
2340  if (!phy->is_40mhz) {
2341  b43_radio_write(dev, 0x5F, 0x14);
2342  b43_radio_write(dev, 0xE8, 0x12);
2343  } else {
2344  b43_radio_write(dev, 0x5F, 0x16);
2345  b43_radio_write(dev, 0xE8, 0x16);
2346  }
2347  }
2348  } else {
2349  u16 freq = phy->channel_freq;
2350  if ((freq >= 5180 && freq <= 5230) ||
2351  (freq >= 5745 && freq <= 5805)) {
2352  b43_radio_write(dev, 0x7D, 0xFF);
2353  b43_radio_write(dev, 0xFE, 0xFF);
2354  }
2355  }
2356  } else {
2357  if (phy->radio_rev != 5) {
2358  for (core = 0; core < 2; core++) {
2359  if (core == 0) {
2360  b43_radio_write(dev, 0x5c, 0x61);
2361  b43_radio_write(dev, 0x51, 0x70);
2362  } else {
2363  b43_radio_write(dev, 0xe1, 0x61);
2364  b43_radio_write(dev, 0xd6, 0x70);
2365  }
2366  }
2367  }
2368  }
2369 
2370  if (phy->radio_rev == 4) {
2371  b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20);
2372  b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20);
2373  for (core = 0; core < 2; core++) {
2374  if (core == 0) {
2375  b43_radio_write(dev, 0x1a1, 0x00);
2376  b43_radio_write(dev, 0x1a2, 0x3f);
2377  b43_radio_write(dev, 0x1a6, 0x3f);
2378  } else {
2379  b43_radio_write(dev, 0x1a7, 0x00);
2380  b43_radio_write(dev, 0x1ab, 0x3f);
2381  b43_radio_write(dev, 0x1ac, 0x3f);
2382  }
2383  }
2384  } else {
2385  b43_phy_set(dev, B43_NPHY_AFECTL_C1, 0x4);
2387  b43_phy_set(dev, B43_NPHY_AFECTL_C2, 0x4);
2388  b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4);
2389 
2390  b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x1);
2392  b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x1);
2393  b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x1);
2394  b43_ntab_write(dev, B43_NTAB16(8, 0x05), 0x20);
2395  b43_ntab_write(dev, B43_NTAB16(8, 0x15), 0x20);
2396 
2397  b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x4);
2398  b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x4);
2399  b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x4);
2400  b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4);
2401  }
2402 
2404 
2405  b43_ntab_write(dev, B43_NTAB32(16, 0x100), 20);
2406  b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x138), 2, ntab7_138_146);
2407  b43_ntab_write(dev, B43_NTAB16(7, 0x141), 0x77);
2408  b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x133), 3, ntab7_133);
2409  b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x146), 2, ntab7_138_146);
2410  b43_ntab_write(dev, B43_NTAB16(7, 0x123), 0x77);
2411  b43_ntab_write(dev, B43_NTAB16(7, 0x12A), 0x77);
2412 
2413  if (!phy->is_40mhz) {
2414  b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x18D);
2415  b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x18D);
2416  } else {
2417  b43_ntab_write(dev, B43_NTAB32(16, 0x03), 0x14D);
2418  b43_ntab_write(dev, B43_NTAB32(16, 0x7F), 0x14D);
2419  }
2420 
2421  b43_nphy_gain_ctl_workarounds(dev);
2422 
2423  /* TODO
2424  b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x08), 4,
2425  aux_adc_vmid_rev7_core0);
2426  b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x18), 4,
2427  aux_adc_vmid_rev7_core1);
2428  b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x0C), 4,
2429  aux_adc_gain_rev7);
2430  b43_ntab_write_bulk(dev, B43_NTAB16(8, 0x1C), 4,
2431  aux_adc_gain_rev7);
2432  */
2433 }
2434 
2435 static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
2436 {
2437  struct b43_phy_n *nphy = dev->phy.n;
2438  struct ssb_sprom *sprom = dev->dev->bus_sprom;
2439 
2440  /* TX to RX */
2441  u8 tx2rx_events[8] = { 0x4, 0x3, 0x6, 0x5, 0x2, 0x1, 0x8, 0x1F };
2442  u8 tx2rx_delays[8] = { 8, 4, 2, 2, 4, 4, 6, 1 };
2443  /* RX to TX */
2444  u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
2445  0x1F };
2446  u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
2447  u8 rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F };
2448  u8 rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
2449 
2450  u16 tmp16;
2451  u32 tmp32;
2452 
2453  b43_phy_write(dev, 0x23f, 0x1f8);
2454  b43_phy_write(dev, 0x240, 0x1f8);
2455 
2456  tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
2457  tmp32 &= 0xffffff;
2458  b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
2459 
2460  b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
2461  b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
2462  b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
2463  b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
2464  b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
2465  b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
2466 
2468  b43_phy_write(dev, 0x2AE, 0x000C);
2469 
2470  /* TX to RX */
2471  b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
2472  ARRAY_SIZE(tx2rx_events));
2473 
2474  /* RX to TX */
2475  if (b43_nphy_ipa(dev))
2476  b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
2477  rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
2478  if (nphy->hw_phyrxchain != 3 &&
2479  nphy->hw_phyrxchain != nphy->hw_phytxchain) {
2480  if (b43_nphy_ipa(dev)) {
2481  rx2tx_delays[5] = 59;
2482  rx2tx_delays[6] = 1;
2483  rx2tx_events[7] = 0x1F;
2484  }
2485  b43_nphy_set_rf_sequence(dev, 0, rx2tx_events, rx2tx_delays,
2486  ARRAY_SIZE(rx2tx_events));
2487  }
2488 
2489  tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
2490  0x2 : 0x9C40;
2491  b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
2492 
2493  b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
2494 
2495  if (!dev->phy.is_40mhz) {
2496  b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
2497  b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
2498  } else {
2499  b43_ntab_write(dev, B43_NTAB32(16, 3), 0x14D);
2500  b43_ntab_write(dev, B43_NTAB32(16, 127), 0x14D);
2501  }
2502 
2503  b43_nphy_gain_ctl_workarounds(dev);
2504 
2505  b43_ntab_write(dev, B43_NTAB16(8, 0), 2);
2506  b43_ntab_write(dev, B43_NTAB16(8, 16), 2);
2507 
2508  /* TODO */
2509 
2522 
2523  /* N PHY WAR TX Chain Update with hw_phytxchain as argument */
2524 
2525  if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
2526  b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
2527  (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
2528  b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
2529  tmp32 = 0x00088888;
2530  else
2531  tmp32 = 0x88888888;
2532  b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
2533  b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
2534  b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
2535 
2536  if (dev->phy.rev == 4 &&
2537  b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
2539  0x70);
2541  0x70);
2542  }
2543 
2544  /* Dropped probably-always-true condition */
2545  b43_phy_write(dev, 0x224, 0x03eb);
2546  b43_phy_write(dev, 0x225, 0x03eb);
2547  b43_phy_write(dev, 0x226, 0x0341);
2548  b43_phy_write(dev, 0x227, 0x0341);
2549  b43_phy_write(dev, 0x228, 0x042b);
2550  b43_phy_write(dev, 0x229, 0x042b);
2551  b43_phy_write(dev, 0x22a, 0x0381);
2552  b43_phy_write(dev, 0x22b, 0x0381);
2553  b43_phy_write(dev, 0x22c, 0x042b);
2554  b43_phy_write(dev, 0x22d, 0x042b);
2555  b43_phy_write(dev, 0x22e, 0x0381);
2556  b43_phy_write(dev, 0x22f, 0x0381);
2557 
2558  if (dev->phy.rev >= 6 && sprom->boardflags2_lo & B43_BFL2_SINGLEANT_CCK)
2559  ; /* TODO: 0x0080000000000000 HF */
2560 }
2561 
2562 static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
2563 {
2564  struct ssb_sprom *sprom = dev->dev->bus_sprom;
2565  struct b43_phy *phy = &dev->phy;
2566  struct b43_phy_n *nphy = phy->n;
2567 
2568  u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
2569  u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
2570 
2571  u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
2572  u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
2573 
2574  if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
2575  dev->dev->board_type == 0x8B) {
2576  delays1[0] = 0x1;
2577  delays1[5] = 0x14;
2578  }
2579 
2580  if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
2581  nphy->band5g_pwrgain) {
2584  } else {
2587  }
2588 
2589  b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
2590  b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
2591  if (dev->phy.rev < 3) {
2592  b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
2593  b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
2594  }
2595 
2596  if (dev->phy.rev < 2) {
2597  b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
2598  b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
2599  b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
2600  b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
2601  b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
2602  b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
2603  }
2604 
2609 
2610  b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
2611  b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
2612 
2613  b43_nphy_gain_ctl_workarounds(dev);
2614 
2615  if (dev->phy.rev < 2) {
2616  if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
2617  b43_hf_write(dev, b43_hf_read(dev) |
2618  B43_HF_MLADVW);
2619  } else if (dev->phy.rev == 2) {
2622  }
2623 
2624  if (dev->phy.rev < 2)
2627 
2628  /* Set phase track alpha and beta */
2629  b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
2630  b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
2631  b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
2632  b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
2633  b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
2634  b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
2635 
2636  if (dev->phy.rev < 3) {
2638  ~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
2642  }
2643 
2644  if (dev->phy.rev == 2)
2647 }
2648 
2649 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
2650 static void b43_nphy_workarounds(struct b43_wldev *dev)
2651 {
2652  struct b43_phy *phy = &dev->phy;
2653  struct b43_phy_n *nphy = phy->n;
2654 
2655  if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
2656  b43_nphy_classifier(dev, 1, 0);
2657  else
2658  b43_nphy_classifier(dev, 1, 1);
2659 
2660  if (nphy->hang_avoid)
2661  b43_nphy_stay_in_carrier_search(dev, 1);
2662 
2665 
2666  if (dev->phy.rev >= 7)
2667  b43_nphy_workarounds_rev7plus(dev);
2668  else if (dev->phy.rev >= 3)
2669  b43_nphy_workarounds_rev3plus(dev);
2670  else
2671  b43_nphy_workarounds_rev1_2(dev);
2672 
2673  if (nphy->hang_avoid)
2674  b43_nphy_stay_in_carrier_search(dev, 0);
2675 }
2676 
2677 /**************************************************
2678  * Tx/Rx common
2679  **************************************************/
2680 
2681 /*
2682  * Transmits a known value for LO calibration
2683  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
2684  */
2685 static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val,
2686  bool iqmode, bool dac_test)
2687 {
2688  u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test);
2689  if (samp == 0)
2690  return -1;
2691  b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test);
2692  return 0;
2693 }
2694 
2695 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */
2696 static void b43_nphy_update_txrx_chain(struct b43_wldev *dev)
2697 {
2698  struct b43_phy_n *nphy = dev->phy.n;
2699 
2700  bool override = false;
2701  u16 chain = 0x33;
2702 
2703  if (nphy->txrx_chain == 0) {
2704  chain = 0x11;
2705  override = true;
2706  } else if (nphy->txrx_chain == 1) {
2707  chain = 0x22;
2708  override = true;
2709  }
2710 
2713  chain);
2714 
2715  if (override)
2718  else
2721 }
2722 
2723 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
2724 static void b43_nphy_stop_playback(struct b43_wldev *dev)
2725 {
2726  struct b43_phy_n *nphy = dev->phy.n;
2727  u16 tmp;
2728 
2729  if (nphy->hang_avoid)
2730  b43_nphy_stay_in_carrier_search(dev, 1);
2731 
2732  tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT);
2733  if (tmp & 0x1)
2735  else if (tmp & 0x2)
2736  b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
2737 
2738  b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004);
2739 
2740  if (nphy->bb_mult_save & 0x80000000) {
2741  tmp = nphy->bb_mult_save & 0xFFFF;
2742  b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
2743  nphy->bb_mult_save = 0;
2744  }
2745 
2746  if (nphy->hang_avoid)
2747  b43_nphy_stay_in_carrier_search(dev, 0);
2748 }
2749 
2750 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */
2751 static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core,
2752  struct nphy_txgains target,
2753  struct nphy_iqcal_params *params)
2754 {
2755  int i, j, indx;
2756  u16 gain;
2757 
2758  if (dev->phy.rev >= 3) {
2759  params->txgm = target.txgm[core];
2760  params->pga = target.pga[core];
2761  params->pad = target.pad[core];
2762  params->ipa = target.ipa[core];
2763  params->cal_gain = (params->txgm << 12) | (params->pga << 8) |
2764  (params->pad << 4) | (params->ipa);
2765  for (j = 0; j < 5; j++)
2766  params->ncorr[j] = 0x79;
2767  } else {
2768  gain = (target.pad[core]) | (target.pga[core] << 4) |
2769  (target.txgm[core] << 8);
2770 
2771  indx = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ?
2772  1 : 0;
2773  for (i = 0; i < 9; i++)
2774  if (tbl_iqcal_gainparams[indx][i][0] == gain)
2775  break;
2776  i = min(i, 8);
2777 
2778  params->txgm = tbl_iqcal_gainparams[indx][i][1];
2779  params->pga = tbl_iqcal_gainparams[indx][i][2];
2780  params->pad = tbl_iqcal_gainparams[indx][i][3];
2781  params->cal_gain = (params->txgm << 7) | (params->pga << 4) |
2782  (params->pad << 2);
2783  for (j = 0; j < 4; j++)
2784  params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j];
2785  }
2786 }
2787 
2788 /**************************************************
2789  * Tx and Rx
2790  **************************************************/
2791 
2793 {//TODO
2794 }
2795 
2796 static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev)
2797 {//TODO
2798 }
2799 
2800 static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
2801  bool ignore_tssi)
2802 {//TODO
2803  return B43_TXPWR_RES_DONE;
2804 }
2805 
2806 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
2807 static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
2808 {
2809  struct b43_phy_n *nphy = dev->phy.n;
2810  u8 i;
2811  u16 bmask, val, tmp;
2812  enum ieee80211_band band = b43_current_band(dev->wl);
2813 
2814  if (nphy->hang_avoid)
2815  b43_nphy_stay_in_carrier_search(dev, 1);
2816 
2817  nphy->txpwrctrl = enable;
2818  if (!enable) {
2819  if (dev->phy.rev >= 3 &&
2824  /* We disable enabled TX pwr ctl, save it's state */
2825  nphy->tx_pwr_idx[0] = b43_phy_read(dev,
2826  B43_NPHY_C1_TXPCTL_STAT) & 0x7f;
2827  nphy->tx_pwr_idx[1] = b43_phy_read(dev,
2828  B43_NPHY_C2_TXPCTL_STAT) & 0x7f;
2829  }
2830 
2831  b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840);
2832  for (i = 0; i < 84; i++)
2834 
2835  b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6C40);
2836  for (i = 0; i < 84; i++)
2838 
2840  if (dev->phy.rev >= 3)
2842  b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, ~tmp);
2843 
2844  if (dev->phy.rev >= 3) {
2845  b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
2846  b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
2847  } else {
2848  b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
2849  }
2850 
2851  if (dev->phy.rev == 2)
2853  ~B43_NPHY_BPHY_CTL3_SCALE, 0x53);
2854  else if (dev->phy.rev < 2)
2856  ~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
2857 
2858  if (dev->phy.rev < 2 && dev->phy.is_40mhz)
2860  } else {
2861  b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,
2862  nphy->adj_pwr_tbl);
2863  b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84,
2864  nphy->adj_pwr_tbl);
2865 
2866  bmask = B43_NPHY_TXPCTL_CMD_COEFF |
2868  /* wl does useless check for "enable" param here */
2870  if (dev->phy.rev >= 3) {
2871  bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN;
2872  if (val)
2874  }
2875  b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
2876 
2877  if (band == IEEE80211_BAND_5GHZ) {
2879  ~B43_NPHY_TXPCTL_CMD_INIT, 0x64);
2880  if (dev->phy.rev > 1)
2883  0x64);
2884  }
2885 
2886  if (dev->phy.rev >= 3) {
2887  if (nphy->tx_pwr_idx[0] != 128 &&
2888  nphy->tx_pwr_idx[1] != 128) {
2889  /* Recover TX pwr ctl state */
2892  nphy->tx_pwr_idx[0]);
2893  if (dev->phy.rev > 1)
2894  b43_phy_maskset(dev,
2896  ~0xff, nphy->tx_pwr_idx[1]);
2897  }
2898  }
2899 
2900  if (dev->phy.rev >= 3) {
2901  b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
2902  b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
2903  } else {
2904  b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000);
2905  }
2906 
2907  if (dev->phy.rev == 2)
2908  b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b);
2909  else if (dev->phy.rev < 2)
2910  b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);
2911 
2912  if (dev->phy.rev < 2 && dev->phy.is_40mhz)
2914 
2915  if (b43_nphy_ipa(dev)) {
2916  b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4);
2917  b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4);
2918  }
2919  }
2920 
2921  if (nphy->hang_avoid)
2922  b43_nphy_stay_in_carrier_search(dev, 0);
2923 }
2924 
2925 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */
2926 static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
2927 {
2928  struct b43_phy_n *nphy = dev->phy.n;
2929  struct ssb_sprom *sprom = dev->dev->bus_sprom;
2930 
2931  u8 txpi[2], bbmult, i;
2932  u16 tmp, radio_gain, dac_gain;
2933  u16 freq = dev->phy.channel_freq;
2934  u32 txgain;
2935  /* u32 gaintbl; rev3+ */
2936 
2937  if (nphy->hang_avoid)
2938  b43_nphy_stay_in_carrier_search(dev, 1);
2939 
2940  if (dev->phy.rev >= 7) {
2941  txpi[0] = txpi[1] = 30;
2942  } else if (dev->phy.rev >= 3) {
2943  txpi[0] = 40;
2944  txpi[1] = 40;
2945  } else if (sprom->revision < 4) {
2946  txpi[0] = 72;
2947  txpi[1] = 72;
2948  } else {
2949  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2950  txpi[0] = sprom->txpid2g[0];
2951  txpi[1] = sprom->txpid2g[1];
2952  } else if (freq >= 4900 && freq < 5100) {
2953  txpi[0] = sprom->txpid5gl[0];
2954  txpi[1] = sprom->txpid5gl[1];
2955  } else if (freq >= 5100 && freq < 5500) {
2956  txpi[0] = sprom->txpid5g[0];
2957  txpi[1] = sprom->txpid5g[1];
2958  } else if (freq >= 5500) {
2959  txpi[0] = sprom->txpid5gh[0];
2960  txpi[1] = sprom->txpid5gh[1];
2961  } else {
2962  txpi[0] = 91;
2963  txpi[1] = 91;
2964  }
2965  }
2966  if (dev->phy.rev < 7 &&
2967  (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 100))
2968  txpi[0] = txpi[1] = 91;
2969 
2970  /*
2971  for (i = 0; i < 2; i++) {
2972  nphy->txpwrindex[i].index_internal = txpi[i];
2973  nphy->txpwrindex[i].index_internal_save = txpi[i];
2974  }
2975  */
2976 
2977  for (i = 0; i < 2; i++) {
2978  txgain = *(b43_nphy_get_tx_gain_table(dev) + txpi[i]);
2979 
2980  if (dev->phy.rev >= 3)
2981  radio_gain = (txgain >> 16) & 0x1FFFF;
2982  else
2983  radio_gain = (txgain >> 16) & 0x1FFF;
2984 
2985  if (dev->phy.rev >= 7)
2986  dac_gain = (txgain >> 8) & 0x7;
2987  else
2988  dac_gain = (txgain >> 8) & 0x3F;
2989  bbmult = txgain & 0xFF;
2990 
2991  if (dev->phy.rev >= 3) {
2992  if (i == 0)
2993  b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
2994  else
2995  b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
2996  } else {
2997  b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
2998  }
2999 
3000  if (i == 0)
3001  b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, dac_gain);
3002  else
3003  b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);
3004 
3005  b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain);
3006 
3007  tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57));
3008  if (i == 0)
3009  tmp = (tmp & 0x00FF) | (bbmult << 8);
3010  else
3011  tmp = (tmp & 0xFF00) | bbmult;
3012  b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp);
3013 
3014  if (b43_nphy_ipa(dev)) {
3015  u32 tmp32;
3016  u16 reg = (i == 0) ?
3018  tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i,
3019  576 + txpi[i]));
3020  b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);
3021  b43_phy_set(dev, reg, 0x4);
3022  }
3023  }
3024 
3026 
3027  if (nphy->hang_avoid)
3028  b43_nphy_stay_in_carrier_search(dev, 0);
3029 }
3030 
3031 static void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev)
3032 {
3033  struct b43_phy *phy = &dev->phy;
3034 
3035  u8 core;
3036  u16 r; /* routing */
3037 
3038  if (phy->rev >= 7) {
3039  for (core = 0; core < 2; core++) {
3040  r = core ? 0x190 : 0x170;
3041  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
3042  b43_radio_write(dev, r + 0x5, 0x5);
3043  b43_radio_write(dev, r + 0x9, 0xE);
3044  if (phy->rev != 5)
3045  b43_radio_write(dev, r + 0xA, 0);
3046  if (phy->rev != 7)
3047  b43_radio_write(dev, r + 0xB, 1);
3048  else
3049  b43_radio_write(dev, r + 0xB, 0x31);
3050  } else {
3051  b43_radio_write(dev, r + 0x5, 0x9);
3052  b43_radio_write(dev, r + 0x9, 0xC);
3053  b43_radio_write(dev, r + 0xB, 0x0);
3054  if (phy->rev != 5)
3055  b43_radio_write(dev, r + 0xA, 1);
3056  else
3057  b43_radio_write(dev, r + 0xA, 0x31);
3058  }
3059  b43_radio_write(dev, r + 0x6, 0);
3060  b43_radio_write(dev, r + 0x7, 0);
3061  b43_radio_write(dev, r + 0x8, 3);
3062  b43_radio_write(dev, r + 0xC, 0);
3063  }
3064  } else {
3065  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
3067  else
3071 
3072  for (core = 0; core < 2; core++) {
3073  r = core ? B2056_TX1 : B2056_TX0;
3074 
3076  b43_radio_write(dev, r | B2056_TX_IQCAL_IDAC, 0);
3077  b43_radio_write(dev, r | B2056_TX_TSSI_VCM, 3);
3078  b43_radio_write(dev, r | B2056_TX_TX_AMP_DET, 0);
3079  b43_radio_write(dev, r | B2056_TX_TSSI_MISC1, 8);
3080  b43_radio_write(dev, r | B2056_TX_TSSI_MISC2, 0);
3081  b43_radio_write(dev, r | B2056_TX_TSSI_MISC3, 0);
3082  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
3084  0x5);
3085  if (phy->rev != 5)
3087  0x00);
3088  if (phy->rev >= 5)
3090  0x31);
3091  else
3093  0x11);
3095  0xE);
3096  } else {
3098  0x9);
3099  b43_radio_write(dev, r | B2056_TX_TSSIA, 0x31);
3100  b43_radio_write(dev, r | B2056_TX_TSSIG, 0x0);
3102  0xC);
3103  }
3104  }
3105  }
3106 }
3107 
3108 /*
3109  * Stop radio and transmit known signal. Then check received signal strength to
3110  * get TSSI (Transmit Signal Strength Indicator).
3111  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlIdleTssi
3112  */
3113 static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
3114 {
3115  struct b43_phy *phy = &dev->phy;
3116  struct b43_phy_n *nphy = dev->phy.n;
3117 
3118  u32 tmp;
3119  s32 rssi[4] = { };
3120 
3121  /* TODO: check if we can transmit */
3122 
3123  if (b43_nphy_ipa(dev))
3124  b43_nphy_ipa_internal_tssi_setup(dev);
3125 
3126  if (phy->rev >= 7)
3127  b43_nphy_rf_control_override_rev7(dev, 0x2000, 0, 3, false, 0);
3128  else if (phy->rev >= 3)
3129  b43_nphy_rf_control_override(dev, 0x2000, 0, 3, false);
3130 
3131  b43_nphy_stop_playback(dev);
3132  b43_nphy_tx_tone(dev, 0xFA0, 0, false, false);
3133  udelay(20);
3134  tmp = b43_nphy_poll_rssi(dev, 4, rssi, 1);
3135  b43_nphy_stop_playback(dev);
3136  b43_nphy_rssi_select(dev, 0, 0);
3137 
3138  if (phy->rev >= 7)
3139  b43_nphy_rf_control_override_rev7(dev, 0x2000, 0, 3, true, 0);
3140  else if (phy->rev >= 3)
3141  b43_nphy_rf_control_override(dev, 0x2000, 0, 3, true);
3142 
3143  if (phy->rev >= 3) {
3144  nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF;
3145  nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF;
3146  } else {
3147  nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 16) & 0xFF;
3148  nphy->pwr_ctl_info[1].idle_tssi_5g = tmp & 0xFF;
3149  }
3150  nphy->pwr_ctl_info[0].idle_tssi_2g = (tmp >> 24) & 0xFF;
3151  nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF;
3152 }
3153 
3154 /* http://bcm-v4.sipsolutions.net/PHY/N/TxPwrLimitToTbl */
3155 static void b43_nphy_tx_prepare_adjusted_power_table(struct b43_wldev *dev)
3156 {
3157  struct b43_phy_n *nphy = dev->phy.n;
3158 
3159  u8 idx, delta;
3160  u8 i, stf_mode;
3161 
3162  for (i = 0; i < 4; i++)
3163  nphy->adj_pwr_tbl[i] = nphy->tx_power_offset[i];
3164 
3165  for (stf_mode = 0; stf_mode < 4; stf_mode++) {
3166  delta = 0;
3167  switch (stf_mode) {
3168  case 0:
3169  if (dev->phy.is_40mhz && dev->phy.rev >= 5) {
3170  idx = 68;
3171  } else {
3172  delta = 1;
3173  idx = dev->phy.is_40mhz ? 52 : 4;
3174  }
3175  break;
3176  case 1:
3177  idx = dev->phy.is_40mhz ? 76 : 28;
3178  break;
3179  case 2:
3180  idx = dev->phy.is_40mhz ? 84 : 36;
3181  break;
3182  case 3:
3183  idx = dev->phy.is_40mhz ? 92 : 44;
3184  break;
3185  }
3186 
3187  for (i = 0; i < 20; i++) {
3188  nphy->adj_pwr_tbl[4 + 4 * i + stf_mode] =
3189  nphy->tx_power_offset[idx];
3190  if (i == 0)
3191  idx += delta;
3192  if (i == 14)
3193  idx += 1 - delta;
3194  if (i == 3 || i == 4 || i == 7 || i == 8 || i == 11 ||
3195  i == 13)
3196  idx += 1;
3197  }
3198  }
3199 }
3200 
3201 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlSetup */
3202 static void b43_nphy_tx_power_ctl_setup(struct b43_wldev *dev)
3203 {
3204  struct b43_phy_n *nphy = dev->phy.n;
3205  struct ssb_sprom *sprom = dev->dev->bus_sprom;
3206 
3207  s16 a1[2], b0[2], b1[2];
3208  u8 idle[2];
3209  s8 target[2];
3210  s32 num, den, pwr;
3211  u32 regval[64];
3212 
3213  u16 freq = dev->phy.channel_freq;
3214  u16 tmp;
3215  u16 r; /* routing */
3216  u8 i, c;
3217 
3218  if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) {
3219  b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000);
3220  b43_read32(dev, B43_MMIO_MACCTL);
3221  udelay(1);
3222  }
3223 
3224  if (nphy->hang_avoid)
3225  b43_nphy_stay_in_carrier_search(dev, true);
3226 
3228  if (dev->phy.rev >= 3)
3230  ~B43_NPHY_TXPCTL_CMD_PCTLEN & 0xFFFF);
3231  else
3234 
3235  if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12)
3236  b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0);
3237 
3238  if (sprom->revision < 4) {
3239  idle[0] = nphy->pwr_ctl_info[0].idle_tssi_2g;
3240  idle[1] = nphy->pwr_ctl_info[1].idle_tssi_2g;
3241  target[0] = target[1] = 52;
3242  a1[0] = a1[1] = -424;
3243  b0[0] = b0[1] = 5612;
3244  b1[0] = b1[1] = -1393;
3245  } else {
3246  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
3247  for (c = 0; c < 2; c++) {
3248  idle[c] = nphy->pwr_ctl_info[c].idle_tssi_2g;
3249  target[c] = sprom->core_pwr_info[c].maxpwr_2g;
3250  a1[c] = sprom->core_pwr_info[c].pa_2g[0];
3251  b0[c] = sprom->core_pwr_info[c].pa_2g[1];
3252  b1[c] = sprom->core_pwr_info[c].pa_2g[2];
3253  }
3254  } else if (freq >= 4900 && freq < 5100) {
3255  for (c = 0; c < 2; c++) {
3256  idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
3257  target[c] = sprom->core_pwr_info[c].maxpwr_5gl;
3258  a1[c] = sprom->core_pwr_info[c].pa_5gl[0];
3259  b0[c] = sprom->core_pwr_info[c].pa_5gl[1];
3260  b1[c] = sprom->core_pwr_info[c].pa_5gl[2];
3261  }
3262  } else if (freq >= 5100 && freq < 5500) {
3263  for (c = 0; c < 2; c++) {
3264  idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
3265  target[c] = sprom->core_pwr_info[c].maxpwr_5g;
3266  a1[c] = sprom->core_pwr_info[c].pa_5g[0];
3267  b0[c] = sprom->core_pwr_info[c].pa_5g[1];
3268  b1[c] = sprom->core_pwr_info[c].pa_5g[2];
3269  }
3270  } else if (freq >= 5500) {
3271  for (c = 0; c < 2; c++) {
3272  idle[c] = nphy->pwr_ctl_info[c].idle_tssi_5g;
3273  target[c] = sprom->core_pwr_info[c].maxpwr_5gh;
3274  a1[c] = sprom->core_pwr_info[c].pa_5gh[0];
3275  b0[c] = sprom->core_pwr_info[c].pa_5gh[1];
3276  b1[c] = sprom->core_pwr_info[c].pa_5gh[2];
3277  }
3278  } else {
3279  idle[0] = nphy->pwr_ctl_info[0].idle_tssi_5g;
3280  idle[1] = nphy->pwr_ctl_info[1].idle_tssi_5g;
3281  target[0] = target[1] = 52;
3282  a1[0] = a1[1] = -424;
3283  b0[0] = b0[1] = 5612;
3284  b1[0] = b1[1] = -1393;
3285  }
3286  }
3287  /* target[0] = target[1] = nphy->tx_power_max; */
3288 
3289  if (dev->phy.rev >= 3) {
3290  if (sprom->fem.ghz2.tssipos)
3291  b43_phy_set(dev, B43_NPHY_TXPCTL_ITSSI, 0x4000);
3292  if (dev->phy.rev >= 7) {
3293  for (c = 0; c < 2; c++) {
3294  r = c ? 0x190 : 0x170;
3295  if (b43_nphy_ipa(dev))
3296  b43_radio_write(dev, r + 0x9, (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ? 0xE : 0xC);
3297  }
3298  } else {
3299  if (b43_nphy_ipa(dev)) {
3300  tmp = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
3301  b43_radio_write(dev,
3303  b43_radio_write(dev,
3305  } else {
3306  b43_radio_write(dev,
3307  B2056_TX0 | B2056_TX_TX_SSI_MUX, 0x11);
3308  b43_radio_write(dev,
3309  B2056_TX1 | B2056_TX_TX_SSI_MUX, 0x11);
3310  }
3311  }
3312  }
3313 
3314  if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12) {
3315  b43_maskset32(dev, B43_MMIO_MACCTL, ~0, 0x200000);
3316  b43_read32(dev, B43_MMIO_MACCTL);
3317  udelay(1);
3318  }
3319 
3320  if (dev->phy.rev >= 7) {
3322  ~B43_NPHY_TXPCTL_CMD_INIT, 0x19);
3325  } else {
3327  ~B43_NPHY_TXPCTL_CMD_INIT, 0x40);
3328  if (dev->phy.rev > 1)
3331  }
3332 
3333  if (dev->dev->core_rev == 11 || dev->dev->core_rev == 12)
3334  b43_maskset32(dev, B43_MMIO_MACCTL, ~0x200000, 0);
3335 
3340  idle[0] << B43_NPHY_TXPCTL_ITSSI_0_SHIFT |
3341  idle[1] << B43_NPHY_TXPCTL_ITSSI_1_SHIFT |
3344  target[0] << B43_NPHY_TXPCTL_TPWR_0_SHIFT |
3345  target[1] << B43_NPHY_TXPCTL_TPWR_1_SHIFT);
3346 
3347  for (c = 0; c < 2; c++) {
3348  for (i = 0; i < 64; i++) {
3349  num = 8 * (16 * b0[c] + b1[c] * i);
3350  den = 32768 + a1[c] * i;
3351  pwr = max((4 * num + den / 2) / den, -8);
3352  if (dev->phy.rev < 3 && (i <= (31 - idle[c] + 1)))
3353  pwr = max(pwr, target[c] + 1);
3354  regval[i] = pwr;
3355  }
3356  b43_ntab_write_bulk(dev, B43_NTAB32(26 + c, 0), 64, regval);
3357  }
3358 
3359  b43_nphy_tx_prepare_adjusted_power_table(dev);
3360  /*
3361  b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84, nphy->adj_pwr_tbl);
3362  b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84, nphy->adj_pwr_tbl);
3363  */
3364 
3365  if (nphy->hang_avoid)
3366  b43_nphy_stay_in_carrier_search(dev, false);
3367 }
3368 
3369 static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
3370 {
3371  struct b43_phy *phy = &dev->phy;
3372 
3373  const u32 *table = NULL;
3374  u32 rfpwr_offset;
3375  u8 pga_gain;
3376  int i;
3377 
3378  table = b43_nphy_get_tx_gain_table(dev);
3379  b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
3380  b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
3381 
3382  if (phy->rev >= 3) {
3383 #if 0
3384  nphy->gmval = (table[0] >> 16) & 0x7000;
3385 #endif
3386 
3387  for (i = 0; i < 128; i++) {
3388  pga_gain = (table[i] >> 24) & 0xF;
3389  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
3390  rfpwr_offset =
3392  else
3393  rfpwr_offset =
3394  0; /* FIXME */
3395  b43_ntab_write(dev, B43_NTAB32(26, 576 + i),
3396  rfpwr_offset);
3397  b43_ntab_write(dev, B43_NTAB32(27, 576 + i),
3398  rfpwr_offset);
3399  }
3400  }
3401 }
3402 
3403 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
3404 static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
3405 {
3406  struct b43_phy_n *nphy = dev->phy.n;
3407  enum ieee80211_band band;
3408  u16 tmp;
3409 
3410  if (!enable) {
3411  nphy->rfctrl_intc1_save = b43_phy_read(dev,
3413  nphy->rfctrl_intc2_save = b43_phy_read(dev,
3415  band = b43_current_band(dev->wl);
3416  if (dev->phy.rev >= 3) {
3417  if (band == IEEE80211_BAND_5GHZ)
3418  tmp = 0x600;
3419  else
3420  tmp = 0x480;
3421  } else {
3422  if (band == IEEE80211_BAND_5GHZ)
3423  tmp = 0x180;
3424  else
3425  tmp = 0x120;
3426  }
3429  } else {
3431  nphy->rfctrl_intc1_save);
3433  nphy->rfctrl_intc2_save);
3434  }
3435 }
3436 
3437 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
3438 static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
3439 {
3440  u16 tmp;
3441 
3442  if (dev->phy.rev >= 3) {
3443  if (b43_nphy_ipa(dev)) {
3444  tmp = 4;
3446  (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
3447  }
3448 
3449  tmp = 1;
3451  (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
3452  }
3453 }
3454 
3455 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
3456 static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est,
3457  u16 samps, u8 time, bool wait)
3458 {
3459  int i;
3460  u16 tmp;
3461 
3462  b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps);
3464  if (wait)
3466  else
3468 
3470 
3471  for (i = 1000; i; i--) {
3472  tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD);
3473  if (!(tmp & B43_NPHY_IQEST_CMD_START)) {
3474  est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) |
3476  est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) |
3478  est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) |
3480 
3481  est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) |
3483  est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) |
3485  est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) |
3487  return;
3488  }
3489  udelay(10);
3490  }
3491  memset(est, 0, sizeof(*est));
3492 }
3493 
3494 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */
3495 static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write,
3496  struct b43_phy_n_iq_comp *pcomp)
3497 {
3498  if (write) {
3503  } else {
3504  pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0);
3505  pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0);
3506  pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1);
3507  pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1);
3508  }
3509 }
3510 
3511 #if 0
3512 /* Ready but not used anywhere */
3513 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
3514 static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core)
3515 {
3516  u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
3517 
3518  b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]);
3519  if (core == 0) {
3520  b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]);
3521  b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
3522  } else {
3523  b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
3524  b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
3525  }
3526  b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]);
3527  b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]);
3528  b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]);
3529  b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]);
3530  b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]);
3531  b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]);
3532  b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
3533  b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
3534 }
3535 
3536 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */
3537 static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
3538 {
3539  u8 rxval, txval;
3540  u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
3541 
3542  regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
3543  if (core == 0) {
3544  regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
3545  regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
3546  } else {
3547  regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
3548  regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
3549  }
3550  regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
3551  regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
3552  regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
3553  regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
3554  regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1);
3555  regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
3556  regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
3557  regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
3558 
3559  b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
3560  b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
3561 
3563  ~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
3564  ((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
3566  ((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT));
3568  (core << B43_NPHY_RFSEQCA_RXEN_SHIFT));
3570  (core << B43_NPHY_RFSEQCA_TXDIS_SHIFT));
3571 
3572  if (core == 0) {
3573  b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007);
3574  b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007);
3575  } else {
3576  b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007);
3577  b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);
3578  }
3579 
3580  b43_nphy_rf_control_intc_override(dev, 2, 0, 3);
3581  b43_nphy_rf_control_override(dev, 8, 0, 3, false);
3582  b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
3583 
3584  if (core == 0) {
3585  rxval = 1;
3586  txval = 8;
3587  } else {
3588  rxval = 4;
3589  txval = 2;
3590  }
3591  b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1));
3592  b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core));
3593 }
3594 #endif
3595 
3596 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
3597 static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
3598 {
3599  int i;
3600  s32 iq;
3601  u32 ii;
3602  u32 qq;
3603  int iq_nbits, qq_nbits;
3604  int arsh, brsh;
3605  u16 tmp, a, b;
3606 
3607  struct nphy_iq_est est;
3608  struct b43_phy_n_iq_comp old;
3609  struct b43_phy_n_iq_comp new = { };
3610  bool error = false;
3611 
3612  if (mask == 0)
3613  return;
3614 
3615  b43_nphy_rx_iq_coeffs(dev, false, &old);
3616  b43_nphy_rx_iq_coeffs(dev, true, &new);
3617  b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false);
3618  new = old;
3619 
3620  for (i = 0; i < 2; i++) {
3621  if (i == 0 && (mask & 1)) {
3622  iq = est.iq0_prod;
3623  ii = est.i0_pwr;
3624  qq = est.q0_pwr;
3625  } else if (i == 1 && (mask & 2)) {
3626  iq = est.iq1_prod;
3627  ii = est.i1_pwr;
3628  qq = est.q1_pwr;
3629  } else {
3630  continue;
3631  }
3632 
3633  if (ii + qq < 2) {
3634  error = true;
3635  break;
3636  }
3637 
3638  iq_nbits = fls(abs(iq));
3639  qq_nbits = fls(qq);
3640 
3641  arsh = iq_nbits - 20;
3642  if (arsh >= 0) {
3643  a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
3644  tmp = ii >> arsh;
3645  } else {
3646  a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
3647  tmp = ii << -arsh;
3648  }
3649  if (tmp == 0) {
3650  error = true;
3651  break;
3652  }
3653  a /= tmp;
3654 
3655  brsh = qq_nbits - 11;
3656  if (brsh >= 0) {
3657  b = (qq << (31 - qq_nbits));
3658  tmp = ii >> brsh;
3659  } else {
3660  b = (qq << (31 - qq_nbits));
3661  tmp = ii << -brsh;
3662  }
3663  if (tmp == 0) {
3664  error = true;
3665  break;
3666  }
3667  b = int_sqrt(b / tmp - a * a) - (1 << 10);
3668 
3669  if (i == 0 && (mask & 0x1)) {
3670  if (dev->phy.rev >= 3) {
3671  new.a0 = a & 0x3FF;
3672  new.b0 = b & 0x3FF;
3673  } else {
3674  new.a0 = b & 0x3FF;
3675  new.b0 = a & 0x3FF;
3676  }
3677  } else if (i == 1 && (mask & 0x2)) {
3678  if (dev->phy.rev >= 3) {
3679  new.a1 = a & 0x3FF;
3680  new.b1 = b & 0x3FF;
3681  } else {
3682  new.a1 = b & 0x3FF;
3683  new.b1 = a & 0x3FF;
3684  }
3685  }
3686  }
3687 
3688  if (error)
3689  new = old;
3690 
3691  b43_nphy_rx_iq_coeffs(dev, true, &new);
3692 }
3693 
3694 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */
3695 static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
3696 {
3697  u16 array[4];
3698  b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array);
3699 
3704 }
3705 
3706 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */
3707 static void b43_nphy_spur_workaround(struct b43_wldev *dev)
3708 {
3709  struct b43_phy_n *nphy = dev->phy.n;
3710 
3711  u8 channel = dev->phy.channel;
3712  int tone[2] = { 57, 58 };
3713  u32 noise[2] = { 0x3FF, 0x3FF };
3714 
3715  B43_WARN_ON(dev->phy.rev < 3);
3716 
3717  if (nphy->hang_avoid)
3718  b43_nphy_stay_in_carrier_search(dev, 1);
3719 
3720  if (nphy->gband_spurwar_en) {
3721  /* TODO: N PHY Adjust Analog Pfbw (7) */
3722  if (channel == 11 && dev->phy.is_40mhz)
3723  ; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/
3724  else
3725  ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
3726  /* TODO: N PHY Adjust CRS Min Power (0x1E) */
3727  }
3728 
3729  if (nphy->aband_spurwar_en) {
3730  if (channel == 54) {
3731  tone[0] = 0x20;
3732  noise[0] = 0x25F;
3733  } else if (channel == 38 || channel == 102 || channel == 118) {
3734  if (0 /* FIXME */) {
3735  tone[0] = 0x20;
3736  noise[0] = 0x21F;
3737  } else {
3738  tone[0] = 0;
3739  noise[0] = 0;
3740  }
3741  } else if (channel == 134) {
3742  tone[0] = 0x20;
3743  noise[0] = 0x21F;
3744  } else if (channel == 151) {
3745  tone[0] = 0x10;
3746  noise[0] = 0x23F;
3747  } else if (channel == 153 || channel == 161) {
3748  tone[0] = 0x30;
3749  noise[0] = 0x23F;
3750  } else {
3751  tone[0] = 0;
3752  noise[0] = 0;
3753  }
3754 
3755  if (!tone[0] && !noise[0])
3756  ; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/
3757  else
3758  ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
3759  }
3760 
3761  if (nphy->hang_avoid)
3762  b43_nphy_stay_in_carrier_search(dev, 0);
3763 }
3764 
3765 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
3766 static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
3767 {
3768  struct b43_phy_n *nphy = dev->phy.n;
3769  int i, j;
3770  u32 tmp;
3771  u32 cur_real, cur_imag, real_part, imag_part;
3772 
3773  u16 buffer[7];
3774 
3775  if (nphy->hang_avoid)
3776  b43_nphy_stay_in_carrier_search(dev, true);
3777 
3778  b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
3779 
3780  for (i = 0; i < 2; i++) {
3781  tmp = ((buffer[i * 2] & 0x3FF) << 10) |
3782  (buffer[i * 2 + 1] & 0x3FF);
3784  (((i + 26) << 10) | 320));
3785  for (j = 0; j < 128; j++) {
3787  ((tmp >> 16) & 0xFFFF));
3789  (tmp & 0xFFFF));
3790  }
3791  }
3792 
3793  for (i = 0; i < 2; i++) {
3794  tmp = buffer[5 + i];
3795  real_part = (tmp >> 8) & 0xFF;
3796  imag_part = (tmp & 0xFF);
3798  (((i + 26) << 10) | 448));
3799 
3800  if (dev->phy.rev >= 3) {
3801  cur_real = real_part;
3802  cur_imag = imag_part;
3803  tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF);
3804  }
3805 
3806  for (j = 0; j < 128; j++) {
3807  if (dev->phy.rev < 3) {
3808  cur_real = (real_part * loscale[j] + 128) >> 8;
3809  cur_imag = (imag_part * loscale[j] + 128) >> 8;
3810  tmp = ((cur_real & 0xFF) << 8) |
3811  (cur_imag & 0xFF);
3812  }
3814  ((tmp >> 16) & 0xFFFF));
3816  (tmp & 0xFFFF));
3817  }
3818  }
3819 
3820  if (dev->phy.rev >= 3) {
3822  B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF);
3824  B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF);
3825  }
3826 
3827  if (nphy->hang_avoid)
3828  b43_nphy_stay_in_carrier_search(dev, false);
3829 }
3830 
3831 /*
3832  * Restore RSSI Calibration
3833  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal
3834  */
3835 static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
3836 {
3837  struct b43_phy_n *nphy = dev->phy.n;
3838 
3839  u16 *rssical_radio_regs = NULL;
3840  u16 *rssical_phy_regs = NULL;
3841 
3842  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
3843  if (!nphy->rssical_chanspec_2G.center_freq)
3844  return;
3845  rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
3846  rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
3847  } else {
3848  if (!nphy->rssical_chanspec_5G.center_freq)
3849  return;
3850  rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
3851  rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
3852  }
3853 
3854  /* TODO use some definitions */
3855  b43_radio_maskset(dev, 0x602B, 0xE3, rssical_radio_regs[0]);
3856  b43_radio_maskset(dev, 0x702B, 0xE3, rssical_radio_regs[1]);
3857 
3858  b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]);
3859  b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]);
3860  b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]);
3861  b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]);
3862 
3863  b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]);
3864  b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]);
3865  b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]);
3866  b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]);
3867 
3868  b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]);
3869  b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]);
3870  b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]);
3871  b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
3872 }
3873 
3874 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
3875 static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
3876 {
3877  struct b43_phy_n *nphy = dev->phy.n;
3878  u16 *save = nphy->tx_rx_cal_radio_saveregs;
3879  u16 tmp;
3880  u8 offset, i;
3881 
3882  if (dev->phy.rev >= 3) {
3883  for (i = 0; i < 2; i++) {
3884  tmp = (i == 0) ? 0x2000 : 0x3000;
3885  offset = i * 11;
3886 
3887  save[offset + 0] = b43_radio_read16(dev, B2055_CAL_RVARCTL);
3888  save[offset + 1] = b43_radio_read16(dev, B2055_CAL_LPOCTL);
3889  save[offset + 2] = b43_radio_read16(dev, B2055_CAL_TS);
3890  save[offset + 3] = b43_radio_read16(dev, B2055_CAL_RCCALRTS);
3891  save[offset + 4] = b43_radio_read16(dev, B2055_CAL_RCALRTS);
3892  save[offset + 5] = b43_radio_read16(dev, B2055_PADDRV);
3893  save[offset + 6] = b43_radio_read16(dev, B2055_XOCTL1);
3894  save[offset + 7] = b43_radio_read16(dev, B2055_XOCTL2);
3895  save[offset + 8] = b43_radio_read16(dev, B2055_XOREGUL);
3896  save[offset + 9] = b43_radio_read16(dev, B2055_XOMISC);
3897  save[offset + 10] = b43_radio_read16(dev, B2055_PLL_LFC1);
3898 
3899  if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
3900  b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x0A);
3901  b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
3902  b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
3903  b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
3904  b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
3905  if (nphy->ipa5g_on) {
3906  b43_radio_write16(dev, tmp | B2055_PADDRV, 4);
3907  b43_radio_write16(dev, tmp | B2055_XOCTL1, 1);
3908  } else {
3909  b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
3910  b43_radio_write16(dev, tmp | B2055_XOCTL1, 0x2F);
3911  }
3912  b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
3913  } else {
3914  b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x06);
3915  b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
3916  b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
3917  b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
3918  b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
3919  b43_radio_write16(dev, tmp | B2055_XOCTL1, 0);
3920  if (nphy->ipa2g_on) {
3921  b43_radio_write16(dev, tmp | B2055_PADDRV, 6);
3922  b43_radio_write16(dev, tmp | B2055_XOCTL2,
3923  (dev->phy.rev < 5) ? 0x11 : 0x01);
3924  } else {
3925  b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
3926  b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
3927  }
3928  }
3929  b43_radio_write16(dev, tmp | B2055_XOREGUL, 0);
3930  b43_radio_write16(dev, tmp | B2055_XOMISC, 0);
3931  b43_radio_write16(dev, tmp | B2055_PLL_LFC1, 0);
3932  }
3933  } else {
3934  save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1);
3936 
3937  save[1] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL2);
3939 
3940  save[2] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL1);
3942 
3943  save[3] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL2);
3945 
3946  save[3] = b43_radio_read16(dev, B2055_C1_PWRDET_RXTX);
3947  save[4] = b43_radio_read16(dev, B2055_C2_PWRDET_RXTX);
3948 
3949  if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) &
3953  } else {
3956  }
3957 
3958  if (dev->phy.rev < 2) {
3959  b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20);
3960  b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20);
3961  } else {
3962  b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20);
3963  b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20);
3964  }
3965  }
3966 }
3967 
3968 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */
3969 static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)
3970 {
3971  struct b43_phy_n *nphy = dev->phy.n;
3972  int i;
3973  u16 scale, entry;
3974 
3975  u16 tmp = nphy->txcal_bbmult;
3976  if (core == 0)
3977  tmp >>= 8;
3978  tmp &= 0xff;
3979 
3980  for (i = 0; i < 18; i++) {
3981  scale = (ladder_lo[i].percent * tmp) / 100;
3982  entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env;
3983  b43_ntab_write(dev, B43_NTAB16(15, i), entry);
3984 
3985  scale = (ladder_iq[i].percent * tmp) / 100;
3986  entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env;
3987  b43_ntab_write(dev, B43_NTAB16(15, i + 32), entry);
3988  }
3989 }
3990 
3991 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
3992 static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev)
3993 {
3994  int i;
3995  for (i = 0; i < 15; i++)
3996  b43_phy_write(dev, B43_PHY_N(0x2C5 + i),
3997  tbl_tx_filter_coef_rev4[2][i]);
3998 }
3999 
4000 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
4001 static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev)
4002 {
4003  int i, j;
4004  /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
4005  static const u16 offset[] = { 0x186, 0x195, 0x2C5 };
4006 
4007  for (i = 0; i < 3; i++)
4008  for (j = 0; j < 15; j++)
4009  b43_phy_write(dev, B43_PHY_N(offset[i] + j),
4010  tbl_tx_filter_coef_rev4[i][j]);
4011 
4012  if (dev->phy.is_40mhz) {
4013  for (j = 0; j < 15; j++)
4014  b43_phy_write(dev, B43_PHY_N(offset[0] + j),
4015  tbl_tx_filter_coef_rev4[3][j]);
4016  } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
4017  for (j = 0; j < 15; j++)
4018  b43_phy_write(dev, B43_PHY_N(offset[0] + j),
4019  tbl_tx_filter_coef_rev4[5][j]);
4020  }
4021 
4022  if (dev->phy.channel == 14)
4023  for (j = 0; j < 15; j++)
4024  b43_phy_write(dev, B43_PHY_N(offset[0] + j),
4025  tbl_tx_filter_coef_rev4[6][j]);
4026 }
4027 
4028 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
4029 static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
4030 {
4031  struct b43_phy_n *nphy = dev->phy.n;
4032 
4033  u16 curr_gain[2];
4034  struct nphy_txgains target;
4035  const u32 *table = NULL;
4036 
4037  if (!nphy->txpwrctrl) {
4038  int i;
4039 
4040  if (nphy->hang_avoid)
4041  b43_nphy_stay_in_carrier_search(dev, true);
4042  b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, curr_gain);
4043  if (nphy->hang_avoid)
4044  b43_nphy_stay_in_carrier_search(dev, false);
4045 
4046  for (i = 0; i < 2; ++i) {
4047  if (dev->phy.rev >= 3) {
4048  target.ipa[i] = curr_gain[i] & 0x000F;
4049  target.pad[i] = (curr_gain[i] & 0x00F0) >> 4;
4050  target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
4051  target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
4052  } else {
4053  target.ipa[i] = curr_gain[i] & 0x0003;
4054  target.pad[i] = (curr_gain[i] & 0x000C) >> 2;
4055  target.pga[i] = (curr_gain[i] & 0x0070) >> 4;
4056  target.txgm[i] = (curr_gain[i] & 0x0380) >> 7;
4057  }
4058  }
4059  } else {
4060  int i;
4061  u16 index[2];
4062  index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) &
4065  index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) &
4068 
4069  for (i = 0; i < 2; ++i) {
4070  table = b43_nphy_get_tx_gain_table(dev);
4071  if (dev->phy.rev >= 3) {
4072  target.ipa[i] = (table[index[i]] >> 16) & 0xF;
4073  target.pad[i] = (table[index[i]] >> 20) & 0xF;
4074  target.pga[i] = (table[index[i]] >> 24) & 0xF;
4075  target.txgm[i] = (table[index[i]] >> 28) & 0xF;
4076  } else {
4077  target.ipa[i] = (table[index[i]] >> 16) & 0x3;
4078  target.pad[i] = (table[index[i]] >> 18) & 0x3;
4079  target.pga[i] = (table[index[i]] >> 20) & 0x7;
4080  target.txgm[i] = (table[index[i]] >> 23) & 0x7;
4081  }
4082  }
4083  }
4084 
4085  return target;
4086 }
4087 
4088 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */
4089 static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev)
4090 {
4091  u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
4092 
4093  if (dev->phy.rev >= 3) {
4094  b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[0]);
4095  b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
4096  b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
4097  b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]);
4098  b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]);
4099  b43_ntab_write(dev, B43_NTAB16(8, 3), regs[5]);
4100  b43_ntab_write(dev, B43_NTAB16(8, 19), regs[6]);
4101  b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]);
4102  b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]);
4103  b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
4104  b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
4105  b43_nphy_reset_cca(dev);
4106  } else {
4107  b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]);
4108  b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]);
4109  b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
4110  b43_ntab_write(dev, B43_NTAB16(8, 2), regs[3]);
4111  b43_ntab_write(dev, B43_NTAB16(8, 18), regs[4]);
4112  b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]);
4113  b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]);
4114  }
4115 }
4116 
4117 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
4118 static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
4119 {
4120  u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
4121  u16 tmp;
4122 
4123  regs[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
4124  regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
4125  if (dev->phy.rev >= 3) {
4126  b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0xF0FF, 0x0A00);
4127  b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0xF0FF, 0x0A00);
4128 
4129  tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
4130  regs[2] = tmp;
4131  b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, tmp | 0x0600);
4132 
4133  tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
4134  regs[3] = tmp;
4135  b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600);
4136 
4137  regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG);
4139  ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
4140 
4141  tmp = b43_ntab_read(dev, B43_NTAB16(8, 3));
4142  regs[5] = tmp;
4143  b43_ntab_write(dev, B43_NTAB16(8, 3), 0);
4144 
4145  tmp = b43_ntab_read(dev, B43_NTAB16(8, 19));
4146  regs[6] = tmp;
4147  b43_ntab_write(dev, B43_NTAB16(8, 19), 0);
4148  regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
4149  regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
4150 
4151  b43_nphy_rf_control_intc_override(dev, 2, 1, 3);
4152  b43_nphy_rf_control_intc_override(dev, 1, 2, 1);
4153  b43_nphy_rf_control_intc_override(dev, 1, 8, 2);
4154 
4155  regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
4156  regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
4157  b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
4158  b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
4159  } else {
4160  b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000);
4161  b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000);
4162  tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
4163  regs[2] = tmp;
4164  b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000);
4165  tmp = b43_ntab_read(dev, B43_NTAB16(8, 2));
4166  regs[3] = tmp;
4167  tmp |= 0x2000;
4168  b43_ntab_write(dev, B43_NTAB16(8, 2), tmp);
4169  tmp = b43_ntab_read(dev, B43_NTAB16(8, 18));
4170  regs[4] = tmp;
4171  tmp |= 0x2000;
4172  b43_ntab_write(dev, B43_NTAB16(8, 18), tmp);
4173  regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
4174  regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
4175  if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
4176  tmp = 0x0180;
4177  else
4178  tmp = 0x0120;
4181  }
4182 }
4183 
4184 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */
4185 static void b43_nphy_save_cal(struct b43_wldev *dev)
4186 {
4187  struct b43_phy_n *nphy = dev->phy.n;
4188 
4189  struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
4190  u16 *txcal_radio_regs = NULL;
4191  struct b43_chanspec *iqcal_chanspec;
4192  u16 *table = NULL;
4193 
4194  if (nphy->hang_avoid)
4195  b43_nphy_stay_in_carrier_search(dev, 1);
4196 
4197  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
4198  rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
4199  txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
4200  iqcal_chanspec = &nphy->iqcal_chanspec_2G;
4201  table = nphy->cal_cache.txcal_coeffs_2G;
4202  } else {
4203  rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
4204  txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
4205  iqcal_chanspec = &nphy->iqcal_chanspec_5G;
4206  table = nphy->cal_cache.txcal_coeffs_5G;
4207  }
4208 
4209  b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs);
4210  /* TODO use some definitions */
4211  if (dev->phy.rev >= 3) {
4212  txcal_radio_regs[0] = b43_radio_read(dev, 0x2021);
4213  txcal_radio_regs[1] = b43_radio_read(dev, 0x2022);
4214  txcal_radio_regs[2] = b43_radio_read(dev, 0x3021);
4215  txcal_radio_regs[3] = b43_radio_read(dev, 0x3022);
4216  txcal_radio_regs[4] = b43_radio_read(dev, 0x2023);
4217  txcal_radio_regs[5] = b43_radio_read(dev, 0x2024);
4218  txcal_radio_regs[6] = b43_radio_read(dev, 0x3023);
4219  txcal_radio_regs[7] = b43_radio_read(dev, 0x3024);
4220  } else {
4221  txcal_radio_regs[0] = b43_radio_read(dev, 0x8B);
4222  txcal_radio_regs[1] = b43_radio_read(dev, 0xBA);
4223  txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);
4224  txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);
4225  }
4226  iqcal_chanspec->center_freq = dev->phy.channel_freq;
4227  iqcal_chanspec->channel_type = dev->phy.channel_type;
4228  b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table);
4229 
4230  if (nphy->hang_avoid)
4231  b43_nphy_stay_in_carrier_search(dev, 0);
4232 }
4233 
4234 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
4235 static void b43_nphy_restore_cal(struct b43_wldev *dev)
4236 {
4237  struct b43_phy_n *nphy = dev->phy.n;
4238 
4239  u16 coef[4];
4240  u16 *loft = NULL;
4241  u16 *table = NULL;
4242 
4243  int i;
4244  u16 *txcal_radio_regs = NULL;
4245  struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
4246 
4247  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
4248  if (!nphy->iqcal_chanspec_2G.center_freq)
4249  return;
4250  table = nphy->cal_cache.txcal_coeffs_2G;
4251  loft = &nphy->cal_cache.txcal_coeffs_2G[5];
4252  } else {
4253  if (!nphy->iqcal_chanspec_5G.center_freq)
4254  return;
4255  table = nphy->cal_cache.txcal_coeffs_5G;
4256  loft = &nphy->cal_cache.txcal_coeffs_5G[5];
4257  }
4258 
4259  b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, table);
4260 
4261  for (i = 0; i < 4; i++) {
4262  if (dev->phy.rev >= 3)
4263  table[i] = coef[i];
4264  else
4265  coef[i] = 0;
4266  }
4267 
4268  b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, coef);
4269  b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, loft);
4270  b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, loft);
4271 
4272  if (dev->phy.rev < 2)
4273  b43_nphy_tx_iq_workaround(dev);
4274 
4275  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
4276  txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
4277  rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
4278  } else {
4279  txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
4280  rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
4281  }
4282 
4283  /* TODO use some definitions */
4284  if (dev->phy.rev >= 3) {
4285  b43_radio_write(dev, 0x2021, txcal_radio_regs[0]);
4286  b43_radio_write(dev, 0x2022, txcal_radio_regs[1]);
4287  b43_radio_write(dev, 0x3021, txcal_radio_regs[2]);
4288  b43_radio_write(dev, 0x3022, txcal_radio_regs[3]);
4289  b43_radio_write(dev, 0x2023, txcal_radio_regs[4]);
4290  b43_radio_write(dev, 0x2024, txcal_radio_regs[5]);
4291  b43_radio_write(dev, 0x3023, txcal_radio_regs[6]);
4292  b43_radio_write(dev, 0x3024, txcal_radio_regs[7]);
4293  } else {
4294  b43_radio_write(dev, 0x8B, txcal_radio_regs[0]);
4295  b43_radio_write(dev, 0xBA, txcal_radio_regs[1]);
4296  b43_radio_write(dev, 0x8D, txcal_radio_regs[2]);
4297  b43_radio_write(dev, 0xBC, txcal_radio_regs[3]);
4298  }
4299  b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs);
4300 }
4301 
4302 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */
4303 static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
4304  struct nphy_txgains target,
4305  bool full, bool mphase)
4306 {
4307  struct b43_phy_n *nphy = dev->phy.n;
4308  int i;
4309  int error = 0;
4310  int freq;
4311  bool avoid = false;
4312  u8 length;
4313  u16 tmp, core, type, count, max, numb, last = 0, cmd;
4314  const u16 *table;
4315  bool phy6or5x;
4316 
4317  u16 buffer[11];
4318  u16 diq_start = 0;
4319  u16 save[2];
4320  u16 gain[2];
4321  struct nphy_iqcal_params params[2];
4322  bool updated[2] = { };
4323 
4324  b43_nphy_stay_in_carrier_search(dev, true);
4325 
4326  if (dev->phy.rev >= 4) {
4327  avoid = nphy->hang_avoid;
4328  nphy->hang_avoid = false;
4329  }
4330 
4331  b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
4332 
4333  for (i = 0; i < 2; i++) {
4334  b43_nphy_iq_cal_gain_params(dev, i, target, &params[i]);
4335  gain[i] = params[i].cal_gain;
4336  }
4337 
4338  b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain);
4339 
4340  b43_nphy_tx_cal_radio_setup(dev);
4341  b43_nphy_tx_cal_phy_setup(dev);
4342 
4343  phy6or5x = dev->phy.rev >= 6 ||
4344  (dev->phy.rev == 5 && nphy->ipa2g_on &&
4345  b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ);
4346  if (phy6or5x) {
4347  if (dev->phy.is_40mhz) {
4348  b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
4350  b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
4352  } else {
4353  b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
4355  b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
4357  }
4358  }
4359 
4361 
4362  if (!dev->phy.is_40mhz)
4363  freq = 2500;
4364  else
4365  freq = 5000;
4366 
4367  if (nphy->mphase_cal_phase_id > 2)
4368  b43_nphy_run_samples(dev, (dev->phy.is_40mhz ? 40 : 20) * 8,
4369  0xFFFF, 0, true, false);
4370  else
4371  error = b43_nphy_tx_tone(dev, freq, 250, true, false);
4372 
4373  if (error == 0) {
4374  if (nphy->mphase_cal_phase_id > 2) {
4375  table = nphy->mphase_txcal_bestcoeffs;
4376  length = 11;
4377  if (dev->phy.rev < 3)
4378  length -= 2;
4379  } else {
4380  if (!full && nphy->txiqlocal_coeffsvalid) {
4381  table = nphy->txiqlocal_bestc;
4382  length = 11;
4383  if (dev->phy.rev < 3)
4384  length -= 2;
4385  } else {
4386  full = true;
4387  if (dev->phy.rev >= 3) {
4390  } else {
4393  }
4394  }
4395  }
4396 
4397  b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, table);
4398 
4399  if (full) {
4400  if (dev->phy.rev >= 3)
4402  else
4404  } else {
4405  if (dev->phy.rev >= 3)
4407  else
4409  }
4410 
4411  if (mphase) {
4412  count = nphy->mphase_txcal_cmdidx;
4413  numb = min(max,
4414  (u16)(count + nphy->mphase_txcal_numcmds));
4415  } else {
4416  count = 0;
4417  numb = max;
4418  }
4419 
4420  for (; count < numb; count++) {
4421  if (full) {
4422  if (dev->phy.rev >= 3)
4424  else
4426  } else {
4427  if (dev->phy.rev >= 3)
4429  else
4431  }
4432 
4433  core = (cmd & 0x3000) >> 12;
4434  type = (cmd & 0x0F00) >> 8;
4435 
4436  if (phy6or5x && updated[core] == 0) {
4437  b43_nphy_update_tx_cal_ladder(dev, core);
4438  updated[core] = true;
4439  }
4440 
4441  tmp = (params[core].ncorr[type] << 8) | 0x66;
4443 
4444  if (type == 1 || type == 3 || type == 4) {
4445  buffer[0] = b43_ntab_read(dev,
4446  B43_NTAB16(15, 69 + core));
4447  diq_start = buffer[0];
4448  buffer[0] = 0;
4449  b43_ntab_write(dev, B43_NTAB16(15, 69 + core),
4450  0);
4451  }
4452 
4454  for (i = 0; i < 2000; i++) {
4455  tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD);
4456  if (tmp & 0xC000)
4457  break;
4458  udelay(10);
4459  }
4460 
4461  b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
4462  buffer);
4463  b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length,
4464  buffer);
4465 
4466  if (type == 1 || type == 3 || type == 4)
4467  buffer[0] = diq_start;
4468  }
4469 
4470  if (mphase)
4471  nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb;
4472 
4473  last = (dev->phy.rev < 3) ? 6 : 7;
4474 
4475  if (!mphase || nphy->mphase_cal_phase_id == last) {
4476  b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer);
4477  b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 4, buffer);
4478  if (dev->phy.rev < 3) {
4479  buffer[0] = 0;
4480  buffer[1] = 0;
4481  buffer[2] = 0;
4482  buffer[3] = 0;
4483  }
4484  b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
4485  buffer);
4486  b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2,
4487  buffer);
4488  b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
4489  buffer);
4490  b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
4491  buffer);
4492  length = 11;
4493  if (dev->phy.rev < 3)
4494  length -= 2;
4495  b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
4496  nphy->txiqlocal_bestc);
4497  nphy->txiqlocal_coeffsvalid = true;
4498  nphy->txiqlocal_chanspec.center_freq =
4499  dev->phy.channel_freq;
4500  nphy->txiqlocal_chanspec.channel_type =
4501  dev->phy.channel_type;
4502  } else {
4503  length = 11;
4504  if (dev->phy.rev < 3)
4505  length -= 2;
4506  b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
4507  nphy->mphase_txcal_bestcoeffs);
4508  }
4509 
4510  b43_nphy_stop_playback(dev);
4512  }
4513 
4514  b43_nphy_tx_cal_phy_cleanup(dev);
4515  b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
4516 
4517  if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last))
4518  b43_nphy_tx_iq_workaround(dev);
4519 
4520  if (dev->phy.rev >= 4)
4521  nphy->hang_avoid = avoid;
4522 
4523  b43_nphy_stay_in_carrier_search(dev, false);
4524 
4525  return error;
4526 }
4527 
4528 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */
4529 static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev)
4530 {
4531  struct b43_phy_n *nphy = dev->phy.n;
4532  u8 i;
4533  u16 buffer[7];
4534  bool equal = true;
4535 
4536  if (!nphy->txiqlocal_coeffsvalid ||
4537  nphy->txiqlocal_chanspec.center_freq != dev->phy.channel_freq ||
4538  nphy->txiqlocal_chanspec.channel_type != dev->phy.channel_type)
4539  return;
4540 
4541  b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
4542  for (i = 0; i < 4; i++) {
4543  if (buffer[i] != nphy->txiqlocal_bestc[i]) {
4544  equal = false;
4545  break;
4546  }
4547  }
4548 
4549  if (!equal) {
4550  b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4,
4551  nphy->txiqlocal_bestc);
4552  for (i = 0; i < 4; i++)
4553  buffer[i] = 0;
4554  b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
4555  buffer);
4556  b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
4557  &nphy->txiqlocal_bestc[5]);
4558  b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
4559  &nphy->txiqlocal_bestc[5]);
4560  }
4561 }
4562 
4563 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */
4564 static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
4565  struct nphy_txgains target, u8 type, bool debug)
4566 {
4567  struct b43_phy_n *nphy = dev->phy.n;
4568  int i, j, index;
4569  u8 rfctl[2];
4570  u8 afectl_core;
4571  u16 tmp[6];
4572  u16 uninitialized_var(cur_hpf1), uninitialized_var(cur_hpf2), cur_lna;
4573  u32 real, imag;
4574  enum ieee80211_band band;
4575 
4576  u8 use;
4577  u16 cur_hpf;
4578  u16 lna[3] = { 3, 3, 1 };
4579  u16 hpf1[3] = { 7, 2, 0 };
4580  u16 hpf2[3] = { 2, 0, 0 };
4581  u32 power[3] = { };
4582  u16 gain_save[2];
4583  u16 cal_gain[2];
4584  struct nphy_iqcal_params cal_params[2];
4585  struct nphy_iq_est est;
4586  int ret = 0;
4587  bool playtone = true;
4588  int desired = 13;
4589 
4590  b43_nphy_stay_in_carrier_search(dev, 1);
4591 
4592  if (dev->phy.rev < 2)
4593  b43_nphy_reapply_tx_cal_coeffs(dev);
4594  b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
4595  for (i = 0; i < 2; i++) {
4596  b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]);
4597  cal_gain[i] = cal_params[i].cal_gain;
4598  }
4599  b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, cal_gain);
4600 
4601  for (i = 0; i < 2; i++) {
4602  if (i == 0) {
4603  rfctl[0] = B43_NPHY_RFCTL_INTC1;
4604  rfctl[1] = B43_NPHY_RFCTL_INTC2;
4605  afectl_core = B43_NPHY_AFECTL_C1;
4606  } else {
4607  rfctl[0] = B43_NPHY_RFCTL_INTC2;
4608  rfctl[1] = B43_NPHY_RFCTL_INTC1;
4609  afectl_core = B43_NPHY_AFECTL_C2;
4610  }
4611 
4612  tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
4613  tmp[2] = b43_phy_read(dev, afectl_core);
4614  tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
4615  tmp[4] = b43_phy_read(dev, rfctl[0]);
4616  tmp[5] = b43_phy_read(dev, rfctl[1]);
4617 
4619  ~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
4620  ((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
4622  (1 - i));
4623  b43_phy_set(dev, afectl_core, 0x0006);
4624  b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006);
4625 
4626  band = b43_current_band(dev->wl);
4627 
4628  if (nphy->rxcalparams & 0xFF000000) {
4629  if (band == IEEE80211_BAND_5GHZ)
4630  b43_phy_write(dev, rfctl[0], 0x140);
4631  else
4632  b43_phy_write(dev, rfctl[0], 0x110);
4633  } else {
4634  if (band == IEEE80211_BAND_5GHZ)
4635  b43_phy_write(dev, rfctl[0], 0x180);
4636  else
4637  b43_phy_write(dev, rfctl[0], 0x120);
4638  }
4639 
4640  if (band == IEEE80211_BAND_5GHZ)
4641  b43_phy_write(dev, rfctl[1], 0x148);
4642  else
4643  b43_phy_write(dev, rfctl[1], 0x114);
4644 
4645  if (nphy->rxcalparams & 0x10000) {
4647  (i + 1));
4649  (2 - i));
4650  }
4651 
4652  for (j = 0; j < 4; j++) {
4653  if (j < 3) {
4654  cur_lna = lna[j];
4655  cur_hpf1 = hpf1[j];
4656  cur_hpf2 = hpf2[j];
4657  } else {
4658  if (power[1] > 10000) {
4659  use = 1;
4660  cur_hpf = cur_hpf1;
4661  index = 2;
4662  } else {
4663  if (power[0] > 10000) {
4664  use = 1;
4665  cur_hpf = cur_hpf1;
4666  index = 1;
4667  } else {
4668  index = 0;
4669  use = 2;
4670  cur_hpf = cur_hpf2;
4671  }
4672  }
4673  cur_lna = lna[index];
4674  cur_hpf1 = hpf1[index];
4675  cur_hpf2 = hpf2[index];
4676  cur_hpf += desired - hweight32(power[index]);
4677  cur_hpf = clamp_val(cur_hpf, 0, 10);
4678  if (use == 1)
4679  cur_hpf1 = cur_hpf;
4680  else
4681  cur_hpf2 = cur_hpf;
4682  }
4683 
4684  tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
4685  (cur_lna << 2));
4686  b43_nphy_rf_control_override(dev, 0x400, tmp[0], 3,
4687  false);
4688  b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
4689  b43_nphy_stop_playback(dev);
4690 
4691  if (playtone) {
4692  ret = b43_nphy_tx_tone(dev, 4000,
4693  (nphy->rxcalparams & 0xFFFF),
4694  false, false);
4695  playtone = false;
4696  } else {
4697  b43_nphy_run_samples(dev, 160, 0xFFFF, 0,
4698  false, false);
4699  }
4700 
4701  if (ret == 0) {
4702  if (j < 3) {
4703  b43_nphy_rx_iq_est(dev, &est, 1024, 32,
4704  false);
4705  if (i == 0) {
4706  real = est.i0_pwr;
4707  imag = est.q0_pwr;
4708  } else {
4709  real = est.i1_pwr;
4710  imag = est.q1_pwr;
4711  }
4712  power[i] = ((real + imag) / 1024) + 1;
4713  } else {
4714  b43_nphy_calc_rx_iq_comp(dev, 1 << i);
4715  }
4716  b43_nphy_stop_playback(dev);
4717  }
4718 
4719  if (ret != 0)
4720  break;
4721  }
4722 
4723  b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC);
4724  b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC);
4725  b43_phy_write(dev, rfctl[1], tmp[5]);
4726  b43_phy_write(dev, rfctl[0], tmp[4]);
4727  b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]);
4728  b43_phy_write(dev, afectl_core, tmp[2]);
4729  b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]);
4730 
4731  if (ret != 0)
4732  break;
4733  }
4734 
4735  b43_nphy_rf_control_override(dev, 0x400, 0, 3, true);
4736  b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
4737  b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
4738 
4739  b43_nphy_stay_in_carrier_search(dev, 0);
4740 
4741  return ret;
4742 }
4743 
4744 static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev,
4745  struct nphy_txgains target, u8 type, bool debug)
4746 {
4747  return -1;
4748 }
4749 
4750 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */
4751 static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
4752  struct nphy_txgains target, u8 type, bool debug)
4753 {
4754  if (dev->phy.rev >= 3)
4755  return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug);
4756  else
4757  return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug);
4758 }
4759 
4760 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */
4761 static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
4762 {
4763  struct b43_phy *phy = &dev->phy;
4764  struct b43_phy_n *nphy = phy->n;
4765  /* u16 buf[16]; it's rev3+ */
4766 
4767  nphy->phyrxchain = mask;
4768 
4769  if (0 /* FIXME clk */)
4770  return;
4771 
4772  b43_mac_suspend(dev);
4773 
4774  if (nphy->hang_avoid)
4775  b43_nphy_stay_in_carrier_search(dev, true);
4776 
4778  (mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT);
4779 
4780  if ((mask & 0x3) != 0x3) {
4782  if (dev->phy.rev >= 3) {
4783  /* TODO */
4784  }
4785  } else {
4787  if (dev->phy.rev >= 3) {
4788  /* TODO */
4789  }
4790  }
4791 
4792  b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
4793 
4794  if (nphy->hang_avoid)
4795  b43_nphy_stay_in_carrier_search(dev, false);
4796 
4797  b43_mac_enable(dev);
4798 }
4799 
4800 /**************************************************
4801  * N-PHY init
4802  **************************************************/
4803 
4804 /*
4805  * Upload the N-PHY tables.
4806  * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
4807  */
4808 static void b43_nphy_tables_init(struct b43_wldev *dev)
4809 {
4810  if (dev->phy.rev < 3)
4812  else
4814 }
4815 
4816 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
4817 static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble)
4818 {
4819  u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG);
4820 
4821  mimocfg |= B43_NPHY_MIMOCFG_AUTO;
4822  if (preamble == 1)
4823  mimocfg |= B43_NPHY_MIMOCFG_GFMIX;
4824  else
4825  mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX;
4826 
4827  b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg);
4828 }
4829 
4830 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */
4831 static void b43_nphy_bphy_init(struct b43_wldev *dev)
4832 {
4833  unsigned int i;
4834  u16 val;
4835 
4836  val = 0x1E1F;
4837  for (i = 0; i < 16; i++) {
4838  b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
4839  val -= 0x202;
4840  }
4841  val = 0x3E3F;
4842  for (i = 0; i < 16; i++) {
4843  b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val);
4844  val -= 0x202;
4845  }
4846  b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
4847 }
4848 
4849 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
4850 static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
4851 {
4852  if (dev->phy.rev >= 3) {
4853  if (!init)
4854  return;
4855  if (0 /* FIXME */) {
4856  b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211);
4857  b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222);
4858  b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144);
4859  b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188);
4860  }
4861  } else {
4864 
4865  switch (dev->dev->bus_type) {
4866 #ifdef CONFIG_B43_BCMA
4867  case B43_BUS_BCMA:
4868  bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc,
4869  0xFC00, 0xFC00);
4870  break;
4871 #endif
4872 #ifdef CONFIG_B43_SSB
4873  case B43_BUS_SSB:
4874  ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco,
4875  0xFC00, 0xFC00);
4876  break;
4877 #endif
4878  }
4879 
4880  b43_maskset32(dev, B43_MMIO_MACCTL, ~B43_MACCTL_GPOUTSMSK, 0);
4881  b43_maskset16(dev, B43_MMIO_GPIO_MASK, ~0, 0xFC00);
4882  b43_maskset16(dev, B43_MMIO_GPIO_CONTROL, (~0xFC00 & 0xFFFF),
4883  0);
4884 
4885  if (init) {
4890  }
4891  }
4892 }
4893 
4894 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */
4895 int b43_phy_initn(struct b43_wldev *dev)
4896 {
4897  struct ssb_sprom *sprom = dev->dev->bus_sprom;
4898  struct b43_phy *phy = &dev->phy;
4899  struct b43_phy_n *nphy = phy->n;
4900  u8 tx_pwr_state;
4901  struct nphy_txgains target;
4902  u16 tmp;
4903  enum ieee80211_band tmp2;
4904  bool do_rssi_cal;
4905 
4906  u16 clip[2];
4907  bool do_cal = false;
4908 
4909  if ((dev->phy.rev >= 3) &&
4910  (sprom->boardflags_lo & B43_BFL_EXTLNA) &&
4911  (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
4912  switch (dev->dev->bus_type) {
4913 #ifdef CONFIG_B43_BCMA
4914  case B43_BUS_BCMA:
4915  bcma_cc_set32(&dev->dev->bdev->bus->drv_cc,
4916  BCMA_CC_CHIPCTL, 0x40);
4917  break;
4918 #endif
4919 #ifdef CONFIG_B43_SSB
4920  case B43_BUS_SSB:
4921  chipco_set32(&dev->dev->sdev->bus->chipco,
4922  SSB_CHIPCO_CHIPCTL, 0x40);
4923  break;
4924 #endif
4925  }
4926  }
4927  nphy->deaf_count = 0;
4928  b43_nphy_tables_init(dev);
4929  nphy->crsminpwr_adjusted = false;
4930  nphy->noisevars_adjusted = false;
4931 
4932  /* Clear all overrides */
4933  if (dev->phy.rev >= 3) {
4938  } else {
4940  }
4943  if (dev->phy.rev < 6) {
4946  }
4950  if (dev->phy.rev >= 3)
4953 
4954  if (dev->phy.rev <= 2) {
4955  tmp = (dev->phy.rev == 2) ? 0x3B : 0x40;
4959  }
4962 
4963  if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
4964  (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
4965  dev->dev->board_type == 0x8B))
4966  b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
4967  else
4968  b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
4972 
4973  b43_nphy_update_mimo_config(dev, nphy->preamble_override);
4974  b43_nphy_update_txrx_chain(dev);
4975 
4976  if (phy->rev < 2) {
4977  b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);
4978  b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4);
4979  }
4980 
4981  tmp2 = b43_current_band(dev->wl);
4982  if (b43_nphy_ipa(dev)) {
4983  b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
4985  nphy->papd_epsilon_offset[0] << 7);
4986  b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1);
4988  nphy->papd_epsilon_offset[1] << 7);
4989  b43_nphy_int_pa_set_tx_dig_filters(dev);
4990  } else if (phy->rev >= 5) {
4991  b43_nphy_ext_pa_set_tx_dig_filters(dev);
4992  }
4993 
4994  b43_nphy_workarounds(dev);
4995 
4996  /* Reset CCA, in init code it differs a little from standard way */
4997  b43_phy_force_clock(dev, 1);
4998  tmp = b43_phy_read(dev, B43_NPHY_BBCFG);
5001  b43_phy_force_clock(dev, 0);
5002 
5003  b43_mac_phy_clock_set(dev, true);
5004 
5005  b43_nphy_pa_override(dev, false);
5006  b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
5007  b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
5008  b43_nphy_pa_override(dev, true);
5009 
5010  b43_nphy_classifier(dev, 0, 0);
5011  b43_nphy_read_clip_detection(dev, clip);
5012  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
5013  b43_nphy_bphy_init(dev);
5014 
5015  tx_pwr_state = nphy->txpwrctrl;
5016  b43_nphy_tx_power_ctrl(dev, false);
5017  b43_nphy_tx_power_fix(dev);
5018  b43_nphy_tx_power_ctl_idle_tssi(dev);
5019  b43_nphy_tx_power_ctl_setup(dev);
5020  b43_nphy_tx_gain_table_upload(dev);
5021 
5022  if (nphy->phyrxchain != 3)
5023  b43_nphy_set_rx_core_state(dev, nphy->phyrxchain);
5024  if (nphy->mphase_cal_phase_id > 0)
5025  ;/* TODO PHY Periodic Calibration Multi-Phase Restart */
5026 
5027  do_rssi_cal = false;
5028  if (phy->rev >= 3) {
5029  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
5030  do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq;
5031  else
5032  do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq;
5033 
5034  if (do_rssi_cal)
5035  b43_nphy_rssi_cal(dev);
5036  else
5037  b43_nphy_restore_rssi_cal(dev);
5038  } else {
5039  b43_nphy_rssi_cal(dev);
5040  }
5041 
5042  if (!((nphy->measure_hold & 0x6) != 0)) {
5043  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
5044  do_cal = !nphy->iqcal_chanspec_2G.center_freq;
5045  else
5046  do_cal = !nphy->iqcal_chanspec_5G.center_freq;
5047 
5048  if (nphy->mute)
5049  do_cal = false;
5050 
5051  if (do_cal) {
5052  target = b43_nphy_get_tx_gains(dev);
5053 
5054  if (nphy->antsel_type == 2)
5055  b43_nphy_superswitch_init(dev, true);
5056  if (nphy->perical != 2) {
5057  b43_nphy_rssi_cal(dev);
5058  if (phy->rev >= 3) {
5059  nphy->cal_orig_pwr_idx[0] =
5060  nphy->txpwrindex[0].index_internal;
5061  nphy->cal_orig_pwr_idx[1] =
5062  nphy->txpwrindex[1].index_internal;
5063  /* TODO N PHY Pre Calibrate TX Gain */
5064  target = b43_nphy_get_tx_gains(dev);
5065  }
5066  if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false))
5067  if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
5068  b43_nphy_save_cal(dev);
5069  } else if (nphy->mphase_cal_phase_id == 0)
5070  ;/* N PHY Periodic Calibration with arg 3 */
5071  } else {
5072  b43_nphy_restore_cal(dev);
5073  }
5074  }
5075 
5076  b43_nphy_tx_pwr_ctrl_coef_setup(dev);
5077  b43_nphy_tx_power_ctrl(dev, tx_pwr_state);
5079  b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);
5080  if (phy->rev >= 3 && phy->rev <= 6)
5082  b43_nphy_tx_lp_fbw(dev);
5083  if (phy->rev >= 3)
5084  b43_nphy_spur_workaround(dev);
5085 
5086  return 0;
5087 }
5088 
5089 /**************************************************
5090  * Channel switching ops.
5091  **************************************************/
5092 
5093 static void b43_chantab_phy_upload(struct b43_wldev *dev,
5094  const struct b43_phy_n_sfo_cfg *e)
5095 {
5102 }
5103 
5104 /* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */
5105 static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)
5106 {
5107  struct bcma_drv_cc __maybe_unused *cc;
5108  u32 __maybe_unused pmu_ctl;
5109 
5110  switch (dev->dev->bus_type) {
5111 #ifdef CONFIG_B43_BCMA
5112  case B43_BUS_BCMA:
5113  cc = &dev->dev->bdev->bus->drv_cc;
5114  if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
5115  if (avoid) {
5116  bcma_chipco_pll_write(cc, 0x0, 0x11500010);
5117  bcma_chipco_pll_write(cc, 0x1, 0x000C0C06);
5118  bcma_chipco_pll_write(cc, 0x2, 0x0F600a08);
5119  bcma_chipco_pll_write(cc, 0x3, 0x00000000);
5120  bcma_chipco_pll_write(cc, 0x4, 0x2001E920);
5121  bcma_chipco_pll_write(cc, 0x5, 0x88888815);
5122  } else {
5123  bcma_chipco_pll_write(cc, 0x0, 0x11100010);
5124  bcma_chipco_pll_write(cc, 0x1, 0x000c0c06);
5125  bcma_chipco_pll_write(cc, 0x2, 0x03000a08);
5126  bcma_chipco_pll_write(cc, 0x3, 0x00000000);
5127  bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
5128  bcma_chipco_pll_write(cc, 0x5, 0x88888815);
5129  }
5130  pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD;
5131  } else if (dev->dev->chip_id == 0x4716) {
5132  if (avoid) {
5133  bcma_chipco_pll_write(cc, 0x0, 0x11500060);
5134  bcma_chipco_pll_write(cc, 0x1, 0x080C0C06);
5135  bcma_chipco_pll_write(cc, 0x2, 0x0F600000);
5136  bcma_chipco_pll_write(cc, 0x3, 0x00000000);
5137  bcma_chipco_pll_write(cc, 0x4, 0x2001E924);
5138  bcma_chipco_pll_write(cc, 0x5, 0x88888815);
5139  } else {
5140  bcma_chipco_pll_write(cc, 0x0, 0x11100060);
5141  bcma_chipco_pll_write(cc, 0x1, 0x080c0c06);
5142  bcma_chipco_pll_write(cc, 0x2, 0x03000000);
5143  bcma_chipco_pll_write(cc, 0x3, 0x00000000);
5144  bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
5145  bcma_chipco_pll_write(cc, 0x5, 0x88888815);
5146  }
5147  pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD |
5149  } else if (dev->dev->chip_id == 0x4322 ||
5150  dev->dev->chip_id == 0x4340 ||
5151  dev->dev->chip_id == 0x4341) {
5152  bcma_chipco_pll_write(cc, 0x0, 0x11100070);
5153  bcma_chipco_pll_write(cc, 0x1, 0x1014140a);
5154  bcma_chipco_pll_write(cc, 0x5, 0x88888854);
5155  if (avoid)
5156  bcma_chipco_pll_write(cc, 0x2, 0x05201828);
5157  else
5158  bcma_chipco_pll_write(cc, 0x2, 0x05001828);
5159  pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD;
5160  } else {
5161  return;
5162  }
5163  bcma_cc_set32(cc, BCMA_CC_PMU_CTL, pmu_ctl);
5164  break;
5165 #endif
5166 #ifdef CONFIG_B43_SSB
5167  case B43_BUS_SSB:
5168  /* FIXME */
5169  break;
5170 #endif
5171  }
5172 }
5173 
5174 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
5175 static void b43_nphy_channel_setup(struct b43_wldev *dev,
5176  const struct b43_phy_n_sfo_cfg *e,
5177  struct ieee80211_channel *new_channel)
5178 {
5179  struct b43_phy *phy = &dev->phy;
5180  struct b43_phy_n *nphy = dev->phy.n;
5181  int ch = new_channel->hw_value;
5182 
5183  u16 old_band_5ghz;
5184  u32 tmp32;
5185 
5186  old_band_5ghz =
5188  if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
5189  tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
5190  b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
5191  b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000);
5192  b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
5194  } else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
5196  tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
5197  b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
5198  b43_phy_mask(dev, B43_PHY_B_BBCFG, 0x3FFF);
5199  b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
5200  }
5201 
5202  b43_chantab_phy_upload(dev, e);
5203 
5204  if (new_channel->hw_value == 14) {
5205  b43_nphy_classifier(dev, 2, 0);
5206  b43_phy_set(dev, B43_PHY_B_TEST, 0x0800);
5207  } else {
5208  b43_nphy_classifier(dev, 2, 2);
5209  if (new_channel->band == IEEE80211_BAND_2GHZ)
5210  b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840);
5211  }
5212 
5213  if (!nphy->txpwrctrl)
5214  b43_nphy_tx_power_fix(dev);
5215 
5216  if (dev->phy.rev < 3)
5217  b43_nphy_adjust_lna_gain_table(dev);
5218 
5219  b43_nphy_tx_lp_fbw(dev);
5220 
5221  if (dev->phy.rev >= 3 &&
5222  dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) {
5223  bool avoid = false;
5224  if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) {
5225  avoid = true;
5226  } else if (!b43_channel_type_is_40mhz(phy->channel_type)) {
5227  if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
5228  avoid = true;
5229  } else { /* 40MHz */
5230  if (nphy->aband_spurwar_en &&
5231  (ch == 38 || ch == 102 || ch == 118))
5232  avoid = dev->dev->chip_id == 0x4716;
5233  }
5234 
5235  b43_nphy_pmu_spur_avoid(dev, avoid);
5236 
5237  if (dev->dev->chip_id == 43222 || dev->dev->chip_id == 43224 ||
5238  dev->dev->chip_id == 43225) {
5239  b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW,
5240  avoid ? 0x5341 : 0x8889);
5241  b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
5242  }
5243 
5244  if (dev->phy.rev == 3 || dev->phy.rev == 4)
5245  ; /* TODO: reset PLL */
5246 
5247  if (avoid)
5249  else
5251  ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
5252 
5253  b43_nphy_reset_cca(dev);
5254 
5255  /* wl sets useless phy_isspuravoid here */
5256  }
5257 
5258  b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830);
5259 
5260  if (phy->rev >= 3)
5261  b43_nphy_spur_workaround(dev);
5262 }
5263 
5264 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */
5265 static int b43_nphy_set_channel(struct b43_wldev *dev,
5266  struct ieee80211_channel *channel,
5268 {
5269  struct b43_phy *phy = &dev->phy;
5270 
5271  const struct b43_nphy_channeltab_entry_rev2 *tabent_r2 = NULL;
5272  const struct b43_nphy_channeltab_entry_rev3 *tabent_r3 = NULL;
5273 
5274  u8 tmp;
5275 
5276  if (dev->phy.rev >= 3) {
5277  tabent_r3 = b43_nphy_get_chantabent_rev3(dev,
5278  channel->center_freq);
5279  if (!tabent_r3)
5280  return -ESRCH;
5281  } else {
5282  tabent_r2 = b43_nphy_get_chantabent_rev2(dev,
5283  channel->hw_value);
5284  if (!tabent_r2)
5285  return -ESRCH;
5286  }
5287 
5288  /* Channel is set later in common code, but we need to set it on our
5289  own to let this function's subcalls work properly. */
5290  phy->channel = channel->hw_value;
5291  phy->channel_freq = channel->center_freq;
5292 
5294  b43_channel_type_is_40mhz(channel_type))
5295  ; /* TODO: BMAC BW Set (channel_type) */
5296 
5297  if (channel_type == NL80211_CHAN_HT40PLUS)
5300  else if (channel_type == NL80211_CHAN_HT40MINUS)
5303 
5304  if (dev->phy.rev >= 3) {
5305  tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0;
5306  b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
5307  b43_radio_2056_setup(dev, tabent_r3);
5308  b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel);
5309  } else {
5310  tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 0x0020 : 0x0050;
5311  b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp);
5312  b43_radio_2055_setup(dev, tabent_r2);
5313  b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel);
5314  }
5315 
5316  return 0;
5317 }
5318 
5319 /**************************************************
5320  * Basic PHY ops.
5321  **************************************************/
5322 
5323 static int b43_nphy_op_allocate(struct b43_wldev *dev)
5324 {
5325  struct b43_phy_n *nphy;
5326 
5327  nphy = kzalloc(sizeof(*nphy), GFP_KERNEL);
5328  if (!nphy)
5329  return -ENOMEM;
5330  dev->phy.n = nphy;
5331 
5332  return 0;
5333 }
5334 
5335 static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
5336 {
5337  struct b43_phy *phy = &dev->phy;
5338  struct b43_phy_n *nphy = phy->n;
5339  struct ssb_sprom *sprom = dev->dev->bus_sprom;
5340 
5341  memset(nphy, 0, sizeof(*nphy));
5342 
5343  nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4);
5344  nphy->spur_avoid = (phy->rev >= 3) ?
5346  nphy->init_por = true;
5347  nphy->gain_boost = true; /* this way we follow wl, assume it is true */
5348  nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
5349  nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
5350  nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */
5351  /* 128 can mean disabled-by-default state of TX pwr ctl. Max value is
5352  * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */
5353  nphy->tx_pwr_idx[0] = 128;
5354  nphy->tx_pwr_idx[1] = 128;
5355 
5356  /* Hardware TX power control and 5GHz power gain */
5357  nphy->txpwrctrl = false;
5358  nphy->pwg_gain_5ghz = false;
5359  if (dev->phy.rev >= 3 ||
5360  (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
5361  (dev->dev->core_rev == 11 || dev->dev->core_rev == 12))) {
5362  nphy->txpwrctrl = true;
5363  nphy->pwg_gain_5ghz = true;
5364  } else if (sprom->revision >= 4) {
5365  if (dev->phy.rev >= 2 &&
5367  nphy->txpwrctrl = true;
5368 #ifdef CONFIG_B43_SSB
5369  if (dev->dev->bus_type == B43_BUS_SSB &&
5370  dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) {
5371  struct pci_dev *pdev =
5372  dev->dev->sdev->bus->host_pci;
5373  if (pdev->device == 0x4328 ||
5374  pdev->device == 0x432a)
5375  nphy->pwg_gain_5ghz = true;
5376  }
5377 #endif
5378  } else if (sprom->boardflags2_lo & B43_BFL2_5G_PWRGAIN) {
5379  nphy->pwg_gain_5ghz = true;
5380  }
5381  }
5382 
5383  if (dev->phy.rev >= 3) {
5384  nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2;
5385  nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2;
5386  }
5387 
5388  nphy->init_por = true;
5389 }
5390 
5391 static void b43_nphy_op_free(struct b43_wldev *dev)
5392 {
5393  struct b43_phy *phy = &dev->phy;
5394  struct b43_phy_n *nphy = phy->n;
5395 
5396  kfree(nphy);
5397  phy->n = NULL;
5398 }
5399 
5400 static int b43_nphy_op_init(struct b43_wldev *dev)
5401 {
5402  return b43_phy_initn(dev);
5403 }
5404 
5405 static inline void check_phyreg(struct b43_wldev *dev, u16 offset)
5406 {
5407 #if B43_DEBUG
5408  if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
5409  /* OFDM registers are onnly available on A/G-PHYs */
5410  b43err(dev->wl, "Invalid OFDM PHY access at "
5411  "0x%04X on N-PHY\n", offset);
5412  dump_stack();
5413  }
5414  if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
5415  /* Ext-G registers are only available on G-PHYs */
5416  b43err(dev->wl, "Invalid EXT-G PHY access at "
5417  "0x%04X on N-PHY\n", offset);
5418  dump_stack();
5419  }
5420 #endif /* B43_DEBUG */
5421 }
5422 
5423 static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg)
5424 {
5425  check_phyreg(dev, reg);
5426  b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
5427  return b43_read16(dev, B43_MMIO_PHY_DATA);
5428 }
5429 
5430 static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
5431 {
5432  check_phyreg(dev, reg);
5433  b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
5434  b43_write16(dev, B43_MMIO_PHY_DATA, value);
5435 }
5436 
5437 static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
5438  u16 set)
5439 {
5440  check_phyreg(dev, reg);
5441  b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
5442  b43_maskset16(dev, B43_MMIO_PHY_DATA, mask, set);
5443 }
5444 
5445 static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
5446 {
5447  /* Register 1 is a 32-bit register. */
5448  B43_WARN_ON(reg == 1);
5449  /* N-PHY needs 0x100 for read access */
5450  reg |= 0x100;
5451 
5452  b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
5453  return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
5454 }
5455 
5456 static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
5457 {
5458  /* Register 1 is a 32-bit register. */
5459  B43_WARN_ON(reg == 1);
5460 
5461  b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
5462  b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
5463 }
5464 
5465 /* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
5466 static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
5467  bool blocked)
5468 {
5469  if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
5470  b43err(dev->wl, "MAC not suspended\n");
5471 
5472  if (blocked) {
5475  if (dev->phy.rev >= 7) {
5476  /* TODO */
5477  } else if (dev->phy.rev >= 3) {
5478  b43_radio_mask(dev, 0x09, ~0x2);
5479 
5480  b43_radio_write(dev, 0x204D, 0);
5481  b43_radio_write(dev, 0x2053, 0);
5482  b43_radio_write(dev, 0x2058, 0);
5483  b43_radio_write(dev, 0x205E, 0);
5484  b43_radio_mask(dev, 0x2062, ~0xF0);
5485  b43_radio_write(dev, 0x2064, 0);
5486 
5487  b43_radio_write(dev, 0x304D, 0);
5488  b43_radio_write(dev, 0x3053, 0);
5489  b43_radio_write(dev, 0x3058, 0);
5490  b43_radio_write(dev, 0x305E, 0);
5491  b43_radio_mask(dev, 0x3062, ~0xF0);
5492  b43_radio_write(dev, 0x3064, 0);
5493  }
5494  } else {
5495  if (dev->phy.rev >= 7) {
5496  b43_radio_2057_init(dev);
5497  b43_switch_channel(dev, dev->phy.channel);
5498  } else if (dev->phy.rev >= 3) {
5499  b43_radio_init2056(dev);
5500  b43_switch_channel(dev, dev->phy.channel);
5501  } else {
5502  b43_radio_init2055(dev);
5503  }
5504  }
5505 }
5506 
5507 /* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
5508 static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
5509 {
5510  u16 override = on ? 0x0 : 0x7FFF;
5511  u16 core = on ? 0xD : 0x00FD;
5512 
5513  if (dev->phy.rev >= 3) {
5514  if (on) {
5515  b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
5516  b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
5517  b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
5518  b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
5519  } else {
5520  b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
5521  b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
5522  b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
5523  b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
5524  }
5525  } else {
5526  b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
5527  }
5528 }
5529 
5530 static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
5531  unsigned int new_channel)
5532 {
5533  struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
5534  enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
5535 
5536  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
5537  if ((new_channel < 1) || (new_channel > 14))
5538  return -EINVAL;
5539  } else {
5540  if (new_channel > 200)
5541  return -EINVAL;
5542  }
5543 
5544  return b43_nphy_set_channel(dev, channel, channel_type);
5545 }
5546 
5547 static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
5548 {
5549  if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
5550  return 1;
5551  return 36;
5552 }
5553 
5555  .allocate = b43_nphy_op_allocate,
5556  .free = b43_nphy_op_free,
5557  .prepare_structs = b43_nphy_op_prepare_structs,
5558  .init = b43_nphy_op_init,
5559  .phy_read = b43_nphy_op_read,
5560  .phy_write = b43_nphy_op_write,
5561  .phy_maskset = b43_nphy_op_maskset,
5562  .radio_read = b43_nphy_op_radio_read,
5563  .radio_write = b43_nphy_op_radio_write,
5564  .software_rfkill = b43_nphy_op_software_rfkill,
5565  .switch_analog = b43_nphy_op_switch_analog,
5566  .switch_channel = b43_nphy_op_switch_channel,
5567  .get_default_chan = b43_nphy_op_get_default_chan,
5568  .recalc_txpower = b43_nphy_op_recalc_txpower,
5569  .adjust_txpower = b43_nphy_op_adjust_txpower,
5570 };