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