aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/b43/phy_n.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/net/wireless/b43/phy_n.c')
-rw-r--r--drivers/net/wireless/b43/phy_n.c1795
1 files changed, 1709 insertions, 86 deletions
diff --git a/drivers/net/wireless/b43/phy_n.c b/drivers/net/wireless/b43/phy_n.c
index 992318a78077..4a817e3da163 100644
--- a/drivers/net/wireless/b43/phy_n.c
+++ b/drivers/net/wireless/b43/phy_n.c
@@ -28,7 +28,32 @@
28#include "b43.h" 28#include "b43.h"
29#include "phy_n.h" 29#include "phy_n.h"
30#include "tables_nphy.h" 30#include "tables_nphy.h"
31#include "main.h"
31 32
33struct nphy_txgains {
34 u16 txgm[2];
35 u16 pga[2];
36 u16 pad[2];
37 u16 ipa[2];
38};
39
40struct nphy_iqcal_params {
41 u16 txgm;
42 u16 pga;
43 u16 pad;
44 u16 ipa;
45 u16 cal_gain;
46 u16 ncorr[5];
47};
48
49struct nphy_iq_est {
50 s32 iq0_prod;
51 u32 i0_pwr;
52 u32 q0_pwr;
53 s32 iq1_prod;
54 u32 i1_pwr;
55 u32 q1_pwr;
56};
32 57
33void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna) 58void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
34{//TODO 59{//TODO
@@ -197,44 +222,16 @@ void b43_nphy_radio_turn_off(struct b43_wldev *dev)
197 ~B43_NPHY_RFCTL_CMD_EN); 222 ~B43_NPHY_RFCTL_CMD_EN);
198} 223}
199 224
200#define ntab_upload(dev, offset, data) do { \ 225/*
201 unsigned int i; \ 226 * Upload the N-PHY tables.
202 for (i = 0; i < (offset##_SIZE); i++) \ 227 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
203 b43_ntab_write(dev, (offset) + i, (data)[i]); \ 228 */
204 } while (0)
205
206/* Upload the N-PHY tables. */
207static void b43_nphy_tables_init(struct b43_wldev *dev) 229static void b43_nphy_tables_init(struct b43_wldev *dev)
208{ 230{
209 /* Static tables */ 231 if (dev->phy.rev < 3)
210 ntab_upload(dev, B43_NTAB_FRAMESTRUCT, b43_ntab_framestruct); 232 b43_nphy_rev0_1_2_tables_init(dev);
211 ntab_upload(dev, B43_NTAB_FRAMELT, b43_ntab_framelookup); 233 else
212 ntab_upload(dev, B43_NTAB_TMAP, b43_ntab_tmap); 234 b43_nphy_rev3plus_tables_init(dev);
213 ntab_upload(dev, B43_NTAB_TDTRN, b43_ntab_tdtrn);
214 ntab_upload(dev, B43_NTAB_INTLEVEL, b43_ntab_intlevel);
215 ntab_upload(dev, B43_NTAB_PILOT, b43_ntab_pilot);
216 ntab_upload(dev, B43_NTAB_PILOTLT, b43_ntab_pilotlt);
217 ntab_upload(dev, B43_NTAB_TDI20A0, b43_ntab_tdi20a0);
218 ntab_upload(dev, B43_NTAB_TDI20A1, b43_ntab_tdi20a1);
219 ntab_upload(dev, B43_NTAB_TDI40A0, b43_ntab_tdi40a0);
220 ntab_upload(dev, B43_NTAB_TDI40A1, b43_ntab_tdi40a1);
221 ntab_upload(dev, B43_NTAB_BDI, b43_ntab_bdi);
222 ntab_upload(dev, B43_NTAB_CHANEST, b43_ntab_channelest);
223 ntab_upload(dev, B43_NTAB_MCS, b43_ntab_mcs);
224
225 /* Volatile tables */
226 ntab_upload(dev, B43_NTAB_NOISEVAR10, b43_ntab_noisevar10);
227 ntab_upload(dev, B43_NTAB_NOISEVAR11, b43_ntab_noisevar11);
228 ntab_upload(dev, B43_NTAB_C0_ESTPLT, b43_ntab_estimatepowerlt0);
229 ntab_upload(dev, B43_NTAB_C1_ESTPLT, b43_ntab_estimatepowerlt1);
230 ntab_upload(dev, B43_NTAB_C0_ADJPLT, b43_ntab_adjustpower0);
231 ntab_upload(dev, B43_NTAB_C1_ADJPLT, b43_ntab_adjustpower1);
232 ntab_upload(dev, B43_NTAB_C0_GAINCTL, b43_ntab_gainctl0);
233 ntab_upload(dev, B43_NTAB_C1_GAINCTL, b43_ntab_gainctl1);
234 ntab_upload(dev, B43_NTAB_C0_IQLT, b43_ntab_iqlt0);
235 ntab_upload(dev, B43_NTAB_C1_IQLT, b43_ntab_iqlt1);
236 ntab_upload(dev, B43_NTAB_C0_LOFEEDTH, b43_ntab_loftlt0);
237 ntab_upload(dev, B43_NTAB_C1_LOFEEDTH, b43_ntab_loftlt1);
238} 235}
239 236
240static void b43_nphy_workarounds(struct b43_wldev *dev) 237static void b43_nphy_workarounds(struct b43_wldev *dev)
@@ -341,18 +338,386 @@ static void b43_nphy_workarounds(struct b43_wldev *dev)
341 b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20); 338 b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
342} 339}
343 340
341/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
342static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
343{
344 struct b43_phy_n *nphy = dev->phy.n;
345 enum ieee80211_band band;
346 u16 tmp;
347
348 if (!enable) {
349 nphy->rfctrl_intc1_save = b43_phy_read(dev,
350 B43_NPHY_RFCTL_INTC1);
351 nphy->rfctrl_intc2_save = b43_phy_read(dev,
352 B43_NPHY_RFCTL_INTC2);
353 band = b43_current_band(dev->wl);
354 if (dev->phy.rev >= 3) {
355 if (band == IEEE80211_BAND_5GHZ)
356 tmp = 0x600;
357 else
358 tmp = 0x480;
359 } else {
360 if (band == IEEE80211_BAND_5GHZ)
361 tmp = 0x180;
362 else
363 tmp = 0x120;
364 }
365 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
366 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
367 } else {
368 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1,
369 nphy->rfctrl_intc1_save);
370 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2,
371 nphy->rfctrl_intc2_save);
372 }
373}
374
375/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
376static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
377{
378 struct b43_phy_n *nphy = dev->phy.n;
379 u16 tmp;
380 enum ieee80211_band band = b43_current_band(dev->wl);
381 bool ipa = (nphy->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
382 (nphy->ipa5g_on && band == IEEE80211_BAND_5GHZ);
383
384 if (dev->phy.rev >= 3) {
385 if (ipa) {
386 tmp = 4;
387 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
388 (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
389 }
390
391 tmp = 1;
392 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2,
393 (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
394 }
395}
396
397/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
398static void b43_nphy_bmac_clock_fgc(struct b43_wldev *dev, bool force)
399{
400 u32 tmslow;
401
402 if (dev->phy.type != B43_PHYTYPE_N)
403 return;
404
405 tmslow = ssb_read32(dev->dev, SSB_TMSLOW);
406 if (force)
407 tmslow |= SSB_TMSLOW_FGC;
408 else
409 tmslow &= ~SSB_TMSLOW_FGC;
410 ssb_write32(dev->dev, SSB_TMSLOW, tmslow);
411}
412
413/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
344static void b43_nphy_reset_cca(struct b43_wldev *dev) 414static void b43_nphy_reset_cca(struct b43_wldev *dev)
345{ 415{
346 u16 bbcfg; 416 u16 bbcfg;
347 417
348 ssb_write32(dev->dev, SSB_TMSLOW, 418 b43_nphy_bmac_clock_fgc(dev, 1);
349 ssb_read32(dev->dev, SSB_TMSLOW) | SSB_TMSLOW_FGC);
350 bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG); 419 bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
351 b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTCCA); 420 b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
352 b43_phy_write(dev, B43_NPHY_BBCFG, 421 udelay(1);
353 bbcfg & ~B43_NPHY_BBCFG_RSTCCA); 422 b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
354 ssb_write32(dev->dev, SSB_TMSLOW, 423 b43_nphy_bmac_clock_fgc(dev, 0);
355 ssb_read32(dev->dev, SSB_TMSLOW) & ~SSB_TMSLOW_FGC); 424 /* TODO: N PHY Force RF Seq with argument 2 */
425}
426
427/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
428static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est,
429 u16 samps, u8 time, bool wait)
430{
431 int i;
432 u16 tmp;
433
434 b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps);
435 b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time);
436 if (wait)
437 b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE);
438 else
439 b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE);
440
441 b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START);
442
443 for (i = 1000; i; i--) {
444 tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD);
445 if (!(tmp & B43_NPHY_IQEST_CMD_START)) {
446 est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) |
447 b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0);
448 est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) |
449 b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0);
450 est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) |
451 b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0);
452
453 est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) |
454 b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1);
455 est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) |
456 b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1);
457 est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) |
458 b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1);
459 return;
460 }
461 udelay(10);
462 }
463 memset(est, 0, sizeof(*est));
464}
465
466/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */
467static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write,
468 struct b43_phy_n_iq_comp *pcomp)
469{
470 if (write) {
471 b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0);
472 b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0);
473 b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1);
474 b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1);
475 } else {
476 pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0);
477 pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0);
478 pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1);
479 pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1);
480 }
481}
482
483/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
484static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
485{
486 int i;
487 s32 iq;
488 u32 ii;
489 u32 qq;
490 int iq_nbits, qq_nbits;
491 int arsh, brsh;
492 u16 tmp, a, b;
493
494 struct nphy_iq_est est;
495 struct b43_phy_n_iq_comp old;
496 struct b43_phy_n_iq_comp new = { };
497 bool error = false;
498
499 if (mask == 0)
500 return;
501
502 b43_nphy_rx_iq_coeffs(dev, false, &old);
503 b43_nphy_rx_iq_coeffs(dev, true, &new);
504 b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false);
505 new = old;
506
507 for (i = 0; i < 2; i++) {
508 if (i == 0 && (mask & 1)) {
509 iq = est.iq0_prod;
510 ii = est.i0_pwr;
511 qq = est.q0_pwr;
512 } else if (i == 1 && (mask & 2)) {
513 iq = est.iq1_prod;
514 ii = est.i1_pwr;
515 qq = est.q1_pwr;
516 } else {
517 B43_WARN_ON(1);
518 continue;
519 }
520
521 if (ii + qq < 2) {
522 error = true;
523 break;
524 }
525
526 iq_nbits = fls(abs(iq));
527 qq_nbits = fls(qq);
528
529 arsh = iq_nbits - 20;
530 if (arsh >= 0) {
531 a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
532 tmp = ii >> arsh;
533 } else {
534 a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
535 tmp = ii << -arsh;
536 }
537 if (tmp == 0) {
538 error = true;
539 break;
540 }
541 a /= tmp;
542
543 brsh = qq_nbits - 11;
544 if (brsh >= 0) {
545 b = (qq << (31 - qq_nbits));
546 tmp = ii >> brsh;
547 } else {
548 b = (qq << (31 - qq_nbits));
549 tmp = ii << -brsh;
550 }
551 if (tmp == 0) {
552 error = true;
553 break;
554 }
555 b = int_sqrt(b / tmp - a * a) - (1 << 10);
556
557 if (i == 0 && (mask & 0x1)) {
558 if (dev->phy.rev >= 3) {
559 new.a0 = a & 0x3FF;
560 new.b0 = b & 0x3FF;
561 } else {
562 new.a0 = b & 0x3FF;
563 new.b0 = a & 0x3FF;
564 }
565 } else if (i == 1 && (mask & 0x2)) {
566 if (dev->phy.rev >= 3) {
567 new.a1 = a & 0x3FF;
568 new.b1 = b & 0x3FF;
569 } else {
570 new.a1 = b & 0x3FF;
571 new.b1 = a & 0x3FF;
572 }
573 }
574 }
575
576 if (error)
577 new = old;
578
579 b43_nphy_rx_iq_coeffs(dev, true, &new);
580}
581
582/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */
583static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
584{
585 u16 array[4];
586 int i;
587
588 b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x3C50);
589 for (i = 0; i < 4; i++)
590 array[i] = b43_phy_read(dev, B43_NPHY_TABLE_DATALO);
591
592 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);
593 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);
594 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]);
595 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]);
596}
597
598/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
599static void b43_nphy_write_clip_detection(struct b43_wldev *dev, u16 *clip_st)
600{
601 b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]);
602 b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]);
603}
604
605/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
606static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
607{
608 clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES);
609 clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES);
610}
611
612/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
613static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
614{
615 u16 tmp;
616
617 if (dev->dev->id.revision == 16)
618 b43_mac_suspend(dev);
619
620 tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
621 tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN |
622 B43_NPHY_CLASSCTL_WAITEDEN);
623 tmp &= ~mask;
624 tmp |= (val & mask);
625 b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
626
627 if (dev->dev->id.revision == 16)
628 b43_mac_enable(dev);
629
630 return tmp;
631}
632
633/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
634static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
635{
636 struct b43_phy *phy = &dev->phy;
637 struct b43_phy_n *nphy = phy->n;
638
639 if (enable) {
640 u16 clip[] = { 0xFFFF, 0xFFFF };
641 if (nphy->deaf_count++ == 0) {
642 nphy->classifier_state = b43_nphy_classifier(dev, 0, 0);
643 b43_nphy_classifier(dev, 0x7, 0);
644 b43_nphy_read_clip_detection(dev, nphy->clip_state);
645 b43_nphy_write_clip_detection(dev, clip);
646 }
647 b43_nphy_reset_cca(dev);
648 } else {
649 if (--nphy->deaf_count == 0) {
650 b43_nphy_classifier(dev, 0x7, nphy->classifier_state);
651 b43_nphy_write_clip_detection(dev, nphy->clip_state);
652 }
653 }
654}
655
656/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
657static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
658{
659 struct b43_phy_n *nphy = dev->phy.n;
660 int i, j;
661 u32 tmp;
662 u32 cur_real, cur_imag, real_part, imag_part;
663
664 u16 buffer[7];
665
666 if (nphy->hang_avoid)
667 b43_nphy_stay_in_carrier_search(dev, true);
668
669 /* TODO: Read an N PHY Table with ID 15, length 7, offset 80,
670 width 16, and data pointer buffer */
671
672 for (i = 0; i < 2; i++) {
673 tmp = ((buffer[i * 2] & 0x3FF) << 10) |
674 (buffer[i * 2 + 1] & 0x3FF);
675 b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
676 (((i + 26) << 10) | 320));
677 for (j = 0; j < 128; j++) {
678 b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
679 ((tmp >> 16) & 0xFFFF));
680 b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
681 (tmp & 0xFFFF));
682 }
683 }
684
685 for (i = 0; i < 2; i++) {
686 tmp = buffer[5 + i];
687 real_part = (tmp >> 8) & 0xFF;
688 imag_part = (tmp & 0xFF);
689 b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
690 (((i + 26) << 10) | 448));
691
692 if (dev->phy.rev >= 3) {
693 cur_real = real_part;
694 cur_imag = imag_part;
695 tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF);
696 }
697
698 for (j = 0; j < 128; j++) {
699 if (dev->phy.rev < 3) {
700 cur_real = (real_part * loscale[j] + 128) >> 8;
701 cur_imag = (imag_part * loscale[j] + 128) >> 8;
702 tmp = ((cur_real & 0xFF) << 8) |
703 (cur_imag & 0xFF);
704 }
705 b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
706 ((tmp >> 16) & 0xFFFF));
707 b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
708 (tmp & 0xFFFF));
709 }
710 }
711
712 if (dev->phy.rev >= 3) {
713 b43_shm_write16(dev, B43_SHM_SHARED,
714 B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF);
715 b43_shm_write16(dev, B43_SHM_SHARED,
716 B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF);
717 }
718
719 if (nphy->hang_avoid)
720 b43_nphy_stay_in_carrier_search(dev, false);
356} 721}
357 722
358enum b43_nphy_rf_sequence { 723enum b43_nphy_rf_sequence {
@@ -411,81 +776,1339 @@ static void b43_nphy_bphy_init(struct b43_wldev *dev)
411 b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668); 776 b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
412} 777}
413 778
414/* RSSI Calibration */ 779/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
415static void b43_nphy_rssi_cal(struct b43_wldev *dev, u8 type) 780static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
781 s8 offset, u8 core, u8 rail, u8 type)
416{ 782{
417 //TODO 783 u16 tmp;
784 bool core1or5 = (core == 1) || (core == 5);
785 bool core2or5 = (core == 2) || (core == 5);
786
787 offset = clamp_val(offset, -32, 31);
788 tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
789
790 if (core1or5 && (rail == 0) && (type == 2))
791 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
792 if (core1or5 && (rail == 1) && (type == 2))
793 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
794 if (core2or5 && (rail == 0) && (type == 2))
795 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
796 if (core2or5 && (rail == 1) && (type == 2))
797 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
798 if (core1or5 && (rail == 0) && (type == 0))
799 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
800 if (core1or5 && (rail == 1) && (type == 0))
801 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
802 if (core2or5 && (rail == 0) && (type == 0))
803 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
804 if (core2or5 && (rail == 1) && (type == 0))
805 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
806 if (core1or5 && (rail == 0) && (type == 1))
807 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
808 if (core1or5 && (rail == 1) && (type == 1))
809 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
810 if (core2or5 && (rail == 0) && (type == 1))
811 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
812 if (core2or5 && (rail == 1) && (type == 1))
813 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
814 if (core1or5 && (rail == 0) && (type == 6))
815 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
816 if (core1or5 && (rail == 1) && (type == 6))
817 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
818 if (core2or5 && (rail == 0) && (type == 6))
819 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
820 if (core2or5 && (rail == 1) && (type == 6))
821 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
822 if (core1or5 && (rail == 0) && (type == 3))
823 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
824 if (core1or5 && (rail == 1) && (type == 3))
825 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
826 if (core2or5 && (rail == 0) && (type == 3))
827 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
828 if (core2or5 && (rail == 1) && (type == 3))
829 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
830 if (core1or5 && (type == 4))
831 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
832 if (core2or5 && (type == 4))
833 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
834 if (core1or5 && (type == 5))
835 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
836 if (core2or5 && (type == 5))
837 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
838}
839
840/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
841static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
842{
843 u16 val;
844
845 if (dev->phy.rev >= 3) {
846 /* TODO */
847 } else {
848 if (type < 3)
849 val = 0;
850 else if (type == 6)
851 val = 1;
852 else if (type == 3)
853 val = 2;
854 else
855 val = 3;
856
857 val = (val << 12) | (val << 14);
858 b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
859 b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
860
861 if (type < 3) {
862 b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
863 (type + 1) << 4);
864 b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
865 (type + 1) << 4);
866 }
867
868 /* TODO use some definitions */
869 if (code == 0) {
870 b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF, 0);
871 if (type < 3) {
872 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
873 0xFEC7, 0);
874 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
875 0xEFDC, 0);
876 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
877 0xFFFE, 0);
878 udelay(20);
879 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
880 0xFFFE, 0);
881 }
882 } else {
883 b43_phy_maskset(dev, B43_NPHY_AFECTL_OVER, 0xCFFF,
884 0x3000);
885 if (type < 3) {
886 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
887 0xFEC7, 0x0180);
888 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
889 0xEFDC, (code << 1 | 0x1021));
890 b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
891 0xFFFE, 0x0001);
892 udelay(20);
893 b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
894 0xFFFE, 0);
895 }
896 }
897 }
898}
899
900/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
901static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf)
902{
903 int i;
904 for (i = 0; i < 2; i++) {
905 if (type == 2) {
906 if (i == 0) {
907 b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM,
908 0xFC, buf[0]);
909 b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
910 0xFC, buf[1]);
911 } else {
912 b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM,
913 0xFC, buf[2 * i]);
914 b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
915 0xFC, buf[2 * i + 1]);
916 }
917 } else {
918 if (i == 0)
919 b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
920 0xF3, buf[0] << 2);
921 else
922 b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
923 0xF3, buf[2 * i + 1] << 2);
924 }
925 }
926}
927
928/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
929static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
930 u8 nsamp)
931{
932 int i;
933 int out;
934 u16 save_regs_phy[9];
935 u16 s[2];
936
937 if (dev->phy.rev >= 3) {
938 save_regs_phy[0] = b43_phy_read(dev,
939 B43_NPHY_RFCTL_LUT_TRSW_UP1);
940 save_regs_phy[1] = b43_phy_read(dev,
941 B43_NPHY_RFCTL_LUT_TRSW_UP2);
942 save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
943 save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
944 save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
945 save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
946 save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
947 save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
948 }
949
950 b43_nphy_rssi_select(dev, 5, type);
951
952 if (dev->phy.rev < 2) {
953 save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
954 b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5);
955 }
956
957 for (i = 0; i < 4; i++)
958 buf[i] = 0;
959
960 for (i = 0; i < nsamp; i++) {
961 if (dev->phy.rev < 2) {
962 s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT);
963 s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT);
964 } else {
965 s[0] = b43_phy_read(dev, B43_NPHY_RSSI1);
966 s[1] = b43_phy_read(dev, B43_NPHY_RSSI2);
967 }
968
969 buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2;
970 buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2;
971 buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2;
972 buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2;
973 }
974 out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 |
975 (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF);
976
977 if (dev->phy.rev < 2)
978 b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]);
979
980 if (dev->phy.rev >= 3) {
981 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1,
982 save_regs_phy[0]);
983 b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2,
984 save_regs_phy[1]);
985 b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]);
986 b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]);
987 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]);
988 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
989 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
990 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
991 }
992
993 return out;
994}
995
996/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
997static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
998{
999 int i, j;
1000 u8 state[4];
1001 u8 code, val;
1002 u16 class, override;
1003 u8 regs_save_radio[2];
1004 u16 regs_save_phy[2];
1005 s8 offset[4];
1006
1007 u16 clip_state[2];
1008 u16 clip_off[2] = { 0xFFFF, 0xFFFF };
1009 s32 results_min[4] = { };
1010 u8 vcm_final[4] = { };
1011 s32 results[4][4] = { };
1012 s32 miniq[4][2] = { };
1013
1014 if (type == 2) {
1015 code = 0;
1016 val = 6;
1017 } else if (type < 2) {
1018 code = 25;
1019 val = 4;
1020 } else {
1021 B43_WARN_ON(1);
1022 return;
1023 }
1024
1025 class = b43_nphy_classifier(dev, 0, 0);
1026 b43_nphy_classifier(dev, 7, 4);
1027 b43_nphy_read_clip_detection(dev, clip_state);
1028 b43_nphy_write_clip_detection(dev, clip_off);
1029
1030 if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
1031 override = 0x140;
1032 else
1033 override = 0x110;
1034
1035 regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
1036 regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX);
1037 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override);
1038 b43_radio_write16(dev, B2055_C1_PD_RXTX, val);
1039
1040 regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
1041 regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX);
1042 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override);
1043 b43_radio_write16(dev, B2055_C2_PD_RXTX, val);
1044
1045 state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07;
1046 state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07;
1047 b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8);
1048 b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8);
1049 state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07;
1050 state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07;
1051
1052 b43_nphy_rssi_select(dev, 5, type);
1053 b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type);
1054 b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type);
1055
1056 for (i = 0; i < 4; i++) {
1057 u8 tmp[4];
1058 for (j = 0; j < 4; j++)
1059 tmp[j] = i;
1060 if (type != 1)
1061 b43_nphy_set_rssi_2055_vcm(dev, type, tmp);
1062 b43_nphy_poll_rssi(dev, type, results[i], 8);
1063 if (type < 2)
1064 for (j = 0; j < 2; j++)
1065 miniq[i][j] = min(results[i][2 * j],
1066 results[i][2 * j + 1]);
1067 }
1068
1069 for (i = 0; i < 4; i++) {
1070 s32 mind = 40;
1071 u8 minvcm = 0;
1072 s32 minpoll = 249;
1073 s32 curr;
1074 for (j = 0; j < 4; j++) {
1075 if (type == 2)
1076 curr = abs(results[j][i]);
1077 else
1078 curr = abs(miniq[j][i / 2] - code * 8);
1079
1080 if (curr < mind) {
1081 mind = curr;
1082 minvcm = j;
1083 }
1084
1085 if (results[j][i] < minpoll)
1086 minpoll = results[j][i];
1087 }
1088 results_min[i] = minpoll;
1089 vcm_final[i] = minvcm;
1090 }
1091
1092 if (type != 1)
1093 b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final);
1094
1095 for (i = 0; i < 4; i++) {
1096 offset[i] = (code * 8) - results[vcm_final[i]][i];
1097
1098 if (offset[i] < 0)
1099 offset[i] = -((abs(offset[i]) + 4) / 8);
1100 else
1101 offset[i] = (offset[i] + 4) / 8;
1102
1103 if (results_min[i] == 248)
1104 offset[i] = code - 32;
1105
1106 if (i % 2 == 0)
1107 b43_nphy_scale_offset_rssi(dev, 0, offset[i], 1, 0,
1108 type);
1109 else
1110 b43_nphy_scale_offset_rssi(dev, 0, offset[i], 2, 1,
1111 type);
1112 }
1113
1114 b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]);
1115 b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[1]);
1116
1117 switch (state[2]) {
1118 case 1:
1119 b43_nphy_rssi_select(dev, 1, 2);
1120 break;
1121 case 4:
1122 b43_nphy_rssi_select(dev, 1, 0);
1123 break;
1124 case 2:
1125 b43_nphy_rssi_select(dev, 1, 1);
1126 break;
1127 default:
1128 b43_nphy_rssi_select(dev, 1, 1);
1129 break;
1130 }
1131
1132 switch (state[3]) {
1133 case 1:
1134 b43_nphy_rssi_select(dev, 2, 2);
1135 break;
1136 case 4:
1137 b43_nphy_rssi_select(dev, 2, 0);
1138 break;
1139 default:
1140 b43_nphy_rssi_select(dev, 2, 1);
1141 break;
1142 }
1143
1144 b43_nphy_rssi_select(dev, 0, type);
1145
1146 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]);
1147 b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
1148 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]);
1149 b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
1150
1151 b43_nphy_classifier(dev, 7, class);
1152 b43_nphy_write_clip_detection(dev, clip_state);
1153}
1154
1155/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
1156static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
1157{
1158 /* TODO */
1159}
1160
1161/*
1162 * RSSI Calibration
1163 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
1164 */
1165static void b43_nphy_rssi_cal(struct b43_wldev *dev)
1166{
1167 if (dev->phy.rev >= 3) {
1168 b43_nphy_rev3_rssi_cal(dev);
1169 } else {
1170 b43_nphy_rev2_rssi_cal(dev, 2);
1171 b43_nphy_rev2_rssi_cal(dev, 0);
1172 b43_nphy_rev2_rssi_cal(dev, 1);
1173 }
1174}
1175
1176/*
1177 * Restore RSSI Calibration
1178 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal
1179 */
1180static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
1181{
1182 struct b43_phy_n *nphy = dev->phy.n;
1183
1184 u16 *rssical_radio_regs = NULL;
1185 u16 *rssical_phy_regs = NULL;
1186
1187 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
1188 if (!nphy->rssical_chanspec_2G)
1189 return;
1190 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
1191 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
1192 } else {
1193 if (!nphy->rssical_chanspec_5G)
1194 return;
1195 rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
1196 rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
1197 }
1198
1199 /* TODO use some definitions */
1200 b43_radio_maskset(dev, 0x602B, 0xE3, rssical_radio_regs[0]);
1201 b43_radio_maskset(dev, 0x702B, 0xE3, rssical_radio_regs[1]);
1202
1203 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]);
1204 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]);
1205 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]);
1206 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]);
1207
1208 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]);
1209 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]);
1210 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]);
1211 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]);
1212
1213 b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]);
1214 b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]);
1215 b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]);
1216 b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
1217}
1218
1219/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
1220static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
1221{
1222 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
1223 if (dev->phy.rev >= 6) {
1224 /* TODO If the chip is 47162
1225 return txpwrctrl_tx_gain_ipa_rev5 */
1226 return txpwrctrl_tx_gain_ipa_rev6;
1227 } else if (dev->phy.rev >= 5) {
1228 return txpwrctrl_tx_gain_ipa_rev5;
1229 } else {
1230 return txpwrctrl_tx_gain_ipa;
1231 }
1232 } else {
1233 return txpwrctrl_tx_gain_ipa_5g;
1234 }
1235}
1236
1237/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
1238static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
1239{
1240 struct b43_phy_n *nphy = dev->phy.n;
1241 u16 *save = nphy->tx_rx_cal_radio_saveregs;
1242
1243 if (dev->phy.rev >= 3) {
1244 /* TODO */
1245 } else {
1246 save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1);
1247 b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29);
1248
1249 save[1] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL2);
1250 b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL2, 0x54);
1251
1252 save[2] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL1);
1253 b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL1, 0x29);
1254
1255 save[3] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL2);
1256 b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL2, 0x54);
1257
1258 save[3] = b43_radio_read16(dev, B2055_C1_PWRDET_RXTX);
1259 save[4] = b43_radio_read16(dev, B2055_C2_PWRDET_RXTX);
1260
1261 if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) &
1262 B43_NPHY_BANDCTL_5GHZ)) {
1263 b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x04);
1264 b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x04);
1265 } else {
1266 b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x20);
1267 b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x20);
1268 }
1269
1270 if (dev->phy.rev < 2) {
1271 b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20);
1272 b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20);
1273 } else {
1274 b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20);
1275 b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20);
1276 }
1277 }
1278}
1279
1280/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */
1281static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core,
1282 struct nphy_txgains target,
1283 struct nphy_iqcal_params *params)
1284{
1285 int i, j, indx;
1286 u16 gain;
1287
1288 if (dev->phy.rev >= 3) {
1289 params->txgm = target.txgm[core];
1290 params->pga = target.pga[core];
1291 params->pad = target.pad[core];
1292 params->ipa = target.ipa[core];
1293 params->cal_gain = (params->txgm << 12) | (params->pga << 8) |
1294 (params->pad << 4) | (params->ipa);
1295 for (j = 0; j < 5; j++)
1296 params->ncorr[j] = 0x79;
1297 } else {
1298 gain = (target.pad[core]) | (target.pga[core] << 4) |
1299 (target.txgm[core] << 8);
1300
1301 indx = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ?
1302 1 : 0;
1303 for (i = 0; i < 9; i++)
1304 if (tbl_iqcal_gainparams[indx][i][0] == gain)
1305 break;
1306 i = min(i, 8);
1307
1308 params->txgm = tbl_iqcal_gainparams[indx][i][1];
1309 params->pga = tbl_iqcal_gainparams[indx][i][2];
1310 params->pad = tbl_iqcal_gainparams[indx][i][3];
1311 params->cal_gain = (params->txgm << 7) | (params->pga << 4) |
1312 (params->pad << 2);
1313 for (j = 0; j < 4; j++)
1314 params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j];
1315 }
1316}
1317
1318/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */
1319static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)
1320{
1321 struct b43_phy_n *nphy = dev->phy.n;
1322 int i;
1323 u16 scale, entry;
1324
1325 u16 tmp = nphy->txcal_bbmult;
1326 if (core == 0)
1327 tmp >>= 8;
1328 tmp &= 0xff;
1329
1330 for (i = 0; i < 18; i++) {
1331 scale = (ladder_lo[i].percent * tmp) / 100;
1332 entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env;
1333 /* TODO: Write an N PHY Table with ID 15, length 1,
1334 offset i, width 16, and data entry */
1335
1336 scale = (ladder_iq[i].percent * tmp) / 100;
1337 entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env;
1338 /* TODO: Write an N PHY Table with ID 15, length 1,
1339 offset i + 32, width 16, and data entry */
1340 }
1341}
1342
1343/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
1344static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
1345{
1346 struct b43_phy_n *nphy = dev->phy.n;
1347
1348 u16 curr_gain[2];
1349 struct nphy_txgains target;
1350 const u32 *table = NULL;
1351
1352 if (nphy->txpwrctrl == 0) {
1353 int i;
1354
1355 if (nphy->hang_avoid)
1356 b43_nphy_stay_in_carrier_search(dev, true);
1357 /* TODO: Read an N PHY Table with ID 7, length 2,
1358 offset 0x110, width 16, and curr_gain */
1359 if (nphy->hang_avoid)
1360 b43_nphy_stay_in_carrier_search(dev, false);
1361
1362 for (i = 0; i < 2; ++i) {
1363 if (dev->phy.rev >= 3) {
1364 target.ipa[i] = curr_gain[i] & 0x000F;
1365 target.pad[i] = (curr_gain[i] & 0x00F0) >> 4;
1366 target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
1367 target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
1368 } else {
1369 target.ipa[i] = curr_gain[i] & 0x0003;
1370 target.pad[i] = (curr_gain[i] & 0x000C) >> 2;
1371 target.pga[i] = (curr_gain[i] & 0x0070) >> 4;
1372 target.txgm[i] = (curr_gain[i] & 0x0380) >> 7;
1373 }
1374 }
1375 } else {
1376 int i;
1377 u16 index[2];
1378 index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) &
1379 B43_NPHY_TXPCTL_STAT_BIDX) >>
1380 B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
1381 index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) &
1382 B43_NPHY_TXPCTL_STAT_BIDX) >>
1383 B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
1384
1385 for (i = 0; i < 2; ++i) {
1386 if (dev->phy.rev >= 3) {
1387 enum ieee80211_band band =
1388 b43_current_band(dev->wl);
1389
1390 if ((nphy->ipa2g_on &&
1391 band == IEEE80211_BAND_2GHZ) ||
1392 (nphy->ipa5g_on &&
1393 band == IEEE80211_BAND_5GHZ)) {
1394 table = b43_nphy_get_ipa_gain_table(dev);
1395 } else {
1396 if (band == IEEE80211_BAND_5GHZ) {
1397 if (dev->phy.rev == 3)
1398 table = b43_ntab_tx_gain_rev3_5ghz;
1399 else if (dev->phy.rev == 4)
1400 table = b43_ntab_tx_gain_rev4_5ghz;
1401 else
1402 table = b43_ntab_tx_gain_rev5plus_5ghz;
1403 } else {
1404 table = b43_ntab_tx_gain_rev3plus_2ghz;
1405 }
1406 }
1407
1408 target.ipa[i] = (table[index[i]] >> 16) & 0xF;
1409 target.pad[i] = (table[index[i]] >> 20) & 0xF;
1410 target.pga[i] = (table[index[i]] >> 24) & 0xF;
1411 target.txgm[i] = (table[index[i]] >> 28) & 0xF;
1412 } else {
1413 table = b43_ntab_tx_gain_rev0_1_2;
1414
1415 target.ipa[i] = (table[index[i]] >> 16) & 0x3;
1416 target.pad[i] = (table[index[i]] >> 18) & 0x3;
1417 target.pga[i] = (table[index[i]] >> 20) & 0x7;
1418 target.txgm[i] = (table[index[i]] >> 23) & 0x7;
1419 }
1420 }
1421 }
1422
1423 return target;
1424}
1425
1426/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
1427static void b43_nphy_restore_cal(struct b43_wldev *dev)
1428{
1429 struct b43_phy_n *nphy = dev->phy.n;
1430
1431 u16 coef[4];
1432 u16 *loft = NULL;
1433 u16 *table = NULL;
1434
1435 int i;
1436 u16 *txcal_radio_regs = NULL;
1437 struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
1438
1439 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
1440 if (nphy->iqcal_chanspec_2G == 0)
1441 return;
1442 table = nphy->cal_cache.txcal_coeffs_2G;
1443 loft = &nphy->cal_cache.txcal_coeffs_2G[5];
1444 } else {
1445 if (nphy->iqcal_chanspec_5G == 0)
1446 return;
1447 table = nphy->cal_cache.txcal_coeffs_5G;
1448 loft = &nphy->cal_cache.txcal_coeffs_5G[5];
1449 }
1450
1451 /* TODO: Write an N PHY table with ID 15, length 4, offset 80,
1452 width 16, and data from table */
1453
1454 for (i = 0; i < 4; i++) {
1455 if (dev->phy.rev >= 3)
1456 table[i] = coef[i];
1457 else
1458 coef[i] = 0;
1459 }
1460
1461 /* TODO: Write an N PHY table with ID 15, length 4, offset 88,
1462 width 16, and data from coef */
1463 /* TODO: Write an N PHY table with ID 15, length 2, offset 85,
1464 width 16 and data from loft */
1465 /* TODO: Write an N PHY table with ID 15, length 2, offset 93,
1466 width 16 and data from loft */
1467
1468 if (dev->phy.rev < 2)
1469 b43_nphy_tx_iq_workaround(dev);
1470
1471 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
1472 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
1473 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
1474 } else {
1475 txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
1476 rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
1477 }
1478
1479 /* TODO use some definitions */
1480 if (dev->phy.rev >= 3) {
1481 b43_radio_write(dev, 0x2021, txcal_radio_regs[0]);
1482 b43_radio_write(dev, 0x2022, txcal_radio_regs[1]);
1483 b43_radio_write(dev, 0x3021, txcal_radio_regs[2]);
1484 b43_radio_write(dev, 0x3022, txcal_radio_regs[3]);
1485 b43_radio_write(dev, 0x2023, txcal_radio_regs[4]);
1486 b43_radio_write(dev, 0x2024, txcal_radio_regs[5]);
1487 b43_radio_write(dev, 0x3023, txcal_radio_regs[6]);
1488 b43_radio_write(dev, 0x3024, txcal_radio_regs[7]);
1489 } else {
1490 b43_radio_write(dev, 0x8B, txcal_radio_regs[0]);
1491 b43_radio_write(dev, 0xBA, txcal_radio_regs[1]);
1492 b43_radio_write(dev, 0x8D, txcal_radio_regs[2]);
1493 b43_radio_write(dev, 0xBC, txcal_radio_regs[3]);
1494 }
1495 b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs);
1496}
1497
1498/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */
1499static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
1500 struct nphy_txgains target,
1501 bool full, bool mphase)
1502{
1503 struct b43_phy_n *nphy = dev->phy.n;
1504 int i;
1505 int error = 0;
1506 int freq;
1507 bool avoid = false;
1508 u8 length;
1509 u16 tmp, core, type, count, max, numb, last, cmd;
1510 const u16 *table;
1511 bool phy6or5x;
1512
1513 u16 buffer[11];
1514 u16 diq_start = 0;
1515 u16 save[2];
1516 u16 gain[2];
1517 struct nphy_iqcal_params params[2];
1518 bool updated[2] = { };
1519
1520 b43_nphy_stay_in_carrier_search(dev, true);
1521
1522 if (dev->phy.rev >= 4) {
1523 avoid = nphy->hang_avoid;
1524 nphy->hang_avoid = 0;
1525 }
1526
1527 /* TODO: Read an N PHY Table with ID 7, length 2, offset 0x110,
1528 width 16, and data pointer save */
1529
1530 for (i = 0; i < 2; i++) {
1531 b43_nphy_iq_cal_gain_params(dev, i, target, &params[i]);
1532 gain[i] = params[i].cal_gain;
1533 }
1534 /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110,
1535 width 16, and data pointer gain */
1536
1537 b43_nphy_tx_cal_radio_setup(dev);
1538 /* TODO: Call N PHY TX Cal PHY Setup */
1539
1540 phy6or5x = dev->phy.rev >= 6 ||
1541 (dev->phy.rev == 5 && nphy->ipa2g_on &&
1542 b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ);
1543 if (phy6or5x) {
1544 /* TODO */
1545 }
1546
1547 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
1548
1549 if (1 /* FIXME: the band width is 20 MHz */)
1550 freq = 2500;
1551 else
1552 freq = 5000;
1553
1554 if (nphy->mphase_cal_phase_id > 2)
1555 ;/* TODO: Call N PHY Run Samples with (band width * 8),
1556 0xFFFF, 0, 1, 0 as arguments */
1557 else
1558 ;/* TODO: Call N PHY TX Tone with freq, 250, 1, 0 as arguments
1559 and save result as error */
1560
1561 if (error == 0) {
1562 if (nphy->mphase_cal_phase_id > 2) {
1563 table = nphy->mphase_txcal_bestcoeffs;
1564 length = 11;
1565 if (dev->phy.rev < 3)
1566 length -= 2;
1567 } else {
1568 if (!full && nphy->txiqlocal_coeffsvalid) {
1569 table = nphy->txiqlocal_bestc;
1570 length = 11;
1571 if (dev->phy.rev < 3)
1572 length -= 2;
1573 } else {
1574 full = true;
1575 if (dev->phy.rev >= 3) {
1576 table = tbl_tx_iqlo_cal_startcoefs_nphyrev3;
1577 length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3;
1578 } else {
1579 table = tbl_tx_iqlo_cal_startcoefs;
1580 length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS;
1581 }
1582 }
1583 }
1584
1585 /* TODO: Write an N PHY Table with ID 15, length from above,
1586 offset 64, width 16, and the data pointer from above */
1587
1588 if (full) {
1589 if (dev->phy.rev >= 3)
1590 max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3;
1591 else
1592 max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL;
1593 } else {
1594 if (dev->phy.rev >= 3)
1595 max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3;
1596 else
1597 max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL;
1598 }
1599
1600 if (mphase) {
1601 count = nphy->mphase_txcal_cmdidx;
1602 numb = min(max,
1603 (u16)(count + nphy->mphase_txcal_numcmds));
1604 } else {
1605 count = 0;
1606 numb = max;
1607 }
1608
1609 for (; count < numb; count++) {
1610 if (full) {
1611 if (dev->phy.rev >= 3)
1612 cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count];
1613 else
1614 cmd = tbl_tx_iqlo_cal_cmds_fullcal[count];
1615 } else {
1616 if (dev->phy.rev >= 3)
1617 cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count];
1618 else
1619 cmd = tbl_tx_iqlo_cal_cmds_recal[count];
1620 }
1621
1622 core = (cmd & 0x3000) >> 12;
1623 type = (cmd & 0x0F00) >> 8;
1624
1625 if (phy6or5x && updated[core] == 0) {
1626 b43_nphy_update_tx_cal_ladder(dev, core);
1627 updated[core] = 1;
1628 }
1629
1630 tmp = (params[core].ncorr[type] << 8) | 0x66;
1631 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp);
1632
1633 if (type == 1 || type == 3 || type == 4) {
1634 /* TODO: Read an N PHY Table with ID 15,
1635 length 1, offset 69 + core,
1636 width 16, and data pointer buffer */
1637 diq_start = buffer[0];
1638 buffer[0] = 0;
1639 /* TODO: Write an N PHY Table with ID 15,
1640 length 1, offset 69 + core, width 16,
1641 and data of 0 */
1642 }
1643
1644 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd);
1645 for (i = 0; i < 2000; i++) {
1646 tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD);
1647 if (tmp & 0xC000)
1648 break;
1649 udelay(10);
1650 }
1651
1652 /* TODO: Read an N PHY Table with ID 15,
1653 length table_length, offset 96, width 16,
1654 and data pointer buffer */
1655 /* TODO: Write an N PHY Table with ID 15,
1656 length table_length, offset 64, width 16,
1657 and data pointer buffer */
1658
1659 if (type == 1 || type == 3 || type == 4)
1660 buffer[0] = diq_start;
1661 }
1662
1663 if (mphase)
1664 nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb;
1665
1666 last = (dev->phy.rev < 3) ? 6 : 7;
1667
1668 if (!mphase || nphy->mphase_cal_phase_id == last) {
1669 /* TODO: Write an N PHY Table with ID 15, length 4,
1670 offset 96, width 16, and data pointer buffer */
1671 /* TODO: Read an N PHY Table with ID 15, length 4,
1672 offset 80, width 16, and data pointer buffer */
1673 if (dev->phy.rev < 3) {
1674 buffer[0] = 0;
1675 buffer[1] = 0;
1676 buffer[2] = 0;
1677 buffer[3] = 0;
1678 }
1679 /* TODO: Write an N PHY Table with ID 15, length 4,
1680 offset 88, width 16, and data pointer buffer */
1681 /* TODO: Read an N PHY Table with ID 15, length 2,
1682 offset 101, width 16, and data pointer buffer*/
1683 /* TODO: Write an N PHY Table with ID 15, length 2,
1684 offset 85, width 16, and data pointer buffer */
1685 /* TODO: Write an N PHY Table with ID 15, length 2,
1686 offset 93, width 16, and data pointer buffer */
1687 length = 11;
1688 if (dev->phy.rev < 3)
1689 length -= 2;
1690 /* TODO: Read an N PHY Table with ID 15, length length,
1691 offset 96, width 16, and data pointer
1692 nphy->txiqlocal_bestc */
1693 nphy->txiqlocal_coeffsvalid = true;
1694 /* TODO: Set nphy->txiqlocal_chanspec to
1695 the current channel */
1696 } else {
1697 length = 11;
1698 if (dev->phy.rev < 3)
1699 length -= 2;
1700 /* TODO: Read an N PHY Table with ID 5, length length,
1701 offset 96, width 16, and data pointer
1702 nphy->mphase_txcal_bestcoeffs */
1703 }
1704
1705 /* TODO: Call N PHY Stop Playback */
1706 b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0);
1707 }
1708
1709 /* TODO: Call N PHY TX Cal PHY Cleanup */
1710 /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110,
1711 width 16, and data from save */
1712
1713 if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last))
1714 b43_nphy_tx_iq_workaround(dev);
1715
1716 if (dev->phy.rev >= 4)
1717 nphy->hang_avoid = avoid;
1718
1719 b43_nphy_stay_in_carrier_search(dev, false);
1720
1721 return error;
418} 1722}
419 1723
1724/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */
1725static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
1726 struct nphy_txgains target, u8 type, bool debug)
1727{
1728 struct b43_phy_n *nphy = dev->phy.n;
1729 int i, j, index;
1730 u8 rfctl[2];
1731 u8 afectl_core;
1732 u16 tmp[6];
1733 u16 cur_hpf1, cur_hpf2, cur_lna;
1734 u32 real, imag;
1735 enum ieee80211_band band;
1736
1737 u8 use;
1738 u16 cur_hpf;
1739 u16 lna[3] = { 3, 3, 1 };
1740 u16 hpf1[3] = { 7, 2, 0 };
1741 u16 hpf2[3] = { 2, 0, 0 };
1742 u32 power[3];
1743 u16 gain_save[2];
1744 u16 cal_gain[2];
1745 struct nphy_iqcal_params cal_params[2];
1746 struct nphy_iq_est est;
1747 int ret = 0;
1748 bool playtone = true;
1749 int desired = 13;
1750
1751 b43_nphy_stay_in_carrier_search(dev, 1);
1752
1753 if (dev->phy.rev < 2)
1754 ;/* TODO: Call N PHY Reapply TX Cal Coeffs */
1755 /* TODO: Read an N PHY Table with ID 7, length 2, offset 0x110,
1756 width 16, and data gain_save */
1757 for (i = 0; i < 2; i++) {
1758 b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]);
1759 cal_gain[i] = cal_params[i].cal_gain;
1760 }
1761 /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110,
1762 width 16, and data from cal_gain */
1763
1764 for (i = 0; i < 2; i++) {
1765 if (i == 0) {
1766 rfctl[0] = B43_NPHY_RFCTL_INTC1;
1767 rfctl[1] = B43_NPHY_RFCTL_INTC2;
1768 afectl_core = B43_NPHY_AFECTL_C1;
1769 } else {
1770 rfctl[0] = B43_NPHY_RFCTL_INTC2;
1771 rfctl[1] = B43_NPHY_RFCTL_INTC1;
1772 afectl_core = B43_NPHY_AFECTL_C2;
1773 }
1774
1775 tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
1776 tmp[2] = b43_phy_read(dev, afectl_core);
1777 tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
1778 tmp[4] = b43_phy_read(dev, rfctl[0]);
1779 tmp[5] = b43_phy_read(dev, rfctl[1]);
1780
1781 b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
1782 (u16)~B43_NPHY_RFSEQCA_RXDIS,
1783 ((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
1784 b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
1785 (1 - i));
1786 b43_phy_set(dev, afectl_core, 0x0006);
1787 b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006);
1788
1789 band = b43_current_band(dev->wl);
1790
1791 if (nphy->rxcalparams & 0xFF000000) {
1792 if (band == IEEE80211_BAND_5GHZ)
1793 b43_phy_write(dev, rfctl[0], 0x140);
1794 else
1795 b43_phy_write(dev, rfctl[0], 0x110);
1796 } else {
1797 if (band == IEEE80211_BAND_5GHZ)
1798 b43_phy_write(dev, rfctl[0], 0x180);
1799 else
1800 b43_phy_write(dev, rfctl[0], 0x120);
1801 }
1802
1803 if (band == IEEE80211_BAND_5GHZ)
1804 b43_phy_write(dev, rfctl[1], 0x148);
1805 else
1806 b43_phy_write(dev, rfctl[1], 0x114);
1807
1808 if (nphy->rxcalparams & 0x10000) {
1809 b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC,
1810 (i + 1));
1811 b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC,
1812 (2 - i));
1813 }
1814
1815 for (j = 0; i < 4; j++) {
1816 if (j < 3) {
1817 cur_lna = lna[j];
1818 cur_hpf1 = hpf1[j];
1819 cur_hpf2 = hpf2[j];
1820 } else {
1821 if (power[1] > 10000) {
1822 use = 1;
1823 cur_hpf = cur_hpf1;
1824 index = 2;
1825 } else {
1826 if (power[0] > 10000) {
1827 use = 1;
1828 cur_hpf = cur_hpf1;
1829 index = 1;
1830 } else {
1831 index = 0;
1832 use = 2;
1833 cur_hpf = cur_hpf2;
1834 }
1835 }
1836 cur_lna = lna[index];
1837 cur_hpf1 = hpf1[index];
1838 cur_hpf2 = hpf2[index];
1839 cur_hpf += desired - hweight32(power[index]);
1840 cur_hpf = clamp_val(cur_hpf, 0, 10);
1841 if (use == 1)
1842 cur_hpf1 = cur_hpf;
1843 else
1844 cur_hpf2 = cur_hpf;
1845 }
1846
1847 tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
1848 (cur_lna << 2));
1849 /* TODO:Call N PHY RF Ctrl Override with 0x400, tmp[0],
1850 3, 0 as arguments */
1851 /* TODO: Call N PHY Force RF Seq with 2 as argument */
1852 /* TODO: Call N PHT Stop Playback */
1853
1854 if (playtone) {
1855 /* TODO: Call N PHY TX Tone with 4000,
1856 (nphy_rxcalparams & 0xffff), 0, 0
1857 as arguments and save result as ret */
1858 playtone = false;
1859 } else {
1860 /* TODO: Call N PHY Run Samples with 160,
1861 0xFFFF, 0, 0, 0 as arguments */
1862 }
1863
1864 if (ret == 0) {
1865 if (j < 3) {
1866 b43_nphy_rx_iq_est(dev, &est, 1024, 32,
1867 false);
1868 if (i == 0) {
1869 real = est.i0_pwr;
1870 imag = est.q0_pwr;
1871 } else {
1872 real = est.i1_pwr;
1873 imag = est.q1_pwr;
1874 }
1875 power[i] = ((real + imag) / 1024) + 1;
1876 } else {
1877 b43_nphy_calc_rx_iq_comp(dev, 1 << i);
1878 }
1879 /* TODO: Call N PHY Stop Playback */
1880 }
1881
1882 if (ret != 0)
1883 break;
1884 }
1885
1886 b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC);
1887 b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC);
1888 b43_phy_write(dev, rfctl[1], tmp[5]);
1889 b43_phy_write(dev, rfctl[0], tmp[4]);
1890 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]);
1891 b43_phy_write(dev, afectl_core, tmp[2]);
1892 b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]);
1893
1894 if (ret != 0)
1895 break;
1896 }
1897
1898 /* TODO: Call N PHY RF Ctrl Override with 0x400, 0, 3, 1 as arguments*/
1899 /* TODO: Call N PHY Force RF Seq with 2 as argument */
1900 /* TODO: Write an N PHY Table with ID 7, length 2, offset 0x110,
1901 width 16, and data from gain_save */
1902
1903 b43_nphy_stay_in_carrier_search(dev, 0);
1904
1905 return ret;
1906}
1907
1908static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev,
1909 struct nphy_txgains target, u8 type, bool debug)
1910{
1911 return -1;
1912}
1913
1914/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */
1915static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
1916 struct nphy_txgains target, u8 type, bool debug)
1917{
1918 if (dev->phy.rev >= 3)
1919 return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug);
1920 else
1921 return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug);
1922}
1923
1924/*
1925 * Init N-PHY
1926 * http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N
1927 */
420int b43_phy_initn(struct b43_wldev *dev) 1928int b43_phy_initn(struct b43_wldev *dev)
421{ 1929{
1930 struct ssb_bus *bus = dev->dev->bus;
422 struct b43_phy *phy = &dev->phy; 1931 struct b43_phy *phy = &dev->phy;
1932 struct b43_phy_n *nphy = phy->n;
1933 u8 tx_pwr_state;
1934 struct nphy_txgains target;
423 u16 tmp; 1935 u16 tmp;
1936 enum ieee80211_band tmp2;
1937 bool do_rssi_cal;
1938
1939 u16 clip[2];
1940 bool do_cal = false;
424 1941
425 //TODO: Spectral management 1942 if ((dev->phy.rev >= 3) &&
1943 (bus->sprom.boardflags_lo & B43_BFL_EXTLNA) &&
1944 (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
1945 chipco_set32(&dev->dev->bus->chipco, SSB_CHIPCO_CHIPCTL, 0x40);
1946 }
1947 nphy->deaf_count = 0;
426 b43_nphy_tables_init(dev); 1948 b43_nphy_tables_init(dev);
1949 nphy->crsminpwr_adjusted = false;
1950 nphy->noisevars_adjusted = false;
427 1951
428 /* Clear all overrides */ 1952 /* Clear all overrides */
429 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0); 1953 if (dev->phy.rev >= 3) {
1954 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0);
1955 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
1956 b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0);
1957 b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0);
1958 } else {
1959 b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
1960 }
430 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0); 1961 b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0);
431 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0); 1962 b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0);
432 b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0); 1963 if (dev->phy.rev < 6) {
433 b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0); 1964 b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0);
1965 b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0);
1966 }
434 b43_phy_mask(dev, B43_NPHY_RFSEQMODE, 1967 b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
435 ~(B43_NPHY_RFSEQMODE_CAOVER | 1968 ~(B43_NPHY_RFSEQMODE_CAOVER |
436 B43_NPHY_RFSEQMODE_TROVER)); 1969 B43_NPHY_RFSEQMODE_TROVER));
1970 if (dev->phy.rev >= 3)
1971 b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0);
437 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0); 1972 b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0);
438 1973
439 tmp = (phy->rev < 2) ? 64 : 59; 1974 if (dev->phy.rev <= 2) {
440 b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, 1975 tmp = (dev->phy.rev == 2) ? 0x3B : 0x40;
441 ~B43_NPHY_BPHY_CTL3_SCALE, 1976 b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
442 tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT); 1977 ~B43_NPHY_BPHY_CTL3_SCALE,
443 1978 tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT);
1979 }
444 b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20); 1980 b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
445 b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20); 1981 b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
446 1982
447 b43_phy_write(dev, B43_NPHY_TXREALFD, 184); 1983 if (bus->sprom.boardflags2_lo & 0x100 ||
448 b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 200); 1984 (bus->boardinfo.vendor == PCI_VENDOR_ID_APPLE &&
449 b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 80); 1985 bus->boardinfo.type == 0x8B))
450 b43_phy_write(dev, B43_NPHY_C2_BCLIPBKOFF, 511); 1986 b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
1987 else
1988 b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
1989 b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8);
1990 b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
1991 b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);
451 1992
452 //TODO MIMO-Config 1993 /* TODO MIMO-Config */
453 //TODO Update TX/RX chain 1994 /* TODO Update TX/RX chain */
454 1995
455 if (phy->rev < 2) { 1996 if (phy->rev < 2) {
456 b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8); 1997 b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);
457 b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4); 1998 b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4);
458 } 1999 }
2000
2001 tmp2 = b43_current_band(dev->wl);
2002 if ((nphy->ipa2g_on && tmp2 == IEEE80211_BAND_2GHZ) ||
2003 (nphy->ipa5g_on && tmp2 == IEEE80211_BAND_5GHZ)) {
2004 b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
2005 b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,
2006 nphy->papd_epsilon_offset[0] << 7);
2007 b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1);
2008 b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F,
2009 nphy->papd_epsilon_offset[1] << 7);
2010 /* TODO N PHY IPA Set TX Dig Filters */
2011 } else if (phy->rev >= 5) {
2012 /* TODO N PHY Ext PA Set TX Dig Filters */
2013 }
2014
459 b43_nphy_workarounds(dev); 2015 b43_nphy_workarounds(dev);
460 b43_nphy_reset_cca(dev);
461 2016
462 ssb_write32(dev->dev, SSB_TMSLOW, 2017 /* Reset CCA, in init code it differs a little from standard way */
463 ssb_read32(dev->dev, SSB_TMSLOW) | B43_TMSLOW_MACPHYCLKEN); 2018 b43_nphy_bmac_clock_fgc(dev, 1);
2019 tmp = b43_phy_read(dev, B43_NPHY_BBCFG);
2020 b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);
2021 b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
2022 b43_nphy_bmac_clock_fgc(dev, 0);
2023
2024 /* TODO N PHY MAC PHY Clock Set with argument 1 */
2025
2026 b43_nphy_pa_override(dev, false);
464 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX); 2027 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
465 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX); 2028 b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
2029 b43_nphy_pa_override(dev, true);
2030
2031 b43_nphy_classifier(dev, 0, 0);
2032 b43_nphy_read_clip_detection(dev, clip);
2033 tx_pwr_state = nphy->txpwrctrl;
2034 /* TODO N PHY TX power control with argument 0
2035 (turning off power control) */
2036 /* TODO Fix the TX Power Settings */
2037 /* TODO N PHY TX Power Control Idle TSSI */
2038 /* TODO N PHY TX Power Control Setup */
2039
2040 if (phy->rev >= 3) {
2041 /* TODO */
2042 } else {
2043 /* TODO Write an N PHY table with ID 26, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */
2044 /* TODO Write an N PHY table with ID 27, length 128, offset 192, width 32, and the data from Rev 2 TX Power Control Table */
2045 }
2046
2047 if (nphy->phyrxchain != 3)
2048 ;/* TODO N PHY RX Core Set State with phyrxchain as argument */
2049 if (nphy->mphase_cal_phase_id > 0)
2050 ;/* TODO PHY Periodic Calibration Multi-Phase Restart */
2051
2052 do_rssi_cal = false;
2053 if (phy->rev >= 3) {
2054 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
2055 do_rssi_cal = (nphy->rssical_chanspec_2G == 0);
2056 else
2057 do_rssi_cal = (nphy->rssical_chanspec_5G == 0);
2058
2059 if (do_rssi_cal)
2060 b43_nphy_rssi_cal(dev);
2061 else
2062 b43_nphy_restore_rssi_cal(dev);
2063 } else {
2064 b43_nphy_rssi_cal(dev);
2065 }
2066
2067 if (!((nphy->measure_hold & 0x6) != 0)) {
2068 if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
2069 do_cal = (nphy->iqcal_chanspec_2G == 0);
2070 else
2071 do_cal = (nphy->iqcal_chanspec_5G == 0);
2072
2073 if (nphy->mute)
2074 do_cal = false;
2075
2076 if (do_cal) {
2077 target = b43_nphy_get_tx_gains(dev);
2078
2079 if (nphy->antsel_type == 2)
2080 ;/*TODO NPHY Superswitch Init with argument 1*/
2081 if (nphy->perical != 2) {
2082 b43_nphy_rssi_cal(dev);
2083 if (phy->rev >= 3) {
2084 nphy->cal_orig_pwr_idx[0] =
2085 nphy->txpwrindex[0].index_internal;
2086 nphy->cal_orig_pwr_idx[1] =
2087 nphy->txpwrindex[1].index_internal;
2088 /* TODO N PHY Pre Calibrate TX Gain */
2089 target = b43_nphy_get_tx_gains(dev);
2090 }
2091 }
2092 }
2093 }
2094
2095 if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false)) {
2096 if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
2097 ;/* Call N PHY Save Cal */
2098 else if (nphy->mphase_cal_phase_id == 0)
2099 ;/* N PHY Periodic Calibration with argument 3 */
2100 } else {
2101 b43_nphy_restore_cal(dev);
2102 }
466 2103
467 b43_phy_read(dev, B43_NPHY_CLASSCTL); /* dummy read */ 2104 b43_nphy_tx_pwr_ctrl_coef_setup(dev);
468 //TODO read core1/2 clip1 thres regs 2105 /* TODO N PHY TX Power Control Enable with argument tx_pwr_state */
469 2106 b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015);
470 if (1 /* FIXME Band is 2.4GHz */) 2107 b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);
471 b43_nphy_bphy_init(dev); 2108 if (phy->rev >= 3 && phy->rev <= 6)
472 //TODO disable TX power control 2109 b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0014);
473 //TODO Fix the TX power settings 2110 b43_nphy_tx_lp_fbw(dev);
474 //TODO Init periodic calibration with reason 3 2111 /* TODO N PHY Spur Workaround */
475 b43_nphy_rssi_cal(dev, 2);
476 b43_nphy_rssi_cal(dev, 0);
477 b43_nphy_rssi_cal(dev, 1);
478 //TODO get TX gain
479 //TODO init superswitch
480 //TODO calibrate LO
481 //TODO idle TSSI TX pctl
482 //TODO TX power control power setup
483 //TODO table writes
484 //TODO TX power control coefficients
485 //TODO enable TX power control
486 //TODO control antenna selection
487 //TODO init radar detection
488 //TODO reset channel if changed
489 2112
490 b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n"); 2113 b43err(dev->wl, "IEEE 802.11n devices are not supported, yet.\n");
491 return 0; 2114 return 0;