linux/drivers/net/wireless/b43/phy_n.c
<<
>>
Prefs
   1/*
   2
   3  Broadcom B43 wireless driver
   4  IEEE 802.11n PHY support
   5
   6  Copyright (c) 2008 Michael Buesch <m@bues.ch>
   7  Copyright (c) 2010-2011 Rafał Miłecki <zajec5@gmail.com>
   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 "main.h"
  36
  37struct nphy_txgains {
  38        u16 txgm[2];
  39        u16 pga[2];
  40        u16 pad[2];
  41        u16 ipa[2];
  42};
  43
  44struct nphy_iqcal_params {
  45        u16 txgm;
  46        u16 pga;
  47        u16 pad;
  48        u16 ipa;
  49        u16 cal_gain;
  50        u16 ncorr[5];
  51};
  52
  53struct nphy_iq_est {
  54        s32 iq0_prod;
  55        u32 i0_pwr;
  56        u32 q0_pwr;
  57        s32 iq1_prod;
  58        u32 i1_pwr;
  59        u32 q1_pwr;
  60};
  61
  62enum b43_nphy_rf_sequence {
  63        B43_RFSEQ_RX2TX,
  64        B43_RFSEQ_TX2RX,
  65        B43_RFSEQ_RESET2RX,
  66        B43_RFSEQ_UPDATE_GAINH,
  67        B43_RFSEQ_UPDATE_GAINL,
  68        B43_RFSEQ_UPDATE_GAINU,
  69};
  70
  71enum b43_nphy_rssi_type {
  72        B43_NPHY_RSSI_X = 0,
  73        B43_NPHY_RSSI_Y,
  74        B43_NPHY_RSSI_Z,
  75        B43_NPHY_RSSI_PWRDET,
  76        B43_NPHY_RSSI_TSSI_I,
  77        B43_NPHY_RSSI_TSSI_Q,
  78        B43_NPHY_RSSI_TBD,
  79};
  80
  81static inline bool b43_nphy_ipa(struct b43_wldev *dev)
  82{
  83        enum ieee80211_band band = b43_current_band(dev->wl);
  84        return ((dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) ||
  85                (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ));
  86}
  87
  88/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetIpaGainTbl */
  89static const u32 *b43_nphy_get_ipa_gain_table(struct b43_wldev *dev)
  90{
  91        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
  92                if (dev->phy.rev >= 6) {
  93                        if (dev->dev->chip_id == 47162)
  94                                return txpwrctrl_tx_gain_ipa_rev5;
  95                        return txpwrctrl_tx_gain_ipa_rev6;
  96                } else if (dev->phy.rev >= 5) {
  97                        return txpwrctrl_tx_gain_ipa_rev5;
  98                } else {
  99                        return txpwrctrl_tx_gain_ipa;
 100                }
 101        } else {
 102                return txpwrctrl_tx_gain_ipa_5g;
 103        }
 104}
 105
 106/**************************************************
 107 * RF (just without b43_nphy_rf_control_intc_override)
 108 **************************************************/
 109
 110/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ForceRFSeq */
 111static void b43_nphy_force_rf_sequence(struct b43_wldev *dev,
 112                                       enum b43_nphy_rf_sequence seq)
 113{
 114        static const u16 trigger[] = {
 115                [B43_RFSEQ_RX2TX]               = B43_NPHY_RFSEQTR_RX2TX,
 116                [B43_RFSEQ_TX2RX]               = B43_NPHY_RFSEQTR_TX2RX,
 117                [B43_RFSEQ_RESET2RX]            = B43_NPHY_RFSEQTR_RST2RX,
 118                [B43_RFSEQ_UPDATE_GAINH]        = B43_NPHY_RFSEQTR_UPGH,
 119                [B43_RFSEQ_UPDATE_GAINL]        = B43_NPHY_RFSEQTR_UPGL,
 120                [B43_RFSEQ_UPDATE_GAINU]        = B43_NPHY_RFSEQTR_UPGU,
 121        };
 122        int i;
 123        u16 seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
 124
 125        B43_WARN_ON(seq >= ARRAY_SIZE(trigger));
 126
 127        b43_phy_set(dev, B43_NPHY_RFSEQMODE,
 128                    B43_NPHY_RFSEQMODE_CAOVER | B43_NPHY_RFSEQMODE_TROVER);
 129        b43_phy_set(dev, B43_NPHY_RFSEQTR, trigger[seq]);
 130        for (i = 0; i < 200; i++) {
 131                if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & trigger[seq]))
 132                        goto ok;
 133                msleep(1);
 134        }
 135        b43err(dev->wl, "RF sequence status timeout\n");
 136ok:
 137        b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
 138}
 139
 140/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlOverride */
 141static void b43_nphy_rf_control_override(struct b43_wldev *dev, u16 field,
 142                                                u16 value, u8 core, bool off)
 143{
 144        int i;
 145        u8 index = fls(field);
 146        u8 addr, en_addr, val_addr;
 147        /* we expect only one bit set */
 148        B43_WARN_ON(field & (~(1 << (index - 1))));
 149
 150        if (dev->phy.rev >= 3) {
 151                const struct nphy_rf_control_override_rev3 *rf_ctrl;
 152                for (i = 0; i < 2; i++) {
 153                        if (index == 0 || index == 16) {
 154                                b43err(dev->wl,
 155                                        "Unsupported RF Ctrl Override call\n");
 156                                return;
 157                        }
 158
 159                        rf_ctrl = &tbl_rf_control_override_rev3[index - 1];
 160                        en_addr = B43_PHY_N((i == 0) ?
 161                                rf_ctrl->en_addr0 : rf_ctrl->en_addr1);
 162                        val_addr = B43_PHY_N((i == 0) ?
 163                                rf_ctrl->val_addr0 : rf_ctrl->val_addr1);
 164
 165                        if (off) {
 166                                b43_phy_mask(dev, en_addr, ~(field));
 167                                b43_phy_mask(dev, val_addr,
 168                                                ~(rf_ctrl->val_mask));
 169                        } else {
 170                                if (core == 0 || ((1 << i) & core)) {
 171                                        b43_phy_set(dev, en_addr, field);
 172                                        b43_phy_maskset(dev, val_addr,
 173                                                ~(rf_ctrl->val_mask),
 174                                                (value << rf_ctrl->val_shift));
 175                                }
 176                        }
 177                }
 178        } else {
 179                const struct nphy_rf_control_override_rev2 *rf_ctrl;
 180                if (off) {
 181                        b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~(field));
 182                        value = 0;
 183                } else {
 184                        b43_phy_set(dev, B43_NPHY_RFCTL_OVER, field);
 185                }
 186
 187                for (i = 0; i < 2; i++) {
 188                        if (index <= 1 || index == 16) {
 189                                b43err(dev->wl,
 190                                        "Unsupported RF Ctrl Override call\n");
 191                                return;
 192                        }
 193
 194                        if (index == 2 || index == 10 ||
 195                            (index >= 13 && index <= 15)) {
 196                                core = 1;
 197                        }
 198
 199                        rf_ctrl = &tbl_rf_control_override_rev2[index - 2];
 200                        addr = B43_PHY_N((i == 0) ?
 201                                rf_ctrl->addr0 : rf_ctrl->addr1);
 202
 203                        if ((1 << i) & core)
 204                                b43_phy_maskset(dev, addr, ~(rf_ctrl->bmask),
 205                                                (value << rf_ctrl->shift));
 206
 207                        b43_phy_set(dev, B43_NPHY_RFCTL_OVER, 0x1);
 208                        b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
 209                                        B43_NPHY_RFCTL_CMD_START);
 210                        udelay(1);
 211                        b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, 0xFFFE);
 212                }
 213        }
 214}
 215
 216/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RFCtrlIntcOverride */
 217static void b43_nphy_rf_control_intc_override(struct b43_wldev *dev, u8 field,
 218                                                u16 value, u8 core)
 219{
 220        u8 i, j;
 221        u16 reg, tmp, val;
 222
 223        B43_WARN_ON(dev->phy.rev < 3);
 224        B43_WARN_ON(field > 4);
 225
 226        for (i = 0; i < 2; i++) {
 227                if ((core == 1 && i == 1) || (core == 2 && !i))
 228                        continue;
 229
 230                reg = (i == 0) ?
 231                        B43_NPHY_RFCTL_INTC1 : B43_NPHY_RFCTL_INTC2;
 232                b43_phy_mask(dev, reg, 0xFBFF);
 233
 234                switch (field) {
 235                case 0:
 236                        b43_phy_write(dev, reg, 0);
 237                        b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
 238                        break;
 239                case 1:
 240                        if (!i) {
 241                                b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC1,
 242                                                0xFC3F, (value << 6));
 243                                b43_phy_maskset(dev, B43_NPHY_TXF_40CO_B1S1,
 244                                                0xFFFE, 1);
 245                                b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
 246                                                B43_NPHY_RFCTL_CMD_START);
 247                                for (j = 0; j < 100; j++) {
 248                                        if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_START) {
 249                                                j = 0;
 250                                                break;
 251                                        }
 252                                        udelay(10);
 253                                }
 254                                if (j)
 255                                        b43err(dev->wl,
 256                                                "intc override timeout\n");
 257                                b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S1,
 258                                                0xFFFE);
 259                        } else {
 260                                b43_phy_maskset(dev, B43_NPHY_RFCTL_INTC2,
 261                                                0xFC3F, (value << 6));
 262                                b43_phy_maskset(dev, B43_NPHY_RFCTL_OVER,
 263                                                0xFFFE, 1);
 264                                b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
 265                                                B43_NPHY_RFCTL_CMD_RXTX);
 266                                for (j = 0; j < 100; j++) {
 267                                        if (b43_phy_read(dev, B43_NPHY_RFCTL_CMD) & B43_NPHY_RFCTL_CMD_RXTX) {
 268                                                j = 0;
 269                                                break;
 270                                        }
 271                                        udelay(10);
 272                                }
 273                                if (j)
 274                                        b43err(dev->wl,
 275                                                "intc override timeout\n");
 276                                b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
 277                                                0xFFFE);
 278                        }
 279                        break;
 280                case 2:
 281                        if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
 282                                tmp = 0x0020;
 283                                val = value << 5;
 284                        } else {
 285                                tmp = 0x0010;
 286                                val = value << 4;
 287                        }
 288                        b43_phy_maskset(dev, reg, ~tmp, val);
 289                        break;
 290                case 3:
 291                        if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
 292                                tmp = 0x0001;
 293                                val = value;
 294                        } else {
 295                                tmp = 0x0004;
 296                                val = value << 2;
 297                        }
 298                        b43_phy_maskset(dev, reg, ~tmp, val);
 299                        break;
 300                case 4:
 301                        if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
 302                                tmp = 0x0002;
 303                                val = value << 1;
 304                        } else {
 305                                tmp = 0x0008;
 306                                val = value << 3;
 307                        }
 308                        b43_phy_maskset(dev, reg, ~tmp, val);
 309                        break;
 310                }
 311        }
 312}
 313
 314/**************************************************
 315 * Various PHY ops
 316 **************************************************/
 317
 318/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
 319static void b43_nphy_write_clip_detection(struct b43_wldev *dev,
 320                                          const u16 *clip_st)
 321{
 322        b43_phy_write(dev, B43_NPHY_C1_CLIP1THRES, clip_st[0]);
 323        b43_phy_write(dev, B43_NPHY_C2_CLIP1THRES, clip_st[1]);
 324}
 325
 326/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/clip-detection */
 327static void b43_nphy_read_clip_detection(struct b43_wldev *dev, u16 *clip_st)
 328{
 329        clip_st[0] = b43_phy_read(dev, B43_NPHY_C1_CLIP1THRES);
 330        clip_st[1] = b43_phy_read(dev, B43_NPHY_C2_CLIP1THRES);
 331}
 332
 333/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/classifier */
 334static u16 b43_nphy_classifier(struct b43_wldev *dev, u16 mask, u16 val)
 335{
 336        u16 tmp;
 337
 338        if (dev->dev->core_rev == 16)
 339                b43_mac_suspend(dev);
 340
 341        tmp = b43_phy_read(dev, B43_NPHY_CLASSCTL);
 342        tmp &= (B43_NPHY_CLASSCTL_CCKEN | B43_NPHY_CLASSCTL_OFDMEN |
 343                B43_NPHY_CLASSCTL_WAITEDEN);
 344        tmp &= ~mask;
 345        tmp |= (val & mask);
 346        b43_phy_maskset(dev, B43_NPHY_CLASSCTL, 0xFFF8, tmp);
 347
 348        if (dev->dev->core_rev == 16)
 349                b43_mac_enable(dev);
 350
 351        return tmp;
 352}
 353
 354/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CCA */
 355static void b43_nphy_reset_cca(struct b43_wldev *dev)
 356{
 357        u16 bbcfg;
 358
 359        b43_phy_force_clock(dev, 1);
 360        bbcfg = b43_phy_read(dev, B43_NPHY_BBCFG);
 361        b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg | B43_NPHY_BBCFG_RSTCCA);
 362        udelay(1);
 363        b43_phy_write(dev, B43_NPHY_BBCFG, bbcfg & ~B43_NPHY_BBCFG_RSTCCA);
 364        b43_phy_force_clock(dev, 0);
 365        b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
 366}
 367
 368/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/carriersearch */
 369static void b43_nphy_stay_in_carrier_search(struct b43_wldev *dev, bool enable)
 370{
 371        struct b43_phy *phy = &dev->phy;
 372        struct b43_phy_n *nphy = phy->n;
 373
 374        if (enable) {
 375                static const u16 clip[] = { 0xFFFF, 0xFFFF };
 376                if (nphy->deaf_count++ == 0) {
 377                        nphy->classifier_state = b43_nphy_classifier(dev, 0, 0);
 378                        b43_nphy_classifier(dev, 0x7, 0);
 379                        b43_nphy_read_clip_detection(dev, nphy->clip_state);
 380                        b43_nphy_write_clip_detection(dev, clip);
 381                }
 382                b43_nphy_reset_cca(dev);
 383        } else {
 384                if (--nphy->deaf_count == 0) {
 385                        b43_nphy_classifier(dev, 0x7, nphy->classifier_state);
 386                        b43_nphy_write_clip_detection(dev, nphy->clip_state);
 387                }
 388        }
 389}
 390
 391/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/AdjustLnaGainTbl */
 392static void b43_nphy_adjust_lna_gain_table(struct b43_wldev *dev)
 393{
 394        struct b43_phy_n *nphy = dev->phy.n;
 395
 396        u8 i;
 397        s16 tmp;
 398        u16 data[4];
 399        s16 gain[2];
 400        u16 minmax[2];
 401        static const u16 lna_gain[4] = { -2, 10, 19, 25 };
 402
 403        if (nphy->hang_avoid)
 404                b43_nphy_stay_in_carrier_search(dev, 1);
 405
 406        if (nphy->gain_boost) {
 407                if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
 408                        gain[0] = 6;
 409                        gain[1] = 6;
 410                } else {
 411                        tmp = 40370 - 315 * dev->phy.channel;
 412                        gain[0] = ((tmp >> 13) + ((tmp >> 12) & 1));
 413                        tmp = 23242 - 224 * dev->phy.channel;
 414                        gain[1] = ((tmp >> 13) + ((tmp >> 12) & 1));
 415                }
 416        } else {
 417                gain[0] = 0;
 418                gain[1] = 0;
 419        }
 420
 421        for (i = 0; i < 2; i++) {
 422                if (nphy->elna_gain_config) {
 423                        data[0] = 19 + gain[i];
 424                        data[1] = 25 + gain[i];
 425                        data[2] = 25 + gain[i];
 426                        data[3] = 25 + gain[i];
 427                } else {
 428                        data[0] = lna_gain[0] + gain[i];
 429                        data[1] = lna_gain[1] + gain[i];
 430                        data[2] = lna_gain[2] + gain[i];
 431                        data[3] = lna_gain[3] + gain[i];
 432                }
 433                b43_ntab_write_bulk(dev, B43_NTAB16(i, 8), 4, data);
 434
 435                minmax[i] = 23 + gain[i];
 436        }
 437
 438        b43_phy_maskset(dev, B43_NPHY_C1_MINMAX_GAIN, ~B43_NPHY_C1_MINGAIN,
 439                                minmax[0] << B43_NPHY_C1_MINGAIN_SHIFT);
 440        b43_phy_maskset(dev, B43_NPHY_C2_MINMAX_GAIN, ~B43_NPHY_C2_MINGAIN,
 441                                minmax[1] << B43_NPHY_C2_MINGAIN_SHIFT);
 442
 443        if (nphy->hang_avoid)
 444                b43_nphy_stay_in_carrier_search(dev, 0);
 445}
 446
 447/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRfSeq */
 448static void b43_nphy_set_rf_sequence(struct b43_wldev *dev, u8 cmd,
 449                                        u8 *events, u8 *delays, u8 length)
 450{
 451        struct b43_phy_n *nphy = dev->phy.n;
 452        u8 i;
 453        u8 end = (dev->phy.rev >= 3) ? 0x1F : 0x0F;
 454        u16 offset1 = cmd << 4;
 455        u16 offset2 = offset1 + 0x80;
 456
 457        if (nphy->hang_avoid)
 458                b43_nphy_stay_in_carrier_search(dev, true);
 459
 460        b43_ntab_write_bulk(dev, B43_NTAB8(7, offset1), length, events);
 461        b43_ntab_write_bulk(dev, B43_NTAB8(7, offset2), length, delays);
 462
 463        for (i = length; i < 16; i++) {
 464                b43_ntab_write(dev, B43_NTAB8(7, offset1 + i), end);
 465                b43_ntab_write(dev, B43_NTAB8(7, offset2 + i), 1);
 466        }
 467
 468        if (nphy->hang_avoid)
 469                b43_nphy_stay_in_carrier_search(dev, false);
 470}
 471
 472/**************************************************
 473 * Radio 0x2056
 474 **************************************************/
 475
 476static void b43_chantab_radio_2056_upload(struct b43_wldev *dev,
 477                                const struct b43_nphy_channeltab_entry_rev3 *e)
 478{
 479        b43_radio_write(dev, B2056_SYN_PLL_VCOCAL1, e->radio_syn_pll_vcocal1);
 480        b43_radio_write(dev, B2056_SYN_PLL_VCOCAL2, e->radio_syn_pll_vcocal2);
 481        b43_radio_write(dev, B2056_SYN_PLL_REFDIV, e->radio_syn_pll_refdiv);
 482        b43_radio_write(dev, B2056_SYN_PLL_MMD2, e->radio_syn_pll_mmd2);
 483        b43_radio_write(dev, B2056_SYN_PLL_MMD1, e->radio_syn_pll_mmd1);
 484        b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1,
 485                                        e->radio_syn_pll_loopfilter1);
 486        b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2,
 487                                        e->radio_syn_pll_loopfilter2);
 488        b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER3,
 489                                        e->radio_syn_pll_loopfilter3);
 490        b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4,
 491                                        e->radio_syn_pll_loopfilter4);
 492        b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER5,
 493                                        e->radio_syn_pll_loopfilter5);
 494        b43_radio_write(dev, B2056_SYN_RESERVED_ADDR27,
 495                                        e->radio_syn_reserved_addr27);
 496        b43_radio_write(dev, B2056_SYN_RESERVED_ADDR28,
 497                                        e->radio_syn_reserved_addr28);
 498        b43_radio_write(dev, B2056_SYN_RESERVED_ADDR29,
 499                                        e->radio_syn_reserved_addr29);
 500        b43_radio_write(dev, B2056_SYN_LOGEN_VCOBUF1,
 501                                        e->radio_syn_logen_vcobuf1);
 502        b43_radio_write(dev, B2056_SYN_LOGEN_MIXER2, e->radio_syn_logen_mixer2);
 503        b43_radio_write(dev, B2056_SYN_LOGEN_BUF3, e->radio_syn_logen_buf3);
 504        b43_radio_write(dev, B2056_SYN_LOGEN_BUF4, e->radio_syn_logen_buf4);
 505
 506        b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA_TUNE,
 507                                        e->radio_rx0_lnaa_tune);
 508        b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG_TUNE,
 509                                        e->radio_rx0_lnag_tune);
 510
 511        b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAA_BOOST_TUNE,
 512                                        e->radio_tx0_intpaa_boost_tune);
 513        b43_radio_write(dev, B2056_TX0 | B2056_TX_INTPAG_BOOST_TUNE,
 514                                        e->radio_tx0_intpag_boost_tune);
 515        b43_radio_write(dev, B2056_TX0 | B2056_TX_PADA_BOOST_TUNE,
 516                                        e->radio_tx0_pada_boost_tune);
 517        b43_radio_write(dev, B2056_TX0 | B2056_TX_PADG_BOOST_TUNE,
 518                                        e->radio_tx0_padg_boost_tune);
 519        b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAA_BOOST_TUNE,
 520                                        e->radio_tx0_pgaa_boost_tune);
 521        b43_radio_write(dev, B2056_TX0 | B2056_TX_PGAG_BOOST_TUNE,
 522                                        e->radio_tx0_pgag_boost_tune);
 523        b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXA_BOOST_TUNE,
 524                                        e->radio_tx0_mixa_boost_tune);
 525        b43_radio_write(dev, B2056_TX0 | B2056_TX_MIXG_BOOST_TUNE,
 526                                        e->radio_tx0_mixg_boost_tune);
 527
 528        b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA_TUNE,
 529                                        e->radio_rx1_lnaa_tune);
 530        b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG_TUNE,
 531                                        e->radio_rx1_lnag_tune);
 532
 533        b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAA_BOOST_TUNE,
 534                                        e->radio_tx1_intpaa_boost_tune);
 535        b43_radio_write(dev, B2056_TX1 | B2056_TX_INTPAG_BOOST_TUNE,
 536                                        e->radio_tx1_intpag_boost_tune);
 537        b43_radio_write(dev, B2056_TX1 | B2056_TX_PADA_BOOST_TUNE,
 538                                        e->radio_tx1_pada_boost_tune);
 539        b43_radio_write(dev, B2056_TX1 | B2056_TX_PADG_BOOST_TUNE,
 540                                        e->radio_tx1_padg_boost_tune);
 541        b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAA_BOOST_TUNE,
 542                                        e->radio_tx1_pgaa_boost_tune);
 543        b43_radio_write(dev, B2056_TX1 | B2056_TX_PGAG_BOOST_TUNE,
 544                                        e->radio_tx1_pgag_boost_tune);
 545        b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXA_BOOST_TUNE,
 546                                        e->radio_tx1_mixa_boost_tune);
 547        b43_radio_write(dev, B2056_TX1 | B2056_TX_MIXG_BOOST_TUNE,
 548                                        e->radio_tx1_mixg_boost_tune);
 549}
 550
 551/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2056Setup */
 552static void b43_radio_2056_setup(struct b43_wldev *dev,
 553                                const struct b43_nphy_channeltab_entry_rev3 *e)
 554{
 555        struct ssb_sprom *sprom = dev->dev->bus_sprom;
 556        enum ieee80211_band band = b43_current_band(dev->wl);
 557        u16 offset;
 558        u8 i;
 559        u16 bias, cbias, pag_boost, pgag_boost, mixg_boost, padg_boost;
 560
 561        B43_WARN_ON(dev->phy.rev < 3);
 562
 563        b43_chantab_radio_2056_upload(dev, e);
 564        b2056_upload_syn_pll_cp2(dev, band == IEEE80211_BAND_5GHZ);
 565
 566        if (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
 567            b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
 568                b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
 569                b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
 570                if (dev->dev->chip_id == 0x4716) {
 571                        b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x14);
 572                        b43_radio_write(dev, B2056_SYN_PLL_CP2, 0);
 573                } else {
 574                        b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x0B);
 575                        b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x14);
 576                }
 577        }
 578        if (sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
 579            b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
 580                b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER1, 0x1F);
 581                b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER2, 0x1F);
 582                b43_radio_write(dev, B2056_SYN_PLL_LOOPFILTER4, 0x05);
 583                b43_radio_write(dev, B2056_SYN_PLL_CP2, 0x0C);
 584        }
 585
 586        if (dev->phy.n->ipa2g_on && band == IEEE80211_BAND_2GHZ) {
 587                for (i = 0; i < 2; i++) {
 588                        offset = i ? B2056_TX1 : B2056_TX0;
 589                        if (dev->phy.rev >= 5) {
 590                                b43_radio_write(dev,
 591                                        offset | B2056_TX_PADG_IDAC, 0xcc);
 592
 593                                if (dev->dev->chip_id == 0x4716) {
 594                                        bias = 0x40;
 595                                        cbias = 0x45;
 596                                        pag_boost = 0x5;
 597                                        pgag_boost = 0x33;
 598                                        mixg_boost = 0x55;
 599                                } else {
 600                                        bias = 0x25;
 601                                        cbias = 0x20;
 602                                        pag_boost = 0x4;
 603                                        pgag_boost = 0x03;
 604                                        mixg_boost = 0x65;
 605                                }
 606                                padg_boost = 0x77;
 607
 608                                b43_radio_write(dev,
 609                                        offset | B2056_TX_INTPAG_IMAIN_STAT,
 610                                        bias);
 611                                b43_radio_write(dev,
 612                                        offset | B2056_TX_INTPAG_IAUX_STAT,
 613                                        bias);
 614                                b43_radio_write(dev,
 615                                        offset | B2056_TX_INTPAG_CASCBIAS,
 616                                        cbias);
 617                                b43_radio_write(dev,
 618                                        offset | B2056_TX_INTPAG_BOOST_TUNE,
 619                                        pag_boost);
 620                                b43_radio_write(dev,
 621                                        offset | B2056_TX_PGAG_BOOST_TUNE,
 622                                        pgag_boost);
 623                                b43_radio_write(dev,
 624                                        offset | B2056_TX_PADG_BOOST_TUNE,
 625                                        padg_boost);
 626                                b43_radio_write(dev,
 627                                        offset | B2056_TX_MIXG_BOOST_TUNE,
 628                                        mixg_boost);
 629                        } else {
 630                                bias = dev->phy.is_40mhz ? 0x40 : 0x20;
 631                                b43_radio_write(dev,
 632                                        offset | B2056_TX_INTPAG_IMAIN_STAT,
 633                                        bias);
 634                                b43_radio_write(dev,
 635                                        offset | B2056_TX_INTPAG_IAUX_STAT,
 636                                        bias);
 637                                b43_radio_write(dev,
 638                                        offset | B2056_TX_INTPAG_CASCBIAS,
 639                                        0x30);
 640                        }
 641                        b43_radio_write(dev, offset | B2056_TX_PA_SPARE1, 0xee);
 642                }
 643        } else if (dev->phy.n->ipa5g_on && band == IEEE80211_BAND_5GHZ) {
 644                /* TODO */
 645        }
 646
 647        udelay(50);
 648        /* VCO calibration */
 649        b43_radio_write(dev, B2056_SYN_PLL_VCOCAL12, 0x00);
 650        b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
 651        b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x18);
 652        b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x38);
 653        b43_radio_write(dev, B2056_TX_INTPAA_PA_MISC, 0x39);
 654        udelay(300);
 655}
 656
 657static void b43_radio_init2056_pre(struct b43_wldev *dev)
 658{
 659        b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
 660                     ~B43_NPHY_RFCTL_CMD_CHIP0PU);
 661        /* Maybe wl meant to reset and set (order?) RFCTL_CMD_OEPORFORCE? */
 662        b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
 663                     B43_NPHY_RFCTL_CMD_OEPORFORCE);
 664        b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
 665                    ~B43_NPHY_RFCTL_CMD_OEPORFORCE);
 666        b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
 667                    B43_NPHY_RFCTL_CMD_CHIP0PU);
 668}
 669
 670static void b43_radio_init2056_post(struct b43_wldev *dev)
 671{
 672        b43_radio_set(dev, B2056_SYN_COM_CTRL, 0xB);
 673        b43_radio_set(dev, B2056_SYN_COM_PU, 0x2);
 674        b43_radio_set(dev, B2056_SYN_COM_RESET, 0x2);
 675        msleep(1);
 676        b43_radio_mask(dev, B2056_SYN_COM_RESET, ~0x2);
 677        b43_radio_mask(dev, B2056_SYN_PLL_MAST2, ~0xFC);
 678        b43_radio_mask(dev, B2056_SYN_RCCAL_CTRL0, ~0x1);
 679        /*
 680        if (nphy->init_por)
 681                Call Radio 2056 Recalibrate
 682        */
 683}
 684
 685/*
 686 * Initialize a Broadcom 2056 N-radio
 687 * http://bcm-v4.sipsolutions.net/802.11/Radio/2056/Init
 688 */
 689static void b43_radio_init2056(struct b43_wldev *dev)
 690{
 691        b43_radio_init2056_pre(dev);
 692        b2056_upload_inittabs(dev, 0, 0);
 693        b43_radio_init2056_post(dev);
 694}
 695
 696/**************************************************
 697 * Radio 0x2055
 698 **************************************************/
 699
 700static void b43_chantab_radio_upload(struct b43_wldev *dev,
 701                                const struct b43_nphy_channeltab_entry_rev2 *e)
 702{
 703        b43_radio_write(dev, B2055_PLL_REF, e->radio_pll_ref);
 704        b43_radio_write(dev, B2055_RF_PLLMOD0, e->radio_rf_pllmod0);
 705        b43_radio_write(dev, B2055_RF_PLLMOD1, e->radio_rf_pllmod1);
 706        b43_radio_write(dev, B2055_VCO_CAPTAIL, e->radio_vco_captail);
 707        b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
 708
 709        b43_radio_write(dev, B2055_VCO_CAL1, e->radio_vco_cal1);
 710        b43_radio_write(dev, B2055_VCO_CAL2, e->radio_vco_cal2);
 711        b43_radio_write(dev, B2055_PLL_LFC1, e->radio_pll_lfc1);
 712        b43_radio_write(dev, B2055_PLL_LFR1, e->radio_pll_lfr1);
 713        b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
 714
 715        b43_radio_write(dev, B2055_PLL_LFC2, e->radio_pll_lfc2);
 716        b43_radio_write(dev, B2055_LGBUF_CENBUF, e->radio_lgbuf_cenbuf);
 717        b43_radio_write(dev, B2055_LGEN_TUNE1, e->radio_lgen_tune1);
 718        b43_radio_write(dev, B2055_LGEN_TUNE2, e->radio_lgen_tune2);
 719        b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
 720
 721        b43_radio_write(dev, B2055_C1_LGBUF_ATUNE, e->radio_c1_lgbuf_atune);
 722        b43_radio_write(dev, B2055_C1_LGBUF_GTUNE, e->radio_c1_lgbuf_gtune);
 723        b43_radio_write(dev, B2055_C1_RX_RFR1, e->radio_c1_rx_rfr1);
 724        b43_radio_write(dev, B2055_C1_TX_PGAPADTN, e->radio_c1_tx_pgapadtn);
 725        b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
 726
 727        b43_radio_write(dev, B2055_C1_TX_MXBGTRIM, e->radio_c1_tx_mxbgtrim);
 728        b43_radio_write(dev, B2055_C2_LGBUF_ATUNE, e->radio_c2_lgbuf_atune);
 729        b43_radio_write(dev, B2055_C2_LGBUF_GTUNE, e->radio_c2_lgbuf_gtune);
 730        b43_radio_write(dev, B2055_C2_RX_RFR1, e->radio_c2_rx_rfr1);
 731        b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
 732
 733        b43_radio_write(dev, B2055_C2_TX_PGAPADTN, e->radio_c2_tx_pgapadtn);
 734        b43_radio_write(dev, B2055_C2_TX_MXBGTRIM, e->radio_c2_tx_mxbgtrim);
 735}
 736
 737/* http://bcm-v4.sipsolutions.net/802.11/PHY/Radio/2055Setup */
 738static void b43_radio_2055_setup(struct b43_wldev *dev,
 739                                const struct b43_nphy_channeltab_entry_rev2 *e)
 740{
 741        B43_WARN_ON(dev->phy.rev >= 3);
 742
 743        b43_chantab_radio_upload(dev, e);
 744        udelay(50);
 745        b43_radio_write(dev, B2055_VCO_CAL10, 0x05);
 746        b43_radio_write(dev, B2055_VCO_CAL10, 0x45);
 747        b43_read32(dev, B43_MMIO_MACCTL); /* flush writes */
 748        b43_radio_write(dev, B2055_VCO_CAL10, 0x65);
 749        udelay(300);
 750}
 751
 752static void b43_radio_init2055_pre(struct b43_wldev *dev)
 753{
 754        b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
 755                     ~B43_NPHY_RFCTL_CMD_PORFORCE);
 756        b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
 757                    B43_NPHY_RFCTL_CMD_CHIP0PU |
 758                    B43_NPHY_RFCTL_CMD_OEPORFORCE);
 759        b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
 760                    B43_NPHY_RFCTL_CMD_PORFORCE);
 761}
 762
 763static void b43_radio_init2055_post(struct b43_wldev *dev)
 764{
 765        struct b43_phy_n *nphy = dev->phy.n;
 766        struct ssb_sprom *sprom = dev->dev->bus_sprom;
 767        int i;
 768        u16 val;
 769        bool workaround = false;
 770
 771        if (sprom->revision < 4)
 772                workaround = (dev->dev->board_vendor != PCI_VENDOR_ID_BROADCOM
 773                              && dev->dev->board_type == 0x46D
 774                              && dev->dev->board_rev >= 0x41);
 775        else
 776                workaround =
 777                        !(sprom->boardflags2_lo & B43_BFL2_RXBB_INT_REG_DIS);
 778
 779        b43_radio_mask(dev, B2055_MASTER1, 0xFFF3);
 780        if (workaround) {
 781                b43_radio_mask(dev, B2055_C1_RX_BB_REG, 0x7F);
 782                b43_radio_mask(dev, B2055_C2_RX_BB_REG, 0x7F);
 783        }
 784        b43_radio_maskset(dev, B2055_RRCCAL_NOPTSEL, 0xFFC0, 0x2C);
 785        b43_radio_write(dev, B2055_CAL_MISC, 0x3C);
 786        b43_radio_mask(dev, B2055_CAL_MISC, 0xFFBE);
 787        b43_radio_set(dev, B2055_CAL_LPOCTL, 0x80);
 788        b43_radio_set(dev, B2055_CAL_MISC, 0x1);
 789        msleep(1);
 790        b43_radio_set(dev, B2055_CAL_MISC, 0x40);
 791        for (i = 0; i < 200; i++) {
 792                val = b43_radio_read(dev, B2055_CAL_COUT2);
 793                if (val & 0x80) {
 794                        i = 0;
 795                        break;
 796                }
 797                udelay(10);
 798        }
 799        if (i)
 800                b43err(dev->wl, "radio post init timeout\n");
 801        b43_radio_mask(dev, B2055_CAL_LPOCTL, 0xFF7F);
 802        b43_switch_channel(dev, dev->phy.channel);
 803        b43_radio_write(dev, B2055_C1_RX_BB_LPF, 0x9);
 804        b43_radio_write(dev, B2055_C2_RX_BB_LPF, 0x9);
 805        b43_radio_write(dev, B2055_C1_RX_BB_MIDACHP, 0x83);
 806        b43_radio_write(dev, B2055_C2_RX_BB_MIDACHP, 0x83);
 807        b43_radio_maskset(dev, B2055_C1_LNA_GAINBST, 0xFFF8, 0x6);
 808        b43_radio_maskset(dev, B2055_C2_LNA_GAINBST, 0xFFF8, 0x6);
 809        if (!nphy->gain_boost) {
 810                b43_radio_set(dev, B2055_C1_RX_RFSPC1, 0x2);
 811                b43_radio_set(dev, B2055_C2_RX_RFSPC1, 0x2);
 812        } else {
 813                b43_radio_mask(dev, B2055_C1_RX_RFSPC1, 0xFFFD);
 814                b43_radio_mask(dev, B2055_C2_RX_RFSPC1, 0xFFFD);
 815        }
 816        udelay(2);
 817}
 818
 819/*
 820 * Initialize a Broadcom 2055 N-radio
 821 * http://bcm-v4.sipsolutions.net/802.11/Radio/2055/Init
 822 */
 823static void b43_radio_init2055(struct b43_wldev *dev)
 824{
 825        b43_radio_init2055_pre(dev);
 826        if (b43_status(dev) < B43_STAT_INITIALIZED) {
 827                /* Follow wl, not specs. Do not force uploading all regs */
 828                b2055_upload_inittab(dev, 0, 0);
 829        } else {
 830                bool ghz5 = b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ;
 831                b2055_upload_inittab(dev, ghz5, 0);
 832        }
 833        b43_radio_init2055_post(dev);
 834}
 835
 836/**************************************************
 837 * Samples
 838 **************************************************/
 839
 840/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/LoadSampleTable */
 841static int b43_nphy_load_samples(struct b43_wldev *dev,
 842                                        struct b43_c32 *samples, u16 len) {
 843        struct b43_phy_n *nphy = dev->phy.n;
 844        u16 i;
 845        u32 *data;
 846
 847        data = kzalloc(len * sizeof(u32), GFP_KERNEL);
 848        if (!data) {
 849                b43err(dev->wl, "allocation for samples loading failed\n");
 850                return -ENOMEM;
 851        }
 852        if (nphy->hang_avoid)
 853                b43_nphy_stay_in_carrier_search(dev, 1);
 854
 855        for (i = 0; i < len; i++) {
 856                data[i] = (samples[i].i & 0x3FF << 10);
 857                data[i] |= samples[i].q & 0x3FF;
 858        }
 859        b43_ntab_write_bulk(dev, B43_NTAB32(17, 0), len, data);
 860
 861        kfree(data);
 862        if (nphy->hang_avoid)
 863                b43_nphy_stay_in_carrier_search(dev, 0);
 864        return 0;
 865}
 866
 867/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GenLoadSamples */
 868static u16 b43_nphy_gen_load_samples(struct b43_wldev *dev, u32 freq, u16 max,
 869                                        bool test)
 870{
 871        int i;
 872        u16 bw, len, rot, angle;
 873        struct b43_c32 *samples;
 874
 875
 876        bw = (dev->phy.is_40mhz) ? 40 : 20;
 877        len = bw << 3;
 878
 879        if (test) {
 880                if (b43_phy_read(dev, B43_NPHY_BBCFG) & B43_NPHY_BBCFG_RSTRX)
 881                        bw = 82;
 882                else
 883                        bw = 80;
 884
 885                if (dev->phy.is_40mhz)
 886                        bw <<= 1;
 887
 888                len = bw << 1;
 889        }
 890
 891        samples = kcalloc(len, sizeof(struct b43_c32), GFP_KERNEL);
 892        if (!samples) {
 893                b43err(dev->wl, "allocation for samples generation failed\n");
 894                return 0;
 895        }
 896        rot = (((freq * 36) / bw) << 16) / 100;
 897        angle = 0;
 898
 899        for (i = 0; i < len; i++) {
 900                samples[i] = b43_cordic(angle);
 901                angle += rot;
 902                samples[i].q = CORDIC_CONVERT(samples[i].q * max);
 903                samples[i].i = CORDIC_CONVERT(samples[i].i * max);
 904        }
 905
 906        i = b43_nphy_load_samples(dev, samples, len);
 907        kfree(samples);
 908        return (i < 0) ? 0 : len;
 909}
 910
 911/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RunSamples */
 912static void b43_nphy_run_samples(struct b43_wldev *dev, u16 samps, u16 loops,
 913                                        u16 wait, bool iqmode, bool dac_test)
 914{
 915        struct b43_phy_n *nphy = dev->phy.n;
 916        int i;
 917        u16 seq_mode;
 918        u32 tmp;
 919
 920        if (nphy->hang_avoid)
 921                b43_nphy_stay_in_carrier_search(dev, true);
 922
 923        if ((nphy->bb_mult_save & 0x80000000) == 0) {
 924                tmp = b43_ntab_read(dev, B43_NTAB16(15, 87));
 925                nphy->bb_mult_save = (tmp & 0xFFFF) | 0x80000000;
 926        }
 927
 928        if (!dev->phy.is_40mhz)
 929                tmp = 0x6464;
 930        else
 931                tmp = 0x4747;
 932        b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
 933
 934        if (nphy->hang_avoid)
 935                b43_nphy_stay_in_carrier_search(dev, false);
 936
 937        b43_phy_write(dev, B43_NPHY_SAMP_DEPCNT, (samps - 1));
 938
 939        if (loops != 0xFFFF)
 940                b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, (loops - 1));
 941        else
 942                b43_phy_write(dev, B43_NPHY_SAMP_LOOPCNT, loops);
 943
 944        b43_phy_write(dev, B43_NPHY_SAMP_WAITCNT, wait);
 945
 946        seq_mode = b43_phy_read(dev, B43_NPHY_RFSEQMODE);
 947
 948        b43_phy_set(dev, B43_NPHY_RFSEQMODE, B43_NPHY_RFSEQMODE_CAOVER);
 949        if (iqmode) {
 950                b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
 951                b43_phy_set(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8000);
 952        } else {
 953                if (dac_test)
 954                        b43_phy_write(dev, B43_NPHY_SAMP_CMD, 5);
 955                else
 956                        b43_phy_write(dev, B43_NPHY_SAMP_CMD, 1);
 957        }
 958        for (i = 0; i < 100; i++) {
 959                if (!(b43_phy_read(dev, B43_NPHY_RFSEQST) & 1)) {
 960                        i = 0;
 961                        break;
 962                }
 963                udelay(10);
 964        }
 965        if (i)
 966                b43err(dev->wl, "run samples timeout\n");
 967
 968        b43_phy_write(dev, B43_NPHY_RFSEQMODE, seq_mode);
 969}
 970
 971/**************************************************
 972 * RSSI
 973 **************************************************/
 974
 975/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ScaleOffsetRssi */
 976static void b43_nphy_scale_offset_rssi(struct b43_wldev *dev, u16 scale,
 977                                        s8 offset, u8 core, u8 rail,
 978                                        enum b43_nphy_rssi_type type)
 979{
 980        u16 tmp;
 981        bool core1or5 = (core == 1) || (core == 5);
 982        bool core2or5 = (core == 2) || (core == 5);
 983
 984        offset = clamp_val(offset, -32, 31);
 985        tmp = ((scale & 0x3F) << 8) | (offset & 0x3F);
 986
 987        if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
 988                b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, tmp);
 989        if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
 990                b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, tmp);
 991        if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Z))
 992                b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, tmp);
 993        if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Z))
 994                b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, tmp);
 995
 996        if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
 997                b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, tmp);
 998        if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
 999                b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, tmp);
1000        if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_X))
1001                b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, tmp);
1002        if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_X))
1003                b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, tmp);
1004
1005        if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
1006                b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, tmp);
1007        if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
1008                b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, tmp);
1009        if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_Y))
1010                b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, tmp);
1011        if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_Y))
1012                b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, tmp);
1013
1014        if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
1015                b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TBD, tmp);
1016        if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
1017                b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TBD, tmp);
1018        if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_TBD))
1019                b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TBD, tmp);
1020        if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_TBD))
1021                b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TBD, tmp);
1022
1023        if (core1or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
1024                b43_phy_write(dev, B43_NPHY_RSSIMC_0I_PWRDET, tmp);
1025        if (core1or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
1026                b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_PWRDET, tmp);
1027        if (core2or5 && (rail == 0) && (type == B43_NPHY_RSSI_PWRDET))
1028                b43_phy_write(dev, B43_NPHY_RSSIMC_1I_PWRDET, tmp);
1029        if (core2or5 && (rail == 1) && (type == B43_NPHY_RSSI_PWRDET))
1030                b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_PWRDET, tmp);
1031
1032        if (core1or5 && (type == B43_NPHY_RSSI_TSSI_I))
1033                b43_phy_write(dev, B43_NPHY_RSSIMC_0I_TSSI, tmp);
1034        if (core2or5 && (type == B43_NPHY_RSSI_TSSI_I))
1035                b43_phy_write(dev, B43_NPHY_RSSIMC_1I_TSSI, tmp);
1036
1037        if (core1or5 && (type == B43_NPHY_RSSI_TSSI_Q))
1038                b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_TSSI, tmp);
1039        if (core2or5 && (type == B43_NPHY_RSSI_TSSI_Q))
1040                b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_TSSI, tmp);
1041}
1042
1043static void b43_nphy_rev3_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
1044{
1045        u8 i;
1046        u16 reg, val;
1047
1048        if (code == 0) {
1049                b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, 0xFDFF);
1050                b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, 0xFDFF);
1051                b43_phy_mask(dev, B43_NPHY_AFECTL_C1, 0xFCFF);
1052                b43_phy_mask(dev, B43_NPHY_AFECTL_C2, 0xFCFF);
1053                b43_phy_mask(dev, B43_NPHY_TXF_40CO_B1S0, 0xFFDF);
1054                b43_phy_mask(dev, B43_NPHY_TXF_40CO_B32S1, 0xFFDF);
1055                b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0xFFC3);
1056                b43_phy_mask(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0xFFC3);
1057        } else {
1058                for (i = 0; i < 2; i++) {
1059                        if ((code == 1 && i == 1) || (code == 2 && !i))
1060                                continue;
1061
1062                        reg = (i == 0) ?
1063                                B43_NPHY_AFECTL_OVER1 : B43_NPHY_AFECTL_OVER;
1064                        b43_phy_maskset(dev, reg, 0xFDFF, 0x0200);
1065
1066                        if (type < 3) {
1067                                reg = (i == 0) ?
1068                                        B43_NPHY_AFECTL_C1 :
1069                                        B43_NPHY_AFECTL_C2;
1070                                b43_phy_maskset(dev, reg, 0xFCFF, 0);
1071
1072                                reg = (i == 0) ?
1073                                        B43_NPHY_RFCTL_LUT_TRSW_UP1 :
1074                                        B43_NPHY_RFCTL_LUT_TRSW_UP2;
1075                                b43_phy_maskset(dev, reg, 0xFFC3, 0);
1076
1077                                if (type == 0)
1078                                        val = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ? 4 : 8;
1079                                else if (type == 1)
1080                                        val = 16;
1081                                else
1082                                        val = 32;
1083                                b43_phy_set(dev, reg, val);
1084
1085                                reg = (i == 0) ?
1086                                        B43_NPHY_TXF_40CO_B1S0 :
1087                                        B43_NPHY_TXF_40CO_B32S1;
1088                                b43_phy_set(dev, reg, 0x0020);
1089                        } else {
1090                                if (type == 6)
1091                                        val = 0x0100;
1092                                else if (type == 3)
1093                                        val = 0x0200;
1094                                else
1095                                        val = 0x0300;
1096
1097                                reg = (i == 0) ?
1098                                        B43_NPHY_AFECTL_C1 :
1099                                        B43_NPHY_AFECTL_C2;
1100
1101                                b43_phy_maskset(dev, reg, 0xFCFF, val);
1102                                b43_phy_maskset(dev, reg, 0xF3FF, val << 2);
1103
1104                                if (type != 3 && type != 6) {
1105                                        enum ieee80211_band band =
1106                                                b43_current_band(dev->wl);
1107
1108                                        if (b43_nphy_ipa(dev))
1109                                                val = (band == IEEE80211_BAND_5GHZ) ? 0xC : 0xE;
1110                                        else
1111                                                val = 0x11;
1112                                        reg = (i == 0) ? 0x2000 : 0x3000;
1113                                        reg |= B2055_PADDRV;
1114                                        b43_radio_write16(dev, reg, val);
1115
1116                                        reg = (i == 0) ?
1117                                                B43_NPHY_AFECTL_OVER1 :
1118                                                B43_NPHY_AFECTL_OVER;
1119                                        b43_phy_set(dev, reg, 0x0200);
1120                                }
1121                        }
1122                }
1123        }
1124}
1125
1126static void b43_nphy_rev2_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
1127{
1128        u16 val;
1129
1130        if (type < 3)
1131                val = 0;
1132        else if (type == 6)
1133                val = 1;
1134        else if (type == 3)
1135                val = 2;
1136        else
1137                val = 3;
1138
1139        val = (val << 12) | (val << 14);
1140        b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, val);
1141        b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, val);
1142
1143        if (type < 3) {
1144                b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO1, 0xFFCF,
1145                                (type + 1) << 4);
1146                b43_phy_maskset(dev, B43_NPHY_RFCTL_RSSIO2, 0xFFCF,
1147                                (type + 1) << 4);
1148        }
1149
1150        if (code == 0) {
1151                b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x3000);
1152                if (type < 3) {
1153                        b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
1154                                ~(B43_NPHY_RFCTL_CMD_RXEN |
1155                                  B43_NPHY_RFCTL_CMD_CORESEL));
1156                        b43_phy_mask(dev, B43_NPHY_RFCTL_OVER,
1157                                ~(0x1 << 12 |
1158                                  0x1 << 5 |
1159                                  0x1 << 1 |
1160                                  0x1));
1161                        b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
1162                                ~B43_NPHY_RFCTL_CMD_START);
1163                        udelay(20);
1164                        b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
1165                }
1166        } else {
1167                b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x3000);
1168                if (type < 3) {
1169                        b43_phy_maskset(dev, B43_NPHY_RFCTL_CMD,
1170                                ~(B43_NPHY_RFCTL_CMD_RXEN |
1171                                  B43_NPHY_RFCTL_CMD_CORESEL),
1172                                (B43_NPHY_RFCTL_CMD_RXEN |
1173                                 code << B43_NPHY_RFCTL_CMD_CORESEL_SHIFT));
1174                        b43_phy_set(dev, B43_NPHY_RFCTL_OVER,
1175                                (0x1 << 12 |
1176                                  0x1 << 5 |
1177                                  0x1 << 1 |
1178                                  0x1));
1179                        b43_phy_set(dev, B43_NPHY_RFCTL_CMD,
1180                                B43_NPHY_RFCTL_CMD_START);
1181                        udelay(20);
1182                        b43_phy_mask(dev, B43_NPHY_RFCTL_OVER, ~0x1);
1183                }
1184        }
1185}
1186
1187/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSISel */
1188static void b43_nphy_rssi_select(struct b43_wldev *dev, u8 code, u8 type)
1189{
1190        if (dev->phy.rev >= 3)
1191                b43_nphy_rev3_rssi_select(dev, code, type);
1192        else
1193                b43_nphy_rev2_rssi_select(dev, code, type);
1194}
1195
1196/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetRssi2055Vcm */
1197static void b43_nphy_set_rssi_2055_vcm(struct b43_wldev *dev, u8 type, u8 *buf)
1198{
1199        int i;
1200        for (i = 0; i < 2; i++) {
1201                if (type == 2) {
1202                        if (i == 0) {
1203                                b43_radio_maskset(dev, B2055_C1_B0NB_RSSIVCM,
1204                                                  0xFC, buf[0]);
1205                                b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
1206                                                  0xFC, buf[1]);
1207                        } else {
1208                                b43_radio_maskset(dev, B2055_C2_B0NB_RSSIVCM,
1209                                                  0xFC, buf[2 * i]);
1210                                b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
1211                                                  0xFC, buf[2 * i + 1]);
1212                        }
1213                } else {
1214                        if (i == 0)
1215                                b43_radio_maskset(dev, B2055_C1_RX_BB_RSSICTL5,
1216                                                  0xF3, buf[0] << 2);
1217                        else
1218                                b43_radio_maskset(dev, B2055_C2_RX_BB_RSSICTL5,
1219                                                  0xF3, buf[2 * i + 1] << 2);
1220                }
1221        }
1222}
1223
1224/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PollRssi */
1225static int b43_nphy_poll_rssi(struct b43_wldev *dev, u8 type, s32 *buf,
1226                                u8 nsamp)
1227{
1228        int i;
1229        int out;
1230        u16 save_regs_phy[9];
1231        u16 s[2];
1232
1233        if (dev->phy.rev >= 3) {
1234                save_regs_phy[0] = b43_phy_read(dev,
1235                                                B43_NPHY_RFCTL_LUT_TRSW_UP1);
1236                save_regs_phy[1] = b43_phy_read(dev,
1237                                                B43_NPHY_RFCTL_LUT_TRSW_UP2);
1238                save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
1239                save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
1240                save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
1241                save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
1242                save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S0);
1243                save_regs_phy[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B32S1);
1244                save_regs_phy[8] = 0;
1245        } else {
1246                save_regs_phy[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
1247                save_regs_phy[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
1248                save_regs_phy[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
1249                save_regs_phy[3] = b43_phy_read(dev, B43_NPHY_RFCTL_CMD);
1250                save_regs_phy[4] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
1251                save_regs_phy[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
1252                save_regs_phy[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
1253                save_regs_phy[7] = 0;
1254                save_regs_phy[8] = 0;
1255        }
1256
1257        b43_nphy_rssi_select(dev, 5, type);
1258
1259        if (dev->phy.rev < 2) {
1260                save_regs_phy[8] = b43_phy_read(dev, B43_NPHY_GPIO_SEL);
1261                b43_phy_write(dev, B43_NPHY_GPIO_SEL, 5);
1262        }
1263
1264        for (i = 0; i < 4; i++)
1265                buf[i] = 0;
1266
1267        for (i = 0; i < nsamp; i++) {
1268                if (dev->phy.rev < 2) {
1269                        s[0] = b43_phy_read(dev, B43_NPHY_GPIO_LOOUT);
1270                        s[1] = b43_phy_read(dev, B43_NPHY_GPIO_HIOUT);
1271                } else {
1272                        s[0] = b43_phy_read(dev, B43_NPHY_RSSI1);
1273                        s[1] = b43_phy_read(dev, B43_NPHY_RSSI2);
1274                }
1275
1276                buf[0] += ((s8)((s[0] & 0x3F) << 2)) >> 2;
1277                buf[1] += ((s8)(((s[0] >> 8) & 0x3F) << 2)) >> 2;
1278                buf[2] += ((s8)((s[1] & 0x3F) << 2)) >> 2;
1279                buf[3] += ((s8)(((s[1] >> 8) & 0x3F) << 2)) >> 2;
1280        }
1281        out = (buf[0] & 0xFF) << 24 | (buf[1] & 0xFF) << 16 |
1282                (buf[2] & 0xFF) << 8 | (buf[3] & 0xFF);
1283
1284        if (dev->phy.rev < 2)
1285                b43_phy_write(dev, B43_NPHY_GPIO_SEL, save_regs_phy[8]);
1286
1287        if (dev->phy.rev >= 3) {
1288                b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1,
1289                                save_regs_phy[0]);
1290                b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2,
1291                                save_regs_phy[1]);
1292                b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[2]);
1293                b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[3]);
1294                b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, save_regs_phy[4]);
1295                b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[5]);
1296                b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, save_regs_phy[6]);
1297                b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, save_regs_phy[7]);
1298        } else {
1299                b43_phy_write(dev, B43_NPHY_AFECTL_C1, save_regs_phy[0]);
1300                b43_phy_write(dev, B43_NPHY_AFECTL_C2, save_regs_phy[1]);
1301                b43_phy_write(dev, B43_NPHY_AFECTL_OVER, save_regs_phy[2]);
1302                b43_phy_write(dev, B43_NPHY_RFCTL_CMD, save_regs_phy[3]);
1303                b43_phy_write(dev, B43_NPHY_RFCTL_OVER, save_regs_phy[4]);
1304                b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, save_regs_phy[5]);
1305                b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, save_regs_phy[6]);
1306        }
1307
1308        return out;
1309}
1310
1311/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal */
1312static void b43_nphy_rev2_rssi_cal(struct b43_wldev *dev, u8 type)
1313{
1314        int i, j;
1315        u8 state[4];
1316        u8 code, val;
1317        u16 class, override;
1318        u8 regs_save_radio[2];
1319        u16 regs_save_phy[2];
1320
1321        s8 offset[4];
1322        u8 core;
1323        u8 rail;
1324
1325        u16 clip_state[2];
1326        u16 clip_off[2] = { 0xFFFF, 0xFFFF };
1327        s32 results_min[4] = { };
1328        u8 vcm_final[4] = { };
1329        s32 results[4][4] = { };
1330        s32 miniq[4][2] = { };
1331
1332        if (type == 2) {
1333                code = 0;
1334                val = 6;
1335        } else if (type < 2) {
1336                code = 25;
1337                val = 4;
1338        } else {
1339                B43_WARN_ON(1);
1340                return;
1341        }
1342
1343        class = b43_nphy_classifier(dev, 0, 0);
1344        b43_nphy_classifier(dev, 7, 4);
1345        b43_nphy_read_clip_detection(dev, clip_state);
1346        b43_nphy_write_clip_detection(dev, clip_off);
1347
1348        if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
1349                override = 0x140;
1350        else
1351                override = 0x110;
1352
1353        regs_save_phy[0] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
1354        regs_save_radio[0] = b43_radio_read16(dev, B2055_C1_PD_RXTX);
1355        b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, override);
1356        b43_radio_write16(dev, B2055_C1_PD_RXTX, val);
1357
1358        regs_save_phy[1] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
1359        regs_save_radio[1] = b43_radio_read16(dev, B2055_C2_PD_RXTX);
1360        b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, override);
1361        b43_radio_write16(dev, B2055_C2_PD_RXTX, val);
1362
1363        state[0] = b43_radio_read16(dev, B2055_C1_PD_RSSIMISC) & 0x07;
1364        state[1] = b43_radio_read16(dev, B2055_C2_PD_RSSIMISC) & 0x07;
1365        b43_radio_mask(dev, B2055_C1_PD_RSSIMISC, 0xF8);
1366        b43_radio_mask(dev, B2055_C2_PD_RSSIMISC, 0xF8);
1367        state[2] = b43_radio_read16(dev, B2055_C1_SP_RSSI) & 0x07;
1368        state[3] = b43_radio_read16(dev, B2055_C2_SP_RSSI) & 0x07;
1369
1370        b43_nphy_rssi_select(dev, 5, type);
1371        b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 0, type);
1372        b43_nphy_scale_offset_rssi(dev, 0, 0, 5, 1, type);
1373
1374        for (i = 0; i < 4; i++) {
1375                u8 tmp[4];
1376                for (j = 0; j < 4; j++)
1377                        tmp[j] = i;
1378                if (type != 1)
1379                        b43_nphy_set_rssi_2055_vcm(dev, type, tmp);
1380                b43_nphy_poll_rssi(dev, type, results[i], 8);
1381                if (type < 2)
1382                        for (j = 0; j < 2; j++)
1383                                miniq[i][j] = min(results[i][2 * j],
1384                                                results[i][2 * j + 1]);
1385        }
1386
1387        for (i = 0; i < 4; i++) {
1388                s32 mind = 40;
1389                u8 minvcm = 0;
1390                s32 minpoll = 249;
1391                s32 curr;
1392                for (j = 0; j < 4; j++) {
1393                        if (type == 2)
1394                                curr = abs(results[j][i]);
1395                        else
1396                                curr = abs(miniq[j][i / 2] - code * 8);
1397
1398                        if (curr < mind) {
1399                                mind = curr;
1400                                minvcm = j;
1401                        }
1402
1403                        if (results[j][i] < minpoll)
1404                                minpoll = results[j][i];
1405                }
1406                results_min[i] = minpoll;
1407                vcm_final[i] = minvcm;
1408        }
1409
1410        if (type != 1)
1411                b43_nphy_set_rssi_2055_vcm(dev, type, vcm_final);
1412
1413        for (i = 0; i < 4; i++) {
1414                offset[i] = (code * 8) - results[vcm_final[i]][i];
1415
1416                if (offset[i] < 0)
1417                        offset[i] = -((abs(offset[i]) + 4) / 8);
1418                else
1419                        offset[i] = (offset[i] + 4) / 8;
1420
1421                if (results_min[i] == 248)
1422                        offset[i] = code - 32;
1423
1424                core = (i / 2) ? 2 : 1;
1425                rail = (i % 2) ? 1 : 0;
1426
1427                b43_nphy_scale_offset_rssi(dev, 0, offset[i], core, rail,
1428                                                type);
1429        }
1430
1431        b43_radio_maskset(dev, B2055_C1_PD_RSSIMISC, 0xF8, state[0]);
1432        b43_radio_maskset(dev, B2055_C2_PD_RSSIMISC, 0xF8, state[1]);
1433
1434        switch (state[2]) {
1435        case 1:
1436                b43_nphy_rssi_select(dev, 1, 2);
1437                break;
1438        case 4:
1439                b43_nphy_rssi_select(dev, 1, 0);
1440                break;
1441        case 2:
1442                b43_nphy_rssi_select(dev, 1, 1);
1443                break;
1444        default:
1445                b43_nphy_rssi_select(dev, 1, 1);
1446                break;
1447        }
1448
1449        switch (state[3]) {
1450        case 1:
1451                b43_nphy_rssi_select(dev, 2, 2);
1452                break;
1453        case 4:
1454                b43_nphy_rssi_select(dev, 2, 0);
1455                break;
1456        default:
1457                b43_nphy_rssi_select(dev, 2, 1);
1458                break;
1459        }
1460
1461        b43_nphy_rssi_select(dev, 0, type);
1462
1463        b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs_save_phy[0]);
1464        b43_radio_write16(dev, B2055_C1_PD_RXTX, regs_save_radio[0]);
1465        b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs_save_phy[1]);
1466        b43_radio_write16(dev, B2055_C2_PD_RXTX, regs_save_radio[1]);
1467
1468        b43_nphy_classifier(dev, 7, class);
1469        b43_nphy_write_clip_detection(dev, clip_state);
1470        /* Specs don't say about reset here, but it makes wl and b43 dumps
1471           identical, it really seems wl performs this */
1472        b43_nphy_reset_cca(dev);
1473}
1474
1475/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICalRev3 */
1476static void b43_nphy_rev3_rssi_cal(struct b43_wldev *dev)
1477{
1478        /* TODO */
1479}
1480
1481/*
1482 * RSSI Calibration
1483 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RSSICal
1484 */
1485static void b43_nphy_rssi_cal(struct b43_wldev *dev)
1486{
1487        if (dev->phy.rev >= 3) {
1488                b43_nphy_rev3_rssi_cal(dev);
1489        } else {
1490                b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Z);
1491                b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_X);
1492                b43_nphy_rev2_rssi_cal(dev, B43_NPHY_RSSI_Y);
1493        }
1494}
1495
1496/**************************************************
1497 * Workarounds
1498 **************************************************/
1499
1500static void b43_nphy_gain_ctl_workarounds_rev3plus(struct b43_wldev *dev)
1501{
1502        struct ssb_sprom *sprom = dev->dev->bus_sprom;
1503
1504        bool ghz5;
1505        bool ext_lna;
1506        u16 rssi_gain;
1507        struct nphy_gain_ctl_workaround_entry *e;
1508        u8 lpf_gain[6] = { 0x00, 0x06, 0x0C, 0x12, 0x12, 0x12 };
1509        u8 lpf_bits[6] = { 0, 1, 2, 3, 3, 3 };
1510
1511        /* Prepare values */
1512        ghz5 = b43_phy_read(dev, B43_NPHY_BANDCTL)
1513                & B43_NPHY_BANDCTL_5GHZ;
1514        ext_lna = ghz5 ? sprom->boardflags_hi & B43_BFH_EXTLNA_5GHZ :
1515                sprom->boardflags_lo & B43_BFL_EXTLNA;
1516        e = b43_nphy_get_gain_ctl_workaround_ent(dev, ghz5, ext_lna);
1517        if (ghz5 && dev->phy.rev >= 5)
1518                rssi_gain = 0x90;
1519        else
1520                rssi_gain = 0x50;
1521
1522        b43_phy_set(dev, B43_NPHY_RXCTL, 0x0040);
1523
1524        /* Set Clip 2 detect */
1525        b43_phy_set(dev, B43_NPHY_C1_CGAINI,
1526                        B43_NPHY_C1_CGAINI_CL2DETECT);
1527        b43_phy_set(dev, B43_NPHY_C2_CGAINI,
1528                        B43_NPHY_C2_CGAINI_CL2DETECT);
1529
1530        b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAG1_IDAC,
1531                        0x17);
1532        b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAG1_IDAC,
1533                        0x17);
1534        b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAG2_IDAC, 0xF0);
1535        b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAG2_IDAC, 0xF0);
1536        b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_POLE, 0x00);
1537        b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_POLE, 0x00);
1538        b43_radio_write(dev, B2056_RX0 | B2056_RX_RSSI_GAIN,
1539                        rssi_gain);
1540        b43_radio_write(dev, B2056_RX1 | B2056_RX_RSSI_GAIN,
1541                        rssi_gain);
1542        b43_radio_write(dev, B2056_RX0 | B2056_RX_BIASPOLE_LNAA1_IDAC,
1543                        0x17);
1544        b43_radio_write(dev, B2056_RX1 | B2056_RX_BIASPOLE_LNAA1_IDAC,
1545                        0x17);
1546        b43_radio_write(dev, B2056_RX0 | B2056_RX_LNAA2_IDAC, 0xFF);
1547        b43_radio_write(dev, B2056_RX1 | B2056_RX_LNAA2_IDAC, 0xFF);
1548
1549        b43_ntab_write_bulk(dev, B43_NTAB8(0, 8), 4, e->lna1_gain);
1550        b43_ntab_write_bulk(dev, B43_NTAB8(1, 8), 4, e->lna1_gain);
1551        b43_ntab_write_bulk(dev, B43_NTAB8(0, 16), 4, e->lna2_gain);
1552        b43_ntab_write_bulk(dev, B43_NTAB8(1, 16), 4, e->lna2_gain);
1553        b43_ntab_write_bulk(dev, B43_NTAB8(0, 32), 10, e->gain_db);
1554        b43_ntab_write_bulk(dev, B43_NTAB8(1, 32), 10, e->gain_db);
1555        b43_ntab_write_bulk(dev, B43_NTAB8(2, 32), 10, e->gain_bits);
1556        b43_ntab_write_bulk(dev, B43_NTAB8(3, 32), 10, e->gain_bits);
1557        b43_ntab_write_bulk(dev, B43_NTAB8(0, 0x40), 6, lpf_gain);
1558        b43_ntab_write_bulk(dev, B43_NTAB8(1, 0x40), 6, lpf_gain);
1559        b43_ntab_write_bulk(dev, B43_NTAB8(2, 0x40), 6, lpf_bits);
1560        b43_ntab_write_bulk(dev, B43_NTAB8(3, 0x40), 6, lpf_bits);
1561
1562        b43_phy_write(dev, B43_NPHY_C1_INITGAIN, e->init_gain);
1563        b43_phy_write(dev, 0x2A7, e->init_gain);
1564        b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x106), 2,
1565                                e->rfseq_init);
1566
1567        /* TODO: check defines. Do not match variables names */
1568        b43_phy_write(dev, B43_NPHY_C1_CLIP1_MEDGAIN, e->cliphi_gain);
1569        b43_phy_write(dev, 0x2A9, e->cliphi_gain);
1570        b43_phy_write(dev, B43_NPHY_C1_CLIP2_GAIN, e->clipmd_gain);
1571        b43_phy_write(dev, 0x2AB, e->clipmd_gain);
1572        b43_phy_write(dev, B43_NPHY_C2_CLIP1_HIGAIN, e->cliplo_gain);
1573        b43_phy_write(dev, 0x2AD, e->cliplo_gain);
1574
1575        b43_phy_maskset(dev, 0x27D, 0xFF00, e->crsmin);
1576        b43_phy_maskset(dev, 0x280, 0xFF00, e->crsminl);
1577        b43_phy_maskset(dev, 0x283, 0xFF00, e->crsminu);
1578        b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, e->nbclip);
1579        b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, e->nbclip);
1580        b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
1581                        ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, e->wlclip);
1582        b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
1583                        ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, e->wlclip);
1584        b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
1585}
1586
1587static void b43_nphy_gain_ctl_workarounds_rev1_2(struct b43_wldev *dev)
1588{
1589        struct b43_phy_n *nphy = dev->phy.n;
1590
1591        u8 i, j;
1592        u8 code;
1593        u16 tmp;
1594        u8 rfseq_events[3] = { 6, 8, 7 };
1595        u8 rfseq_delays[3] = { 10, 30, 1 };
1596
1597        /* Set Clip 2 detect */
1598        b43_phy_set(dev, B43_NPHY_C1_CGAINI, B43_NPHY_C1_CGAINI_CL2DETECT);
1599        b43_phy_set(dev, B43_NPHY_C2_CGAINI, B43_NPHY_C2_CGAINI_CL2DETECT);
1600
1601        /* Set narrowband clip threshold */
1602        b43_phy_write(dev, B43_NPHY_C1_NBCLIPTHRES, 0x84);
1603        b43_phy_write(dev, B43_NPHY_C2_NBCLIPTHRES, 0x84);
1604
1605        if (!dev->phy.is_40mhz) {
1606                /* Set dwell lengths */
1607                b43_phy_write(dev, B43_NPHY_CLIP1_NBDWELL_LEN, 0x002B);
1608                b43_phy_write(dev, B43_NPHY_CLIP2_NBDWELL_LEN, 0x002B);
1609                b43_phy_write(dev, B43_NPHY_W1CLIP1_DWELL_LEN, 0x0009);
1610                b43_phy_write(dev, B43_NPHY_W1CLIP2_DWELL_LEN, 0x0009);
1611        }
1612
1613        /* Set wideband clip 2 threshold */
1614        b43_phy_maskset(dev, B43_NPHY_C1_CLIPWBTHRES,
1615                        ~B43_NPHY_C1_CLIPWBTHRES_CLIP2, 21);
1616        b43_phy_maskset(dev, B43_NPHY_C2_CLIPWBTHRES,
1617                        ~B43_NPHY_C2_CLIPWBTHRES_CLIP2, 21);
1618
1619        if (!dev->phy.is_40mhz) {
1620                b43_phy_maskset(dev, B43_NPHY_C1_CGAINI,
1621                        ~B43_NPHY_C1_CGAINI_GAINBKOFF, 0x1);
1622                b43_phy_maskset(dev, B43_NPHY_C2_CGAINI,
1623                        ~B43_NPHY_C2_CGAINI_GAINBKOFF, 0x1);
1624                b43_phy_maskset(dev, B43_NPHY_C1_CCK_CGAINI,
1625                        ~B43_NPHY_C1_CCK_CGAINI_GAINBKOFF, 0x1);
1626                b43_phy_maskset(dev, B43_NPHY_C2_CCK_CGAINI,
1627                        ~B43_NPHY_C2_CCK_CGAINI_GAINBKOFF, 0x1);
1628        }
1629
1630        b43_phy_write(dev, B43_NPHY_CCK_SHIFTB_REF, 0x809C);
1631
1632        if (nphy->gain_boost) {
1633                if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ &&
1634                        dev->phy.is_40mhz)
1635                        code = 4;
1636                else
1637                        code = 5;
1638        } else {
1639                code = dev->phy.is_40mhz ? 6 : 7;
1640        }
1641
1642        /* Set HPVGA2 index */
1643        b43_phy_maskset(dev, B43_NPHY_C1_INITGAIN, ~B43_NPHY_C1_INITGAIN_HPVGA2,
1644                        code << B43_NPHY_C1_INITGAIN_HPVGA2_SHIFT);
1645        b43_phy_maskset(dev, B43_NPHY_C2_INITGAIN, ~B43_NPHY_C2_INITGAIN_HPVGA2,
1646                        code << B43_NPHY_C2_INITGAIN_HPVGA2_SHIFT);
1647
1648        b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
1649        /* specs say about 2 loops, but wl does 4 */
1650        for (i = 0; i < 4; i++)
1651                b43_phy_write(dev, B43_NPHY_TABLE_DATALO, (code << 8 | 0x7C));
1652
1653        b43_nphy_adjust_lna_gain_table(dev);
1654
1655        if (nphy->elna_gain_config) {
1656                b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0808);
1657                b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
1658                b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1659                b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1660                b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1661
1662                b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x0C08);
1663                b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x0);
1664                b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1665                b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1666                b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0x1);
1667
1668                b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x1D06);
1669                /* specs say about 2 loops, but wl does 4 */
1670                for (i = 0; i < 4; i++)
1671                        b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
1672                                                (code << 8 | 0x74));
1673        }
1674
1675        if (dev->phy.rev == 2) {
1676                for (i = 0; i < 4; i++) {
1677                        b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
1678                                        (0x0400 * i) + 0x0020);
1679                        for (j = 0; j < 21; j++) {
1680                                tmp = j * (i < 2 ? 3 : 1);
1681                                b43_phy_write(dev,
1682                                        B43_NPHY_TABLE_DATALO, tmp);
1683                        }
1684                }
1685        }
1686
1687        b43_nphy_set_rf_sequence(dev, 5, rfseq_events, rfseq_delays, 3);
1688        b43_phy_maskset(dev, B43_NPHY_OVER_DGAIN1,
1689                ~B43_NPHY_OVER_DGAIN_CCKDGECV & 0xFFFF,
1690                0x5A << B43_NPHY_OVER_DGAIN_CCKDGECV_SHIFT);
1691
1692        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
1693                b43_phy_maskset(dev, B43_PHY_N(0xC5D), 0xFF80, 4);
1694}
1695
1696/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/WorkaroundsGainCtrl */
1697static void b43_nphy_gain_ctl_workarounds(struct b43_wldev *dev)
1698{
1699        if (dev->phy.rev >= 3)
1700                b43_nphy_gain_ctl_workarounds_rev3plus(dev);
1701        else
1702                b43_nphy_gain_ctl_workarounds_rev1_2(dev);
1703}
1704
1705static void b43_nphy_workarounds_rev3plus(struct b43_wldev *dev)
1706{
1707        struct b43_phy_n *nphy = dev->phy.n;
1708        struct ssb_sprom *sprom = dev->dev->bus_sprom;
1709
1710        /* TX to RX */
1711        u8 tx2rx_events[8] = { 0x4, 0x3, 0x6, 0x5, 0x2, 0x1, 0x8, 0x1F };
1712        u8 tx2rx_delays[8] = { 8, 4, 2, 2, 4, 4, 6, 1 };
1713        /* RX to TX */
1714        u8 rx2tx_events_ipa[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0xF, 0x3,
1715                                        0x1F };
1716        u8 rx2tx_delays_ipa[9] = { 8, 6, 6, 4, 4, 16, 43, 1, 1 };
1717        u8 rx2tx_events[9] = { 0x0, 0x1, 0x2, 0x8, 0x5, 0x6, 0x3, 0x4, 0x1F };
1718        u8 rx2tx_delays[9] = { 8, 6, 6, 4, 4, 18, 42, 1, 1 };
1719
1720        u16 tmp16;
1721        u32 tmp32;
1722
1723        b43_phy_write(dev, 0x23f, 0x1f8);
1724        b43_phy_write(dev, 0x240, 0x1f8);
1725
1726        tmp32 = b43_ntab_read(dev, B43_NTAB32(30, 0));
1727        tmp32 &= 0xffffff;
1728        b43_ntab_write(dev, B43_NTAB32(30, 0), tmp32);
1729
1730        b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x0125);
1731        b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x01B3);
1732        b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x0105);
1733        b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x016E);
1734        b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0x00CD);
1735        b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x0020);
1736
1737        b43_phy_write(dev, B43_NPHY_C2_CLIP1_MEDGAIN, 0x000C);
1738        b43_phy_write(dev, 0x2AE, 0x000C);
1739
1740        /* TX to RX */
1741        b43_nphy_set_rf_sequence(dev, 1, tx2rx_events, tx2rx_delays,
1742                                 ARRAY_SIZE(tx2rx_events));
1743
1744        /* RX to TX */
1745        if (b43_nphy_ipa(dev))
1746                b43_nphy_set_rf_sequence(dev, 0, rx2tx_events_ipa,
1747                                rx2tx_delays_ipa, ARRAY_SIZE(rx2tx_events_ipa));
1748        if (nphy->hw_phyrxchain != 3 &&
1749            nphy->hw_phyrxchain != nphy->hw_phytxchain) {
1750                if (b43_nphy_ipa(dev)) {
1751                        rx2tx_delays[5] = 59;
1752                        rx2tx_delays[6] = 1;
1753                        rx2tx_events[7] = 0x1F;
1754                }
1755                b43_nphy_set_rf_sequence(dev, 1, rx2tx_events, rx2tx_delays,
1756                                         ARRAY_SIZE(rx2tx_events));
1757        }
1758
1759        tmp16 = (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) ?
1760                0x2 : 0x9C40;
1761        b43_phy_write(dev, B43_NPHY_ENDROP_TLEN, tmp16);
1762
1763        b43_phy_maskset(dev, 0x294, 0xF0FF, 0x0700);
1764
1765        b43_ntab_write(dev, B43_NTAB32(16, 3), 0x18D);
1766        b43_ntab_write(dev, B43_NTAB32(16, 127), 0x18D);
1767
1768        b43_nphy_gain_ctl_workarounds(dev);
1769
1770        b43_ntab_write(dev, B43_NTAB16(8, 0), 2);
1771        b43_ntab_write(dev, B43_NTAB16(8, 16), 2);
1772
1773        /* TODO */
1774
1775        b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_MAST_BIAS, 0x00);
1776        b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_MAST_BIAS, 0x00);
1777        b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
1778        b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_MAIN, 0x06);
1779        b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_BIAS_AUX, 0x07);
1780        b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_BIAS_AUX, 0x07);
1781        b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_LOB_BIAS, 0x88);
1782        b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_LOB_BIAS, 0x88);
1783        b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
1784        b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXA_CMFB_IDAC, 0x00);
1785        b43_radio_write(dev, B2056_RX0 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
1786        b43_radio_write(dev, B2056_RX1 | B2056_RX_MIXG_CMFB_IDAC, 0x00);
1787
1788        /* N PHY WAR TX Chain Update with hw_phytxchain as argument */
1789
1790        if ((sprom->boardflags2_lo & B43_BFL2_APLL_WAR &&
1791             b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
1792            (sprom->boardflags2_lo & B43_BFL2_GPLL_WAR &&
1793             b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ))
1794                tmp32 = 0x00088888;
1795        else
1796                tmp32 = 0x88888888;
1797        b43_ntab_write(dev, B43_NTAB32(30, 1), tmp32);
1798        b43_ntab_write(dev, B43_NTAB32(30, 2), tmp32);
1799        b43_ntab_write(dev, B43_NTAB32(30, 3), tmp32);
1800
1801        if (dev->phy.rev == 4 &&
1802                b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
1803                b43_radio_write(dev, B2056_TX0 | B2056_TX_GMBB_IDAC,
1804                                0x70);
1805                b43_radio_write(dev, B2056_TX1 | B2056_TX_GMBB_IDAC,
1806                                0x70);
1807        }
1808
1809        b43_phy_write(dev, 0x224, 0x03eb);
1810        b43_phy_write(dev, 0x225, 0x03eb);
1811        b43_phy_write(dev, 0x226, 0x0341);
1812        b43_phy_write(dev, 0x227, 0x0341);
1813        b43_phy_write(dev, 0x228, 0x042b);
1814        b43_phy_write(dev, 0x229, 0x042b);
1815        b43_phy_write(dev, 0x22a, 0x0381);
1816        b43_phy_write(dev, 0x22b, 0x0381);
1817        b43_phy_write(dev, 0x22c, 0x042b);
1818        b43_phy_write(dev, 0x22d, 0x042b);
1819        b43_phy_write(dev, 0x22e, 0x0381);
1820        b43_phy_write(dev, 0x22f, 0x0381);
1821}
1822
1823static void b43_nphy_workarounds_rev1_2(struct b43_wldev *dev)
1824{
1825        struct ssb_sprom *sprom = dev->dev->bus_sprom;
1826        struct b43_phy *phy = &dev->phy;
1827        struct b43_phy_n *nphy = phy->n;
1828
1829        u8 events1[7] = { 0x0, 0x1, 0x2, 0x8, 0x4, 0x5, 0x3 };
1830        u8 delays1[7] = { 0x8, 0x6, 0x6, 0x2, 0x4, 0x3C, 0x1 };
1831
1832        u8 events2[7] = { 0x0, 0x3, 0x5, 0x4, 0x2, 0x1, 0x8 };
1833        u8 delays2[7] = { 0x8, 0x6, 0x2, 0x4, 0x4, 0x6, 0x1 };
1834
1835        if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ &&
1836            nphy->band5g_pwrgain) {
1837                b43_radio_mask(dev, B2055_C1_TX_RF_SPARE, ~0x8);
1838                b43_radio_mask(dev, B2055_C2_TX_RF_SPARE, ~0x8);
1839        } else {
1840                b43_radio_set(dev, B2055_C1_TX_RF_SPARE, 0x8);
1841                b43_radio_set(dev, B2055_C2_TX_RF_SPARE, 0x8);
1842        }
1843
1844        b43_ntab_write(dev, B43_NTAB16(8, 0x00), 0x000A);
1845        b43_ntab_write(dev, B43_NTAB16(8, 0x10), 0x000A);
1846        b43_ntab_write(dev, B43_NTAB16(8, 0x02), 0xCDAA);
1847        b43_ntab_write(dev, B43_NTAB16(8, 0x12), 0xCDAA);
1848
1849        if (dev->phy.rev < 2) {
1850                b43_ntab_write(dev, B43_NTAB16(8, 0x08), 0x0000);
1851                b43_ntab_write(dev, B43_NTAB16(8, 0x18), 0x0000);
1852                b43_ntab_write(dev, B43_NTAB16(8, 0x07), 0x7AAB);
1853                b43_ntab_write(dev, B43_NTAB16(8, 0x17), 0x7AAB);
1854                b43_ntab_write(dev, B43_NTAB16(8, 0x06), 0x0800);
1855                b43_ntab_write(dev, B43_NTAB16(8, 0x16), 0x0800);
1856        }
1857
1858        b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
1859        b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
1860        b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
1861        b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
1862
1863        if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD &&
1864            dev->dev->board_type == 0x8B) {
1865                delays1[0] = 0x1;
1866                delays1[5] = 0x14;
1867        }
1868        b43_nphy_set_rf_sequence(dev, 0, events1, delays1, 7);
1869        b43_nphy_set_rf_sequence(dev, 1, events2, delays2, 7);
1870
1871        b43_nphy_gain_ctl_workarounds(dev);
1872
1873        if (dev->phy.rev < 2) {
1874                if (b43_phy_read(dev, B43_NPHY_RXCTL) & 0x2)
1875                        b43_hf_write(dev, b43_hf_read(dev) |
1876                                        B43_HF_MLADVW);
1877        } else if (dev->phy.rev == 2) {
1878                b43_phy_write(dev, B43_NPHY_CRSCHECK2, 0);
1879                b43_phy_write(dev, B43_NPHY_CRSCHECK3, 0);
1880        }
1881
1882        if (dev->phy.rev < 2)
1883                b43_phy_mask(dev, B43_NPHY_SCRAM_SIGCTL,
1884                                ~B43_NPHY_SCRAM_SIGCTL_SCM);
1885
1886        /* Set phase track alpha and beta */
1887        b43_phy_write(dev, B43_NPHY_PHASETR_A0, 0x125);
1888        b43_phy_write(dev, B43_NPHY_PHASETR_A1, 0x1B3);
1889        b43_phy_write(dev, B43_NPHY_PHASETR_A2, 0x105);
1890        b43_phy_write(dev, B43_NPHY_PHASETR_B0, 0x16E);
1891        b43_phy_write(dev, B43_NPHY_PHASETR_B1, 0xCD);
1892        b43_phy_write(dev, B43_NPHY_PHASETR_B2, 0x20);
1893
1894        b43_phy_mask(dev, B43_NPHY_PIL_DW1,
1895                        ~B43_NPHY_PIL_DW_64QAM & 0xFFFF);
1896        b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B1, 0xB5);
1897        b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B2, 0xA4);
1898        b43_phy_write(dev, B43_NPHY_TXF_20CO_S2B3, 0x00);
1899
1900        if (dev->phy.rev == 2)
1901                b43_phy_set(dev, B43_NPHY_FINERX2_CGC,
1902                                B43_NPHY_FINERX2_CGC_DECGC);
1903}
1904
1905/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Workarounds */
1906static void b43_nphy_workarounds(struct b43_wldev *dev)
1907{
1908        struct b43_phy *phy = &dev->phy;
1909        struct b43_phy_n *nphy = phy->n;
1910
1911        if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
1912                b43_nphy_classifier(dev, 1, 0);
1913        else
1914                b43_nphy_classifier(dev, 1, 1);
1915
1916        if (nphy->hang_avoid)
1917                b43_nphy_stay_in_carrier_search(dev, 1);
1918
1919        b43_phy_set(dev, B43_NPHY_IQFLIP,
1920                    B43_NPHY_IQFLIP_ADC1 | B43_NPHY_IQFLIP_ADC2);
1921
1922        if (dev->phy.rev >= 3)
1923                b43_nphy_workarounds_rev3plus(dev);
1924        else
1925                b43_nphy_workarounds_rev1_2(dev);
1926
1927        if (nphy->hang_avoid)
1928                b43_nphy_stay_in_carrier_search(dev, 0);
1929}
1930
1931/**************************************************
1932 * Tx/Rx common
1933 **************************************************/
1934
1935/*
1936 * Transmits a known value for LO calibration
1937 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TXTone
1938 */
1939static int b43_nphy_tx_tone(struct b43_wldev *dev, u32 freq, u16 max_val,
1940                                bool iqmode, bool dac_test)
1941{
1942        u16 samp = b43_nphy_gen_load_samples(dev, freq, max_val, dac_test);
1943        if (samp == 0)
1944                return -1;
1945        b43_nphy_run_samples(dev, samp, 0xFFFF, 0, iqmode, dac_test);
1946        return 0;
1947}
1948
1949/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/Chains */
1950static void b43_nphy_update_txrx_chain(struct b43_wldev *dev)
1951{
1952        struct b43_phy_n *nphy = dev->phy.n;
1953
1954        bool override = false;
1955        u16 chain = 0x33;
1956
1957        if (nphy->txrx_chain == 0) {
1958                chain = 0x11;
1959                override = true;
1960        } else if (nphy->txrx_chain == 1) {
1961                chain = 0x22;
1962                override = true;
1963        }
1964
1965        b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
1966                        ~(B43_NPHY_RFSEQCA_TXEN | B43_NPHY_RFSEQCA_RXEN),
1967                        chain);
1968
1969        if (override)
1970                b43_phy_set(dev, B43_NPHY_RFSEQMODE,
1971                                B43_NPHY_RFSEQMODE_CAOVER);
1972        else
1973                b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
1974                                ~B43_NPHY_RFSEQMODE_CAOVER);
1975}
1976
1977/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/stop-playback */
1978static void b43_nphy_stop_playback(struct b43_wldev *dev)
1979{
1980        struct b43_phy_n *nphy = dev->phy.n;
1981        u16 tmp;
1982
1983        if (nphy->hang_avoid)
1984                b43_nphy_stay_in_carrier_search(dev, 1);
1985
1986        tmp = b43_phy_read(dev, B43_NPHY_SAMP_STAT);
1987        if (tmp & 0x1)
1988                b43_phy_set(dev, B43_NPHY_SAMP_CMD, B43_NPHY_SAMP_CMD_STOP);
1989        else if (tmp & 0x2)
1990                b43_phy_mask(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x7FFF);
1991
1992        b43_phy_mask(dev, B43_NPHY_SAMP_CMD, ~0x0004);
1993
1994        if (nphy->bb_mult_save & 0x80000000) {
1995                tmp = nphy->bb_mult_save & 0xFFFF;
1996                b43_ntab_write(dev, B43_NTAB16(15, 87), tmp);
1997                nphy->bb_mult_save = 0;
1998        }
1999
2000        if (nphy->hang_avoid)
2001                b43_nphy_stay_in_carrier_search(dev, 0);
2002}
2003
2004/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IqCalGainParams */
2005static void b43_nphy_iq_cal_gain_params(struct b43_wldev *dev, u16 core,
2006                                        struct nphy_txgains target,
2007                                        struct nphy_iqcal_params *params)
2008{
2009        int i, j, indx;
2010        u16 gain;
2011
2012        if (dev->phy.rev >= 3) {
2013                params->txgm = target.txgm[core];
2014                params->pga = target.pga[core];
2015                params->pad = target.pad[core];
2016                params->ipa = target.ipa[core];
2017                params->cal_gain = (params->txgm << 12) | (params->pga << 8) |
2018                                        (params->pad << 4) | (params->ipa);
2019                for (j = 0; j < 5; j++)
2020                        params->ncorr[j] = 0x79;
2021        } else {
2022                gain = (target.pad[core]) | (target.pga[core] << 4) |
2023                        (target.txgm[core] << 8);
2024
2025                indx = (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ?
2026                        1 : 0;
2027                for (i = 0; i < 9; i++)
2028                        if (tbl_iqcal_gainparams[indx][i][0] == gain)
2029                                break;
2030                i = min(i, 8);
2031
2032                params->txgm = tbl_iqcal_gainparams[indx][i][1];
2033                params->pga = tbl_iqcal_gainparams[indx][i][2];
2034                params->pad = tbl_iqcal_gainparams[indx][i][3];
2035                params->cal_gain = (params->txgm << 7) | (params->pga << 4) |
2036                                        (params->pad << 2);
2037                for (j = 0; j < 4; j++)
2038                        params->ncorr[j] = tbl_iqcal_gainparams[indx][i][4 + j];
2039        }
2040}
2041
2042/**************************************************
2043 * Tx and Rx
2044 **************************************************/
2045
2046void b43_nphy_set_rxantenna(struct b43_wldev *dev, int antenna)
2047{//TODO
2048}
2049
2050static void b43_nphy_op_adjust_txpower(struct b43_wldev *dev)
2051{//TODO
2052}
2053
2054static enum b43_txpwr_result b43_nphy_op_recalc_txpower(struct b43_wldev *dev,
2055                                                        bool ignore_tssi)
2056{//TODO
2057        return B43_TXPWR_RES_DONE;
2058}
2059
2060/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlEnable */
2061static void b43_nphy_tx_power_ctrl(struct b43_wldev *dev, bool enable)
2062{
2063        struct b43_phy_n *nphy = dev->phy.n;
2064        u8 i;
2065        u16 bmask, val, tmp;
2066        enum ieee80211_band band = b43_current_band(dev->wl);
2067
2068        if (nphy->hang_avoid)
2069                b43_nphy_stay_in_carrier_search(dev, 1);
2070
2071        nphy->txpwrctrl = enable;
2072        if (!enable) {
2073                if (dev->phy.rev >= 3 &&
2074                    (b43_phy_read(dev, B43_NPHY_TXPCTL_CMD) &
2075                     (B43_NPHY_TXPCTL_CMD_COEFF |
2076                      B43_NPHY_TXPCTL_CMD_HWPCTLEN |
2077                      B43_NPHY_TXPCTL_CMD_PCTLEN))) {
2078                        /* We disable enabled TX pwr ctl, save it's state */
2079                        nphy->tx_pwr_idx[0] = b43_phy_read(dev,
2080                                                B43_NPHY_C1_TXPCTL_STAT) & 0x7f;
2081                        nphy->tx_pwr_idx[1] = b43_phy_read(dev,
2082                                                B43_NPHY_C2_TXPCTL_STAT) & 0x7f;
2083                }
2084
2085                b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6840);
2086                for (i = 0; i < 84; i++)
2087                        b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
2088
2089                b43_phy_write(dev, B43_NPHY_TABLE_ADDR, 0x6C40);
2090                for (i = 0; i < 84; i++)
2091                        b43_phy_write(dev, B43_NPHY_TABLE_DATALO, 0);
2092
2093                tmp = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
2094                if (dev->phy.rev >= 3)
2095                        tmp |= B43_NPHY_TXPCTL_CMD_PCTLEN;
2096                b43_phy_mask(dev, B43_NPHY_TXPCTL_CMD, ~tmp);
2097
2098                if (dev->phy.rev >= 3) {
2099                        b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
2100                        b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
2101                } else {
2102                        b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
2103                }
2104
2105                if (dev->phy.rev == 2)
2106                        b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
2107                                ~B43_NPHY_BPHY_CTL3_SCALE, 0x53);
2108                else if (dev->phy.rev < 2)
2109                        b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
2110                                ~B43_NPHY_BPHY_CTL3_SCALE, 0x5A);
2111
2112                if (dev->phy.rev < 2 && dev->phy.is_40mhz)
2113                        b43_hf_write(dev, b43_hf_read(dev) | B43_HF_TSSIRPSMW);
2114        } else {
2115                b43_ntab_write_bulk(dev, B43_NTAB16(26, 64), 84,
2116                                    nphy->adj_pwr_tbl);
2117                b43_ntab_write_bulk(dev, B43_NTAB16(27, 64), 84,
2118                                    nphy->adj_pwr_tbl);
2119
2120                bmask = B43_NPHY_TXPCTL_CMD_COEFF |
2121                        B43_NPHY_TXPCTL_CMD_HWPCTLEN;
2122                /* wl does useless check for "enable" param here */
2123                val = B43_NPHY_TXPCTL_CMD_COEFF | B43_NPHY_TXPCTL_CMD_HWPCTLEN;
2124                if (dev->phy.rev >= 3) {
2125                        bmask |= B43_NPHY_TXPCTL_CMD_PCTLEN;
2126                        if (val)
2127                                val |= B43_NPHY_TXPCTL_CMD_PCTLEN;
2128                }
2129                b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD, ~(bmask), val);
2130
2131                if (band == IEEE80211_BAND_5GHZ) {
2132                        b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
2133                                        ~B43_NPHY_TXPCTL_CMD_INIT, 0x64);
2134                        if (dev->phy.rev > 1)
2135                                b43_phy_maskset(dev, B43_NPHY_TXPCTL_INIT,
2136                                                ~B43_NPHY_TXPCTL_INIT_PIDXI1,
2137                                                0x64);
2138                }
2139
2140                if (dev->phy.rev >= 3) {
2141                        if (nphy->tx_pwr_idx[0] != 128 &&
2142                            nphy->tx_pwr_idx[1] != 128) {
2143                                /* Recover TX pwr ctl state */
2144                                b43_phy_maskset(dev, B43_NPHY_TXPCTL_CMD,
2145                                                ~B43_NPHY_TXPCTL_CMD_INIT,
2146                                                nphy->tx_pwr_idx[0]);
2147                                if (dev->phy.rev > 1)
2148                                        b43_phy_maskset(dev,
2149                                                B43_NPHY_TXPCTL_INIT,
2150                                                ~0xff, nphy->tx_pwr_idx[1]);
2151                        }
2152                }
2153
2154                if (dev->phy.rev >= 3) {
2155                        b43_phy_mask(dev, B43_NPHY_AFECTL_OVER1, ~0x100);
2156                        b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x100);
2157                } else {
2158                        b43_phy_mask(dev, B43_NPHY_AFECTL_OVER, ~0x4000);
2159                }
2160
2161                if (dev->phy.rev == 2)
2162                        b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x3b);
2163                else if (dev->phy.rev < 2)
2164                        b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3, ~0xFF, 0x40);
2165
2166                if (dev->phy.rev < 2 && dev->phy.is_40mhz)
2167                        b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_TSSIRPSMW);
2168
2169                if (b43_nphy_ipa(dev)) {
2170                        b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x4);
2171                        b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x4);
2172                }
2173        }
2174
2175        if (nphy->hang_avoid)
2176                b43_nphy_stay_in_carrier_search(dev, 0);
2177}
2178
2179/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrFix */
2180static void b43_nphy_tx_power_fix(struct b43_wldev *dev)
2181{
2182        struct b43_phy_n *nphy = dev->phy.n;
2183        struct ssb_sprom *sprom = dev->dev->bus_sprom;
2184
2185        u8 txpi[2], bbmult, i;
2186        u16 tmp, radio_gain, dac_gain;
2187        u16 freq = dev->phy.channel_freq;
2188        u32 txgain;
2189        /* u32 gaintbl; rev3+ */
2190
2191        if (nphy->hang_avoid)
2192                b43_nphy_stay_in_carrier_search(dev, 1);
2193
2194        if (dev->phy.rev >= 7) {
2195                txpi[0] = txpi[1] = 30;
2196        } else if (dev->phy.rev >= 3) {
2197                txpi[0] = 40;
2198                txpi[1] = 40;
2199        } else if (sprom->revision < 4) {
2200                txpi[0] = 72;
2201                txpi[1] = 72;
2202        } else {
2203                if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2204                        txpi[0] = sprom->txpid2g[0];
2205                        txpi[1] = sprom->txpid2g[1];
2206                } else if (freq >= 4900 && freq < 5100) {
2207                        txpi[0] = sprom->txpid5gl[0];
2208                        txpi[1] = sprom->txpid5gl[1];
2209                } else if (freq >= 5100 && freq < 5500) {
2210                        txpi[0] = sprom->txpid5g[0];
2211                        txpi[1] = sprom->txpid5g[1];
2212                } else if (freq >= 5500) {
2213                        txpi[0] = sprom->txpid5gh[0];
2214                        txpi[1] = sprom->txpid5gh[1];
2215                } else {
2216                        txpi[0] = 91;
2217                        txpi[1] = 91;
2218                }
2219        }
2220        if (dev->phy.rev < 7 &&
2221            (txpi[0] < 40 || txpi[0] > 100 || txpi[1] < 40 || txpi[1] > 100))
2222                txpi[0] = txpi[1] = 91;
2223
2224        /*
2225        for (i = 0; i < 2; i++) {
2226                nphy->txpwrindex[i].index_internal = txpi[i];
2227                nphy->txpwrindex[i].index_internal_save = txpi[i];
2228        }
2229        */
2230
2231        for (i = 0; i < 2; i++) {
2232                if (dev->phy.rev >= 3) {
2233                        if (b43_nphy_ipa(dev)) {
2234                                txgain = *(b43_nphy_get_ipa_gain_table(dev) +
2235                                                txpi[i]);
2236                        } else if (b43_current_band(dev->wl) ==
2237                                   IEEE80211_BAND_5GHZ) {
2238                                /* FIXME: use 5GHz tables */
2239                                txgain =
2240                                        b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
2241                        } else {
2242                                if (dev->phy.rev >= 5 &&
2243                                    sprom->fem.ghz5.extpa_gain == 3)
2244                                        ; /* FIXME: 5GHz_txgain_HiPwrEPA */
2245                                txgain =
2246                                        b43_ntab_tx_gain_rev3plus_2ghz[txpi[i]];
2247                        }
2248                        radio_gain = (txgain >> 16) & 0x1FFFF;
2249                } else {
2250                        txgain = b43_ntab_tx_gain_rev0_1_2[txpi[i]];
2251                        radio_gain = (txgain >> 16) & 0x1FFF;
2252                }
2253
2254                if (dev->phy.rev >= 7)
2255                        dac_gain = (txgain >> 8) & 0x7;
2256                else
2257                        dac_gain = (txgain >> 8) & 0x3F;
2258                bbmult = txgain & 0xFF;
2259
2260                if (dev->phy.rev >= 3) {
2261                        if (i == 0)
2262                                b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0100);
2263                        else
2264                                b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0100);
2265                } else {
2266                        b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x4000);
2267                }
2268
2269                if (i == 0)
2270                        b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN1, dac_gain);
2271                else
2272                        b43_phy_write(dev, B43_NPHY_AFECTL_DACGAIN2, dac_gain);
2273
2274                b43_ntab_write(dev, B43_NTAB16(0x7, 0x110 + i), radio_gain);
2275
2276                tmp = b43_ntab_read(dev, B43_NTAB16(0xF, 0x57));
2277                if (i == 0)
2278                        tmp = (tmp & 0x00FF) | (bbmult << 8);
2279                else
2280                        tmp = (tmp & 0xFF00) | bbmult;
2281                b43_ntab_write(dev, B43_NTAB16(0xF, 0x57), tmp);
2282
2283                if (b43_nphy_ipa(dev)) {
2284                        u32 tmp32;
2285                        u16 reg = (i == 0) ?
2286                                B43_NPHY_PAPD_EN0 : B43_NPHY_PAPD_EN1;
2287                        tmp32 = b43_ntab_read(dev, B43_NTAB32(26 + i,
2288                                                              576 + txpi[i]));
2289                        b43_phy_maskset(dev, reg, 0xE00F, (u32) tmp32 << 4);
2290                        b43_phy_set(dev, reg, 0x4);
2291                }
2292        }
2293
2294        b43_phy_mask(dev, B43_NPHY_BPHY_CTL2, ~B43_NPHY_BPHY_CTL2_LUT);
2295
2296        if (nphy->hang_avoid)
2297                b43_nphy_stay_in_carrier_search(dev, 0);
2298}
2299
2300static void b43_nphy_ipa_internal_tssi_setup(struct b43_wldev *dev)
2301{
2302        struct b43_phy *phy = &dev->phy;
2303
2304        u8 core;
2305        u16 r; /* routing */
2306
2307        if (phy->rev >= 7) {
2308                for (core = 0; core < 2; core++) {
2309                        r = core ? 0x190 : 0x170;
2310                        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2311                                b43_radio_write(dev, r + 0x5, 0x5);
2312                                b43_radio_write(dev, r + 0x9, 0xE);
2313                                if (phy->rev != 5)
2314                                        b43_radio_write(dev, r + 0xA, 0);
2315                                if (phy->rev != 7)
2316                                        b43_radio_write(dev, r + 0xB, 1);
2317                                else
2318                                        b43_radio_write(dev, r + 0xB, 0x31);
2319                        } else {
2320                                b43_radio_write(dev, r + 0x5, 0x9);
2321                                b43_radio_write(dev, r + 0x9, 0xC);
2322                                b43_radio_write(dev, r + 0xB, 0x0);
2323                                if (phy->rev != 5)
2324                                        b43_radio_write(dev, r + 0xA, 1);
2325                                else
2326                                        b43_radio_write(dev, r + 0xA, 0x31);
2327                        }
2328                        b43_radio_write(dev, r + 0x6, 0);
2329                        b43_radio_write(dev, r + 0x7, 0);
2330                        b43_radio_write(dev, r + 0x8, 3);
2331                        b43_radio_write(dev, r + 0xC, 0);
2332                }
2333        } else {
2334                if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
2335                        b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x128);
2336                else
2337                        b43_radio_write(dev, B2056_SYN_RESERVED_ADDR31, 0x80);
2338                b43_radio_write(dev, B2056_SYN_RESERVED_ADDR30, 0);
2339                b43_radio_write(dev, B2056_SYN_GPIO_MASTER1, 0x29);
2340
2341                for (core = 0; core < 2; core++) {
2342                        r = core ? B2056_TX1 : B2056_TX0;
2343
2344                        b43_radio_write(dev, r | B2056_TX_IQCAL_VCM_HG, 0);
2345                        b43_radio_write(dev, r | B2056_TX_IQCAL_IDAC, 0);
2346                        b43_radio_write(dev, r | B2056_TX_TSSI_VCM, 3);
2347                        b43_radio_write(dev, r | B2056_TX_TX_AMP_DET, 0);
2348                        b43_radio_write(dev, r | B2056_TX_TSSI_MISC1, 8);
2349                        b43_radio_write(dev, r | B2056_TX_TSSI_MISC2, 0);
2350                        b43_radio_write(dev, r | B2056_TX_TSSI_MISC3, 0);
2351                        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2352                                b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER,
2353                                                0x5);
2354                                if (phy->rev != 5)
2355                                        b43_radio_write(dev, r | B2056_TX_TSSIA,
2356                                                        0x00);
2357                                if (phy->rev >= 5)
2358                                        b43_radio_write(dev, r | B2056_TX_TSSIG,
2359                                                        0x31);
2360                                else
2361                                        b43_radio_write(dev, r | B2056_TX_TSSIG,
2362                                                        0x11);
2363                                b43_radio_write(dev, r | B2056_TX_TX_SSI_MUX,
2364                                                0xE);
2365                        } else {
2366                                b43_radio_write(dev, r | B2056_TX_TX_SSI_MASTER,
2367                                                0x9);
2368                                b43_radio_write(dev, r | B2056_TX_TSSIA, 0x31);
2369                                b43_radio_write(dev, r | B2056_TX_TSSIG, 0x0);
2370                                b43_radio_write(dev, r | B2056_TX_TX_SSI_MUX,
2371                                                0xC);
2372                        }
2373                }
2374        }
2375}
2376
2377/*
2378 * Stop radio and transmit known signal. Then check received signal strength to
2379 * get TSSI (Transmit Signal Strength Indicator).
2380 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlIdleTssi
2381 */
2382static void b43_nphy_tx_power_ctl_idle_tssi(struct b43_wldev *dev)
2383{
2384        struct b43_phy *phy = &dev->phy;
2385        struct b43_phy_n *nphy = dev->phy.n;
2386
2387        u32 tmp;
2388        s32 rssi[4] = { };
2389
2390        /* TODO: check if we can transmit */
2391
2392        if (b43_nphy_ipa(dev))
2393                b43_nphy_ipa_internal_tssi_setup(dev);
2394
2395        if (phy->rev >= 7)
2396                ; /* TODO: Override Rev7 with 0x2000, 0, 3, 0, 0 as arguments */
2397        else if (phy->rev >= 3)
2398                b43_nphy_rf_control_override(dev, 0x2000, 0, 3, false);
2399
2400        b43_nphy_stop_playback(dev);
2401        b43_nphy_tx_tone(dev, 0xFA0, 0, false, false);
2402        udelay(20);
2403        tmp = b43_nphy_poll_rssi(dev, 4, rssi, 1);
2404        b43_nphy_stop_playback(dev);
2405        b43_nphy_rssi_select(dev, 0, 0);
2406
2407        if (phy->rev >= 7)
2408                ; /* TODO: Override Rev7 with 0x2000, 0, 3, 1, 0 as arguments */
2409        else if (phy->rev >= 3)
2410                b43_nphy_rf_control_override(dev, 0x2000, 0, 3, true);
2411
2412        if (phy->rev >= 3) {
2413                nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 24) & 0xFF;
2414                nphy->pwr_ctl_info[1].idle_tssi_5g = (tmp >> 8) & 0xFF;
2415        } else {
2416                nphy->pwr_ctl_info[0].idle_tssi_5g = (tmp >> 16) & 0xFF;
2417                nphy->pwr_ctl_info[1].idle_tssi_5g = tmp & 0xFF;
2418        }
2419        nphy->pwr_ctl_info[0].idle_tssi_2g = (tmp >> 24) & 0xFF;
2420        nphy->pwr_ctl_info[1].idle_tssi_2g = (tmp >> 8) & 0xFF;
2421}
2422
2423static void b43_nphy_tx_gain_table_upload(struct b43_wldev *dev)
2424{
2425        struct b43_phy *phy = &dev->phy;
2426
2427        const u32 *table = NULL;
2428#if 0
2429        TODO: b43_ntab_papd_pga_gain_delta_ipa_2*
2430        u32 rfpwr_offset;
2431        u8 pga_gain;
2432        int i;
2433#endif
2434
2435        if (phy->rev >= 3) {
2436                if (b43_nphy_ipa(dev)) {
2437                        table = b43_nphy_get_ipa_gain_table(dev);
2438                } else {
2439                        if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
2440                                if (phy->rev == 3)
2441                                        table = b43_ntab_tx_gain_rev3_5ghz;
2442                                if (phy->rev == 4)
2443                                        table = b43_ntab_tx_gain_rev4_5ghz;
2444                                else
2445                                        table = b43_ntab_tx_gain_rev5plus_5ghz;
2446                        } else {
2447                                table = b43_ntab_tx_gain_rev3plus_2ghz;
2448                        }
2449                }
2450        } else {
2451                table = b43_ntab_tx_gain_rev0_1_2;
2452        }
2453        b43_ntab_write_bulk(dev, B43_NTAB32(26, 192), 128, table);
2454        b43_ntab_write_bulk(dev, B43_NTAB32(27, 192), 128, table);
2455
2456        if (phy->rev >= 3) {
2457#if 0
2458                nphy->gmval = (table[0] >> 16) & 0x7000;
2459
2460                for (i = 0; i < 128; i++) {
2461                        pga_gain = (table[i] >> 24) & 0xF;
2462                        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
2463                                rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_2g[pga_gain];
2464                        else
2465                                rfpwr_offset = b43_ntab_papd_pga_gain_delta_ipa_5g[pga_gain];
2466                        b43_ntab_write(dev, B43_NTAB32(26, 576 + i),
2467                                       rfpwr_offset);
2468                        b43_ntab_write(dev, B43_NTAB32(27, 576 + i),
2469                                       rfpwr_offset);
2470                }
2471#endif
2472        }
2473}
2474
2475/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/PA%20override */
2476static void b43_nphy_pa_override(struct b43_wldev *dev, bool enable)
2477{
2478        struct b43_phy_n *nphy = dev->phy.n;
2479        enum ieee80211_band band;
2480        u16 tmp;
2481
2482        if (!enable) {
2483                nphy->rfctrl_intc1_save = b43_phy_read(dev,
2484                                                       B43_NPHY_RFCTL_INTC1);
2485                nphy->rfctrl_intc2_save = b43_phy_read(dev,
2486                                                       B43_NPHY_RFCTL_INTC2);
2487                band = b43_current_band(dev->wl);
2488                if (dev->phy.rev >= 3) {
2489                        if (band == IEEE80211_BAND_5GHZ)
2490                                tmp = 0x600;
2491                        else
2492                                tmp = 0x480;
2493                } else {
2494                        if (band == IEEE80211_BAND_5GHZ)
2495                                tmp = 0x180;
2496                        else
2497                                tmp = 0x120;
2498                }
2499                b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
2500                b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
2501        } else {
2502                b43_phy_write(dev, B43_NPHY_RFCTL_INTC1,
2503                                nphy->rfctrl_intc1_save);
2504                b43_phy_write(dev, B43_NPHY_RFCTL_INTC2,
2505                                nphy->rfctrl_intc2_save);
2506        }
2507}
2508
2509/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxLpFbw */
2510static void b43_nphy_tx_lp_fbw(struct b43_wldev *dev)
2511{
2512        u16 tmp;
2513
2514        if (dev->phy.rev >= 3) {
2515                if (b43_nphy_ipa(dev)) {
2516                        tmp = 4;
2517                        b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S2,
2518                              (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
2519                }
2520
2521                tmp = 1;
2522                b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S2,
2523                              (((((tmp << 3) | tmp) << 3) | tmp) << 3) | tmp);
2524        }
2525}
2526
2527/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqEst */
2528static void b43_nphy_rx_iq_est(struct b43_wldev *dev, struct nphy_iq_est *est,
2529                                u16 samps, u8 time, bool wait)
2530{
2531        int i;
2532        u16 tmp;
2533
2534        b43_phy_write(dev, B43_NPHY_IQEST_SAMCNT, samps);
2535        b43_phy_maskset(dev, B43_NPHY_IQEST_WT, ~B43_NPHY_IQEST_WT_VAL, time);
2536        if (wait)
2537                b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_MODE);
2538        else
2539                b43_phy_mask(dev, B43_NPHY_IQEST_CMD, ~B43_NPHY_IQEST_CMD_MODE);
2540
2541        b43_phy_set(dev, B43_NPHY_IQEST_CMD, B43_NPHY_IQEST_CMD_START);
2542
2543        for (i = 1000; i; i--) {
2544                tmp = b43_phy_read(dev, B43_NPHY_IQEST_CMD);
2545                if (!(tmp & B43_NPHY_IQEST_CMD_START)) {
2546                        est->i0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI0) << 16) |
2547                                        b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO0);
2548                        est->q0_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI0) << 16) |
2549                                        b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO0);
2550                        est->iq0_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI0) << 16) |
2551                                        b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO0);
2552
2553                        est->i1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_IPACC_HI1) << 16) |
2554                                        b43_phy_read(dev, B43_NPHY_IQEST_IPACC_LO1);
2555                        est->q1_pwr = (b43_phy_read(dev, B43_NPHY_IQEST_QPACC_HI1) << 16) |
2556                                        b43_phy_read(dev, B43_NPHY_IQEST_QPACC_LO1);
2557                        est->iq1_prod = (b43_phy_read(dev, B43_NPHY_IQEST_IQACC_HI1) << 16) |
2558                                        b43_phy_read(dev, B43_NPHY_IQEST_IQACC_LO1);
2559                        return;
2560                }
2561                udelay(10);
2562        }
2563        memset(est, 0, sizeof(*est));
2564}
2565
2566/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxIqCoeffs */
2567static void b43_nphy_rx_iq_coeffs(struct b43_wldev *dev, bool write,
2568                                        struct b43_phy_n_iq_comp *pcomp)
2569{
2570        if (write) {
2571                b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPA0, pcomp->a0);
2572                b43_phy_write(dev, B43_NPHY_C1_RXIQ_COMPB0, pcomp->b0);
2573                b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPA1, pcomp->a1);
2574                b43_phy_write(dev, B43_NPHY_C2_RXIQ_COMPB1, pcomp->b1);
2575        } else {
2576                pcomp->a0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPA0);
2577                pcomp->b0 = b43_phy_read(dev, B43_NPHY_C1_RXIQ_COMPB0);
2578                pcomp->a1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPA1);
2579                pcomp->b1 = b43_phy_read(dev, B43_NPHY_C2_RXIQ_COMPB1);
2580        }
2581}
2582
2583#if 0
2584/* Ready but not used anywhere */
2585/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhyCleanup */
2586static void b43_nphy_rx_cal_phy_cleanup(struct b43_wldev *dev, u8 core)
2587{
2588        u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
2589
2590        b43_phy_write(dev, B43_NPHY_RFSEQCA, regs[0]);
2591        if (core == 0) {
2592                b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[1]);
2593                b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
2594        } else {
2595                b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
2596                b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
2597        }
2598        b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[3]);
2599        b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[4]);
2600        b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO1, regs[5]);
2601        b43_phy_write(dev, B43_NPHY_RFCTL_RSSIO2, regs[6]);
2602        b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, regs[7]);
2603        b43_phy_write(dev, B43_NPHY_RFCTL_OVER, regs[8]);
2604        b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
2605        b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
2606}
2607
2608/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCalPhySetup */
2609static void b43_nphy_rx_cal_phy_setup(struct b43_wldev *dev, u8 core)
2610{
2611        u8 rxval, txval;
2612        u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
2613
2614        regs[0] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
2615        if (core == 0) {
2616                regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
2617                regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
2618        } else {
2619                regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
2620                regs[2] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
2621        }
2622        regs[3] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
2623        regs[4] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
2624        regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO1);
2625        regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_RSSIO2);
2626        regs[7] = b43_phy_read(dev, B43_NPHY_TXF_40CO_B1S1);
2627        regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_OVER);
2628        regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
2629        regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
2630
2631        b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
2632        b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
2633
2634        b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
2635                        ~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
2636                        ((1 - core) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
2637        b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
2638                        ((1 - core) << B43_NPHY_RFSEQCA_TXEN_SHIFT));
2639        b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
2640                        (core << B43_NPHY_RFSEQCA_RXEN_SHIFT));
2641        b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXDIS,
2642                        (core << B43_NPHY_RFSEQCA_TXDIS_SHIFT));
2643
2644        if (core == 0) {
2645                b43_phy_mask(dev, B43_NPHY_AFECTL_C1, ~0x0007);
2646                b43_phy_set(dev, B43_NPHY_AFECTL_OVER1, 0x0007);
2647        } else {
2648                b43_phy_mask(dev, B43_NPHY_AFECTL_C2, ~0x0007);
2649                b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0007);
2650        }
2651
2652        b43_nphy_rf_control_intc_override(dev, 2, 0, 3);
2653        b43_nphy_rf_control_override(dev, 8, 0, 3, false);
2654        b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
2655
2656        if (core == 0) {
2657                rxval = 1;
2658                txval = 8;
2659        } else {
2660                rxval = 4;
2661                txval = 2;
2662        }
2663        b43_nphy_rf_control_intc_override(dev, 1, rxval, (core + 1));
2664        b43_nphy_rf_control_intc_override(dev, 1, txval, (2 - core));
2665}
2666#endif
2667
2668/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalcRxIqComp */
2669static void b43_nphy_calc_rx_iq_comp(struct b43_wldev *dev, u8 mask)
2670{
2671        int i;
2672        s32 iq;
2673        u32 ii;
2674        u32 qq;
2675        int iq_nbits, qq_nbits;
2676        int arsh, brsh;
2677        u16 tmp, a, b;
2678
2679        struct nphy_iq_est est;
2680        struct b43_phy_n_iq_comp old;
2681        struct b43_phy_n_iq_comp new = { };
2682        bool error = false;
2683
2684        if (mask == 0)
2685                return;
2686
2687        b43_nphy_rx_iq_coeffs(dev, false, &old);
2688        b43_nphy_rx_iq_coeffs(dev, true, &new);
2689        b43_nphy_rx_iq_est(dev, &est, 0x4000, 32, false);
2690        new = old;
2691
2692        for (i = 0; i < 2; i++) {
2693                if (i == 0 && (mask & 1)) {
2694                        iq = est.iq0_prod;
2695                        ii = est.i0_pwr;
2696                        qq = est.q0_pwr;
2697                } else if (i == 1 && (mask & 2)) {
2698                        iq = est.iq1_prod;
2699                        ii = est.i1_pwr;
2700                        qq = est.q1_pwr;
2701                } else {
2702                        continue;
2703                }
2704
2705                if (ii + qq < 2) {
2706                        error = true;
2707                        break;
2708                }
2709
2710                iq_nbits = fls(abs(iq));
2711                qq_nbits = fls(qq);
2712
2713                arsh = iq_nbits - 20;
2714                if (arsh >= 0) {
2715                        a = -((iq << (30 - iq_nbits)) + (ii >> (1 + arsh)));
2716                        tmp = ii >> arsh;
2717                } else {
2718                        a = -((iq << (30 - iq_nbits)) + (ii << (-1 - arsh)));
2719                        tmp = ii << -arsh;
2720                }
2721                if (tmp == 0) {
2722                        error = true;
2723                        break;
2724                }
2725                a /= tmp;
2726
2727                brsh = qq_nbits - 11;
2728                if (brsh >= 0) {
2729                        b = (qq << (31 - qq_nbits));
2730                        tmp = ii >> brsh;
2731                } else {
2732                        b = (qq << (31 - qq_nbits));
2733                        tmp = ii << -brsh;
2734                }
2735                if (tmp == 0) {
2736                        error = true;
2737                        break;
2738                }
2739                b = int_sqrt(b / tmp - a * a) - (1 << 10);
2740
2741                if (i == 0 && (mask & 0x1)) {
2742                        if (dev->phy.rev >= 3) {
2743                                new.a0 = a & 0x3FF;
2744                                new.b0 = b & 0x3FF;
2745                        } else {
2746                                new.a0 = b & 0x3FF;
2747                                new.b0 = a & 0x3FF;
2748                        }
2749                } else if (i == 1 && (mask & 0x2)) {
2750                        if (dev->phy.rev >= 3) {
2751                                new.a1 = a & 0x3FF;
2752                                new.b1 = b & 0x3FF;
2753                        } else {
2754                                new.a1 = b & 0x3FF;
2755                                new.b1 = a & 0x3FF;
2756                        }
2757                }
2758        }
2759
2760        if (error)
2761                new = old;
2762
2763        b43_nphy_rx_iq_coeffs(dev, true, &new);
2764}
2765
2766/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxIqWar */
2767static void b43_nphy_tx_iq_workaround(struct b43_wldev *dev)
2768{
2769        u16 array[4];
2770        b43_ntab_read_bulk(dev, B43_NTAB16(0xF, 0x50), 4, array);
2771
2772        b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW0, array[0]);
2773        b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW1, array[1]);
2774        b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW2, array[2]);
2775        b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_NPHY_TXIQW3, array[3]);
2776}
2777
2778/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SpurWar */
2779static void b43_nphy_spur_workaround(struct b43_wldev *dev)
2780{
2781        struct b43_phy_n *nphy = dev->phy.n;
2782
2783        u8 channel = dev->phy.channel;
2784        int tone[2] = { 57, 58 };
2785        u32 noise[2] = { 0x3FF, 0x3FF };
2786
2787        B43_WARN_ON(dev->phy.rev < 3);
2788
2789        if (nphy->hang_avoid)
2790                b43_nphy_stay_in_carrier_search(dev, 1);
2791
2792        if (nphy->gband_spurwar_en) {
2793                /* TODO: N PHY Adjust Analog Pfbw (7) */
2794                if (channel == 11 && dev->phy.is_40mhz)
2795                        ; /* TODO: N PHY Adjust Min Noise Var(2, tone, noise)*/
2796                else
2797                        ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
2798                /* TODO: N PHY Adjust CRS Min Power (0x1E) */
2799        }
2800
2801        if (nphy->aband_spurwar_en) {
2802                if (channel == 54) {
2803                        tone[0] = 0x20;
2804                        noise[0] = 0x25F;
2805                } else if (channel == 38 || channel == 102 || channel == 118) {
2806                        if (0 /* FIXME */) {
2807                                tone[0] = 0x20;
2808                                noise[0] = 0x21F;
2809                        } else {
2810                                tone[0] = 0;
2811                                noise[0] = 0;
2812                        }
2813                } else if (channel == 134) {
2814                        tone[0] = 0x20;
2815                        noise[0] = 0x21F;
2816                } else if (channel == 151) {
2817                        tone[0] = 0x10;
2818                        noise[0] = 0x23F;
2819                } else if (channel == 153 || channel == 161) {
2820                        tone[0] = 0x30;
2821                        noise[0] = 0x23F;
2822                } else {
2823                        tone[0] = 0;
2824                        noise[0] = 0;
2825                }
2826
2827                if (!tone[0] && !noise[0])
2828                        ; /* TODO: N PHY Adjust Min Noise Var(1, tone, noise)*/
2829                else
2830                        ; /* TODO: N PHY Adjust Min Noise Var(0, NULL, NULL)*/
2831        }
2832
2833        if (nphy->hang_avoid)
2834                b43_nphy_stay_in_carrier_search(dev, 0);
2835}
2836
2837/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxPwrCtrlCoefSetup */
2838static void b43_nphy_tx_pwr_ctrl_coef_setup(struct b43_wldev *dev)
2839{
2840        struct b43_phy_n *nphy = dev->phy.n;
2841        int i, j;
2842        u32 tmp;
2843        u32 cur_real, cur_imag, real_part, imag_part;
2844
2845        u16 buffer[7];
2846
2847        if (nphy->hang_avoid)
2848                b43_nphy_stay_in_carrier_search(dev, true);
2849
2850        b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
2851
2852        for (i = 0; i < 2; i++) {
2853                tmp = ((buffer[i * 2] & 0x3FF) << 10) |
2854                        (buffer[i * 2 + 1] & 0x3FF);
2855                b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
2856                                (((i + 26) << 10) | 320));
2857                for (j = 0; j < 128; j++) {
2858                        b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
2859                                        ((tmp >> 16) & 0xFFFF));
2860                        b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
2861                                        (tmp & 0xFFFF));
2862                }
2863        }
2864
2865        for (i = 0; i < 2; i++) {
2866                tmp = buffer[5 + i];
2867                real_part = (tmp >> 8) & 0xFF;
2868                imag_part = (tmp & 0xFF);
2869                b43_phy_write(dev, B43_NPHY_TABLE_ADDR,
2870                                (((i + 26) << 10) | 448));
2871
2872                if (dev->phy.rev >= 3) {
2873                        cur_real = real_part;
2874                        cur_imag = imag_part;
2875                        tmp = ((cur_real & 0xFF) << 8) | (cur_imag & 0xFF);
2876                }
2877
2878                for (j = 0; j < 128; j++) {
2879                        if (dev->phy.rev < 3) {
2880                                cur_real = (real_part * loscale[j] + 128) >> 8;
2881                                cur_imag = (imag_part * loscale[j] + 128) >> 8;
2882                                tmp = ((cur_real & 0xFF) << 8) |
2883                                        (cur_imag & 0xFF);
2884                        }
2885                        b43_phy_write(dev, B43_NPHY_TABLE_DATAHI,
2886                                        ((tmp >> 16) & 0xFFFF));
2887                        b43_phy_write(dev, B43_NPHY_TABLE_DATALO,
2888                                        (tmp & 0xFFFF));
2889                }
2890        }
2891
2892        if (dev->phy.rev >= 3) {
2893                b43_shm_write16(dev, B43_SHM_SHARED,
2894                                B43_SHM_SH_NPHY_TXPWR_INDX0, 0xFFFF);
2895                b43_shm_write16(dev, B43_SHM_SHARED,
2896                                B43_SHM_SH_NPHY_TXPWR_INDX1, 0xFFFF);
2897        }
2898
2899        if (nphy->hang_avoid)
2900                b43_nphy_stay_in_carrier_search(dev, false);
2901}
2902
2903/*
2904 * Restore RSSI Calibration
2905 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreRssiCal
2906 */
2907static void b43_nphy_restore_rssi_cal(struct b43_wldev *dev)
2908{
2909        struct b43_phy_n *nphy = dev->phy.n;
2910
2911        u16 *rssical_radio_regs = NULL;
2912        u16 *rssical_phy_regs = NULL;
2913
2914        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
2915                if (!nphy->rssical_chanspec_2G.center_freq)
2916                        return;
2917                rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_2G;
2918                rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_2G;
2919        } else {
2920                if (!nphy->rssical_chanspec_5G.center_freq)
2921                        return;
2922                rssical_radio_regs = nphy->rssical_cache.rssical_radio_regs_5G;
2923                rssical_phy_regs = nphy->rssical_cache.rssical_phy_regs_5G;
2924        }
2925
2926        /* TODO use some definitions */
2927        b43_radio_maskset(dev, 0x602B, 0xE3, rssical_radio_regs[0]);
2928        b43_radio_maskset(dev, 0x702B, 0xE3, rssical_radio_regs[1]);
2929
2930        b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Z, rssical_phy_regs[0]);
2931        b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Z, rssical_phy_regs[1]);
2932        b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Z, rssical_phy_regs[2]);
2933        b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Z, rssical_phy_regs[3]);
2934
2935        b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_X, rssical_phy_regs[4]);
2936        b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_X, rssical_phy_regs[5]);
2937        b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_X, rssical_phy_regs[6]);
2938        b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_X, rssical_phy_regs[7]);
2939
2940        b43_phy_write(dev, B43_NPHY_RSSIMC_0I_RSSI_Y, rssical_phy_regs[8]);
2941        b43_phy_write(dev, B43_NPHY_RSSIMC_0Q_RSSI_Y, rssical_phy_regs[9]);
2942        b43_phy_write(dev, B43_NPHY_RSSIMC_1I_RSSI_Y, rssical_phy_regs[10]);
2943        b43_phy_write(dev, B43_NPHY_RSSIMC_1Q_RSSI_Y, rssical_phy_regs[11]);
2944}
2945
2946/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalRadioSetup */
2947static void b43_nphy_tx_cal_radio_setup(struct b43_wldev *dev)
2948{
2949        struct b43_phy_n *nphy = dev->phy.n;
2950        u16 *save = nphy->tx_rx_cal_radio_saveregs;
2951        u16 tmp;
2952        u8 offset, i;
2953
2954        if (dev->phy.rev >= 3) {
2955            for (i = 0; i < 2; i++) {
2956                tmp = (i == 0) ? 0x2000 : 0x3000;
2957                offset = i * 11;
2958
2959                save[offset + 0] = b43_radio_read16(dev, B2055_CAL_RVARCTL);
2960                save[offset + 1] = b43_radio_read16(dev, B2055_CAL_LPOCTL);
2961                save[offset + 2] = b43_radio_read16(dev, B2055_CAL_TS);
2962                save[offset + 3] = b43_radio_read16(dev, B2055_CAL_RCCALRTS);
2963                save[offset + 4] = b43_radio_read16(dev, B2055_CAL_RCALRTS);
2964                save[offset + 5] = b43_radio_read16(dev, B2055_PADDRV);
2965                save[offset + 6] = b43_radio_read16(dev, B2055_XOCTL1);
2966                save[offset + 7] = b43_radio_read16(dev, B2055_XOCTL2);
2967                save[offset + 8] = b43_radio_read16(dev, B2055_XOREGUL);
2968                save[offset + 9] = b43_radio_read16(dev, B2055_XOMISC);
2969                save[offset + 10] = b43_radio_read16(dev, B2055_PLL_LFC1);
2970
2971                if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
2972                        b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x0A);
2973                        b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
2974                        b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
2975                        b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
2976                        b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
2977                        if (nphy->ipa5g_on) {
2978                                b43_radio_write16(dev, tmp | B2055_PADDRV, 4);
2979                                b43_radio_write16(dev, tmp | B2055_XOCTL1, 1);
2980                        } else {
2981                                b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
2982                                b43_radio_write16(dev, tmp | B2055_XOCTL1, 0x2F);
2983                        }
2984                        b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
2985                } else {
2986                        b43_radio_write16(dev, tmp | B2055_CAL_RVARCTL, 0x06);
2987                        b43_radio_write16(dev, tmp | B2055_CAL_LPOCTL, 0x40);
2988                        b43_radio_write16(dev, tmp | B2055_CAL_TS, 0x55);
2989                        b43_radio_write16(dev, tmp | B2055_CAL_RCCALRTS, 0);
2990                        b43_radio_write16(dev, tmp | B2055_CAL_RCALRTS, 0);
2991                        b43_radio_write16(dev, tmp | B2055_XOCTL1, 0);
2992                        if (nphy->ipa2g_on) {
2993                                b43_radio_write16(dev, tmp | B2055_PADDRV, 6);
2994                                b43_radio_write16(dev, tmp | B2055_XOCTL2,
2995                                        (dev->phy.rev < 5) ? 0x11 : 0x01);
2996                        } else {
2997                                b43_radio_write16(dev, tmp | B2055_PADDRV, 0);
2998                                b43_radio_write16(dev, tmp | B2055_XOCTL2, 0);
2999                        }
3000                }
3001                b43_radio_write16(dev, tmp | B2055_XOREGUL, 0);
3002                b43_radio_write16(dev, tmp | B2055_XOMISC, 0);
3003                b43_radio_write16(dev, tmp | B2055_PLL_LFC1, 0);
3004            }
3005        } else {
3006                save[0] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL1);
3007                b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL1, 0x29);
3008
3009                save[1] = b43_radio_read16(dev, B2055_C1_TX_RF_IQCAL2);
3010                b43_radio_write16(dev, B2055_C1_TX_RF_IQCAL2, 0x54);
3011
3012                save[2] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL1);
3013                b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL1, 0x29);
3014
3015                save[3] = b43_radio_read16(dev, B2055_C2_TX_RF_IQCAL2);
3016                b43_radio_write16(dev, B2055_C2_TX_RF_IQCAL2, 0x54);
3017
3018                save[3] = b43_radio_read16(dev, B2055_C1_PWRDET_RXTX);
3019                save[4] = b43_radio_read16(dev, B2055_C2_PWRDET_RXTX);
3020
3021                if (!(b43_phy_read(dev, B43_NPHY_BANDCTL) &
3022                    B43_NPHY_BANDCTL_5GHZ)) {
3023                        b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x04);
3024                        b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x04);
3025                } else {
3026                        b43_radio_write16(dev, B2055_C1_PWRDET_RXTX, 0x20);
3027                        b43_radio_write16(dev, B2055_C2_PWRDET_RXTX, 0x20);
3028                }
3029
3030                if (dev->phy.rev < 2) {
3031                        b43_radio_set(dev, B2055_C1_TX_BB_MXGM, 0x20);
3032                        b43_radio_set(dev, B2055_C2_TX_BB_MXGM, 0x20);
3033                } else {
3034                        b43_radio_mask(dev, B2055_C1_TX_BB_MXGM, ~0x20);
3035                        b43_radio_mask(dev, B2055_C2_TX_BB_MXGM, ~0x20);
3036                }
3037        }
3038}
3039
3040/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/UpdateTxCalLadder */
3041static void b43_nphy_update_tx_cal_ladder(struct b43_wldev *dev, u16 core)
3042{
3043        struct b43_phy_n *nphy = dev->phy.n;
3044        int i;
3045        u16 scale, entry;
3046
3047        u16 tmp = nphy->txcal_bbmult;
3048        if (core == 0)
3049                tmp >>= 8;
3050        tmp &= 0xff;
3051
3052        for (i = 0; i < 18; i++) {
3053                scale = (ladder_lo[i].percent * tmp) / 100;
3054                entry = ((scale & 0xFF) << 8) | ladder_lo[i].g_env;
3055                b43_ntab_write(dev, B43_NTAB16(15, i), entry);
3056
3057                scale = (ladder_iq[i].percent * tmp) / 100;
3058                entry = ((scale & 0xFF) << 8) | ladder_iq[i].g_env;
3059                b43_ntab_write(dev, B43_NTAB16(15, i + 32), entry);
3060        }
3061}
3062
3063/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ExtPaSetTxDigiFilts */
3064static void b43_nphy_ext_pa_set_tx_dig_filters(struct b43_wldev *dev)
3065{
3066        int i;
3067        for (i = 0; i < 15; i++)
3068                b43_phy_write(dev, B43_PHY_N(0x2C5 + i),
3069                                tbl_tx_filter_coef_rev4[2][i]);
3070}
3071
3072/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/IpaSetTxDigiFilts */
3073static void b43_nphy_int_pa_set_tx_dig_filters(struct b43_wldev *dev)
3074{
3075        int i, j;
3076        /* B43_NPHY_TXF_20CO_S0A1, B43_NPHY_TXF_40CO_S0A1, unknown */
3077        static const u16 offset[] = { 0x186, 0x195, 0x2C5 };
3078
3079        for (i = 0; i < 3; i++)
3080                for (j = 0; j < 15; j++)
3081                        b43_phy_write(dev, B43_PHY_N(offset[i] + j),
3082                                        tbl_tx_filter_coef_rev4[i][j]);
3083
3084        if (dev->phy.is_40mhz) {
3085                for (j = 0; j < 15; j++)
3086                        b43_phy_write(dev, B43_PHY_N(offset[0] + j),
3087                                        tbl_tx_filter_coef_rev4[3][j]);
3088        } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) {
3089                for (j = 0; j < 15; j++)
3090                        b43_phy_write(dev, B43_PHY_N(offset[0] + j),
3091                                        tbl_tx_filter_coef_rev4[5][j]);
3092        }
3093
3094        if (dev->phy.channel == 14)
3095                for (j = 0; j < 15; j++)
3096                        b43_phy_write(dev, B43_PHY_N(offset[0] + j),
3097                                        tbl_tx_filter_coef_rev4[6][j]);
3098}
3099
3100/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/GetTxGain */
3101static struct nphy_txgains b43_nphy_get_tx_gains(struct b43_wldev *dev)
3102{
3103        struct b43_phy_n *nphy = dev->phy.n;
3104
3105        u16 curr_gain[2];
3106        struct nphy_txgains target;
3107        const u32 *table = NULL;
3108
3109        if (!nphy->txpwrctrl) {
3110                int i;
3111
3112                if (nphy->hang_avoid)
3113                        b43_nphy_stay_in_carrier_search(dev, true);
3114                b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, curr_gain);
3115                if (nphy->hang_avoid)
3116                        b43_nphy_stay_in_carrier_search(dev, false);
3117
3118                for (i = 0; i < 2; ++i) {
3119                        if (dev->phy.rev >= 3) {
3120                                target.ipa[i] = curr_gain[i] & 0x000F;
3121                                target.pad[i] = (curr_gain[i] & 0x00F0) >> 4;
3122                                target.pga[i] = (curr_gain[i] & 0x0F00) >> 8;
3123                                target.txgm[i] = (curr_gain[i] & 0x7000) >> 12;
3124                        } else {
3125                                target.ipa[i] = curr_gain[i] & 0x0003;
3126                                target.pad[i] = (curr_gain[i] & 0x000C) >> 2;
3127                                target.pga[i] = (curr_gain[i] & 0x0070) >> 4;
3128                                target.txgm[i] = (curr_gain[i] & 0x0380) >> 7;
3129                        }
3130                }
3131        } else {
3132                int i;
3133                u16 index[2];
3134                index[0] = (b43_phy_read(dev, B43_NPHY_C1_TXPCTL_STAT) &
3135                        B43_NPHY_TXPCTL_STAT_BIDX) >>
3136                        B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
3137                index[1] = (b43_phy_read(dev, B43_NPHY_C2_TXPCTL_STAT) &
3138                        B43_NPHY_TXPCTL_STAT_BIDX) >>
3139                        B43_NPHY_TXPCTL_STAT_BIDX_SHIFT;
3140
3141                for (i = 0; i < 2; ++i) {
3142                        if (dev->phy.rev >= 3) {
3143                                enum ieee80211_band band =
3144                                        b43_current_band(dev->wl);
3145
3146                                if (b43_nphy_ipa(dev)) {
3147                                        table = b43_nphy_get_ipa_gain_table(dev);
3148                                } else {
3149                                        if (band == IEEE80211_BAND_5GHZ) {
3150                                                if (dev->phy.rev == 3)
3151                                                        table = b43_ntab_tx_gain_rev3_5ghz;
3152                                                else if (dev->phy.rev == 4)
3153                                                        table = b43_ntab_tx_gain_rev4_5ghz;
3154                                                else
3155                                                        table = b43_ntab_tx_gain_rev5plus_5ghz;
3156                                        } else {
3157                                                table = b43_ntab_tx_gain_rev3plus_2ghz;
3158                                        }
3159                                }
3160
3161                                target.ipa[i] = (table[index[i]] >> 16) & 0xF;
3162                                target.pad[i] = (table[index[i]] >> 20) & 0xF;
3163                                target.pga[i] = (table[index[i]] >> 24) & 0xF;
3164                                target.txgm[i] = (table[index[i]] >> 28) & 0xF;
3165                        } else {
3166                                table = b43_ntab_tx_gain_rev0_1_2;
3167
3168                                target.ipa[i] = (table[index[i]] >> 16) & 0x3;
3169                                target.pad[i] = (table[index[i]] >> 18) & 0x3;
3170                                target.pga[i] = (table[index[i]] >> 20) & 0x7;
3171                                target.txgm[i] = (table[index[i]] >> 23) & 0x7;
3172                        }
3173                }
3174        }
3175
3176        return target;
3177}
3178
3179/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhyCleanup */
3180static void b43_nphy_tx_cal_phy_cleanup(struct b43_wldev *dev)
3181{
3182        u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
3183
3184        if (dev->phy.rev >= 3) {
3185                b43_phy_write(dev, B43_NPHY_AFECTL_C1, regs[0]);
3186                b43_phy_write(dev, B43_NPHY_AFECTL_C2, regs[1]);
3187                b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, regs[2]);
3188                b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[3]);
3189                b43_phy_write(dev, B43_NPHY_BBCFG, regs[4]);
3190                b43_ntab_write(dev, B43_NTAB16(8, 3), regs[5]);
3191                b43_ntab_write(dev, B43_NTAB16(8, 19), regs[6]);
3192                b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[7]);
3193                b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[8]);
3194                b43_phy_write(dev, B43_NPHY_PAPD_EN0, regs[9]);
3195                b43_phy_write(dev, B43_NPHY_PAPD_EN1, regs[10]);
3196                b43_nphy_reset_cca(dev);
3197        } else {
3198                b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, regs[0]);
3199                b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, regs[1]);
3200                b43_phy_write(dev, B43_NPHY_AFECTL_OVER, regs[2]);
3201                b43_ntab_write(dev, B43_NTAB16(8, 2), regs[3]);
3202                b43_ntab_write(dev, B43_NTAB16(8, 18), regs[4]);
3203                b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, regs[5]);
3204                b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, regs[6]);
3205        }
3206}
3207
3208/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/TxCalPhySetup */
3209static void b43_nphy_tx_cal_phy_setup(struct b43_wldev *dev)
3210{
3211        u16 *regs = dev->phy.n->tx_rx_cal_phy_saveregs;
3212        u16 tmp;
3213
3214        regs[0] = b43_phy_read(dev, B43_NPHY_AFECTL_C1);
3215        regs[1] = b43_phy_read(dev, B43_NPHY_AFECTL_C2);
3216        if (dev->phy.rev >= 3) {
3217                b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0xF0FF, 0x0A00);
3218                b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0xF0FF, 0x0A00);
3219
3220                tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER1);
3221                regs[2] = tmp;
3222                b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, tmp | 0x0600);
3223
3224                tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
3225                regs[3] = tmp;
3226                b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x0600);
3227
3228                regs[4] = b43_phy_read(dev, B43_NPHY_BBCFG);
3229                b43_phy_mask(dev, B43_NPHY_BBCFG,
3230                             ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
3231
3232                tmp = b43_ntab_read(dev, B43_NTAB16(8, 3));
3233                regs[5] = tmp;
3234                b43_ntab_write(dev, B43_NTAB16(8, 3), 0);
3235
3236                tmp = b43_ntab_read(dev, B43_NTAB16(8, 19));
3237                regs[6] = tmp;
3238                b43_ntab_write(dev, B43_NTAB16(8, 19), 0);
3239                regs[7] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
3240                regs[8] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
3241
3242                b43_nphy_rf_control_intc_override(dev, 2, 1, 3);
3243                b43_nphy_rf_control_intc_override(dev, 1, 2, 1);
3244                b43_nphy_rf_control_intc_override(dev, 1, 8, 2);
3245
3246                regs[9] = b43_phy_read(dev, B43_NPHY_PAPD_EN0);
3247                regs[10] = b43_phy_read(dev, B43_NPHY_PAPD_EN1);
3248                b43_phy_mask(dev, B43_NPHY_PAPD_EN0, ~0x0001);
3249                b43_phy_mask(dev, B43_NPHY_PAPD_EN1, ~0x0001);
3250        } else {
3251                b43_phy_maskset(dev, B43_NPHY_AFECTL_C1, 0x0FFF, 0xA000);
3252                b43_phy_maskset(dev, B43_NPHY_AFECTL_C2, 0x0FFF, 0xA000);
3253                tmp = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
3254                regs[2] = tmp;
3255                b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp | 0x3000);
3256                tmp = b43_ntab_read(dev, B43_NTAB16(8, 2));
3257                regs[3] = tmp;
3258                tmp |= 0x2000;
3259                b43_ntab_write(dev, B43_NTAB16(8, 2), tmp);
3260                tmp = b43_ntab_read(dev, B43_NTAB16(8, 18));
3261                regs[4] = tmp;
3262                tmp |= 0x2000;
3263                b43_ntab_write(dev, B43_NTAB16(8, 18), tmp);
3264                regs[5] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC1);
3265                regs[6] = b43_phy_read(dev, B43_NPHY_RFCTL_INTC2);
3266                if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ)
3267                        tmp = 0x0180;
3268                else
3269                        tmp = 0x0120;
3270                b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, tmp);
3271                b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, tmp);
3272        }
3273}
3274
3275/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SaveCal */
3276static void b43_nphy_save_cal(struct b43_wldev *dev)
3277{
3278        struct b43_phy_n *nphy = dev->phy.n;
3279
3280        struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
3281        u16 *txcal_radio_regs = NULL;
3282        struct b43_chanspec *iqcal_chanspec;
3283        u16 *table = NULL;
3284
3285        if (nphy->hang_avoid)
3286                b43_nphy_stay_in_carrier_search(dev, 1);
3287
3288        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
3289                rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
3290                txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
3291                iqcal_chanspec = &nphy->iqcal_chanspec_2G;
3292                table = nphy->cal_cache.txcal_coeffs_2G;
3293        } else {
3294                rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
3295                txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
3296                iqcal_chanspec = &nphy->iqcal_chanspec_5G;
3297                table = nphy->cal_cache.txcal_coeffs_5G;
3298        }
3299
3300        b43_nphy_rx_iq_coeffs(dev, false, rxcal_coeffs);
3301        /* TODO use some definitions */
3302        if (dev->phy.rev >= 3) {
3303                txcal_radio_regs[0] = b43_radio_read(dev, 0x2021);
3304                txcal_radio_regs[1] = b43_radio_read(dev, 0x2022);
3305                txcal_radio_regs[2] = b43_radio_read(dev, 0x3021);
3306                txcal_radio_regs[3] = b43_radio_read(dev, 0x3022);
3307                txcal_radio_regs[4] = b43_radio_read(dev, 0x2023);
3308                txcal_radio_regs[5] = b43_radio_read(dev, 0x2024);
3309                txcal_radio_regs[6] = b43_radio_read(dev, 0x3023);
3310                txcal_radio_regs[7] = b43_radio_read(dev, 0x3024);
3311        } else {
3312                txcal_radio_regs[0] = b43_radio_read(dev, 0x8B);
3313                txcal_radio_regs[1] = b43_radio_read(dev, 0xBA);
3314                txcal_radio_regs[2] = b43_radio_read(dev, 0x8D);
3315                txcal_radio_regs[3] = b43_radio_read(dev, 0xBC);
3316        }
3317        iqcal_chanspec->center_freq = dev->phy.channel_freq;
3318        iqcal_chanspec->channel_type = dev->phy.channel_type;
3319        b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 8, table);
3320
3321        if (nphy->hang_avoid)
3322                b43_nphy_stay_in_carrier_search(dev, 0);
3323}
3324
3325/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RestoreCal */
3326static void b43_nphy_restore_cal(struct b43_wldev *dev)
3327{
3328        struct b43_phy_n *nphy = dev->phy.n;
3329
3330        u16 coef[4];
3331        u16 *loft = NULL;
3332        u16 *table = NULL;
3333
3334        int i;
3335        u16 *txcal_radio_regs = NULL;
3336        struct b43_phy_n_iq_comp *rxcal_coeffs = NULL;
3337
3338        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
3339                if (!nphy->iqcal_chanspec_2G.center_freq)
3340                        return;
3341                table = nphy->cal_cache.txcal_coeffs_2G;
3342                loft = &nphy->cal_cache.txcal_coeffs_2G[5];
3343        } else {
3344                if (!nphy->iqcal_chanspec_5G.center_freq)
3345                        return;
3346                table = nphy->cal_cache.txcal_coeffs_5G;
3347                loft = &nphy->cal_cache.txcal_coeffs_5G[5];
3348        }
3349
3350        b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4, table);
3351
3352        for (i = 0; i < 4; i++) {
3353                if (dev->phy.rev >= 3)
3354                        table[i] = coef[i];
3355                else
3356                        coef[i] = 0;
3357        }
3358
3359        b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4, coef);
3360        b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2, loft);
3361        b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2, loft);
3362
3363        if (dev->phy.rev < 2)
3364                b43_nphy_tx_iq_workaround(dev);
3365
3366        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
3367                txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_2G;
3368                rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_2G;
3369        } else {
3370                txcal_radio_regs = nphy->cal_cache.txcal_radio_regs_5G;
3371                rxcal_coeffs = &nphy->cal_cache.rxcal_coeffs_5G;
3372        }
3373
3374        /* TODO use some definitions */
3375        if (dev->phy.rev >= 3) {
3376                b43_radio_write(dev, 0x2021, txcal_radio_regs[0]);
3377                b43_radio_write(dev, 0x2022, txcal_radio_regs[1]);
3378                b43_radio_write(dev, 0x3021, txcal_radio_regs[2]);
3379                b43_radio_write(dev, 0x3022, txcal_radio_regs[3]);
3380                b43_radio_write(dev, 0x2023, txcal_radio_regs[4]);
3381                b43_radio_write(dev, 0x2024, txcal_radio_regs[5]);
3382                b43_radio_write(dev, 0x3023, txcal_radio_regs[6]);
3383                b43_radio_write(dev, 0x3024, txcal_radio_regs[7]);
3384        } else {
3385                b43_radio_write(dev, 0x8B, txcal_radio_regs[0]);
3386                b43_radio_write(dev, 0xBA, txcal_radio_regs[1]);
3387                b43_radio_write(dev, 0x8D, txcal_radio_regs[2]);
3388                b43_radio_write(dev, 0xBC, txcal_radio_regs[3]);
3389        }
3390        b43_nphy_rx_iq_coeffs(dev, true, rxcal_coeffs);
3391}
3392
3393/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalTxIqlo */
3394static int b43_nphy_cal_tx_iq_lo(struct b43_wldev *dev,
3395                                struct nphy_txgains target,
3396                                bool full, bool mphase)
3397{
3398        struct b43_phy_n *nphy = dev->phy.n;
3399        int i;
3400        int error = 0;
3401        int freq;
3402        bool avoid = false;
3403        u8 length;
3404        u16 tmp, core, type, count, max, numb, last = 0, cmd;
3405        const u16 *table;
3406        bool phy6or5x;
3407
3408        u16 buffer[11];
3409        u16 diq_start = 0;
3410        u16 save[2];
3411        u16 gain[2];
3412        struct nphy_iqcal_params params[2];
3413        bool updated[2] = { };
3414
3415        b43_nphy_stay_in_carrier_search(dev, true);
3416
3417        if (dev->phy.rev >= 4) {
3418                avoid = nphy->hang_avoid;
3419                nphy->hang_avoid = false;
3420        }
3421
3422        b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
3423
3424        for (i = 0; i < 2; i++) {
3425                b43_nphy_iq_cal_gain_params(dev, i, target, &params[i]);
3426                gain[i] = params[i].cal_gain;
3427        }
3428
3429        b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain);
3430
3431        b43_nphy_tx_cal_radio_setup(dev);
3432        b43_nphy_tx_cal_phy_setup(dev);
3433
3434        phy6or5x = dev->phy.rev >= 6 ||
3435                (dev->phy.rev == 5 && nphy->ipa2g_on &&
3436                b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ);
3437        if (phy6or5x) {
3438                if (dev->phy.is_40mhz) {
3439                        b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
3440                                        tbl_tx_iqlo_cal_loft_ladder_40);
3441                        b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
3442                                        tbl_tx_iqlo_cal_iqimb_ladder_40);
3443                } else {
3444                        b43_ntab_write_bulk(dev, B43_NTAB16(15, 0), 18,
3445                                        tbl_tx_iqlo_cal_loft_ladder_20);
3446                        b43_ntab_write_bulk(dev, B43_NTAB16(15, 32), 18,
3447                                        tbl_tx_iqlo_cal_iqimb_ladder_20);
3448                }
3449        }
3450
3451        b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0x8AA9);
3452
3453        if (!dev->phy.is_40mhz)
3454                freq = 2500;
3455        else
3456                freq = 5000;
3457
3458        if (nphy->mphase_cal_phase_id > 2)
3459                b43_nphy_run_samples(dev, (dev->phy.is_40mhz ? 40 : 20) * 8,
3460                                        0xFFFF, 0, true, false);
3461        else
3462                error = b43_nphy_tx_tone(dev, freq, 250, true, false);
3463
3464        if (error == 0) {
3465                if (nphy->mphase_cal_phase_id > 2) {
3466                        table = nphy->mphase_txcal_bestcoeffs;
3467                        length = 11;
3468                        if (dev->phy.rev < 3)
3469                                length -= 2;
3470                } else {
3471                        if (!full && nphy->txiqlocal_coeffsvalid) {
3472                                table = nphy->txiqlocal_bestc;
3473                                length = 11;
3474                                if (dev->phy.rev < 3)
3475                                        length -= 2;
3476                        } else {
3477                                full = true;
3478                                if (dev->phy.rev >= 3) {
3479                                        table = tbl_tx_iqlo_cal_startcoefs_nphyrev3;
3480                                        length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS_REV3;
3481                                } else {
3482                                        table = tbl_tx_iqlo_cal_startcoefs;
3483                                        length = B43_NTAB_TX_IQLO_CAL_STARTCOEFS;
3484                                }
3485                        }
3486                }
3487
3488                b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length, table);
3489
3490                if (full) {
3491                        if (dev->phy.rev >= 3)
3492                                max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL_REV3;
3493                        else
3494                                max = B43_NTAB_TX_IQLO_CAL_CMDS_FULLCAL;
3495                } else {
3496                        if (dev->phy.rev >= 3)
3497                                max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL_REV3;
3498                        else
3499                                max = B43_NTAB_TX_IQLO_CAL_CMDS_RECAL;
3500                }
3501
3502                if (mphase) {
3503                        count = nphy->mphase_txcal_cmdidx;
3504                        numb = min(max,
3505                                (u16)(count + nphy->mphase_txcal_numcmds));
3506                } else {
3507                        count = 0;
3508                        numb = max;
3509                }
3510
3511                for (; count < numb; count++) {
3512                        if (full) {
3513                                if (dev->phy.rev >= 3)
3514                                        cmd = tbl_tx_iqlo_cal_cmds_fullcal_nphyrev3[count];
3515                                else
3516                                        cmd = tbl_tx_iqlo_cal_cmds_fullcal[count];
3517                        } else {
3518                                if (dev->phy.rev >= 3)
3519                                        cmd = tbl_tx_iqlo_cal_cmds_recal_nphyrev3[count];
3520                                else
3521                                        cmd = tbl_tx_iqlo_cal_cmds_recal[count];
3522                        }
3523
3524                        core = (cmd & 0x3000) >> 12;
3525                        type = (cmd & 0x0F00) >> 8;
3526
3527                        if (phy6or5x && updated[core] == 0) {
3528                                b43_nphy_update_tx_cal_ladder(dev, core);
3529                                updated[core] = true;
3530                        }
3531
3532                        tmp = (params[core].ncorr[type] << 8) | 0x66;
3533                        b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDNNUM, tmp);
3534
3535                        if (type == 1 || type == 3 || type == 4) {
3536                                buffer[0] = b43_ntab_read(dev,
3537                                                B43_NTAB16(15, 69 + core));
3538                                diq_start = buffer[0];
3539                                buffer[0] = 0;
3540                                b43_ntab_write(dev, B43_NTAB16(15, 69 + core),
3541                                                0);
3542                        }
3543
3544                        b43_phy_write(dev, B43_NPHY_IQLOCAL_CMD, cmd);
3545                        for (i = 0; i < 2000; i++) {
3546                                tmp = b43_phy_read(dev, B43_NPHY_IQLOCAL_CMD);
3547                                if (tmp & 0xC000)
3548                                        break;
3549                                udelay(10);
3550                        }
3551
3552                        b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
3553                                                buffer);
3554                        b43_ntab_write_bulk(dev, B43_NTAB16(15, 64), length,
3555                                                buffer);
3556
3557                        if (type == 1 || type == 3 || type == 4)
3558                                buffer[0] = diq_start;
3559                }
3560
3561                if (mphase)
3562                        nphy->mphase_txcal_cmdidx = (numb >= max) ? 0 : numb;
3563
3564                last = (dev->phy.rev < 3) ? 6 : 7;
3565
3566                if (!mphase || nphy->mphase_cal_phase_id == last) {
3567                        b43_ntab_write_bulk(dev, B43_NTAB16(15, 96), 4, buffer);
3568                        b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 4, buffer);
3569                        if (dev->phy.rev < 3) {
3570                                buffer[0] = 0;
3571                                buffer[1] = 0;
3572                                buffer[2] = 0;
3573                                buffer[3] = 0;
3574                        }
3575                        b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
3576                                                buffer);
3577                        b43_ntab_read_bulk(dev, B43_NTAB16(15, 101), 2,
3578                                                buffer);
3579                        b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
3580                                                buffer);
3581                        b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
3582                                                buffer);
3583                        length = 11;
3584                        if (dev->phy.rev < 3)
3585                                length -= 2;
3586                        b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
3587                                                nphy->txiqlocal_bestc);
3588                        nphy->txiqlocal_coeffsvalid = true;
3589                        nphy->txiqlocal_chanspec.center_freq =
3590                                                        dev->phy.channel_freq;
3591                        nphy->txiqlocal_chanspec.channel_type =
3592                                                        dev->phy.channel_type;
3593                } else {
3594                        length = 11;
3595                        if (dev->phy.rev < 3)
3596                                length -= 2;
3597                        b43_ntab_read_bulk(dev, B43_NTAB16(15, 96), length,
3598                                                nphy->mphase_txcal_bestcoeffs);
3599                }
3600
3601                b43_nphy_stop_playback(dev);
3602                b43_phy_write(dev, B43_NPHY_IQLOCAL_CMDGCTL, 0);
3603        }
3604
3605        b43_nphy_tx_cal_phy_cleanup(dev);
3606        b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, save);
3607
3608        if (dev->phy.rev < 2 && (!mphase || nphy->mphase_cal_phase_id == last))
3609                b43_nphy_tx_iq_workaround(dev);
3610
3611        if (dev->phy.rev >= 4)
3612                nphy->hang_avoid = avoid;
3613
3614        b43_nphy_stay_in_carrier_search(dev, false);
3615
3616        return error;
3617}
3618
3619/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ReapplyTxCalCoeffs */
3620static void b43_nphy_reapply_tx_cal_coeffs(struct b43_wldev *dev)
3621{
3622        struct b43_phy_n *nphy = dev->phy.n;
3623        u8 i;
3624        u16 buffer[7];
3625        bool equal = true;
3626
3627        if (!nphy->txiqlocal_coeffsvalid ||
3628            nphy->txiqlocal_chanspec.center_freq != dev->phy.channel_freq ||
3629            nphy->txiqlocal_chanspec.channel_type != dev->phy.channel_type)
3630                return;
3631
3632        b43_ntab_read_bulk(dev, B43_NTAB16(15, 80), 7, buffer);
3633        for (i = 0; i < 4; i++) {
3634                if (buffer[i] != nphy->txiqlocal_bestc[i]) {
3635                        equal = false;
3636                        break;
3637                }
3638        }
3639
3640        if (!equal) {
3641                b43_ntab_write_bulk(dev, B43_NTAB16(15, 80), 4,
3642                                        nphy->txiqlocal_bestc);
3643                for (i = 0; i < 4; i++)
3644                        buffer[i] = 0;
3645                b43_ntab_write_bulk(dev, B43_NTAB16(15, 88), 4,
3646                                        buffer);
3647                b43_ntab_write_bulk(dev, B43_NTAB16(15, 85), 2,
3648                                        &nphy->txiqlocal_bestc[5]);
3649                b43_ntab_write_bulk(dev, B43_NTAB16(15, 93), 2,
3650                                        &nphy->txiqlocal_bestc[5]);
3651        }
3652}
3653
3654/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIqRev2 */
3655static int b43_nphy_rev2_cal_rx_iq(struct b43_wldev *dev,
3656                        struct nphy_txgains target, u8 type, bool debug)
3657{
3658        struct b43_phy_n *nphy = dev->phy.n;
3659        int i, j, index;
3660        u8 rfctl[2];
3661        u8 afectl_core;
3662        u16 tmp[6];
3663        u16 uninitialized_var(cur_hpf1), uninitialized_var(cur_hpf2), cur_lna;
3664        u32 real, imag;
3665        enum ieee80211_band band;
3666
3667        u8 use;
3668        u16 cur_hpf;
3669        u16 lna[3] = { 3, 3, 1 };
3670        u16 hpf1[3] = { 7, 2, 0 };
3671        u16 hpf2[3] = { 2, 0, 0 };
3672        u32 power[3] = { };
3673        u16 gain_save[2];
3674        u16 cal_gain[2];
3675        struct nphy_iqcal_params cal_params[2];
3676        struct nphy_iq_est est;
3677        int ret = 0;
3678        bool playtone = true;
3679        int desired = 13;
3680
3681        b43_nphy_stay_in_carrier_search(dev, 1);
3682
3683        if (dev->phy.rev < 2)
3684                b43_nphy_reapply_tx_cal_coeffs(dev);
3685        b43_ntab_read_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
3686        for (i = 0; i < 2; i++) {
3687                b43_nphy_iq_cal_gain_params(dev, i, target, &cal_params[i]);
3688                cal_gain[i] = cal_params[i].cal_gain;
3689        }
3690        b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, cal_gain);
3691
3692        for (i = 0; i < 2; i++) {
3693                if (i == 0) {
3694                        rfctl[0] = B43_NPHY_RFCTL_INTC1;
3695                        rfctl[1] = B43_NPHY_RFCTL_INTC2;
3696                        afectl_core = B43_NPHY_AFECTL_C1;
3697                } else {
3698                        rfctl[0] = B43_NPHY_RFCTL_INTC2;
3699                        rfctl[1] = B43_NPHY_RFCTL_INTC1;
3700                        afectl_core = B43_NPHY_AFECTL_C2;
3701                }
3702
3703                tmp[1] = b43_phy_read(dev, B43_NPHY_RFSEQCA);
3704                tmp[2] = b43_phy_read(dev, afectl_core);
3705                tmp[3] = b43_phy_read(dev, B43_NPHY_AFECTL_OVER);
3706                tmp[4] = b43_phy_read(dev, rfctl[0]);
3707                tmp[5] = b43_phy_read(dev, rfctl[1]);
3708
3709                b43_phy_maskset(dev, B43_NPHY_RFSEQCA,
3710                                ~B43_NPHY_RFSEQCA_RXDIS & 0xFFFF,
3711                                ((1 - i) << B43_NPHY_RFSEQCA_RXDIS_SHIFT));
3712                b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_TXEN,
3713                                (1 - i));
3714                b43_phy_set(dev, afectl_core, 0x0006);
3715                b43_phy_set(dev, B43_NPHY_AFECTL_OVER, 0x0006);
3716
3717                band = b43_current_band(dev->wl);
3718
3719                if (nphy->rxcalparams & 0xFF000000) {
3720                        if (band == IEEE80211_BAND_5GHZ)
3721                                b43_phy_write(dev, rfctl[0], 0x140);
3722                        else
3723                                b43_phy_write(dev, rfctl[0], 0x110);
3724                } else {
3725                        if (band == IEEE80211_BAND_5GHZ)
3726                                b43_phy_write(dev, rfctl[0], 0x180);
3727                        else
3728                                b43_phy_write(dev, rfctl[0], 0x120);
3729                }
3730
3731                if (band == IEEE80211_BAND_5GHZ)
3732                        b43_phy_write(dev, rfctl[1], 0x148);
3733                else
3734                        b43_phy_write(dev, rfctl[1], 0x114);
3735
3736                if (nphy->rxcalparams & 0x10000) {
3737                        b43_radio_maskset(dev, B2055_C1_GENSPARE2, 0xFC,
3738                                        (i + 1));
3739                        b43_radio_maskset(dev, B2055_C2_GENSPARE2, 0xFC,
3740                                        (2 - i));
3741                }
3742
3743                for (j = 0; j < 4; j++) {
3744                        if (j < 3) {
3745                                cur_lna = lna[j];
3746                                cur_hpf1 = hpf1[j];
3747                                cur_hpf2 = hpf2[j];
3748                        } else {
3749                                if (power[1] > 10000) {
3750                                        use = 1;
3751                                        cur_hpf = cur_hpf1;
3752                                        index = 2;
3753                                } else {
3754                                        if (power[0] > 10000) {
3755                                                use = 1;
3756                                                cur_hpf = cur_hpf1;
3757                                                index = 1;
3758                                        } else {
3759                                                index = 0;
3760                                                use = 2;
3761                                                cur_hpf = cur_hpf2;
3762                                        }
3763                                }
3764                                cur_lna = lna[index];
3765                                cur_hpf1 = hpf1[index];
3766                                cur_hpf2 = hpf2[index];
3767                                cur_hpf += desired - hweight32(power[index]);
3768                                cur_hpf = clamp_val(cur_hpf, 0, 10);
3769                                if (use == 1)
3770                                        cur_hpf1 = cur_hpf;
3771                                else
3772                                        cur_hpf2 = cur_hpf;
3773                        }
3774
3775                        tmp[0] = ((cur_hpf2 << 8) | (cur_hpf1 << 4) |
3776                                        (cur_lna << 2));
3777                        b43_nphy_rf_control_override(dev, 0x400, tmp[0], 3,
3778                                                                        false);
3779                        b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
3780                        b43_nphy_stop_playback(dev);
3781
3782                        if (playtone) {
3783                                ret = b43_nphy_tx_tone(dev, 4000,
3784                                                (nphy->rxcalparams & 0xFFFF),
3785                                                false, false);
3786                                playtone = false;
3787                        } else {
3788                                b43_nphy_run_samples(dev, 160, 0xFFFF, 0,
3789                                                        false, false);
3790                        }
3791
3792                        if (ret == 0) {
3793                                if (j < 3) {
3794                                        b43_nphy_rx_iq_est(dev, &est, 1024, 32,
3795                                                                        false);
3796                                        if (i == 0) {
3797                                                real = est.i0_pwr;
3798                                                imag = est.q0_pwr;
3799                                        } else {
3800                                                real = est.i1_pwr;
3801                                                imag = est.q1_pwr;
3802                                        }
3803                                        power[i] = ((real + imag) / 1024) + 1;
3804                                } else {
3805                                        b43_nphy_calc_rx_iq_comp(dev, 1 << i);
3806                                }
3807                                b43_nphy_stop_playback(dev);
3808                        }
3809
3810                        if (ret != 0)
3811                                break;
3812                }
3813
3814                b43_radio_mask(dev, B2055_C1_GENSPARE2, 0xFC);
3815                b43_radio_mask(dev, B2055_C2_GENSPARE2, 0xFC);
3816                b43_phy_write(dev, rfctl[1], tmp[5]);
3817                b43_phy_write(dev, rfctl[0], tmp[4]);
3818                b43_phy_write(dev, B43_NPHY_AFECTL_OVER, tmp[3]);
3819                b43_phy_write(dev, afectl_core, tmp[2]);
3820                b43_phy_write(dev, B43_NPHY_RFSEQCA, tmp[1]);
3821
3822                if (ret != 0)
3823                        break;
3824        }
3825
3826        b43_nphy_rf_control_override(dev, 0x400, 0, 3, true);
3827        b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
3828        b43_ntab_write_bulk(dev, B43_NTAB16(7, 0x110), 2, gain_save);
3829
3830        b43_nphy_stay_in_carrier_search(dev, 0);
3831
3832        return ret;
3833}
3834
3835static int b43_nphy_rev3_cal_rx_iq(struct b43_wldev *dev,
3836                        struct nphy_txgains target, u8 type, bool debug)
3837{
3838        return -1;
3839}
3840
3841/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/CalRxIq */
3842static int b43_nphy_cal_rx_iq(struct b43_wldev *dev,
3843                        struct nphy_txgains target, u8 type, bool debug)
3844{
3845        if (dev->phy.rev >= 3)
3846                return b43_nphy_rev3_cal_rx_iq(dev, target, type, debug);
3847        else
3848                return b43_nphy_rev2_cal_rx_iq(dev, target, type, debug);
3849}
3850
3851/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/RxCoreSetState */
3852static void b43_nphy_set_rx_core_state(struct b43_wldev *dev, u8 mask)
3853{
3854        struct b43_phy *phy = &dev->phy;
3855        struct b43_phy_n *nphy = phy->n;
3856        /* u16 buf[16]; it's rev3+ */
3857
3858        nphy->phyrxchain = mask;
3859
3860        if (0 /* FIXME clk */)
3861                return;
3862
3863        b43_mac_suspend(dev);
3864
3865        if (nphy->hang_avoid)
3866                b43_nphy_stay_in_carrier_search(dev, true);
3867
3868        b43_phy_maskset(dev, B43_NPHY_RFSEQCA, ~B43_NPHY_RFSEQCA_RXEN,
3869                        (mask & 0x3) << B43_NPHY_RFSEQCA_RXEN_SHIFT);
3870
3871        if ((mask & 0x3) != 0x3) {
3872                b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 1);
3873                if (dev->phy.rev >= 3) {
3874                        /* TODO */
3875                }
3876        } else {
3877                b43_phy_write(dev, B43_NPHY_HPANT_SWTHRES, 0x1E);
3878                if (dev->phy.rev >= 3) {
3879                        /* TODO */
3880                }
3881        }
3882
3883        b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
3884
3885        if (nphy->hang_avoid)
3886                b43_nphy_stay_in_carrier_search(dev, false);
3887
3888        b43_mac_enable(dev);
3889}
3890
3891/**************************************************
3892 * N-PHY init
3893 **************************************************/
3894
3895/*
3896 * Upload the N-PHY tables.
3897 * http://bcm-v4.sipsolutions.net/802.11/PHY/N/InitTables
3898 */
3899static void b43_nphy_tables_init(struct b43_wldev *dev)
3900{
3901        if (dev->phy.rev < 3)
3902                b43_nphy_rev0_1_2_tables_init(dev);
3903        else
3904                b43_nphy_rev3plus_tables_init(dev);
3905}
3906
3907/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/MIMOConfig */
3908static void b43_nphy_update_mimo_config(struct b43_wldev *dev, s32 preamble)
3909{
3910        u16 mimocfg = b43_phy_read(dev, B43_NPHY_MIMOCFG);
3911
3912        mimocfg |= B43_NPHY_MIMOCFG_AUTO;
3913        if (preamble == 1)
3914                mimocfg |= B43_NPHY_MIMOCFG_GFMIX;
3915        else
3916                mimocfg &= ~B43_NPHY_MIMOCFG_GFMIX;
3917
3918        b43_phy_write(dev, B43_NPHY_MIMOCFG, mimocfg);
3919}
3920
3921/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BPHYInit */
3922static void b43_nphy_bphy_init(struct b43_wldev *dev)
3923{
3924        unsigned int i;
3925        u16 val;
3926
3927        val = 0x1E1F;
3928        for (i = 0; i < 16; i++) {
3929                b43_phy_write(dev, B43_PHY_N_BMODE(0x88 + i), val);
3930                val -= 0x202;
3931        }
3932        val = 0x3E3F;
3933        for (i = 0; i < 16; i++) {
3934                b43_phy_write(dev, B43_PHY_N_BMODE(0x98 + i), val);
3935                val -= 0x202;
3936        }
3937        b43_phy_write(dev, B43_PHY_N_BMODE(0x38), 0x668);
3938}
3939
3940/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SuperSwitchInit */
3941static void b43_nphy_superswitch_init(struct b43_wldev *dev, bool init)
3942{
3943        if (dev->phy.rev >= 3) {
3944                if (!init)
3945                        return;
3946                if (0 /* FIXME */) {
3947                        b43_ntab_write(dev, B43_NTAB16(9, 2), 0x211);
3948                        b43_ntab_write(dev, B43_NTAB16(9, 3), 0x222);
3949                        b43_ntab_write(dev, B43_NTAB16(9, 8), 0x144);
3950                        b43_ntab_write(dev, B43_NTAB16(9, 12), 0x188);
3951                }
3952        } else {
3953                b43_phy_write(dev, B43_NPHY_GPIO_LOOEN, 0);
3954                b43_phy_write(dev, B43_NPHY_GPIO_HIOEN, 0);
3955
3956                switch (dev->dev->bus_type) {
3957#ifdef CONFIG_B43_BCMA
3958                case B43_BUS_BCMA:
3959                        bcma_chipco_gpio_control(&dev->dev->bdev->bus->drv_cc,
3960                                                 0xFC00, 0xFC00);
3961                        break;
3962#endif
3963#ifdef CONFIG_B43_SSB
3964                case B43_BUS_SSB:
3965                        ssb_chipco_gpio_control(&dev->dev->sdev->bus->chipco,
3966                                                0xFC00, 0xFC00);
3967                        break;
3968#endif
3969                }
3970
3971                b43_write32(dev, B43_MMIO_MACCTL,
3972                        b43_read32(dev, B43_MMIO_MACCTL) &
3973                        ~B43_MACCTL_GPOUTSMSK);
3974                b43_write16(dev, B43_MMIO_GPIO_MASK,
3975                        b43_read16(dev, B43_MMIO_GPIO_MASK) | 0xFC00);
3976                b43_write16(dev, B43_MMIO_GPIO_CONTROL,
3977                        b43_read16(dev, B43_MMIO_GPIO_CONTROL) & ~0xFC00);
3978
3979                if (init) {
3980                        b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO1, 0x2D8);
3981                        b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP1, 0x301);
3982                        b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_LO2, 0x2D8);
3983                        b43_phy_write(dev, B43_NPHY_RFCTL_LUT_TRSW_UP2, 0x301);
3984                }
3985        }
3986}
3987
3988/* http://bcm-v4.sipsolutions.net/802.11/PHY/Init/N */
3989int b43_phy_initn(struct b43_wldev *dev)
3990{
3991        struct ssb_sprom *sprom = dev->dev->bus_sprom;
3992        struct b43_phy *phy = &dev->phy;
3993        struct b43_phy_n *nphy = phy->n;
3994        u8 tx_pwr_state;
3995        struct nphy_txgains target;
3996        u16 tmp;
3997        enum ieee80211_band tmp2;
3998        bool do_rssi_cal;
3999
4000        u16 clip[2];
4001        bool do_cal = false;
4002
4003        if ((dev->phy.rev >= 3) &&
4004           (sprom->boardflags_lo & B43_BFL_EXTLNA) &&
4005           (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)) {
4006                switch (dev->dev->bus_type) {
4007#ifdef CONFIG_B43_BCMA
4008                case B43_BUS_BCMA:
4009                        bcma_cc_set32(&dev->dev->bdev->bus->drv_cc,
4010                                      BCMA_CC_CHIPCTL, 0x40);
4011                        break;
4012#endif
4013#ifdef CONFIG_B43_SSB
4014                case B43_BUS_SSB:
4015                        chipco_set32(&dev->dev->sdev->bus->chipco,
4016                                     SSB_CHIPCO_CHIPCTL, 0x40);
4017                        break;
4018#endif
4019                }
4020        }
4021        nphy->deaf_count = 0;
4022        b43_nphy_tables_init(dev);
4023        nphy->crsminpwr_adjusted = false;
4024        nphy->noisevars_adjusted = false;
4025
4026        /* Clear all overrides */
4027        if (dev->phy.rev >= 3) {
4028                b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S1, 0);
4029                b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
4030                b43_phy_write(dev, B43_NPHY_TXF_40CO_B1S0, 0);
4031                b43_phy_write(dev, B43_NPHY_TXF_40CO_B32S1, 0);
4032        } else {
4033                b43_phy_write(dev, B43_NPHY_RFCTL_OVER, 0);
4034        }
4035        b43_phy_write(dev, B43_NPHY_RFCTL_INTC1, 0);
4036        b43_phy_write(dev, B43_NPHY_RFCTL_INTC2, 0);
4037        if (dev->phy.rev < 6) {
4038                b43_phy_write(dev, B43_NPHY_RFCTL_INTC3, 0);
4039                b43_phy_write(dev, B43_NPHY_RFCTL_INTC4, 0);
4040        }
4041        b43_phy_mask(dev, B43_NPHY_RFSEQMODE,
4042                     ~(B43_NPHY_RFSEQMODE_CAOVER |
4043                       B43_NPHY_RFSEQMODE_TROVER));
4044        if (dev->phy.rev >= 3)
4045                b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, 0);
4046        b43_phy_write(dev, B43_NPHY_AFECTL_OVER, 0);
4047
4048        if (dev->phy.rev <= 2) {
4049                tmp = (dev->phy.rev == 2) ? 0x3B : 0x40;
4050                b43_phy_maskset(dev, B43_NPHY_BPHY_CTL3,
4051                                ~B43_NPHY_BPHY_CTL3_SCALE,
4052                                tmp << B43_NPHY_BPHY_CTL3_SCALE_SHIFT);
4053        }
4054        b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_20M, 0x20);
4055        b43_phy_write(dev, B43_NPHY_AFESEQ_TX2RX_PUD_40M, 0x20);
4056
4057        if (sprom->boardflags2_lo & B43_BFL2_SKWRKFEM_BRD ||
4058            (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
4059             dev->dev->board_type == 0x8B))
4060                b43_phy_write(dev, B43_NPHY_TXREALFD, 0xA0);
4061        else
4062                b43_phy_write(dev, B43_NPHY_TXREALFD, 0xB8);
4063        b43_phy_write(dev, B43_NPHY_MIMO_CRSTXEXT, 0xC8);
4064        b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x50);
4065        b43_phy_write(dev, B43_NPHY_TXRIFS_FRDEL, 0x30);
4066
4067        b43_nphy_update_mimo_config(dev, nphy->preamble_override);
4068        b43_nphy_update_txrx_chain(dev);
4069
4070        if (phy->rev < 2) {
4071                b43_phy_write(dev, B43_NPHY_DUP40_GFBL, 0xAA8);
4072                b43_phy_write(dev, B43_NPHY_DUP40_BL, 0x9A4);
4073        }
4074
4075        tmp2 = b43_current_band(dev->wl);
4076        if (b43_nphy_ipa(dev)) {
4077                b43_phy_set(dev, B43_NPHY_PAPD_EN0, 0x1);
4078                b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ0, 0x007F,
4079                                nphy->papd_epsilon_offset[0] << 7);
4080                b43_phy_set(dev, B43_NPHY_PAPD_EN1, 0x1);
4081                b43_phy_maskset(dev, B43_NPHY_EPS_TABLE_ADJ1, 0x007F,
4082                                nphy->papd_epsilon_offset[1] << 7);
4083                b43_nphy_int_pa_set_tx_dig_filters(dev);
4084        } else if (phy->rev >= 5) {
4085                b43_nphy_ext_pa_set_tx_dig_filters(dev);
4086        }
4087
4088        b43_nphy_workarounds(dev);
4089
4090        /* Reset CCA, in init code it differs a little from standard way */
4091        b43_phy_force_clock(dev, 1);
4092        tmp = b43_phy_read(dev, B43_NPHY_BBCFG);
4093        b43_phy_write(dev, B43_NPHY_BBCFG, tmp | B43_NPHY_BBCFG_RSTCCA);
4094        b43_phy_write(dev, B43_NPHY_BBCFG, tmp & ~B43_NPHY_BBCFG_RSTCCA);
4095        b43_phy_force_clock(dev, 0);
4096
4097        b43_mac_phy_clock_set(dev, true);
4098
4099        b43_nphy_pa_override(dev, false);
4100        b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RX2TX);
4101        b43_nphy_force_rf_sequence(dev, B43_RFSEQ_RESET2RX);
4102        b43_nphy_pa_override(dev, true);
4103
4104        b43_nphy_classifier(dev, 0, 0);
4105        b43_nphy_read_clip_detection(dev, clip);
4106        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
4107                b43_nphy_bphy_init(dev);
4108
4109        tx_pwr_state = nphy->txpwrctrl;
4110        b43_nphy_tx_power_ctrl(dev, false);
4111        b43_nphy_tx_power_fix(dev);
4112        b43_nphy_tx_power_ctl_idle_tssi(dev);
4113        /* TODO N PHY TX Power Control Setup */
4114        b43_nphy_tx_gain_table_upload(dev);
4115
4116        if (nphy->phyrxchain != 3)
4117                b43_nphy_set_rx_core_state(dev, nphy->phyrxchain);
4118        if (nphy->mphase_cal_phase_id > 0)
4119                ;/* TODO PHY Periodic Calibration Multi-Phase Restart */
4120
4121        do_rssi_cal = false;
4122        if (phy->rev >= 3) {
4123                if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
4124                        do_rssi_cal = !nphy->rssical_chanspec_2G.center_freq;
4125                else
4126                        do_rssi_cal = !nphy->rssical_chanspec_5G.center_freq;
4127
4128                if (do_rssi_cal)
4129                        b43_nphy_rssi_cal(dev);
4130                else
4131                        b43_nphy_restore_rssi_cal(dev);
4132        } else {
4133                b43_nphy_rssi_cal(dev);
4134        }
4135
4136        if (!((nphy->measure_hold & 0x6) != 0)) {
4137                if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
4138                        do_cal = !nphy->iqcal_chanspec_2G.center_freq;
4139                else
4140                        do_cal = !nphy->iqcal_chanspec_5G.center_freq;
4141
4142                if (nphy->mute)
4143                        do_cal = false;
4144
4145                if (do_cal) {
4146                        target = b43_nphy_get_tx_gains(dev);
4147
4148                        if (nphy->antsel_type == 2)
4149                                b43_nphy_superswitch_init(dev, true);
4150                        if (nphy->perical != 2) {
4151                                b43_nphy_rssi_cal(dev);
4152                                if (phy->rev >= 3) {
4153                                        nphy->cal_orig_pwr_idx[0] =
4154                                            nphy->txpwrindex[0].index_internal;
4155                                        nphy->cal_orig_pwr_idx[1] =
4156                                            nphy->txpwrindex[1].index_internal;
4157                                        /* TODO N PHY Pre Calibrate TX Gain */
4158                                        target = b43_nphy_get_tx_gains(dev);
4159                                }
4160                                if (!b43_nphy_cal_tx_iq_lo(dev, target, true, false))
4161                                        if (b43_nphy_cal_rx_iq(dev, target, 2, 0) == 0)
4162                                                b43_nphy_save_cal(dev);
4163                        } else if (nphy->mphase_cal_phase_id == 0)
4164                                ;/* N PHY Periodic Calibration with arg 3 */
4165                } else {
4166                        b43_nphy_restore_cal(dev);
4167                }
4168        }
4169
4170        b43_nphy_tx_pwr_ctrl_coef_setup(dev);
4171        b43_nphy_tx_power_ctrl(dev, tx_pwr_state);
4172        b43_phy_write(dev, B43_NPHY_TXMACIF_HOLDOFF, 0x0015);
4173        b43_phy_write(dev, B43_NPHY_TXMACDELAY, 0x0320);
4174        if (phy->rev >= 3 && phy->rev <= 6)
4175                b43_phy_write(dev, B43_NPHY_PLOAD_CSENSE_EXTLEN, 0x0014);
4176        b43_nphy_tx_lp_fbw(dev);
4177        if (phy->rev >= 3)
4178                b43_nphy_spur_workaround(dev);
4179
4180        return 0;
4181}
4182
4183/**************************************************
4184 * Channel switching ops.
4185 **************************************************/
4186
4187static void b43_chantab_phy_upload(struct b43_wldev *dev,
4188                                   const struct b43_phy_n_sfo_cfg *e)
4189{
4190        b43_phy_write(dev, B43_NPHY_BW1A, e->phy_bw1a);
4191        b43_phy_write(dev, B43_NPHY_BW2, e->phy_bw2);
4192        b43_phy_write(dev, B43_NPHY_BW3, e->phy_bw3);
4193        b43_phy_write(dev, B43_NPHY_BW4, e->phy_bw4);
4194        b43_phy_write(dev, B43_NPHY_BW5, e->phy_bw5);
4195        b43_phy_write(dev, B43_NPHY_BW6, e->phy_bw6);
4196}
4197
4198/* http://bcm-v4.sipsolutions.net/802.11/PmuSpurAvoid */
4199static void b43_nphy_pmu_spur_avoid(struct b43_wldev *dev, bool avoid)
4200{
4201        struct bcma_drv_cc __maybe_unused *cc;
4202        u32 __maybe_unused pmu_ctl;
4203
4204        switch (dev->dev->bus_type) {
4205#ifdef CONFIG_B43_BCMA
4206        case B43_BUS_BCMA:
4207                cc = &dev->dev->bdev->bus->drv_cc;
4208                if (dev->dev->chip_id == 43224 || dev->dev->chip_id == 43225) {
4209                        if (avoid) {
4210                                bcma_chipco_pll_write(cc, 0x0, 0x11500010);
4211                                bcma_chipco_pll_write(cc, 0x1, 0x000C0C06);
4212                                bcma_chipco_pll_write(cc, 0x2, 0x0F600a08);
4213                                bcma_chipco_pll_write(cc, 0x3, 0x00000000);
4214                                bcma_chipco_pll_write(cc, 0x4, 0x2001E920);
4215                                bcma_chipco_pll_write(cc, 0x5, 0x88888815);
4216                        } else {
4217                                bcma_chipco_pll_write(cc, 0x0, 0x11100010);
4218                                bcma_chipco_pll_write(cc, 0x1, 0x000c0c06);
4219                                bcma_chipco_pll_write(cc, 0x2, 0x03000a08);
4220                                bcma_chipco_pll_write(cc, 0x3, 0x00000000);
4221                                bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
4222                                bcma_chipco_pll_write(cc, 0x5, 0x88888815);
4223                        }
4224                        pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD;
4225                } else if (dev->dev->chip_id == 0x4716) {
4226                        if (avoid) {
4227                                bcma_chipco_pll_write(cc, 0x0, 0x11500060);
4228                                bcma_chipco_pll_write(cc, 0x1, 0x080C0C06);
4229                                bcma_chipco_pll_write(cc, 0x2, 0x0F600000);
4230                                bcma_chipco_pll_write(cc, 0x3, 0x00000000);
4231                                bcma_chipco_pll_write(cc, 0x4, 0x2001E924);
4232                                bcma_chipco_pll_write(cc, 0x5, 0x88888815);
4233                        } else {
4234                                bcma_chipco_pll_write(cc, 0x0, 0x11100060);
4235                                bcma_chipco_pll_write(cc, 0x1, 0x080c0c06);
4236                                bcma_chipco_pll_write(cc, 0x2, 0x03000000);
4237                                bcma_chipco_pll_write(cc, 0x3, 0x00000000);
4238                                bcma_chipco_pll_write(cc, 0x4, 0x200005c0);
4239                                bcma_chipco_pll_write(cc, 0x5, 0x88888815);
4240                        }
4241                        pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD |
4242                                  BCMA_CC_PMU_CTL_NOILPONW;
4243                } else if (dev->dev->chip_id == 0x4322 ||
4244                           dev->dev->chip_id == 0x4340 ||
4245                           dev->dev->chip_id == 0x4341) {
4246                        bcma_chipco_pll_write(cc, 0x0, 0x11100070);
4247                        bcma_chipco_pll_write(cc, 0x1, 0x1014140a);
4248                        bcma_chipco_pll_write(cc, 0x5, 0x88888854);
4249                        if (avoid)
4250                                bcma_chipco_pll_write(cc, 0x2, 0x05201828);
4251                        else
4252                                bcma_chipco_pll_write(cc, 0x2, 0x05001828);
4253                        pmu_ctl = BCMA_CC_PMU_CTL_PLL_UPD;
4254                } else {
4255                        return;
4256                }
4257                bcma_cc_set32(cc, BCMA_CC_PMU_CTL, pmu_ctl);
4258                break;
4259#endif
4260#ifdef CONFIG_B43_SSB
4261        case B43_BUS_SSB:
4262                /* FIXME */
4263                break;
4264#endif
4265        }
4266}
4267
4268/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/ChanspecSetup */
4269static void b43_nphy_channel_setup(struct b43_wldev *dev,
4270                                const struct b43_phy_n_sfo_cfg *e,
4271                                struct ieee80211_channel *new_channel)
4272{
4273        struct b43_phy *phy = &dev->phy;
4274        struct b43_phy_n *nphy = dev->phy.n;
4275        int ch = new_channel->hw_value;
4276
4277        u16 old_band_5ghz;
4278        u32 tmp32;
4279
4280        old_band_5ghz =
4281                b43_phy_read(dev, B43_NPHY_BANDCTL) & B43_NPHY_BANDCTL_5GHZ;
4282        if (new_channel->band == IEEE80211_BAND_5GHZ && !old_band_5ghz) {
4283                tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
4284                b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
4285                b43_phy_set(dev, B43_PHY_B_BBCFG, 0xC000);
4286                b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
4287                b43_phy_set(dev, B43_NPHY_BANDCTL, B43_NPHY_BANDCTL_5GHZ);
4288        } else if (new_channel->band == IEEE80211_BAND_2GHZ && old_band_5ghz) {
4289                b43_phy_mask(dev, B43_NPHY_BANDCTL, ~B43_NPHY_BANDCTL_5GHZ);
4290                tmp32 = b43_read32(dev, B43_MMIO_PSM_PHY_HDR);
4291                b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32 | 4);
4292                b43_phy_mask(dev, B43_PHY_B_BBCFG, 0x3FFF);
4293                b43_write32(dev, B43_MMIO_PSM_PHY_HDR, tmp32);
4294        }
4295
4296        b43_chantab_phy_upload(dev, e);
4297
4298        if (new_channel->hw_value == 14) {
4299                b43_nphy_classifier(dev, 2, 0);
4300                b43_phy_set(dev, B43_PHY_B_TEST, 0x0800);
4301        } else {
4302                b43_nphy_classifier(dev, 2, 2);
4303                if (new_channel->band == IEEE80211_BAND_2GHZ)
4304                        b43_phy_mask(dev, B43_PHY_B_TEST, ~0x840);
4305        }
4306
4307        if (!nphy->txpwrctrl)
4308                b43_nphy_tx_power_fix(dev);
4309
4310        if (dev->phy.rev < 3)
4311                b43_nphy_adjust_lna_gain_table(dev);
4312
4313        b43_nphy_tx_lp_fbw(dev);
4314
4315        if (dev->phy.rev >= 3 &&
4316            dev->phy.n->spur_avoid != B43_SPUR_AVOID_DISABLE) {
4317                bool avoid = false;
4318                if (dev->phy.n->spur_avoid == B43_SPUR_AVOID_FORCE) {
4319                        avoid = true;
4320                } else if (!b43_channel_type_is_40mhz(phy->channel_type)) {
4321                        if ((ch >= 5 && ch <= 8) || ch == 13 || ch == 14)
4322                                avoid = true;
4323                } else { /* 40MHz */
4324                        if (nphy->aband_spurwar_en &&
4325                            (ch == 38 || ch == 102 || ch == 118))
4326                                avoid = dev->dev->chip_id == 0x4716;
4327                }
4328
4329                b43_nphy_pmu_spur_avoid(dev, avoid);
4330
4331                if (dev->dev->chip_id == 43222 || dev->dev->chip_id == 43224 ||
4332                    dev->dev->chip_id == 43225) {
4333                        b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_LOW,
4334                                    avoid ? 0x5341 : 0x8889);
4335                        b43_write16(dev, B43_MMIO_TSF_CLK_FRAC_HIGH, 0x8);
4336                }
4337
4338                if (dev->phy.rev == 3 || dev->phy.rev == 4)
4339                        ; /* TODO: reset PLL */
4340
4341                if (avoid)
4342                        b43_phy_set(dev, B43_NPHY_BBCFG, B43_NPHY_BBCFG_RSTRX);
4343                else
4344                        b43_phy_mask(dev, B43_NPHY_BBCFG,
4345                                     ~B43_NPHY_BBCFG_RSTRX & 0xFFFF);
4346
4347                b43_nphy_reset_cca(dev);
4348
4349                /* wl sets useless phy_isspuravoid here */
4350        }
4351
4352        b43_phy_write(dev, B43_NPHY_NDATAT_DUP40, 0x3830);
4353
4354        if (phy->rev >= 3)
4355                b43_nphy_spur_workaround(dev);
4356}
4357
4358/* http://bcm-v4.sipsolutions.net/802.11/PHY/N/SetChanspec */
4359static int b43_nphy_set_channel(struct b43_wldev *dev,
4360                                struct ieee80211_channel *channel,
4361                                enum nl80211_channel_type channel_type)
4362{
4363        struct b43_phy *phy = &dev->phy;
4364
4365        const struct b43_nphy_channeltab_entry_rev2 *tabent_r2 = NULL;
4366        const struct b43_nphy_channeltab_entry_rev3 *tabent_r3 = NULL;
4367
4368        u8 tmp;
4369
4370        if (dev->phy.rev >= 3) {
4371                tabent_r3 = b43_nphy_get_chantabent_rev3(dev,
4372                                                        channel->center_freq);
4373                if (!tabent_r3)
4374                        return -ESRCH;
4375        } else {
4376                tabent_r2 = b43_nphy_get_chantabent_rev2(dev,
4377                                                        channel->hw_value);
4378                if (!tabent_r2)
4379                        return -ESRCH;
4380        }
4381
4382        /* Channel is set later in common code, but we need to set it on our
4383           own to let this function's subcalls work properly. */
4384        phy->channel = channel->hw_value;
4385        phy->channel_freq = channel->center_freq;
4386
4387        if (b43_channel_type_is_40mhz(phy->channel_type) !=
4388                b43_channel_type_is_40mhz(channel_type))
4389                ; /* TODO: BMAC BW Set (channel_type) */
4390
4391        if (channel_type == NL80211_CHAN_HT40PLUS)
4392                b43_phy_set(dev, B43_NPHY_RXCTL,
4393                                B43_NPHY_RXCTL_BSELU20);
4394        else if (channel_type == NL80211_CHAN_HT40MINUS)
4395                b43_phy_mask(dev, B43_NPHY_RXCTL,
4396                                ~B43_NPHY_RXCTL_BSELU20);
4397
4398        if (dev->phy.rev >= 3) {
4399                tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 4 : 0;
4400                b43_radio_maskset(dev, 0x08, 0xFFFB, tmp);
4401                b43_radio_2056_setup(dev, tabent_r3);
4402                b43_nphy_channel_setup(dev, &(tabent_r3->phy_regs), channel);
4403        } else {
4404                tmp = (channel->band == IEEE80211_BAND_5GHZ) ? 0x0020 : 0x0050;
4405                b43_radio_maskset(dev, B2055_MASTER1, 0xFF8F, tmp);
4406                b43_radio_2055_setup(dev, tabent_r2);
4407                b43_nphy_channel_setup(dev, &(tabent_r2->phy_regs), channel);
4408        }
4409
4410        return 0;
4411}
4412
4413/**************************************************
4414 * Basic PHY ops.
4415 **************************************************/
4416
4417static int b43_nphy_op_allocate(struct b43_wldev *dev)
4418{
4419        struct b43_phy_n *nphy;
4420
4421        nphy = kzalloc(sizeof(*nphy), GFP_KERNEL);
4422        if (!nphy)
4423                return -ENOMEM;
4424        dev->phy.n = nphy;
4425
4426        return 0;
4427}
4428
4429static void b43_nphy_op_prepare_structs(struct b43_wldev *dev)
4430{
4431        struct b43_phy *phy = &dev->phy;
4432        struct b43_phy_n *nphy = phy->n;
4433        struct ssb_sprom *sprom = dev->dev->bus_sprom;
4434
4435        memset(nphy, 0, sizeof(*nphy));
4436
4437        nphy->hang_avoid = (phy->rev == 3 || phy->rev == 4);
4438        nphy->spur_avoid = (phy->rev >= 3) ?
4439                                B43_SPUR_AVOID_AUTO : B43_SPUR_AVOID_DISABLE;
4440        nphy->gain_boost = true; /* this way we follow wl, assume it is true */
4441        nphy->txrx_chain = 2; /* sth different than 0 and 1 for now */
4442        nphy->phyrxchain = 3; /* to avoid b43_nphy_set_rx_core_state like wl */
4443        nphy->perical = 2; /* avoid additional rssi cal on init (like wl) */
4444        /* 128 can mean disabled-by-default state of TX pwr ctl. Max value is
4445         * 0x7f == 127 and we check for 128 when restoring TX pwr ctl. */
4446        nphy->tx_pwr_idx[0] = 128;
4447        nphy->tx_pwr_idx[1] = 128;
4448
4449        /* Hardware TX power control and 5GHz power gain */
4450        nphy->txpwrctrl = false;
4451        nphy->pwg_gain_5ghz = false;
4452        if (dev->phy.rev >= 3 ||
4453            (dev->dev->board_vendor == PCI_VENDOR_ID_APPLE &&
4454             (dev->dev->core_rev == 11 || dev->dev->core_rev == 12))) {
4455                nphy->txpwrctrl = true;
4456                nphy->pwg_gain_5ghz = true;
4457        } else if (sprom->revision >= 4) {
4458                if (dev->phy.rev >= 2 &&
4459                    (sprom->boardflags2_lo & B43_BFL2_TXPWRCTRL_EN)) {
4460                        nphy->txpwrctrl = true;
4461#ifdef CONFIG_B43_SSB
4462                        if (dev->dev->bus_type == B43_BUS_SSB &&
4463                            dev->dev->sdev->bus->bustype == SSB_BUSTYPE_PCI) {
4464                                struct pci_dev *pdev =
4465                                        dev->dev->sdev->bus->host_pci;
4466                                if (pdev->device == 0x4328 ||
4467                                    pdev->device == 0x432a)
4468                                        nphy->pwg_gain_5ghz = true;
4469                        }
4470#endif
4471                } else if (sprom->boardflags2_lo & B43_BFL2_5G_PWRGAIN) {
4472                        nphy->pwg_gain_5ghz = true;
4473                }
4474        }
4475
4476        if (dev->phy.rev >= 3) {
4477                nphy->ipa2g_on = sprom->fem.ghz2.extpa_gain == 2;
4478                nphy->ipa5g_on = sprom->fem.ghz5.extpa_gain == 2;
4479        }
4480}
4481
4482static void b43_nphy_op_free(struct b43_wldev *dev)
4483{
4484        struct b43_phy *phy = &dev->phy;
4485        struct b43_phy_n *nphy = phy->n;
4486
4487        kfree(nphy);
4488        phy->n = NULL;
4489}
4490
4491static int b43_nphy_op_init(struct b43_wldev *dev)
4492{
4493        return b43_phy_initn(dev);
4494}
4495
4496static inline void check_phyreg(struct b43_wldev *dev, u16 offset)
4497{
4498#if B43_DEBUG
4499        if ((offset & B43_PHYROUTE) == B43_PHYROUTE_OFDM_GPHY) {
4500                /* OFDM registers are onnly available on A/G-PHYs */
4501                b43err(dev->wl, "Invalid OFDM PHY access at "
4502                       "0x%04X on N-PHY\n", offset);
4503                dump_stack();
4504        }
4505        if ((offset & B43_PHYROUTE) == B43_PHYROUTE_EXT_GPHY) {
4506                /* Ext-G registers are only available on G-PHYs */
4507                b43err(dev->wl, "Invalid EXT-G PHY access at "
4508                       "0x%04X on N-PHY\n", offset);
4509                dump_stack();
4510        }
4511#endif /* B43_DEBUG */
4512}
4513
4514static u16 b43_nphy_op_read(struct b43_wldev *dev, u16 reg)
4515{
4516        check_phyreg(dev, reg);
4517        b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
4518        return b43_read16(dev, B43_MMIO_PHY_DATA);
4519}
4520
4521static void b43_nphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
4522{
4523        check_phyreg(dev, reg);
4524        b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
4525        b43_write16(dev, B43_MMIO_PHY_DATA, value);
4526}
4527
4528static void b43_nphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
4529                                 u16 set)
4530{
4531        check_phyreg(dev, reg);
4532        b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
4533        b43_write16(dev, B43_MMIO_PHY_DATA,
4534                    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
4535}
4536
4537static u16 b43_nphy_op_radio_read(struct b43_wldev *dev, u16 reg)
4538{
4539        /* Register 1 is a 32-bit register. */
4540        B43_WARN_ON(reg == 1);
4541        /* N-PHY needs 0x100 for read access */
4542        reg |= 0x100;
4543
4544        b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
4545        return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
4546}
4547
4548static void b43_nphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
4549{
4550        /* Register 1 is a 32-bit register. */
4551        B43_WARN_ON(reg == 1);
4552
4553        b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
4554        b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
4555}
4556
4557/* http://bcm-v4.sipsolutions.net/802.11/Radio/Switch%20Radio */
4558static void b43_nphy_op_software_rfkill(struct b43_wldev *dev,
4559                                        bool blocked)
4560{
4561        if (b43_read32(dev, B43_MMIO_MACCTL) & B43_MACCTL_ENABLED)
4562                b43err(dev->wl, "MAC not suspended\n");
4563
4564        if (blocked) {
4565                b43_phy_mask(dev, B43_NPHY_RFCTL_CMD,
4566                                ~B43_NPHY_RFCTL_CMD_CHIP0PU);
4567                if (dev->phy.rev >= 3) {
4568                        b43_radio_mask(dev, 0x09, ~0x2);
4569
4570                        b43_radio_write(dev, 0x204D, 0);
4571                        b43_radio_write(dev, 0x2053, 0);
4572                        b43_radio_write(dev, 0x2058, 0);
4573                        b43_radio_write(dev, 0x205E, 0);
4574                        b43_radio_mask(dev, 0x2062, ~0xF0);
4575                        b43_radio_write(dev, 0x2064, 0);
4576
4577                        b43_radio_write(dev, 0x304D, 0);
4578                        b43_radio_write(dev, 0x3053, 0);
4579                        b43_radio_write(dev, 0x3058, 0);
4580                        b43_radio_write(dev, 0x305E, 0);
4581                        b43_radio_mask(dev, 0x3062, ~0xF0);
4582                        b43_radio_write(dev, 0x3064, 0);
4583                }
4584        } else {
4585                if (dev->phy.rev >= 3) {
4586                        b43_radio_init2056(dev);
4587                        b43_switch_channel(dev, dev->phy.channel);
4588                } else {
4589                        b43_radio_init2055(dev);
4590                }
4591        }
4592}
4593
4594/* http://bcm-v4.sipsolutions.net/802.11/PHY/Anacore */
4595static void b43_nphy_op_switch_analog(struct b43_wldev *dev, bool on)
4596{
4597        u16 override = on ? 0x0 : 0x7FFF;
4598        u16 core = on ? 0xD : 0x00FD;
4599
4600        if (dev->phy.rev >= 3) {
4601                if (on) {
4602                        b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
4603                        b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
4604                        b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
4605                        b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
4606                } else {
4607                        b43_phy_write(dev, B43_NPHY_AFECTL_OVER1, override);
4608                        b43_phy_write(dev, B43_NPHY_AFECTL_C1, core);
4609                        b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
4610                        b43_phy_write(dev, B43_NPHY_AFECTL_C2, core);
4611                }
4612        } else {
4613                b43_phy_write(dev, B43_NPHY_AFECTL_OVER, override);
4614        }
4615}
4616
4617static int b43_nphy_op_switch_channel(struct b43_wldev *dev,
4618                                      unsigned int new_channel)
4619{
4620        struct ieee80211_channel *channel = dev->wl->hw->conf.channel;
4621        enum nl80211_channel_type channel_type = dev->wl->hw->conf.channel_type;
4622
4623        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
4624                if ((new_channel < 1) || (new_channel > 14))
4625                        return -EINVAL;
4626        } else {
4627                if (new_channel > 200)
4628                        return -EINVAL;
4629        }
4630
4631        return b43_nphy_set_channel(dev, channel, channel_type);
4632}
4633
4634static unsigned int b43_nphy_op_get_default_chan(struct b43_wldev *dev)
4635{
4636        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
4637                return 1;
4638        return 36;
4639}
4640
4641const struct b43_phy_operations b43_phyops_n = {
4642        .allocate               = b43_nphy_op_allocate,
4643        .free                   = b43_nphy_op_free,
4644        .prepare_structs        = b43_nphy_op_prepare_structs,
4645        .init                   = b43_nphy_op_init,
4646        .phy_read               = b43_nphy_op_read,
4647        .phy_write              = b43_nphy_op_write,
4648        .phy_maskset            = b43_nphy_op_maskset,
4649        .radio_read             = b43_nphy_op_radio_read,
4650        .radio_write            = b43_nphy_op_radio_write,
4651        .software_rfkill        = b43_nphy_op_software_rfkill,
4652        .switch_analog          = b43_nphy_op_switch_analog,
4653        .switch_channel         = b43_nphy_op_switch_channel,
4654        .get_default_chan       = b43_nphy_op_get_default_chan,
4655        .recalc_txpower         = b43_nphy_op_recalc_txpower,
4656        .adjust_txpower         = b43_nphy_op_adjust_txpower,
4657};
4658