linux/drivers/net/wireless/b43/phy_lp.c
<<
>>
Prefs
   1/*
   2
   3  Broadcom B43 wireless driver
   4  IEEE 802.11a/g LP-PHY driver
   5
   6  Copyright (c) 2008-2009 Michael Buesch <m@bues.ch>
   7  Copyright (c) 2009 Gábor Stefanik <netrolller.3d@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/slab.h>
  27
  28#include "b43.h"
  29#include "main.h"
  30#include "phy_lp.h"
  31#include "phy_common.h"
  32#include "tables_lpphy.h"
  33
  34
  35static inline u16 channel2freq_lp(u8 channel)
  36{
  37        if (channel < 14)
  38                return (2407 + 5 * channel);
  39        else if (channel == 14)
  40                return 2484;
  41        else if (channel < 184)
  42                return (5000 + 5 * channel);
  43        else
  44                return (4000 + 5 * channel);
  45}
  46
  47static unsigned int b43_lpphy_op_get_default_chan(struct b43_wldev *dev)
  48{
  49        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
  50                return 1;
  51        return 36;
  52}
  53
  54static int b43_lpphy_op_allocate(struct b43_wldev *dev)
  55{
  56        struct b43_phy_lp *lpphy;
  57
  58        lpphy = kzalloc(sizeof(*lpphy), GFP_KERNEL);
  59        if (!lpphy)
  60                return -ENOMEM;
  61        dev->phy.lp = lpphy;
  62
  63        return 0;
  64}
  65
  66static void b43_lpphy_op_prepare_structs(struct b43_wldev *dev)
  67{
  68        struct b43_phy *phy = &dev->phy;
  69        struct b43_phy_lp *lpphy = phy->lp;
  70
  71        memset(lpphy, 0, sizeof(*lpphy));
  72        lpphy->antenna = B43_ANTENNA_DEFAULT;
  73
  74        //TODO
  75}
  76
  77static void b43_lpphy_op_free(struct b43_wldev *dev)
  78{
  79        struct b43_phy_lp *lpphy = dev->phy.lp;
  80
  81        kfree(lpphy);
  82        dev->phy.lp = NULL;
  83}
  84
  85/* http://bcm-v4.sipsolutions.net/802.11/PHY/LP/ReadBandSrom */
  86static void lpphy_read_band_sprom(struct b43_wldev *dev)
  87{
  88        struct ssb_sprom *sprom = dev->dev->bus_sprom;
  89        struct b43_phy_lp *lpphy = dev->phy.lp;
  90        u16 cckpo, maxpwr;
  91        u32 ofdmpo;
  92        int i;
  93
  94        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
  95                lpphy->tx_isolation_med_band = sprom->tri2g;
  96                lpphy->bx_arch = sprom->bxa2g;
  97                lpphy->rx_pwr_offset = sprom->rxpo2g;
  98                lpphy->rssi_vf = sprom->rssismf2g;
  99                lpphy->rssi_vc = sprom->rssismc2g;
 100                lpphy->rssi_gs = sprom->rssisav2g;
 101                lpphy->txpa[0] = sprom->pa0b0;
 102                lpphy->txpa[1] = sprom->pa0b1;
 103                lpphy->txpa[2] = sprom->pa0b2;
 104                maxpwr = sprom->maxpwr_bg;
 105                lpphy->max_tx_pwr_med_band = maxpwr;
 106                cckpo = sprom->cck2gpo;
 107                /*
 108                 * We don't read SPROM's opo as specs say. On rev8 SPROMs
 109                 * opo == ofdm2gpo and we don't know any SSB with LP-PHY
 110                 * and SPROM rev below 8.
 111                 */
 112                B43_WARN_ON(sprom->revision < 8);
 113                ofdmpo = sprom->ofdm2gpo;
 114                if (cckpo) {
 115                        for (i = 0; i < 4; i++) {
 116                                lpphy->tx_max_rate[i] =
 117                                        maxpwr - (ofdmpo & 0xF) * 2;
 118                                ofdmpo >>= 4;
 119                        }
 120                        ofdmpo = sprom->ofdm2gpo;
 121                        for (i = 4; i < 15; i++) {
 122                                lpphy->tx_max_rate[i] =
 123                                        maxpwr - (ofdmpo & 0xF) * 2;
 124                                ofdmpo >>= 4;
 125                        }
 126                } else {
 127                        ofdmpo &= 0xFF;
 128                        for (i = 0; i < 4; i++)
 129                                lpphy->tx_max_rate[i] = maxpwr;
 130                        for (i = 4; i < 15; i++)
 131                                lpphy->tx_max_rate[i] = maxpwr - ofdmpo;
 132                }
 133        } else { /* 5GHz */
 134                lpphy->tx_isolation_low_band = sprom->tri5gl;
 135                lpphy->tx_isolation_med_band = sprom->tri5g;
 136                lpphy->tx_isolation_hi_band = sprom->tri5gh;
 137                lpphy->bx_arch = sprom->bxa5g;
 138                lpphy->rx_pwr_offset = sprom->rxpo5g;
 139                lpphy->rssi_vf = sprom->rssismf5g;
 140                lpphy->rssi_vc = sprom->rssismc5g;
 141                lpphy->rssi_gs = sprom->rssisav5g;
 142                lpphy->txpa[0] = sprom->pa1b0;
 143                lpphy->txpa[1] = sprom->pa1b1;
 144                lpphy->txpa[2] = sprom->pa1b2;
 145                lpphy->txpal[0] = sprom->pa1lob0;
 146                lpphy->txpal[1] = sprom->pa1lob1;
 147                lpphy->txpal[2] = sprom->pa1lob2;
 148                lpphy->txpah[0] = sprom->pa1hib0;
 149                lpphy->txpah[1] = sprom->pa1hib1;
 150                lpphy->txpah[2] = sprom->pa1hib2;
 151                maxpwr = sprom->maxpwr_al;
 152                ofdmpo = sprom->ofdm5glpo;
 153                lpphy->max_tx_pwr_low_band = maxpwr;
 154                for (i = 4; i < 12; i++) {
 155                        lpphy->tx_max_ratel[i] = maxpwr - (ofdmpo & 0xF) * 2;
 156                        ofdmpo >>= 4;
 157                }
 158                maxpwr = sprom->maxpwr_a;
 159                ofdmpo = sprom->ofdm5gpo;
 160                lpphy->max_tx_pwr_med_band = maxpwr;
 161                for (i = 4; i < 12; i++) {
 162                        lpphy->tx_max_rate[i] = maxpwr - (ofdmpo & 0xF) * 2;
 163                        ofdmpo >>= 4;
 164                }
 165                maxpwr = sprom->maxpwr_ah;
 166                ofdmpo = sprom->ofdm5ghpo;
 167                lpphy->max_tx_pwr_hi_band = maxpwr;
 168                for (i = 4; i < 12; i++) {
 169                        lpphy->tx_max_rateh[i] = maxpwr - (ofdmpo & 0xF) * 2;
 170                        ofdmpo >>= 4;
 171                }
 172        }
 173}
 174
 175static void lpphy_adjust_gain_table(struct b43_wldev *dev, u32 freq)
 176{
 177        struct b43_phy_lp *lpphy = dev->phy.lp;
 178        u16 temp[3];
 179        u16 isolation;
 180
 181        B43_WARN_ON(dev->phy.rev >= 2);
 182
 183        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
 184                isolation = lpphy->tx_isolation_med_band;
 185        else if (freq <= 5320)
 186                isolation = lpphy->tx_isolation_low_band;
 187        else if (freq <= 5700)
 188                isolation = lpphy->tx_isolation_med_band;
 189        else
 190                isolation = lpphy->tx_isolation_hi_band;
 191
 192        temp[0] = ((isolation - 26) / 12) << 12;
 193        temp[1] = temp[0] + 0x1000;
 194        temp[2] = temp[0] + 0x2000;
 195
 196        b43_lptab_write_bulk(dev, B43_LPTAB16(13, 0), 3, temp);
 197        b43_lptab_write_bulk(dev, B43_LPTAB16(12, 0), 3, temp);
 198}
 199
 200static void lpphy_table_init(struct b43_wldev *dev)
 201{
 202        u32 freq = channel2freq_lp(b43_lpphy_op_get_default_chan(dev));
 203
 204        if (dev->phy.rev < 2)
 205                lpphy_rev0_1_table_init(dev);
 206        else
 207                lpphy_rev2plus_table_init(dev);
 208
 209        lpphy_init_tx_gain_table(dev);
 210
 211        if (dev->phy.rev < 2)
 212                lpphy_adjust_gain_table(dev, freq);
 213}
 214
 215static void lpphy_baseband_rev0_1_init(struct b43_wldev *dev)
 216{
 217        struct ssb_bus *bus = dev->dev->sdev->bus;
 218        struct ssb_sprom *sprom = dev->dev->bus_sprom;
 219        struct b43_phy_lp *lpphy = dev->phy.lp;
 220        u16 tmp, tmp2;
 221
 222        b43_phy_mask(dev, B43_LPPHY_AFE_DAC_CTL, 0xF7FF);
 223        b43_phy_write(dev, B43_LPPHY_AFE_CTL, 0);
 224        b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, 0);
 225        b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, 0);
 226        b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0);
 227        b43_phy_set(dev, B43_LPPHY_AFE_DAC_CTL, 0x0004);
 228        b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0x0078);
 229        b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x5800);
 230        b43_phy_write(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x0016);
 231        b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_0, 0xFFF8, 0x0004);
 232        b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0x00FF, 0x5400);
 233        b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2400);
 234        b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100);
 235        b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0x0006);
 236        b43_phy_mask(dev, B43_LPPHY_RX_RADIO_CTL, 0xFFFE);
 237        b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x0005);
 238        b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0x0180);
 239        b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x3C00);
 240        b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFFF0, 0x0005);
 241        b43_phy_maskset(dev, B43_LPPHY_GAIN_MISMATCH_LIMIT, 0xFFC0, 0x001A);
 242        b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0x00B3);
 243        b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00);
 244        b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB,
 245                        0xFF00, lpphy->rx_pwr_offset);
 246        if ((sprom->boardflags_lo & B43_BFL_FEM) &&
 247           ((b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ) ||
 248           (sprom->boardflags_hi & B43_BFH_PAREF))) {
 249                ssb_pmu_set_ldo_voltage(&bus->chipco, LDO_PAREF, 0x28);
 250                ssb_pmu_set_ldo_paref(&bus->chipco, true);
 251                if (dev->phy.rev == 0) {
 252                        b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT,
 253                                        0xFFCF, 0x0010);
 254                }
 255                b43_lptab_write(dev, B43_LPTAB16(11, 7), 60);
 256        } else {
 257                ssb_pmu_set_ldo_paref(&bus->chipco, false);
 258                b43_phy_maskset(dev, B43_LPPHY_LP_RF_SIGNAL_LUT,
 259                                0xFFCF, 0x0020);
 260                b43_lptab_write(dev, B43_LPTAB16(11, 7), 100);
 261        }
 262        tmp = lpphy->rssi_vf | lpphy->rssi_vc << 4 | 0xA000;
 263        b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, tmp);
 264        if (sprom->boardflags_hi & B43_BFH_RSSIINV)
 265                b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x0AAA);
 266        else
 267                b43_phy_maskset(dev, B43_LPPHY_AFE_RSSI_CTL_1, 0xF000, 0x02AA);
 268        b43_lptab_write(dev, B43_LPTAB16(11, 1), 24);
 269        b43_phy_maskset(dev, B43_LPPHY_RX_RADIO_CTL,
 270                        0xFFF9, (lpphy->bx_arch << 1));
 271        if (dev->phy.rev == 1 &&
 272           (sprom->boardflags_hi & B43_BFH_FEM_BT)) {
 273                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);
 274                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0x3F00, 0x0900);
 275                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A);
 276                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0B00);
 277                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x000A);
 278                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0400);
 279                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x000A);
 280                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0B00);
 281                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_5, 0xFFC0, 0x000A);
 282                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_5, 0xC0FF, 0x0900);
 283                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_6, 0xFFC0, 0x000A);
 284                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_6, 0xC0FF, 0x0B00);
 285                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xFFC0, 0x000A);
 286                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_7, 0xC0FF, 0x0900);
 287                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xFFC0, 0x000A);
 288                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_8, 0xC0FF, 0x0B00);
 289        } else if (b43_current_band(dev->wl) == IEEE80211_BAND_5GHZ ||
 290                  (dev->dev->board_type == 0x048A) || ((dev->phy.rev == 0) &&
 291                  (sprom->boardflags_lo & B43_BFL_FEM))) {
 292                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0001);
 293                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0400);
 294                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0001);
 295                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0500);
 296                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0002);
 297                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0800);
 298                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);
 299                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0A00);
 300        } else if (dev->phy.rev == 1 ||
 301                  (sprom->boardflags_lo & B43_BFL_FEM)) {
 302                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x0004);
 303                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0800);
 304                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x0004);
 305                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0C00);
 306                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0002);
 307                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0100);
 308                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0002);
 309                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0300);
 310        } else {
 311                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xFFC0, 0x000A);
 312                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_1, 0xC0FF, 0x0900);
 313                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xFFC0, 0x000A);
 314                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_2, 0xC0FF, 0x0B00);
 315                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xFFC0, 0x0006);
 316                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_3, 0xC0FF, 0x0500);
 317                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xFFC0, 0x0006);
 318                b43_phy_maskset(dev, B43_LPPHY_TR_LOOKUP_4, 0xC0FF, 0x0700);
 319        }
 320        if (dev->phy.rev == 1 && (sprom->boardflags_hi & B43_BFH_PAREF)) {
 321                b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_5, B43_LPPHY_TR_LOOKUP_1);
 322                b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_6, B43_LPPHY_TR_LOOKUP_2);
 323                b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_7, B43_LPPHY_TR_LOOKUP_3);
 324                b43_phy_copy(dev, B43_LPPHY_TR_LOOKUP_8, B43_LPPHY_TR_LOOKUP_4);
 325        }
 326        if ((sprom->boardflags_hi & B43_BFH_FEM_BT) &&
 327            (dev->dev->chip_id == 0x5354) &&
 328            (dev->dev->chip_pkg == SSB_CHIPPACK_BCM4712S)) {
 329                b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0006);
 330                b43_phy_write(dev, B43_LPPHY_GPIO_SELECT, 0x0005);
 331                b43_phy_write(dev, B43_LPPHY_GPIO_OUTEN, 0xFFFF);
 332                //FIXME the Broadcom driver caches & delays this HF write!
 333                b43_hf_write(dev, b43_hf_read(dev) | B43_HF_PR45960W);
 334        }
 335        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
 336                b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x8000);
 337                b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x0040);
 338                b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0xA400);
 339                b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xF0FF, 0x0B00);
 340                b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x0007);
 341                b43_phy_maskset(dev, B43_LPPHY_DSSS_CONFIRM_CNT, 0xFFF8, 0x0003);
 342                b43_phy_maskset(dev, B43_LPPHY_DSSS_CONFIRM_CNT, 0xFFC7, 0x0020);
 343                b43_phy_mask(dev, B43_LPPHY_IDLEAFTERPKTRXTO, 0x00FF);
 344        } else { /* 5GHz */
 345                b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0x7FFF);
 346                b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFBF);
 347        }
 348        if (dev->phy.rev == 1) {
 349                tmp = b43_phy_read(dev, B43_LPPHY_CLIPCTRTHRESH);
 350                tmp2 = (tmp & 0x03E0) >> 5;
 351                tmp2 |= tmp2 << 5;
 352                b43_phy_write(dev, B43_LPPHY_4C3, tmp2);
 353                tmp = b43_phy_read(dev, B43_LPPHY_GAINDIRECTMISMATCH);
 354                tmp2 = (tmp & 0x1F00) >> 8;
 355                tmp2 |= tmp2 << 5;
 356                b43_phy_write(dev, B43_LPPHY_4C4, tmp2);
 357                tmp = b43_phy_read(dev, B43_LPPHY_VERYLOWGAINDB);
 358                tmp2 = tmp & 0x00FF;
 359                tmp2 |= tmp << 8;
 360                b43_phy_write(dev, B43_LPPHY_4C5, tmp2);
 361        }
 362}
 363
 364static void lpphy_save_dig_flt_state(struct b43_wldev *dev)
 365{
 366        static const u16 addr[] = {
 367                B43_PHY_OFDM(0xC1),
 368                B43_PHY_OFDM(0xC2),
 369                B43_PHY_OFDM(0xC3),
 370                B43_PHY_OFDM(0xC4),
 371                B43_PHY_OFDM(0xC5),
 372                B43_PHY_OFDM(0xC6),
 373                B43_PHY_OFDM(0xC7),
 374                B43_PHY_OFDM(0xC8),
 375                B43_PHY_OFDM(0xCF),
 376        };
 377
 378        static const u16 coefs[] = {
 379                0xDE5E, 0xE832, 0xE331, 0x4D26,
 380                0x0026, 0x1420, 0x0020, 0xFE08,
 381                0x0008,
 382        };
 383
 384        struct b43_phy_lp *lpphy = dev->phy.lp;
 385        int i;
 386
 387        for (i = 0; i < ARRAY_SIZE(addr); i++) {
 388                lpphy->dig_flt_state[i] = b43_phy_read(dev, addr[i]);
 389                b43_phy_write(dev, addr[i], coefs[i]);
 390        }
 391}
 392
 393static void lpphy_restore_dig_flt_state(struct b43_wldev *dev)
 394{
 395        static const u16 addr[] = {
 396                B43_PHY_OFDM(0xC1),
 397                B43_PHY_OFDM(0xC2),
 398                B43_PHY_OFDM(0xC3),
 399                B43_PHY_OFDM(0xC4),
 400                B43_PHY_OFDM(0xC5),
 401                B43_PHY_OFDM(0xC6),
 402                B43_PHY_OFDM(0xC7),
 403                B43_PHY_OFDM(0xC8),
 404                B43_PHY_OFDM(0xCF),
 405        };
 406
 407        struct b43_phy_lp *lpphy = dev->phy.lp;
 408        int i;
 409
 410        for (i = 0; i < ARRAY_SIZE(addr); i++)
 411                b43_phy_write(dev, addr[i], lpphy->dig_flt_state[i]);
 412}
 413
 414static void lpphy_baseband_rev2plus_init(struct b43_wldev *dev)
 415{
 416        struct b43_phy_lp *lpphy = dev->phy.lp;
 417
 418        b43_phy_write(dev, B43_LPPHY_AFE_DAC_CTL, 0x50);
 419        b43_phy_write(dev, B43_LPPHY_AFE_CTL, 0x8800);
 420        b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, 0);
 421        b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0);
 422        b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, 0);
 423        b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0);
 424        b43_phy_write(dev, B43_PHY_OFDM(0xF9), 0);
 425        b43_phy_write(dev, B43_LPPHY_TR_LOOKUP_1, 0);
 426        b43_phy_set(dev, B43_LPPHY_ADC_COMPENSATION_CTL, 0x10);
 427        b43_phy_maskset(dev, B43_LPPHY_OFDMSYNCTHRESH0, 0xFF00, 0xB4);
 428        b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xF8FF, 0x200);
 429        b43_phy_maskset(dev, B43_LPPHY_DCOFFSETTRANSIENT, 0xFF00, 0x7F);
 430        b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xFF0F, 0x40);
 431        b43_phy_maskset(dev, B43_LPPHY_PREAMBLECONFIRMTO, 0xFF00, 0x2);
 432        b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x4000);
 433        b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x2000);
 434        b43_phy_set(dev, B43_PHY_OFDM(0x10A), 0x1);
 435        if (dev->dev->board_rev >= 0x18) {
 436                b43_lptab_write(dev, B43_LPTAB32(17, 65), 0xEC);
 437                b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x14);
 438        } else {
 439                b43_phy_maskset(dev, B43_PHY_OFDM(0x10A), 0xFF01, 0x10);
 440        }
 441        b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0xFF00, 0xF4);
 442        b43_phy_maskset(dev, B43_PHY_OFDM(0xDF), 0x00FF, 0xF100);
 443        b43_phy_write(dev, B43_LPPHY_CLIPTHRESH, 0x48);
 444        b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0xFF00, 0x46);
 445        b43_phy_maskset(dev, B43_PHY_OFDM(0xE4), 0xFF00, 0x10);
 446        b43_phy_maskset(dev, B43_LPPHY_PWR_THRESH1, 0xFFF0, 0x9);
 447        b43_phy_mask(dev, B43_LPPHY_GAINDIRECTMISMATCH, ~0xF);
 448        b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0x00FF, 0x5500);
 449        b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFC1F, 0xA0);
 450        b43_phy_maskset(dev, B43_LPPHY_GAINDIRECTMISMATCH, 0xE0FF, 0x300);
 451        b43_phy_maskset(dev, B43_LPPHY_HIGAINDB, 0x00FF, 0x2A00);
 452        if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
 453                b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x2100);
 454                b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xA);
 455        } else {
 456                b43_phy_maskset(dev, B43_LPPHY_LOWGAINDB, 0x00FF, 0x1E00);
 457                b43_phy_maskset(dev, B43_LPPHY_VERYLOWGAINDB, 0xFF00, 0xD);
 458        }
 459        b43_phy_maskset(dev, B43_PHY_OFDM(0xFE), 0xFFE0, 0x1F);
 460        b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0xFFE0, 0xC);
 461        b43_phy_maskset(dev, B43_PHY_OFDM(0x100), 0xFF00, 0x19);
 462        b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0x03FF, 0x3C00);
 463        b43_phy_maskset(dev, B43_PHY_OFDM(0xFE), 0xFC1F, 0x3E0);
 464        b43_phy_maskset(dev, B43_PHY_OFDM(0xFF), 0xFFE0, 0xC);
 465        b43_phy_maskset(dev, B43_PHY_OFDM(0x100), 0x00FF, 0x1900);
 466        b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0x83FF, 0x5800);
 467        b43_phy_maskset(dev, B43_LPPHY_CLIPCTRTHRESH, 0xFFE0, 0x12);
 468        b43_phy_maskset(dev, B43_LPPHY_GAINMISMATCH, 0x0FFF, 0x9000);
 469
 470        if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
 471                b43_lptab_write(dev, B43_LPTAB16(0x08, 0x14), 0);
 472                b43_lptab_write(dev, B43_LPTAB16(0x08, 0x12), 0x40);
 473        }
 474
 475        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
 476                b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x40);
 477                b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xF0FF, 0xB00);
 478                b43_phy_maskset(dev, B43_LPPHY_SYNCPEAKCNT, 0xFFF8, 0x6);
 479                b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0x00FF, 0x9D00);
 480                b43_phy_maskset(dev, B43_LPPHY_MINPWR_LEVEL, 0xFF00, 0xA1);
 481                b43_phy_mask(dev, B43_LPPHY_IDLEAFTERPKTRXTO, 0x00FF);
 482        } else /* 5GHz */
 483                b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, ~0x40);
 484
 485        b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0xFF00, 0xB3);
 486        b43_phy_maskset(dev, B43_LPPHY_CRS_ED_THRESH, 0x00FF, 0xAD00);
 487        b43_phy_maskset(dev, B43_LPPHY_INPUT_PWRDB, 0xFF00, lpphy->rx_pwr_offset);
 488        b43_phy_set(dev, B43_LPPHY_RESET_CTL, 0x44);
 489        b43_phy_write(dev, B43_LPPHY_RESET_CTL, 0x80);
 490        b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_0, 0xA954);
 491        b43_phy_write(dev, B43_LPPHY_AFE_RSSI_CTL_1,
 492                      0x2000 | ((u16)lpphy->rssi_gs << 10) |
 493                      ((u16)lpphy->rssi_vc << 4) | lpphy->rssi_vf);
 494
 495        if ((dev->dev->chip_id == 0x4325) && (dev->dev->chip_rev == 0)) {
 496                b43_phy_set(dev, B43_LPPHY_AFE_ADC_CTL_0, 0x1C);
 497                b43_phy_maskset(dev, B43_LPPHY_AFE_CTL, 0x00FF, 0x8800);
 498                b43_phy_maskset(dev, B43_LPPHY_AFE_ADC_CTL_1, 0xFC3C, 0x0400);
 499        }
 500
 501        lpphy_save_dig_flt_state(dev);
 502}
 503
 504static void lpphy_baseband_init(struct b43_wldev *dev)
 505{
 506        lpphy_table_init(dev);
 507        if (dev->phy.rev >= 2)
 508                lpphy_baseband_rev2plus_init(dev);
 509        else
 510                lpphy_baseband_rev0_1_init(dev);
 511}
 512
 513struct b2062_freqdata {
 514        u16 freq;
 515        u8 data[6];
 516};
 517
 518/* Initialize the 2062 radio. */
 519static void lpphy_2062_init(struct b43_wldev *dev)
 520{
 521        struct b43_phy_lp *lpphy = dev->phy.lp;
 522        struct ssb_bus *bus = dev->dev->sdev->bus;
 523        u32 crystalfreq, tmp, ref;
 524        unsigned int i;
 525        const struct b2062_freqdata *fd = NULL;
 526
 527        static const struct b2062_freqdata freqdata_tab[] = {
 528                { .freq = 12000, .data[0] =  6, .data[1] =  6, .data[2] =  6,
 529                                 .data[3] =  6, .data[4] = 10, .data[5] =  6, },
 530                { .freq = 13000, .data[0] =  4, .data[1] =  4, .data[2] =  4,
 531                                 .data[3] =  4, .data[4] = 11, .data[5] =  7, },
 532                { .freq = 14400, .data[0] =  3, .data[1] =  3, .data[2] =  3,
 533                                 .data[3] =  3, .data[4] = 12, .data[5] =  7, },
 534                { .freq = 16200, .data[0] =  3, .data[1] =  3, .data[2] =  3,
 535                                 .data[3] =  3, .data[4] = 13, .data[5] =  8, },
 536                { .freq = 18000, .data[0] =  2, .data[1] =  2, .data[2] =  2,
 537                                 .data[3] =  2, .data[4] = 14, .data[5] =  8, },
 538                { .freq = 19200, .data[0] =  1, .data[1] =  1, .data[2] =  1,
 539                                 .data[3] =  1, .data[4] = 14, .data[5] =  9, },
 540        };
 541
 542        b2062_upload_init_table(dev);
 543
 544        b43_radio_write(dev, B2062_N_TX_CTL3, 0);
 545        b43_radio_write(dev, B2062_N_TX_CTL4, 0);
 546        b43_radio_write(dev, B2062_N_TX_CTL5, 0);
 547        b43_radio_write(dev, B2062_N_TX_CTL6, 0);
 548        b43_radio_write(dev, B2062_N_PDN_CTL0, 0x40);
 549        b43_radio_write(dev, B2062_N_PDN_CTL0, 0);
 550        b43_radio_write(dev, B2062_N_CALIB_TS, 0x10);
 551        b43_radio_write(dev, B2062_N_CALIB_TS, 0);
 552        if (dev->phy.rev > 0) {
 553                b43_radio_write(dev, B2062_S_BG_CTL1,
 554                        (b43_radio_read(dev, B2062_N_COMM2) >> 1) | 0x80);
 555        }
 556        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
 557                b43_radio_set(dev, B2062_N_TSSI_CTL0, 0x1);
 558        else
 559                b43_radio_mask(dev, B2062_N_TSSI_CTL0, ~0x1);
 560
 561        /* Get the crystal freq, in Hz. */
 562        crystalfreq = bus->chipco.pmu.crystalfreq * 1000;
 563
 564        B43_WARN_ON(!(bus->chipco.capabilities & SSB_CHIPCO_CAP_PMU));
 565        B43_WARN_ON(crystalfreq == 0);
 566
 567        if (crystalfreq <= 30000000) {
 568                lpphy->pdiv = 1;
 569                b43_radio_mask(dev, B2062_S_RFPLL_CTL1, 0xFFFB);
 570        } else {
 571                lpphy->pdiv = 2;
 572                b43_radio_set(dev, B2062_S_RFPLL_CTL1, 0x4);
 573        }
 574
 575        tmp = (((800000000 * lpphy->pdiv + crystalfreq) /
 576              (2 * crystalfreq)) - 8) & 0xFF;
 577        b43_radio_write(dev, B2062_S_RFPLL_CTL7, tmp);
 578
 579        tmp = (((100 * crystalfreq + 16000000 * lpphy->pdiv) /
 580              (32000000 * lpphy->pdiv)) - 1) & 0xFF;
 581        b43_radio_write(dev, B2062_S_RFPLL_CTL18, tmp);
 582
 583        tmp = (((2 * crystalfreq + 1000000 * lpphy->pdiv) /
 584              (2000000 * lpphy->pdiv)) - 1) & 0xFF;
 585        b43_radio_write(dev, B2062_S_RFPLL_CTL19, tmp);
 586
 587        ref = (1000 * lpphy->pdiv + 2 * crystalfreq) / (2000 * lpphy->pdiv);
 588        ref &= 0xFFFF;
 589        for (i = 0; i < ARRAY_SIZE(freqdata_tab); i++) {
 590                if (ref < freqdata_tab[i].freq) {
 591                        fd = &freqdata_tab[i];
 592                        break;
 593                }
 594        }
 595        if (!fd)
 596                fd = &freqdata_tab[ARRAY_SIZE(freqdata_tab) - 1];
 597        b43dbg(dev->wl, "b2062: Using crystal tab entry %u kHz.\n",
 598               fd->freq); /* FIXME: Keep this printk until the code is fully debugged. */
 599
 600        b43_radio_write(dev, B2062_S_RFPLL_CTL8,
 601                        ((u16)(fd->data[1]) << 4) | fd->data[0]);
 602        b43_radio_write(dev, B2062_S_RFPLL_CTL9,
 603                        ((u16)(fd->data[3]) << 4) | fd->data[2]);
 604        b43_radio_write(dev, B2062_S_RFPLL_CTL10, fd->data[4]);
 605        b43_radio_write(dev, B2062_S_RFPLL_CTL11, fd->data[5]);
 606}
 607
 608/* Initialize the 2063 radio. */
 609static void lpphy_2063_init(struct b43_wldev *dev)
 610{
 611        b2063_upload_init_table(dev);
 612        b43_radio_write(dev, B2063_LOGEN_SP5, 0);
 613        b43_radio_set(dev, B2063_COMM8, 0x38);
 614        b43_radio_write(dev, B2063_REG_SP1, 0x56);
 615        b43_radio_mask(dev, B2063_RX_BB_CTL2, ~0x2);
 616        b43_radio_write(dev, B2063_PA_SP7, 0);
 617        b43_radio_write(dev, B2063_TX_RF_SP6, 0x20);
 618        b43_radio_write(dev, B2063_TX_RF_SP9, 0x40);
 619        if (dev->phy.rev == 2) {
 620                b43_radio_write(dev, B2063_PA_SP3, 0xa0);
 621                b43_radio_write(dev, B2063_PA_SP4, 0xa0);
 622                b43_radio_write(dev, B2063_PA_SP2, 0x18);
 623        } else {
 624                b43_radio_write(dev, B2063_PA_SP3, 0x20);
 625                b43_radio_write(dev, B2063_PA_SP2, 0x20);
 626        }
 627}
 628
 629struct lpphy_stx_table_entry {
 630        u16 phy_offset;
 631        u16 phy_shift;
 632        u16 rf_addr;
 633        u16 rf_shift;
 634        u16 mask;
 635};
 636
 637static const struct lpphy_stx_table_entry lpphy_stx_table[] = {
 638        { .phy_offset = 2, .phy_shift = 6, .rf_addr = 0x3d, .rf_shift = 3, .mask = 0x01, },
 639        { .phy_offset = 1, .phy_shift = 12, .rf_addr = 0x4c, .rf_shift = 1, .mask = 0x01, },
 640        { .phy_offset = 1, .phy_shift = 8, .rf_addr = 0x50, .rf_shift = 0, .mask = 0x7f, },
 641        { .phy_offset = 0, .phy_shift = 8, .rf_addr = 0x44, .rf_shift = 0, .mask = 0xff, },
 642        { .phy_offset = 1, .phy_shift = 0, .rf_addr = 0x4a, .rf_shift = 0, .mask = 0xff, },
 643        { .phy_offset = 0, .phy_shift = 4, .rf_addr = 0x4d, .rf_shift = 0, .mask = 0xff, },
 644        { .phy_offset = 1, .phy_shift = 4, .rf_addr = 0x4e, .rf_shift = 0, .mask = 0xff, },
 645        { .phy_offset = 0, .phy_shift = 12, .rf_addr = 0x4f, .rf_shift = 0, .mask = 0x0f, },
 646        { .phy_offset = 1, .phy_shift = 0, .rf_addr = 0x4f, .rf_shift = 4, .mask = 0x0f, },
 647        { .phy_offset = 3, .phy_shift = 0, .rf_addr = 0x49, .rf_shift = 0, .mask = 0x0f, },
 648        { .phy_offset = 4, .phy_shift = 3, .rf_addr = 0x46, .rf_shift = 4, .mask = 0x07, },
 649        { .phy_offset = 3, .phy_shift = 15, .rf_addr = 0x46, .rf_shift = 0, .mask = 0x01, },
 650        { .phy_offset = 4, .phy_shift = 0, .rf_addr = 0x46, .rf_shift = 1, .mask = 0x07, },
 651        { .phy_offset = 3, .phy_shift = 8, .rf_addr = 0x48, .rf_shift = 4, .mask = 0x07, },
 652        { .phy_offset = 3, .phy_shift = 11, .rf_addr = 0x48, .rf_shift = 0, .mask = 0x0f, },
 653        { .phy_offset = 3, .phy_shift = 4, .rf_addr = 0x49, .rf_shift = 4, .mask = 0x0f, },
 654        { .phy_offset = 2, .phy_shift = 15, .rf_addr = 0x45, .rf_shift = 0, .mask = 0x01, },
 655        { .phy_offset = 5, .phy_shift = 13, .rf_addr = 0x52, .rf_shift = 4, .mask = 0x07, },
 656        { .phy_offset = 6, .phy_shift = 0, .rf_addr = 0x52, .rf_shift = 7, .mask = 0x01, },
 657        { .phy_offset = 5, .phy_shift = 3, .rf_addr = 0x41, .rf_shift = 5, .mask = 0x07, },
 658        { .phy_offset = 5, .phy_shift = 6, .rf_addr = 0x41, .rf_shift = 0, .mask = 0x0f, },
 659        { .phy_offset = 5, .phy_shift = 10, .rf_addr = 0x42, .rf_shift = 5, .mask = 0x07, },
 660        { .phy_offset = 4, .phy_shift = 15, .rf_addr = 0x42, .rf_shift = 0, .mask = 0x01, },
 661        { .phy_offset = 5, .phy_shift = 0, .rf_addr = 0x42, .rf_shift = 1, .mask = 0x07, },
 662        { .phy_offset = 4, .phy_shift = 11, .rf_addr = 0x43, .rf_shift = 4, .mask = 0x0f, },
 663        { .phy_offset = 4, .phy_shift = 7, .rf_addr = 0x43, .rf_shift = 0, .mask = 0x0f, },
 664        { .phy_offset = 4, .phy_shift = 6, .rf_addr = 0x45, .rf_shift = 1, .mask = 0x01, },
 665        { .phy_offset = 2, .phy_shift = 7, .rf_addr = 0x40, .rf_shift = 4, .mask = 0x0f, },
 666        { .phy_offset = 2, .phy_shift = 11, .rf_addr = 0x40, .rf_shift = 0, .mask = 0x0f, },
 667};
 668
 669static void lpphy_sync_stx(struct b43_wldev *dev)
 670{
 671        const struct lpphy_stx_table_entry *e;
 672        unsigned int i;
 673        u16 tmp;
 674
 675        for (i = 0; i < ARRAY_SIZE(lpphy_stx_table); i++) {
 676                e = &lpphy_stx_table[i];
 677                tmp = b43_radio_read(dev, e->rf_addr);
 678                tmp >>= e->rf_shift;
 679                tmp <<= e->phy_shift;
 680                b43_phy_maskset(dev, B43_PHY_OFDM(0xF2 + e->phy_offset),
 681                                ~(e->mask << e->phy_shift), tmp);
 682        }
 683}
 684
 685static void lpphy_radio_init(struct b43_wldev *dev)
 686{
 687        /* The radio is attached through the 4wire bus. */
 688        b43_phy_set(dev, B43_LPPHY_FOURWIRE_CTL, 0x2);
 689        udelay(1);
 690        b43_phy_mask(dev, B43_LPPHY_FOURWIRE_CTL, 0xFFFD);
 691        udelay(1);
 692
 693        if (dev->phy.radio_ver == 0x2062) {
 694                lpphy_2062_init(dev);
 695        } else {
 696                lpphy_2063_init(dev);
 697                lpphy_sync_stx(dev);
 698                b43_phy_write(dev, B43_PHY_OFDM(0xF0), 0x5F80);
 699                b43_phy_write(dev, B43_PHY_OFDM(0xF1), 0);
 700                if (dev->dev->chip_id == 0x4325) {
 701                        // TODO SSB PMU recalibration
 702                }
 703        }
 704}
 705
 706struct lpphy_iq_est { u32 iq_prod, i_pwr, q_pwr; };
 707
 708static void lpphy_set_rc_cap(struct b43_wldev *dev)
 709{
 710        struct b43_phy_lp *lpphy = dev->phy.lp;
 711
 712        u8 rc_cap = (lpphy->rc_cap & 0x1F) >> 1;
 713
 714        if (dev->phy.rev == 1) //FIXME check channel 14!
 715                rc_cap = min_t(u8, rc_cap + 5, 15);
 716
 717        b43_radio_write(dev, B2062_N_RXBB_CALIB2,
 718                        max_t(u8, lpphy->rc_cap - 4, 0x80));
 719        b43_radio_write(dev, B2062_N_TX_CTL_A, rc_cap | 0x80);
 720        b43_radio_write(dev, B2062_S_RXG_CNT16,
 721                        ((lpphy->rc_cap & 0x1F) >> 2) | 0x80);
 722}
 723
 724static u8 lpphy_get_bb_mult(struct b43_wldev *dev)
 725{
 726        return (b43_lptab_read(dev, B43_LPTAB16(0, 87)) & 0xFF00) >> 8;
 727}
 728
 729static void lpphy_set_bb_mult(struct b43_wldev *dev, u8 bb_mult)
 730{
 731        b43_lptab_write(dev, B43_LPTAB16(0, 87), (u16)bb_mult << 8);
 732}
 733
 734static void lpphy_set_deaf(struct b43_wldev *dev, bool user)
 735{
 736        struct b43_phy_lp *lpphy = dev->phy.lp;
 737
 738        if (user)
 739                lpphy->crs_usr_disable = true;
 740        else
 741                lpphy->crs_sys_disable = true;
 742        b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFF1F, 0x80);
 743}
 744
 745static void lpphy_clear_deaf(struct b43_wldev *dev, bool user)
 746{
 747        struct b43_phy_lp *lpphy = dev->phy.lp;
 748
 749        if (user)
 750                lpphy->crs_usr_disable = false;
 751        else
 752                lpphy->crs_sys_disable = false;
 753
 754        if (!lpphy->crs_usr_disable && !lpphy->crs_sys_disable) {
 755                if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
 756                        b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL,
 757                                        0xFF1F, 0x60);
 758                else
 759                        b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL,
 760                                        0xFF1F, 0x20);
 761        }
 762}
 763
 764static void lpphy_set_trsw_over(struct b43_wldev *dev, bool tx, bool rx)
 765{
 766        u16 trsw = (tx << 1) | rx;
 767        b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFC, trsw);
 768        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x3);
 769}
 770
 771static void lpphy_disable_crs(struct b43_wldev *dev, bool user)
 772{
 773        lpphy_set_deaf(dev, user);
 774        lpphy_set_trsw_over(dev, false, true);
 775        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFB);
 776        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x4);
 777        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFF7);
 778        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
 779        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x10);
 780        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
 781        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFDF);
 782        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
 783        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFBF);
 784        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
 785        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x7);
 786        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x38);
 787        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F);
 788        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0x100);
 789        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFDFF);
 790        b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL0, 0);
 791        b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL1, 1);
 792        b43_phy_write(dev, B43_LPPHY_PS_CTL_OVERRIDE_VAL2, 0x20);
 793        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFBFF);
 794        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xF7FF);
 795        b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL, 0);
 796        b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, 0x45AF);
 797        b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, 0x3FF);
 798}
 799
 800static void lpphy_restore_crs(struct b43_wldev *dev, bool user)
 801{
 802        lpphy_clear_deaf(dev, user);
 803        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFF80);
 804        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFC00);
 805}
 806
 807struct lpphy_tx_gains { u16 gm, pga, pad, dac; };
 808
 809static void lpphy_disable_rx_gain_override(struct b43_wldev *dev)
 810{
 811        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFE);
 812        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFEF);
 813        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFBF);
 814        if (dev->phy.rev >= 2) {
 815                b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
 816                if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
 817                        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFBFF);
 818                        b43_phy_mask(dev, B43_PHY_OFDM(0xE5), 0xFFF7);
 819                }
 820        } else {
 821                b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFDFF);
 822        }
 823}
 824
 825static void lpphy_enable_rx_gain_override(struct b43_wldev *dev)
 826{
 827        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1);
 828        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x10);
 829        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x40);
 830        if (dev->phy.rev >= 2) {
 831                b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
 832                if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
 833                        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x400);
 834                        b43_phy_set(dev, B43_PHY_OFDM(0xE5), 0x8);
 835                }
 836        } else {
 837                b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x200);
 838        }
 839}
 840
 841static void lpphy_disable_tx_gain_override(struct b43_wldev *dev)
 842{
 843        if (dev->phy.rev < 2)
 844                b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFEFF);
 845        else {
 846                b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFF7F);
 847                b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xBFFF);
 848        }
 849        b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFBF);
 850}
 851
 852static void lpphy_enable_tx_gain_override(struct b43_wldev *dev)
 853{
 854        if (dev->phy.rev < 2)
 855                b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x100);
 856        else {
 857                b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x80);
 858                b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x4000);
 859        }
 860        b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x40);
 861}
 862
 863static struct lpphy_tx_gains lpphy_get_tx_gains(struct b43_wldev *dev)
 864{
 865        struct lpphy_tx_gains gains;
 866        u16 tmp;
 867
 868        gains.dac = (b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0x380) >> 7;
 869        if (dev->phy.rev < 2) {
 870                tmp = b43_phy_read(dev,
 871                                   B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL) & 0x7FF;
 872                gains.gm = tmp & 0x0007;
 873                gains.pga = (tmp & 0x0078) >> 3;
 874                gains.pad = (tmp & 0x780) >> 7;
 875        } else {
 876                tmp = b43_phy_read(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL);
 877                gains.pad = b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0xFF;
 878                gains.gm = tmp & 0xFF;
 879                gains.pga = (tmp >> 8) & 0xFF;
 880        }
 881
 882        return gains;
 883}
 884
 885static void lpphy_set_dac_gain(struct b43_wldev *dev, u16 dac)
 886{
 887        u16 ctl = b43_phy_read(dev, B43_LPPHY_AFE_DAC_CTL) & 0xC7F;
 888        ctl |= dac << 7;
 889        b43_phy_maskset(dev, B43_LPPHY_AFE_DAC_CTL, 0xF000, ctl);
 890}
 891
 892static u16 lpphy_get_pa_gain(struct b43_wldev *dev)
 893{
 894        return b43_phy_read(dev, B43_PHY_OFDM(0xFB)) & 0x7F;
 895}
 896
 897static void lpphy_set_pa_gain(struct b43_wldev *dev, u16 gain)
 898{
 899        b43_phy_maskset(dev, B43_PHY_OFDM(0xFB), 0xE03F, gain << 6);
 900        b43_phy_maskset(dev, B43_PHY_OFDM(0xFD), 0x80FF, gain << 8);
 901}
 902
 903static void lpphy_set_tx_gains(struct b43_wldev *dev,
 904                               struct lpphy_tx_gains gains)
 905{
 906        u16 rf_gain, pa_gain;
 907
 908        if (dev->phy.rev < 2) {
 909                rf_gain = (gains.pad << 7) | (gains.pga << 3) | gains.gm;
 910                b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
 911                                0xF800, rf_gain);
 912        } else {
 913                pa_gain = lpphy_get_pa_gain(dev);
 914                b43_phy_write(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
 915                              (gains.pga << 8) | gains.gm);
 916                /*
 917                 * SPEC FIXME The spec calls for (pa_gain << 8) here, but that
 918                 * conflicts with the spec for set_pa_gain! Vendor driver bug?
 919                 */
 920                b43_phy_maskset(dev, B43_PHY_OFDM(0xFB),
 921                                0x8000, gains.pad | (pa_gain << 6));
 922                b43_phy_write(dev, B43_PHY_OFDM(0xFC),
 923                              (gains.pga << 8) | gains.gm);
 924                b43_phy_maskset(dev, B43_PHY_OFDM(0xFD),
 925                                0x8000, gains.pad | (pa_gain << 8));
 926        }
 927        lpphy_set_dac_gain(dev, gains.dac);
 928        lpphy_enable_tx_gain_override(dev);
 929}
 930
 931static void lpphy_rev0_1_set_rx_gain(struct b43_wldev *dev, u32 gain)
 932{
 933        u16 trsw = gain & 0x1;
 934        u16 lna = (gain & 0xFFFC) | ((gain & 0xC) >> 2);
 935        u16 ext_lna = (gain & 2) >> 1;
 936
 937        b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
 938        b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
 939                        0xFBFF, ext_lna << 10);
 940        b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
 941                        0xF7FF, ext_lna << 11);
 942        b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, lna);
 943}
 944
 945static void lpphy_rev2plus_set_rx_gain(struct b43_wldev *dev, u32 gain)
 946{
 947        u16 low_gain = gain & 0xFFFF;
 948        u16 high_gain = (gain >> 16) & 0xF;
 949        u16 ext_lna = (gain >> 21) & 0x1;
 950        u16 trsw = ~(gain >> 20) & 0x1;
 951        u16 tmp;
 952
 953        b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xFFFE, trsw);
 954        b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
 955                        0xFDFF, ext_lna << 9);
 956        b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
 957                        0xFBFF, ext_lna << 10);
 958        b43_phy_write(dev, B43_LPPHY_RX_GAIN_CTL_OVERRIDE_VAL, low_gain);
 959        b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF0, high_gain);
 960        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
 961                tmp = (gain >> 2) & 0x3;
 962                b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL,
 963                                0xE7FF, tmp<<11);
 964                b43_phy_maskset(dev, B43_PHY_OFDM(0xE6), 0xFFE7, tmp << 3);
 965        }
 966}
 967
 968static void lpphy_set_rx_gain(struct b43_wldev *dev, u32 gain)
 969{
 970        if (dev->phy.rev < 2)
 971                lpphy_rev0_1_set_rx_gain(dev, gain);
 972        else
 973                lpphy_rev2plus_set_rx_gain(dev, gain);
 974        lpphy_enable_rx_gain_override(dev);
 975}
 976
 977static void lpphy_set_rx_gain_by_index(struct b43_wldev *dev, u16 idx)
 978{
 979        u32 gain = b43_lptab_read(dev, B43_LPTAB16(12, idx));
 980        lpphy_set_rx_gain(dev, gain);
 981}
 982
 983static void lpphy_stop_ddfs(struct b43_wldev *dev)
 984{
 985        b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFD);
 986        b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xFFDF);
 987}
 988
 989static void lpphy_run_ddfs(struct b43_wldev *dev, int i_on, int q_on,
 990                           int incr1, int incr2, int scale_idx)
 991{
 992        lpphy_stop_ddfs(dev);
 993        b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0xFF80);
 994        b43_phy_mask(dev, B43_LPPHY_AFE_DDFS_POINTER_INIT, 0x80FF);
 995        b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0xFF80, incr1);
 996        b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS_INCR_INIT, 0x80FF, incr2 << 8);
 997        b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFF7, i_on << 3);
 998        b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFFEF, q_on << 4);
 999        b43_phy_maskset(dev, B43_LPPHY_AFE_DDFS, 0xFF9F, scale_idx << 5);
1000        b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0xFFFB);
1001        b43_phy_set(dev, B43_LPPHY_AFE_DDFS, 0x2);
1002        b43_phy_set(dev, B43_LPPHY_LP_PHY_CTL, 0x20);
1003}
1004
1005static bool lpphy_rx_iq_est(struct b43_wldev *dev, u16 samples, u8 time,
1006                           struct lpphy_iq_est *iq_est)
1007{
1008        int i;
1009
1010        b43_phy_mask(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFF7);
1011        b43_phy_write(dev, B43_LPPHY_IQ_NUM_SMPLS_ADDR, samples);
1012        b43_phy_maskset(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFF00, time);
1013        b43_phy_mask(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0xFEFF);
1014        b43_phy_set(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR, 0x200);
1015
1016        for (i = 0; i < 500; i++) {
1017                if (!(b43_phy_read(dev,
1018                                B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200))
1019                        break;
1020                msleep(1);
1021        }
1022
1023        if ((b43_phy_read(dev, B43_LPPHY_IQ_ENABLE_WAIT_TIME_ADDR) & 0x200)) {
1024                b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8);
1025                return false;
1026        }
1027
1028        iq_est->iq_prod = b43_phy_read(dev, B43_LPPHY_IQ_ACC_HI_ADDR);
1029        iq_est->iq_prod <<= 16;
1030        iq_est->iq_prod |= b43_phy_read(dev, B43_LPPHY_IQ_ACC_LO_ADDR);
1031
1032        iq_est->i_pwr = b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_HI_ADDR);
1033        iq_est->i_pwr <<= 16;
1034        iq_est->i_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_I_PWR_ACC_LO_ADDR);
1035
1036        iq_est->q_pwr = b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_HI_ADDR);
1037        iq_est->q_pwr <<= 16;
1038        iq_est->q_pwr |= b43_phy_read(dev, B43_LPPHY_IQ_Q_PWR_ACC_LO_ADDR);
1039
1040        b43_phy_set(dev, B43_LPPHY_CRSGAIN_CTL, 0x8);
1041        return true;
1042}
1043
1044static int lpphy_loopback(struct b43_wldev *dev)
1045{
1046        struct lpphy_iq_est iq_est;
1047        int i, index = -1;
1048        u32 tmp;
1049
1050        memset(&iq_est, 0, sizeof(iq_est));
1051
1052        lpphy_set_trsw_over(dev, true, true);
1053        b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 1);
1054        b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
1055        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
1056        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800);
1057        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
1058        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x8);
1059        b43_radio_write(dev, B2062_N_TX_CTL_A, 0x80);
1060        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x80);
1061        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x80);
1062        for (i = 0; i < 32; i++) {
1063                lpphy_set_rx_gain_by_index(dev, i);
1064                lpphy_run_ddfs(dev, 1, 1, 5, 5, 0);
1065                if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
1066                        continue;
1067                tmp = (iq_est.i_pwr + iq_est.q_pwr) / 1000;
1068                if ((tmp > 4000) && (tmp < 10000)) {
1069                        index = i;
1070                        break;
1071                }
1072        }
1073        lpphy_stop_ddfs(dev);
1074        return index;
1075}
1076
1077/* Fixed-point division algorithm using only integer math. */
1078static u32 lpphy_qdiv_roundup(u32 dividend, u32 divisor, u8 precision)
1079{
1080        u32 quotient, remainder;
1081
1082        if (divisor == 0)
1083                return 0;
1084
1085        quotient = dividend / divisor;
1086        remainder = dividend % divisor;
1087
1088        while (precision > 0) {
1089                quotient <<= 1;
1090                if (remainder << 1 >= divisor) {
1091                        quotient++;
1092                        remainder = (remainder << 1) - divisor;
1093                }
1094                precision--;
1095        }
1096
1097        if (remainder << 1 >= divisor)
1098                quotient++;
1099
1100        return quotient;
1101}
1102
1103/* Read the TX power control mode from hardware. */
1104static void lpphy_read_tx_pctl_mode_from_hardware(struct b43_wldev *dev)
1105{
1106        struct b43_phy_lp *lpphy = dev->phy.lp;
1107        u16 ctl;
1108
1109        ctl = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_CMD);
1110        switch (ctl & B43_LPPHY_TX_PWR_CTL_CMD_MODE) {
1111        case B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF:
1112                lpphy->txpctl_mode = B43_LPPHY_TXPCTL_OFF;
1113                break;
1114        case B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW:
1115                lpphy->txpctl_mode = B43_LPPHY_TXPCTL_SW;
1116                break;
1117        case B43_LPPHY_TX_PWR_CTL_CMD_MODE_HW:
1118                lpphy->txpctl_mode = B43_LPPHY_TXPCTL_HW;
1119                break;
1120        default:
1121                lpphy->txpctl_mode = B43_LPPHY_TXPCTL_UNKNOWN;
1122                B43_WARN_ON(1);
1123                break;
1124        }
1125}
1126
1127/* Set the TX power control mode in hardware. */
1128static void lpphy_write_tx_pctl_mode_to_hardware(struct b43_wldev *dev)
1129{
1130        struct b43_phy_lp *lpphy = dev->phy.lp;
1131        u16 ctl;
1132
1133        switch (lpphy->txpctl_mode) {
1134        case B43_LPPHY_TXPCTL_OFF:
1135                ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF;
1136                break;
1137        case B43_LPPHY_TXPCTL_HW:
1138                ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_HW;
1139                break;
1140        case B43_LPPHY_TXPCTL_SW:
1141                ctl = B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW;
1142                break;
1143        default:
1144                ctl = 0;
1145                B43_WARN_ON(1);
1146        }
1147        b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
1148                        ~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF, ctl);
1149}
1150
1151static void lpphy_set_tx_power_control(struct b43_wldev *dev,
1152                                       enum b43_lpphy_txpctl_mode mode)
1153{
1154        struct b43_phy_lp *lpphy = dev->phy.lp;
1155        enum b43_lpphy_txpctl_mode oldmode;
1156
1157        lpphy_read_tx_pctl_mode_from_hardware(dev);
1158        oldmode = lpphy->txpctl_mode;
1159        if (oldmode == mode)
1160                return;
1161        lpphy->txpctl_mode = mode;
1162
1163        if (oldmode == B43_LPPHY_TXPCTL_HW) {
1164                //TODO Update TX Power NPT
1165                //TODO Clear all TX Power offsets
1166        } else {
1167                if (mode == B43_LPPHY_TXPCTL_HW) {
1168                        //TODO Recalculate target TX power
1169                        b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
1170                                        0xFF80, lpphy->tssi_idx);
1171                        b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM,
1172                                        0x8FFF, ((u16)lpphy->tssi_npt << 16));
1173                        //TODO Set "TSSI Transmit Count" variable to total transmitted frame count
1174                        lpphy_disable_tx_gain_override(dev);
1175                        lpphy->tx_pwr_idx_over = -1;
1176                }
1177        }
1178        if (dev->phy.rev >= 2) {
1179                if (mode == B43_LPPHY_TXPCTL_HW)
1180                        b43_phy_set(dev, B43_PHY_OFDM(0xD0), 0x2);
1181                else
1182                        b43_phy_mask(dev, B43_PHY_OFDM(0xD0), 0xFFFD);
1183        }
1184        lpphy_write_tx_pctl_mode_to_hardware(dev);
1185}
1186
1187static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
1188                                       unsigned int new_channel);
1189
1190static void lpphy_rev0_1_rc_calib(struct b43_wldev *dev)
1191{
1192        struct b43_phy_lp *lpphy = dev->phy.lp;
1193        struct lpphy_iq_est iq_est;
1194        struct lpphy_tx_gains tx_gains;
1195        static const u32 ideal_pwr_table[21] = {
1196                0x10000, 0x10557, 0x10e2d, 0x113e0, 0x10f22, 0x0ff64,
1197                0x0eda2, 0x0e5d4, 0x0efd1, 0x0fbe8, 0x0b7b8, 0x04b35,
1198                0x01a5e, 0x00a0b, 0x00444, 0x001fd, 0x000ff, 0x00088,
1199                0x0004c, 0x0002c, 0x0001a,
1200        };
1201        bool old_txg_ovr;
1202        u8 old_bbmult;
1203        u16 old_rf_ovr, old_rf_ovrval, old_afe_ovr, old_afe_ovrval,
1204            old_rf2_ovr, old_rf2_ovrval, old_phy_ctl;
1205        enum b43_lpphy_txpctl_mode old_txpctl;
1206        u32 normal_pwr, ideal_pwr, mean_sq_pwr, tmp = 0, mean_sq_pwr_min = 0;
1207        int loopback, i, j, inner_sum, err;
1208
1209        memset(&iq_est, 0, sizeof(iq_est));
1210
1211        err = b43_lpphy_op_switch_channel(dev, 7);
1212        if (err) {
1213                b43dbg(dev->wl,
1214                       "RC calib: Failed to switch to channel 7, error = %d\n",
1215                       err);
1216        }
1217        old_txg_ovr = !!(b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40);
1218        old_bbmult = lpphy_get_bb_mult(dev);
1219        if (old_txg_ovr)
1220                tx_gains = lpphy_get_tx_gains(dev);
1221        old_rf_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_0);
1222        old_rf_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_VAL_0);
1223        old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR);
1224        old_afe_ovrval = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVRVAL);
1225        old_rf2_ovr = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2);
1226        old_rf2_ovrval = b43_phy_read(dev, B43_LPPHY_RF_OVERRIDE_2_VAL);
1227        old_phy_ctl = b43_phy_read(dev, B43_LPPHY_LP_PHY_CTL);
1228        lpphy_read_tx_pctl_mode_from_hardware(dev);
1229        old_txpctl = lpphy->txpctl_mode;
1230
1231        lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
1232        lpphy_disable_crs(dev, true);
1233        loopback = lpphy_loopback(dev);
1234        if (loopback == -1)
1235                goto finish;
1236        lpphy_set_rx_gain_by_index(dev, loopback);
1237        b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFFBF, 0x40);
1238        b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFF8, 0x1);
1239        b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFFC7, 0x8);
1240        b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFF3F, 0xC0);
1241        for (i = 128; i <= 159; i++) {
1242                b43_radio_write(dev, B2062_N_RXBB_CALIB2, i);
1243                inner_sum = 0;
1244                for (j = 5; j <= 25; j++) {
1245                        lpphy_run_ddfs(dev, 1, 1, j, j, 0);
1246                        if (!(lpphy_rx_iq_est(dev, 1000, 32, &iq_est)))
1247                                goto finish;
1248                        mean_sq_pwr = iq_est.i_pwr + iq_est.q_pwr;
1249                        if (j == 5)
1250                                tmp = mean_sq_pwr;
1251                        ideal_pwr = ((ideal_pwr_table[j-5] >> 3) + 1) >> 1;
1252                        normal_pwr = lpphy_qdiv_roundup(mean_sq_pwr, tmp, 12);
1253                        mean_sq_pwr = ideal_pwr - normal_pwr;
1254                        mean_sq_pwr *= mean_sq_pwr;
1255                        inner_sum += mean_sq_pwr;
1256                        if ((i == 128) || (inner_sum < mean_sq_pwr_min)) {
1257                                lpphy->rc_cap = i;
1258                                mean_sq_pwr_min = inner_sum;
1259                        }
1260                }
1261        }
1262        lpphy_stop_ddfs(dev);
1263
1264finish:
1265        lpphy_restore_crs(dev, true);
1266        b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, old_rf_ovrval);
1267        b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_0, old_rf_ovr);
1268        b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVRVAL, old_afe_ovrval);
1269        b43_phy_write(dev, B43_LPPHY_AFE_CTL_OVR, old_afe_ovr);
1270        b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, old_rf2_ovrval);
1271        b43_phy_write(dev, B43_LPPHY_RF_OVERRIDE_2, old_rf2_ovr);
1272        b43_phy_write(dev, B43_LPPHY_LP_PHY_CTL, old_phy_ctl);
1273
1274        lpphy_set_bb_mult(dev, old_bbmult);
1275        if (old_txg_ovr) {
1276                /*
1277                 * SPEC FIXME: The specs say "get_tx_gains" here, which is
1278                 * illogical. According to lwfinger, vendor driver v4.150.10.5
1279                 * has a Set here, while v4.174.64.19 has a Get - regression in
1280                 * the vendor driver? This should be tested this once the code
1281                 * is testable.
1282                 */
1283                lpphy_set_tx_gains(dev, tx_gains);
1284        }
1285        lpphy_set_tx_power_control(dev, old_txpctl);
1286        if (lpphy->rc_cap)
1287                lpphy_set_rc_cap(dev);
1288}
1289
1290static void lpphy_rev2plus_rc_calib(struct b43_wldev *dev)
1291{
1292        struct ssb_bus *bus = dev->dev->sdev->bus;
1293        u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
1294        u8 tmp = b43_radio_read(dev, B2063_RX_BB_SP8) & 0xFF;
1295        int i;
1296
1297        b43_radio_write(dev, B2063_RX_BB_SP8, 0x0);
1298        b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
1299        b43_radio_mask(dev, B2063_PLL_SP1, 0xF7);
1300        b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
1301        b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x15);
1302        b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x70);
1303        b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x52);
1304        b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
1305        b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7D);
1306
1307        for (i = 0; i < 10000; i++) {
1308                if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
1309                        break;
1310                msleep(1);
1311        }
1312
1313        if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
1314                b43_radio_write(dev, B2063_RX_BB_SP8, tmp);
1315
1316        tmp = b43_radio_read(dev, B2063_TX_BB_SP3) & 0xFF;
1317
1318        b43_radio_write(dev, B2063_TX_BB_SP3, 0x0);
1319        b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
1320        b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7C);
1321        b43_radio_write(dev, B2063_RC_CALIB_CTL2, 0x55);
1322        b43_radio_write(dev, B2063_RC_CALIB_CTL3, 0x76);
1323
1324        if (crystal_freq == 24000000) {
1325                b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0xFC);
1326                b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x0);
1327        } else {
1328                b43_radio_write(dev, B2063_RC_CALIB_CTL4, 0x13);
1329                b43_radio_write(dev, B2063_RC_CALIB_CTL5, 0x1);
1330        }
1331
1332        b43_radio_write(dev, B2063_PA_SP7, 0x7D);
1333
1334        for (i = 0; i < 10000; i++) {
1335                if (b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2)
1336                        break;
1337                msleep(1);
1338        }
1339
1340        if (!(b43_radio_read(dev, B2063_RC_CALIB_CTL6) & 0x2))
1341                b43_radio_write(dev, B2063_TX_BB_SP3, tmp);
1342
1343        b43_radio_write(dev, B2063_RC_CALIB_CTL1, 0x7E);
1344}
1345
1346static void lpphy_calibrate_rc(struct b43_wldev *dev)
1347{
1348        struct b43_phy_lp *lpphy = dev->phy.lp;
1349
1350        if (dev->phy.rev >= 2) {
1351                lpphy_rev2plus_rc_calib(dev);
1352        } else if (!lpphy->rc_cap) {
1353                if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ)
1354                        lpphy_rev0_1_rc_calib(dev);
1355        } else {
1356                lpphy_set_rc_cap(dev);
1357        }
1358}
1359
1360static void b43_lpphy_op_set_rx_antenna(struct b43_wldev *dev, int antenna)
1361{
1362        if (dev->phy.rev >= 2)
1363                return; // rev2+ doesn't support antenna diversity
1364
1365        if (B43_WARN_ON(antenna > B43_ANTENNA_AUTO1))
1366                return;
1367
1368        b43_hf_write(dev, b43_hf_read(dev) & ~B43_HF_ANTDIVHELP);
1369
1370        b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFD, antenna & 0x2);
1371        b43_phy_maskset(dev, B43_LPPHY_CRSGAIN_CTL, 0xFFFE, antenna & 0x1);
1372
1373        b43_hf_write(dev, b43_hf_read(dev) | B43_HF_ANTDIVHELP);
1374
1375        dev->phy.lp->antenna = antenna;
1376}
1377
1378static void lpphy_set_tx_iqcc(struct b43_wldev *dev, u16 a, u16 b)
1379{
1380        u16 tmp[2];
1381
1382        tmp[0] = a;
1383        tmp[1] = b;
1384        b43_lptab_write_bulk(dev, B43_LPTAB16(0, 80), 2, tmp);
1385}
1386
1387static void lpphy_set_tx_power_by_index(struct b43_wldev *dev, u8 index)
1388{
1389        struct b43_phy_lp *lpphy = dev->phy.lp;
1390        struct lpphy_tx_gains gains;
1391        u32 iq_comp, tx_gain, coeff, rf_power;
1392
1393        lpphy->tx_pwr_idx_over = index;
1394        lpphy_read_tx_pctl_mode_from_hardware(dev);
1395        if (lpphy->txpctl_mode != B43_LPPHY_TXPCTL_OFF)
1396                lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_SW);
1397        if (dev->phy.rev >= 2) {
1398                iq_comp = b43_lptab_read(dev, B43_LPTAB32(7, index + 320));
1399                tx_gain = b43_lptab_read(dev, B43_LPTAB32(7, index + 192));
1400                gains.pad = (tx_gain >> 16) & 0xFF;
1401                gains.gm = tx_gain & 0xFF;
1402                gains.pga = (tx_gain >> 8) & 0xFF;
1403                gains.dac = (iq_comp >> 28) & 0xFF;
1404                lpphy_set_tx_gains(dev, gains);
1405        } else {
1406                iq_comp = b43_lptab_read(dev, B43_LPTAB32(10, index + 320));
1407                tx_gain = b43_lptab_read(dev, B43_LPTAB32(10, index + 192));
1408                b43_phy_maskset(dev, B43_LPPHY_TX_GAIN_CTL_OVERRIDE_VAL,
1409                                0xF800, (tx_gain >> 4) & 0x7FFF);
1410                lpphy_set_dac_gain(dev, tx_gain & 0x7);
1411                lpphy_set_pa_gain(dev, (tx_gain >> 24) & 0x7F);
1412        }
1413        lpphy_set_bb_mult(dev, (iq_comp >> 20) & 0xFF);
1414        lpphy_set_tx_iqcc(dev, (iq_comp >> 10) & 0x3FF, iq_comp & 0x3FF);
1415        if (dev->phy.rev >= 2) {
1416                coeff = b43_lptab_read(dev, B43_LPTAB32(7, index + 448));
1417        } else {
1418                coeff = b43_lptab_read(dev, B43_LPTAB32(10, index + 448));
1419        }
1420        b43_lptab_write(dev, B43_LPTAB16(0, 85), coeff & 0xFFFF);
1421        if (dev->phy.rev >= 2) {
1422                rf_power = b43_lptab_read(dev, B43_LPTAB32(7, index + 576));
1423                b43_phy_maskset(dev, B43_LPPHY_RF_PWR_OVERRIDE, 0xFF00,
1424                                rf_power & 0xFFFF);//SPEC FIXME mask & set != 0
1425        }
1426        lpphy_enable_tx_gain_override(dev);
1427}
1428
1429static void lpphy_btcoex_override(struct b43_wldev *dev)
1430{
1431        b43_write16(dev, B43_MMIO_BTCOEX_CTL, 0x3);
1432        b43_write16(dev, B43_MMIO_BTCOEX_TXCTL, 0xFF);
1433}
1434
1435static void b43_lpphy_op_software_rfkill(struct b43_wldev *dev,
1436                                         bool blocked)
1437{
1438        //TODO check MAC control register
1439        if (blocked) {
1440                if (dev->phy.rev >= 2) {
1441                        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x83FF);
1442                        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1F00);
1443                        b43_phy_mask(dev, B43_LPPHY_AFE_DDFS, 0x80FF);
1444                        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xDFFF);
1445                        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x0808);
1446                } else {
1447                        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xE0FF);
1448                        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x1F00);
1449                        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2_VAL, 0xFCFF);
1450                        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_2, 0x0018);
1451                }
1452        } else {
1453                b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xE0FF);
1454                if (dev->phy.rev >= 2)
1455                        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xF7F7);
1456                else
1457                        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_2, 0xFFE7);
1458        }
1459}
1460
1461/* This was previously called lpphy_japan_filter */
1462static void lpphy_set_analog_filter(struct b43_wldev *dev, int channel)
1463{
1464        struct b43_phy_lp *lpphy = dev->phy.lp;
1465        u16 tmp = (channel == 14); //SPEC FIXME check japanwidefilter!
1466
1467        if (dev->phy.rev < 2) { //SPEC FIXME Isn't this rev0/1-specific?
1468                b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xFCFF, tmp << 9);
1469                if ((dev->phy.rev == 1) && (lpphy->rc_cap))
1470                        lpphy_set_rc_cap(dev);
1471        } else {
1472                b43_radio_write(dev, B2063_TX_BB_SP3, 0x3F);
1473        }
1474}
1475
1476static void lpphy_set_tssi_mux(struct b43_wldev *dev, enum tssi_mux_mode mode)
1477{
1478        if (mode != TSSI_MUX_EXT) {
1479                b43_radio_set(dev, B2063_PA_SP1, 0x2);
1480                b43_phy_set(dev, B43_PHY_OFDM(0xF3), 0x1000);
1481                b43_radio_write(dev, B2063_PA_CTL10, 0x51);
1482                if (mode == TSSI_MUX_POSTPA) {
1483                        b43_radio_mask(dev, B2063_PA_SP1, 0xFFFE);
1484                        b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFC7);
1485                } else {
1486                        b43_radio_maskset(dev, B2063_PA_SP1, 0xFFFE, 0x1);
1487                        b43_phy_maskset(dev, B43_LPPHY_AFE_CTL_OVRVAL,
1488                                        0xFFC7, 0x20);
1489                }
1490        } else {
1491                B43_WARN_ON(1);
1492        }
1493}
1494
1495static void lpphy_tx_pctl_init_hw(struct b43_wldev *dev)
1496{
1497        u16 tmp;
1498        int i;
1499
1500        //SPEC TODO Call LP PHY Clear TX Power offsets
1501        for (i = 0; i < 64; i++) {
1502                if (dev->phy.rev >= 2)
1503                        b43_lptab_write(dev, B43_LPTAB32(7, i + 1), i);
1504                else
1505                        b43_lptab_write(dev, B43_LPTAB32(10, i + 1), i);
1506        }
1507
1508        b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xFF00, 0xFF);
1509        b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0x8FFF, 0x5000);
1510        b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, 0xFFC0, 0x1F);
1511        if (dev->phy.rev < 2) {
1512                b43_phy_mask(dev, B43_LPPHY_LP_PHY_CTL, 0xEFFF);
1513                b43_phy_maskset(dev, B43_LPPHY_LP_PHY_CTL, 0xDFFF, 0x2000);
1514        } else {
1515                b43_phy_mask(dev, B43_PHY_OFDM(0x103), 0xFFFE);
1516                b43_phy_maskset(dev, B43_PHY_OFDM(0x103), 0xFFFB, 0x4);
1517                b43_phy_maskset(dev, B43_PHY_OFDM(0x103), 0xFFEF, 0x10);
1518                b43_radio_maskset(dev, B2063_IQ_CALIB_CTL2, 0xF3, 0x1);
1519                lpphy_set_tssi_mux(dev, TSSI_MUX_POSTPA);
1520        }
1521        b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI, 0x7FFF, 0x8000);
1522        b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xFF);
1523        b43_phy_write(dev, B43_LPPHY_TX_PWR_CTL_DELTAPWR_LIMIT, 0xA);
1524        b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
1525                        ~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF,
1526                        B43_LPPHY_TX_PWR_CTL_CMD_MODE_OFF);
1527        b43_phy_mask(dev, B43_LPPHY_TX_PWR_CTL_NNUM, 0xF8FF);
1528        b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_CMD,
1529                        ~B43_LPPHY_TX_PWR_CTL_CMD_MODE & 0xFFFF,
1530                        B43_LPPHY_TX_PWR_CTL_CMD_MODE_SW);
1531
1532        if (dev->phy.rev < 2) {
1533                b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_0, 0xEFFF, 0x1000);
1534                b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0xEFFF);
1535        } else {
1536                lpphy_set_tx_power_by_index(dev, 0x7F);
1537        }
1538
1539        b43_dummy_transmission(dev, true, true);
1540
1541        tmp = b43_phy_read(dev, B43_LPPHY_TX_PWR_CTL_STAT);
1542        if (tmp & 0x8000) {
1543                b43_phy_maskset(dev, B43_LPPHY_TX_PWR_CTL_IDLETSSI,
1544                                0xFFC0, (tmp & 0xFF) - 32);
1545        }
1546
1547        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xEFFF);
1548
1549        // (SPEC?) TODO Set "Target TX frequency" variable to 0
1550        // SPEC FIXME "Set BB Multiplier to 0xE000" impossible - bb_mult is u8!
1551}
1552
1553static void lpphy_tx_pctl_init_sw(struct b43_wldev *dev)
1554{
1555        struct lpphy_tx_gains gains;
1556
1557        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
1558                gains.gm = 4;
1559                gains.pad = 12;
1560                gains.pga = 12;
1561                gains.dac = 0;
1562        } else {
1563                gains.gm = 7;
1564                gains.pad = 14;
1565                gains.pga = 15;
1566                gains.dac = 0;
1567        }
1568        lpphy_set_tx_gains(dev, gains);
1569        lpphy_set_bb_mult(dev, 150);
1570}
1571
1572/* Initialize TX power control */
1573static void lpphy_tx_pctl_init(struct b43_wldev *dev)
1574{
1575        if (0/*FIXME HWPCTL capable */) {
1576                lpphy_tx_pctl_init_hw(dev);
1577        } else { /* This device is only software TX power control capable. */
1578                lpphy_tx_pctl_init_sw(dev);
1579        }
1580}
1581
1582static void lpphy_pr41573_workaround(struct b43_wldev *dev)
1583{
1584        struct b43_phy_lp *lpphy = dev->phy.lp;
1585        u32 *saved_tab;
1586        const unsigned int saved_tab_size = 256;
1587        enum b43_lpphy_txpctl_mode txpctl_mode;
1588        s8 tx_pwr_idx_over;
1589        u16 tssi_npt, tssi_idx;
1590
1591        saved_tab = kcalloc(saved_tab_size, sizeof(saved_tab[0]), GFP_KERNEL);
1592        if (!saved_tab) {
1593                b43err(dev->wl, "PR41573 failed. Out of memory!\n");
1594                return;
1595        }
1596
1597        lpphy_read_tx_pctl_mode_from_hardware(dev);
1598        txpctl_mode = lpphy->txpctl_mode;
1599        tx_pwr_idx_over = lpphy->tx_pwr_idx_over;
1600        tssi_npt = lpphy->tssi_npt;
1601        tssi_idx = lpphy->tssi_idx;
1602
1603        if (dev->phy.rev < 2) {
1604                b43_lptab_read_bulk(dev, B43_LPTAB32(10, 0x140),
1605                                    saved_tab_size, saved_tab);
1606        } else {
1607                b43_lptab_read_bulk(dev, B43_LPTAB32(7, 0x140),
1608                                    saved_tab_size, saved_tab);
1609        }
1610        //FIXME PHY reset
1611        lpphy_table_init(dev); //FIXME is table init needed?
1612        lpphy_baseband_init(dev);
1613        lpphy_tx_pctl_init(dev);
1614        b43_lpphy_op_software_rfkill(dev, false);
1615        lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
1616        if (dev->phy.rev < 2) {
1617                b43_lptab_write_bulk(dev, B43_LPTAB32(10, 0x140),
1618                                     saved_tab_size, saved_tab);
1619        } else {
1620                b43_lptab_write_bulk(dev, B43_LPTAB32(7, 0x140),
1621                                     saved_tab_size, saved_tab);
1622        }
1623        b43_write16(dev, B43_MMIO_CHANNEL, lpphy->channel);
1624        lpphy->tssi_npt = tssi_npt;
1625        lpphy->tssi_idx = tssi_idx;
1626        lpphy_set_analog_filter(dev, lpphy->channel);
1627        if (tx_pwr_idx_over != -1)
1628                lpphy_set_tx_power_by_index(dev, tx_pwr_idx_over);
1629        if (lpphy->rc_cap)
1630                lpphy_set_rc_cap(dev);
1631        b43_lpphy_op_set_rx_antenna(dev, lpphy->antenna);
1632        lpphy_set_tx_power_control(dev, txpctl_mode);
1633        kfree(saved_tab);
1634}
1635
1636struct lpphy_rx_iq_comp { u8 chan; s8 c1, c0; };
1637
1638static const struct lpphy_rx_iq_comp lpphy_5354_iq_table[] = {
1639        { .chan = 1, .c1 = -66, .c0 = 15, },
1640        { .chan = 2, .c1 = -66, .c0 = 15, },
1641        { .chan = 3, .c1 = -66, .c0 = 15, },
1642        { .chan = 4, .c1 = -66, .c0 = 15, },
1643        { .chan = 5, .c1 = -66, .c0 = 15, },
1644        { .chan = 6, .c1 = -66, .c0 = 15, },
1645        { .chan = 7, .c1 = -66, .c0 = 14, },
1646        { .chan = 8, .c1 = -66, .c0 = 14, },
1647        { .chan = 9, .c1 = -66, .c0 = 14, },
1648        { .chan = 10, .c1 = -66, .c0 = 14, },
1649        { .chan = 11, .c1 = -66, .c0 = 14, },
1650        { .chan = 12, .c1 = -66, .c0 = 13, },
1651        { .chan = 13, .c1 = -66, .c0 = 13, },
1652        { .chan = 14, .c1 = -66, .c0 = 13, },
1653};
1654
1655static const struct lpphy_rx_iq_comp lpphy_rev0_1_iq_table[] = {
1656        { .chan = 1, .c1 = -64, .c0 = 13, },
1657        { .chan = 2, .c1 = -64, .c0 = 13, },
1658        { .chan = 3, .c1 = -64, .c0 = 13, },
1659        { .chan = 4, .c1 = -64, .c0 = 13, },
1660        { .chan = 5, .c1 = -64, .c0 = 12, },
1661        { .chan = 6, .c1 = -64, .c0 = 12, },
1662        { .chan = 7, .c1 = -64, .c0 = 12, },
1663        { .chan = 8, .c1 = -64, .c0 = 12, },
1664        { .chan = 9, .c1 = -64, .c0 = 12, },
1665        { .chan = 10, .c1 = -64, .c0 = 11, },
1666        { .chan = 11, .c1 = -64, .c0 = 11, },
1667        { .chan = 12, .c1 = -64, .c0 = 11, },
1668        { .chan = 13, .c1 = -64, .c0 = 11, },
1669        { .chan = 14, .c1 = -64, .c0 = 10, },
1670        { .chan = 34, .c1 = -62, .c0 = 24, },
1671        { .chan = 38, .c1 = -62, .c0 = 24, },
1672        { .chan = 42, .c1 = -62, .c0 = 24, },
1673        { .chan = 46, .c1 = -62, .c0 = 23, },
1674        { .chan = 36, .c1 = -62, .c0 = 24, },
1675        { .chan = 40, .c1 = -62, .c0 = 24, },
1676        { .chan = 44, .c1 = -62, .c0 = 23, },
1677        { .chan = 48, .c1 = -62, .c0 = 23, },
1678        { .chan = 52, .c1 = -62, .c0 = 23, },
1679        { .chan = 56, .c1 = -62, .c0 = 22, },
1680        { .chan = 60, .c1 = -62, .c0 = 22, },
1681        { .chan = 64, .c1 = -62, .c0 = 22, },
1682        { .chan = 100, .c1 = -62, .c0 = 16, },
1683        { .chan = 104, .c1 = -62, .c0 = 16, },
1684        { .chan = 108, .c1 = -62, .c0 = 15, },
1685        { .chan = 112, .c1 = -62, .c0 = 14, },
1686        { .chan = 116, .c1 = -62, .c0 = 14, },
1687        { .chan = 120, .c1 = -62, .c0 = 13, },
1688        { .chan = 124, .c1 = -62, .c0 = 12, },
1689        { .chan = 128, .c1 = -62, .c0 = 12, },
1690        { .chan = 132, .c1 = -62, .c0 = 12, },
1691        { .chan = 136, .c1 = -62, .c0 = 11, },
1692        { .chan = 140, .c1 = -62, .c0 = 10, },
1693        { .chan = 149, .c1 = -61, .c0 = 9, },
1694        { .chan = 153, .c1 = -61, .c0 = 9, },
1695        { .chan = 157, .c1 = -61, .c0 = 9, },
1696        { .chan = 161, .c1 = -61, .c0 = 8, },
1697        { .chan = 165, .c1 = -61, .c0 = 8, },
1698        { .chan = 184, .c1 = -62, .c0 = 25, },
1699        { .chan = 188, .c1 = -62, .c0 = 25, },
1700        { .chan = 192, .c1 = -62, .c0 = 25, },
1701        { .chan = 196, .c1 = -62, .c0 = 25, },
1702        { .chan = 200, .c1 = -62, .c0 = 25, },
1703        { .chan = 204, .c1 = -62, .c0 = 25, },
1704        { .chan = 208, .c1 = -62, .c0 = 25, },
1705        { .chan = 212, .c1 = -62, .c0 = 25, },
1706        { .chan = 216, .c1 = -62, .c0 = 26, },
1707};
1708
1709static const struct lpphy_rx_iq_comp lpphy_rev2plus_iq_comp = {
1710        .chan = 0,
1711        .c1 = -64,
1712        .c0 = 0,
1713};
1714
1715static int lpphy_calc_rx_iq_comp(struct b43_wldev *dev, u16 samples)
1716{
1717        struct lpphy_iq_est iq_est;
1718        u16 c0, c1;
1719        int prod, ipwr, qpwr, prod_msb, q_msb, tmp1, tmp2, tmp3, tmp4, ret;
1720
1721        c1 = b43_phy_read(dev, B43_LPPHY_RX_COMP_COEFF_S);
1722        c0 = c1 >> 8;
1723        c1 |= 0xFF;
1724
1725        b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, 0x00C0);
1726        b43_phy_mask(dev, B43_LPPHY_RX_COMP_COEFF_S, 0x00FF);
1727
1728        ret = lpphy_rx_iq_est(dev, samples, 32, &iq_est);
1729        if (!ret)
1730                goto out;
1731
1732        prod = iq_est.iq_prod;
1733        ipwr = iq_est.i_pwr;
1734        qpwr = iq_est.q_pwr;
1735
1736        if (ipwr + qpwr < 2) {
1737                ret = 0;
1738                goto out;
1739        }
1740
1741        prod_msb = fls(abs(prod));
1742        q_msb = fls(abs(qpwr));
1743        tmp1 = prod_msb - 20;
1744
1745        if (tmp1 >= 0) {
1746                tmp3 = ((prod << (30 - prod_msb)) + (ipwr >> (1 + tmp1))) /
1747                        (ipwr >> tmp1);
1748        } else {
1749                tmp3 = ((prod << (30 - prod_msb)) + (ipwr << (-1 - tmp1))) /
1750                        (ipwr << -tmp1);
1751        }
1752
1753        tmp2 = q_msb - 11;
1754
1755        if (tmp2 >= 0)
1756                tmp4 = (qpwr << (31 - q_msb)) / (ipwr >> tmp2);
1757        else
1758                tmp4 = (qpwr << (31 - q_msb)) / (ipwr << -tmp2);
1759
1760        tmp4 -= tmp3 * tmp3;
1761        tmp4 = -int_sqrt(tmp4);
1762
1763        c0 = tmp3 >> 3;
1764        c1 = tmp4 >> 4;
1765
1766out:
1767        b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, c1);
1768        b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0x00FF, c0 << 8);
1769        return ret;
1770}
1771
1772static void lpphy_run_samples(struct b43_wldev *dev, u16 samples, u16 loops,
1773                              u16 wait)
1774{
1775        b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_BUFFER_CTL,
1776                        0xFFC0, samples - 1);
1777        if (loops != 0xFFFF)
1778                loops--;
1779        b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_COUNT, 0xF000, loops);
1780        b43_phy_maskset(dev, B43_LPPHY_SMPL_PLAY_BUFFER_CTL, 0x3F, wait << 6);
1781        b43_phy_set(dev, B43_LPPHY_A_PHY_CTL_ADDR, 0x1);
1782}
1783
1784//SPEC FIXME what does a negative freq mean?
1785static void lpphy_start_tx_tone(struct b43_wldev *dev, s32 freq, u16 max)
1786{
1787        struct b43_phy_lp *lpphy = dev->phy.lp;
1788        u16 buf[64];
1789        int i, samples = 0, angle = 0;
1790        int rotation = (((36 * freq) / 20) << 16) / 100;
1791        struct b43_c32 sample;
1792
1793        lpphy->tx_tone_freq = freq;
1794
1795        if (freq) {
1796                /* Find i for which abs(freq) integrally divides 20000 * i */
1797                for (i = 1; samples * abs(freq) != 20000 * i; i++) {
1798                        samples = (20000 * i) / abs(freq);
1799                        if(B43_WARN_ON(samples > 63))
1800                                return;
1801                }
1802        } else {
1803                samples = 2;
1804        }
1805
1806        for (i = 0; i < samples; i++) {
1807                sample = b43_cordic(angle);
1808                angle += rotation;
1809                buf[i] = CORDIC_CONVERT((sample.i * max) & 0xFF) << 8;
1810                buf[i] |= CORDIC_CONVERT((sample.q * max) & 0xFF);
1811        }
1812
1813        b43_lptab_write_bulk(dev, B43_LPTAB16(5, 0), samples, buf);
1814
1815        lpphy_run_samples(dev, samples, 0xFFFF, 0);
1816}
1817
1818static void lpphy_stop_tx_tone(struct b43_wldev *dev)
1819{
1820        struct b43_phy_lp *lpphy = dev->phy.lp;
1821        int i;
1822
1823        lpphy->tx_tone_freq = 0;
1824
1825        b43_phy_mask(dev, B43_LPPHY_SMPL_PLAY_COUNT, 0xF000);
1826        for (i = 0; i < 31; i++) {
1827                if (!(b43_phy_read(dev, B43_LPPHY_A_PHY_CTL_ADDR) & 0x1))
1828                        break;
1829                udelay(100);
1830        }
1831}
1832
1833
1834static void lpphy_papd_cal(struct b43_wldev *dev, struct lpphy_tx_gains gains,
1835                           int mode, bool useindex, u8 index)
1836{
1837        //TODO
1838}
1839
1840static void lpphy_papd_cal_txpwr(struct b43_wldev *dev)
1841{
1842        struct b43_phy_lp *lpphy = dev->phy.lp;
1843        struct lpphy_tx_gains gains, oldgains;
1844        int old_txpctl, old_afe_ovr, old_rf, old_bbmult;
1845
1846        lpphy_read_tx_pctl_mode_from_hardware(dev);
1847        old_txpctl = lpphy->txpctl_mode;
1848        old_afe_ovr = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40;
1849        if (old_afe_ovr)
1850                oldgains = lpphy_get_tx_gains(dev);
1851        old_rf = b43_phy_read(dev, B43_LPPHY_RF_PWR_OVERRIDE) & 0xFF;
1852        old_bbmult = lpphy_get_bb_mult(dev);
1853
1854        lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
1855
1856        if (dev->dev->chip_id == 0x4325 && dev->dev->chip_rev == 0)
1857                lpphy_papd_cal(dev, gains, 0, 1, 30);
1858        else
1859                lpphy_papd_cal(dev, gains, 0, 1, 65);
1860
1861        if (old_afe_ovr)
1862                lpphy_set_tx_gains(dev, oldgains);
1863        lpphy_set_bb_mult(dev, old_bbmult);
1864        lpphy_set_tx_power_control(dev, old_txpctl);
1865        b43_phy_maskset(dev, B43_LPPHY_RF_PWR_OVERRIDE, 0xFF00, old_rf);
1866}
1867
1868static int lpphy_rx_iq_cal(struct b43_wldev *dev, bool noise, bool tx,
1869                            bool rx, bool pa, struct lpphy_tx_gains *gains)
1870{
1871        struct b43_phy_lp *lpphy = dev->phy.lp;
1872        const struct lpphy_rx_iq_comp *iqcomp = NULL;
1873        struct lpphy_tx_gains nogains, oldgains;
1874        u16 tmp;
1875        int i, ret;
1876
1877        memset(&nogains, 0, sizeof(nogains));
1878        memset(&oldgains, 0, sizeof(oldgains));
1879
1880        if (dev->dev->chip_id == 0x5354) {
1881                for (i = 0; i < ARRAY_SIZE(lpphy_5354_iq_table); i++) {
1882                        if (lpphy_5354_iq_table[i].chan == lpphy->channel) {
1883                                iqcomp = &lpphy_5354_iq_table[i];
1884                        }
1885                }
1886        } else if (dev->phy.rev >= 2) {
1887                iqcomp = &lpphy_rev2plus_iq_comp;
1888        } else {
1889                for (i = 0; i < ARRAY_SIZE(lpphy_rev0_1_iq_table); i++) {
1890                        if (lpphy_rev0_1_iq_table[i].chan == lpphy->channel) {
1891                                iqcomp = &lpphy_rev0_1_iq_table[i];
1892                        }
1893                }
1894        }
1895
1896        if (B43_WARN_ON(!iqcomp))
1897                return 0;
1898
1899        b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S, 0xFF00, iqcomp->c1);
1900        b43_phy_maskset(dev, B43_LPPHY_RX_COMP_COEFF_S,
1901                        0x00FF, iqcomp->c0 << 8);
1902
1903        if (noise) {
1904                tx = true;
1905                rx = false;
1906                pa = false;
1907        }
1908
1909        lpphy_set_trsw_over(dev, tx, rx);
1910
1911        if (b43_current_band(dev->wl) == IEEE80211_BAND_2GHZ) {
1912                b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x8);
1913                b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0,
1914                                0xFFF7, pa << 3);
1915        } else {
1916                b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x20);
1917                b43_phy_maskset(dev, B43_LPPHY_RF_OVERRIDE_VAL_0,
1918                                0xFFDF, pa << 5);
1919        }
1920
1921        tmp = b43_phy_read(dev, B43_LPPHY_AFE_CTL_OVR) & 0x40;
1922
1923        if (noise)
1924                lpphy_set_rx_gain(dev, 0x2D5D);
1925        else {
1926                if (tmp)
1927                        oldgains = lpphy_get_tx_gains(dev);
1928                if (!gains)
1929                        gains = &nogains;
1930                lpphy_set_tx_gains(dev, *gains);
1931        }
1932
1933        b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFFE);
1934        b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xFFFE);
1935        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_0, 0x800);
1936        b43_phy_set(dev, B43_LPPHY_RF_OVERRIDE_VAL_0, 0x800);
1937        lpphy_set_deaf(dev, false);
1938        if (noise)
1939                ret = lpphy_calc_rx_iq_comp(dev, 0xFFF0);
1940        else {
1941                lpphy_start_tx_tone(dev, 4000, 100);
1942                ret = lpphy_calc_rx_iq_comp(dev, 0x4000);
1943                lpphy_stop_tx_tone(dev);
1944        }
1945        lpphy_clear_deaf(dev, false);
1946        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFFC);
1947        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFF7);
1948        b43_phy_mask(dev, B43_LPPHY_RF_OVERRIDE_0, 0xFFDF);
1949        if (!noise) {
1950                if (tmp)
1951                        lpphy_set_tx_gains(dev, oldgains);
1952                else
1953                        lpphy_disable_tx_gain_override(dev);
1954        }
1955        lpphy_disable_rx_gain_override(dev);
1956        b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xFFFE);
1957        b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0xF7FF);
1958        return ret;
1959}
1960
1961static void lpphy_calibration(struct b43_wldev *dev)
1962{
1963        struct b43_phy_lp *lpphy = dev->phy.lp;
1964        enum b43_lpphy_txpctl_mode saved_pctl_mode;
1965        bool full_cal = false;
1966
1967        if (lpphy->full_calib_chan != lpphy->channel) {
1968                full_cal = true;
1969                lpphy->full_calib_chan = lpphy->channel;
1970        }
1971
1972        b43_mac_suspend(dev);
1973
1974        lpphy_btcoex_override(dev);
1975        if (dev->phy.rev >= 2)
1976                lpphy_save_dig_flt_state(dev);
1977        lpphy_read_tx_pctl_mode_from_hardware(dev);
1978        saved_pctl_mode = lpphy->txpctl_mode;
1979        lpphy_set_tx_power_control(dev, B43_LPPHY_TXPCTL_OFF);
1980        //TODO Perform transmit power table I/Q LO calibration
1981        if ((dev->phy.rev == 0) && (saved_pctl_mode != B43_LPPHY_TXPCTL_OFF))
1982                lpphy_pr41573_workaround(dev);
1983        if ((dev->phy.rev >= 2) && full_cal) {
1984                lpphy_papd_cal_txpwr(dev);
1985        }
1986        lpphy_set_tx_power_control(dev, saved_pctl_mode);
1987        if (dev->phy.rev >= 2)
1988                lpphy_restore_dig_flt_state(dev);
1989        lpphy_rx_iq_cal(dev, true, true, false, false, NULL);
1990
1991        b43_mac_enable(dev);
1992}
1993
1994static u16 b43_lpphy_op_read(struct b43_wldev *dev, u16 reg)
1995{
1996        b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
1997        return b43_read16(dev, B43_MMIO_PHY_DATA);
1998}
1999
2000static void b43_lpphy_op_write(struct b43_wldev *dev, u16 reg, u16 value)
2001{
2002        b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
2003        b43_write16(dev, B43_MMIO_PHY_DATA, value);
2004}
2005
2006static void b43_lpphy_op_maskset(struct b43_wldev *dev, u16 reg, u16 mask,
2007                                 u16 set)
2008{
2009        b43_write16(dev, B43_MMIO_PHY_CONTROL, reg);
2010        b43_write16(dev, B43_MMIO_PHY_DATA,
2011                    (b43_read16(dev, B43_MMIO_PHY_DATA) & mask) | set);
2012}
2013
2014static u16 b43_lpphy_op_radio_read(struct b43_wldev *dev, u16 reg)
2015{
2016        /* Register 1 is a 32-bit register. */
2017        B43_WARN_ON(reg == 1);
2018        /* LP-PHY needs a special bit set for read access */
2019        if (dev->phy.rev < 2) {
2020                if (reg != 0x4001)
2021                        reg |= 0x100;
2022        } else
2023                reg |= 0x200;
2024
2025        b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
2026        return b43_read16(dev, B43_MMIO_RADIO_DATA_LOW);
2027}
2028
2029static void b43_lpphy_op_radio_write(struct b43_wldev *dev, u16 reg, u16 value)
2030{
2031        /* Register 1 is a 32-bit register. */
2032        B43_WARN_ON(reg == 1);
2033
2034        b43_write16(dev, B43_MMIO_RADIO_CONTROL, reg);
2035        b43_write16(dev, B43_MMIO_RADIO_DATA_LOW, value);
2036}
2037
2038struct b206x_channel {
2039        u8 channel;
2040        u16 freq;
2041        u8 data[12];
2042};
2043
2044static const struct b206x_channel b2062_chantbl[] = {
2045        { .channel = 1, .freq = 2412, .data[0] = 0xFF, .data[1] = 0xFF,
2046          .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
2047          .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
2048        { .channel = 2, .freq = 2417, .data[0] = 0xFF, .data[1] = 0xFF,
2049          .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
2050          .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
2051        { .channel = 3, .freq = 2422, .data[0] = 0xFF, .data[1] = 0xFF,
2052          .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
2053          .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
2054        { .channel = 4, .freq = 2427, .data[0] = 0xFF, .data[1] = 0xFF,
2055          .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
2056          .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
2057        { .channel = 5, .freq = 2432, .data[0] = 0xFF, .data[1] = 0xFF,
2058          .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
2059          .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
2060        { .channel = 6, .freq = 2437, .data[0] = 0xFF, .data[1] = 0xFF,
2061          .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
2062          .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
2063        { .channel = 7, .freq = 2442, .data[0] = 0xFF, .data[1] = 0xFF,
2064          .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
2065          .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
2066        { .channel = 8, .freq = 2447, .data[0] = 0xFF, .data[1] = 0xFF,
2067          .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
2068          .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
2069        { .channel = 9, .freq = 2452, .data[0] = 0xFF, .data[1] = 0xFF,
2070          .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
2071          .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
2072        { .channel = 10, .freq = 2457, .data[0] = 0xFF, .data[1] = 0xFF,
2073          .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
2074          .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
2075        { .channel = 11, .freq = 2462, .data[0] = 0xFF, .data[1] = 0xFF,
2076          .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
2077          .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
2078        { .channel = 12, .freq = 2467, .data[0] = 0xFF, .data[1] = 0xFF,
2079          .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
2080          .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
2081        { .channel = 13, .freq = 2472, .data[0] = 0xFF, .data[1] = 0xFF,
2082          .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
2083          .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
2084        { .channel = 14, .freq = 2484, .data[0] = 0xFF, .data[1] = 0xFF,
2085          .data[2] = 0xB5, .data[3] = 0x1B, .data[4] = 0x24, .data[5] = 0x32,
2086          .data[6] = 0x32, .data[7] = 0x88, .data[8] = 0x88, },
2087        { .channel = 34, .freq = 5170, .data[0] = 0x00, .data[1] = 0x22,
2088          .data[2] = 0x20, .data[3] = 0x84, .data[4] = 0x3C, .data[5] = 0x77,
2089          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
2090        { .channel = 38, .freq = 5190, .data[0] = 0x00, .data[1] = 0x11,
2091          .data[2] = 0x10, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
2092          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
2093        { .channel = 42, .freq = 5210, .data[0] = 0x00, .data[1] = 0x11,
2094          .data[2] = 0x10, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
2095          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
2096        { .channel = 46, .freq = 5230, .data[0] = 0x00, .data[1] = 0x00,
2097          .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
2098          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
2099        { .channel = 36, .freq = 5180, .data[0] = 0x00, .data[1] = 0x11,
2100          .data[2] = 0x20, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
2101          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
2102        { .channel = 40, .freq = 5200, .data[0] = 0x00, .data[1] = 0x11,
2103          .data[2] = 0x10, .data[3] = 0x84, .data[4] = 0x3C, .data[5] = 0x77,
2104          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
2105        { .channel = 44, .freq = 5220, .data[0] = 0x00, .data[1] = 0x11,
2106          .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
2107          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
2108        { .channel = 48, .freq = 5240, .data[0] = 0x00, .data[1] = 0x00,
2109          .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
2110          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
2111        { .channel = 52, .freq = 5260, .data[0] = 0x00, .data[1] = 0x00,
2112          .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
2113          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
2114        { .channel = 56, .freq = 5280, .data[0] = 0x00, .data[1] = 0x00,
2115          .data[2] = 0x00, .data[3] = 0x83, .data[4] = 0x3C, .data[5] = 0x77,
2116          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
2117        { .channel = 60, .freq = 5300, .data[0] = 0x00, .data[1] = 0x00,
2118          .data[2] = 0x00, .data[3] = 0x63, .data[4] = 0x3C, .data[5] = 0x77,
2119          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
2120        { .channel = 64, .freq = 5320, .data[0] = 0x00, .data[1] = 0x00,
2121          .data[2] = 0x00, .data[3] = 0x62, .data[4] = 0x3C, .data[5] = 0x77,
2122          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
2123        { .channel = 100, .freq = 5500, .data[0] = 0x00, .data[1] = 0x00,
2124          .data[2] = 0x00, .data[3] = 0x30, .data[4] = 0x3C, .data[5] = 0x77,
2125          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2126        { .channel = 104, .freq = 5520, .data[0] = 0x00, .data[1] = 0x00,
2127          .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77,
2128          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2129        { .channel = 108, .freq = 5540, .data[0] = 0x00, .data[1] = 0x00,
2130          .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77,
2131          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2132        { .channel = 112, .freq = 5560, .data[0] = 0x00, .data[1] = 0x00,
2133          .data[2] = 0x00, .data[3] = 0x20, .data[4] = 0x3C, .data[5] = 0x77,
2134          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2135        { .channel = 116, .freq = 5580, .data[0] = 0x00, .data[1] = 0x00,
2136          .data[2] = 0x00, .data[3] = 0x10, .data[4] = 0x3C, .data[5] = 0x77,
2137          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2138        { .channel = 120, .freq = 5600, .data[0] = 0x00, .data[1] = 0x00,
2139          .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
2140          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2141        { .channel = 124, .freq = 5620, .data[0] = 0x00, .data[1] = 0x00,
2142          .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
2143          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2144        { .channel = 128, .freq = 5640, .data[0] = 0x00, .data[1] = 0x00,
2145          .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
2146          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2147        { .channel = 132, .freq = 5660, .data[0] = 0x00, .data[1] = 0x00,
2148          .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
2149          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2150        { .channel = 136, .freq = 5680, .data[0] = 0x00, .data[1] = 0x00,
2151          .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
2152          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2153        { .channel = 140, .freq = 5700, .data[0] = 0x00, .data[1] = 0x00,
2154          .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
2155          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2156        { .channel = 149, .freq = 5745, .data[0] = 0x00, .data[1] = 0x00,
2157          .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
2158          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2159        { .channel = 153, .freq = 5765, .data[0] = 0x00, .data[1] = 0x00,
2160          .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
2161          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2162        { .channel = 157, .freq = 5785, .data[0] = 0x00, .data[1] = 0x00,
2163          .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
2164          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2165        { .channel = 161, .freq = 5805, .data[0] = 0x00, .data[1] = 0x00,
2166          .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
2167          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2168        { .channel = 165, .freq = 5825, .data[0] = 0x00, .data[1] = 0x00,
2169          .data[2] = 0x00, .data[3] = 0x00, .data[4] = 0x3C, .data[5] = 0x77,
2170          .data[6] = 0x37, .data[7] = 0xFF, .data[8] = 0x88, },
2171        { .channel = 184, .freq = 4920, .data[0] = 0x55, .data[1] = 0x77,
2172          .data[2] = 0x90, .data[3] = 0xF7, .data[4] = 0x3C, .data[5] = 0x77,
2173          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
2174        { .channel = 188, .freq = 4940, .data[0] = 0x44, .data[1] = 0x77,
2175          .data[2] = 0x80, .data[3] = 0xE7, .data[4] = 0x3C, .data[5] = 0x77,
2176          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
2177        { .channel = 192, .freq = 4960, .data[0] = 0x44, .data[1] = 0x66,
2178          .data[2] = 0x80, .data[3] = 0xE7, .data[4] = 0x3C, .data[5] = 0x77,
2179          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
2180        { .channel = 196, .freq = 4980, .data[0] = 0x33, .data[1] = 0x66,
2181          .data[2] = 0x70, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77,
2182          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
2183        { .channel = 200, .freq = 5000, .data[0] = 0x22, .data[1] = 0x55,
2184          .data[2] = 0x60, .data[3] = 0xD7, .data[4] = 0x3C, .data[5] = 0x77,
2185          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
2186        { .channel = 204, .freq = 5020, .data[0] = 0x22, .data[1] = 0x55,
2187          .data[2] = 0x60, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77,
2188          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
2189        { .channel = 208, .freq = 5040, .data[0] = 0x22, .data[1] = 0x44,
2190          .data[2] = 0x50, .data[3] = 0xC7, .data[4] = 0x3C, .data[5] = 0x77,
2191          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0xFF, },
2192        { .channel = 212, .freq = 5060, .data[0] = 0x11, .data[1] = 0x44,
2193          .data[2] = 0x50, .data[3] = 0xA5, .data[4] = 0x3C, .data[5] = 0x77,
2194          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
2195        { .channel = 216, .freq = 5080, .data[0] = 0x00, .data[1] = 0x44,
2196          .data[2] = 0x40, .data[3] = 0xB6, .data[4] = 0x3C, .data[5] = 0x77,
2197          .data[6] = 0x35, .data[7] = 0xFF, .data[8] = 0x88, },
2198};
2199
2200static const struct b206x_channel b2063_chantbl[] = {
2201        { .channel = 1, .freq = 2412, .data[0] = 0x6F, .data[1] = 0x3C,
2202          .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
2203          .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
2204          .data[10] = 0x80, .data[11] = 0x70, },
2205        { .channel = 2, .freq = 2417, .data[0] = 0x6F, .data[1] = 0x3C,
2206          .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
2207          .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
2208          .data[10] = 0x80, .data[11] = 0x70, },
2209        { .channel = 3, .freq = 2422, .data[0] = 0x6F, .data[1] = 0x3C,
2210          .data[2] = 0x3C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
2211          .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
2212          .data[10] = 0x80, .data[11] = 0x70, },
2213        { .channel = 4, .freq = 2427, .data[0] = 0x6F, .data[1] = 0x2C,
2214          .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
2215          .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
2216          .data[10] = 0x80, .data[11] = 0x70, },
2217        { .channel = 5, .freq = 2432, .data[0] = 0x6F, .data[1] = 0x2C,
2218          .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
2219          .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
2220          .data[10] = 0x80, .data[11] = 0x70, },
2221        { .channel = 6, .freq = 2437, .data[0] = 0x6F, .data[1] = 0x2C,
2222          .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
2223          .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
2224          .data[10] = 0x80, .data[11] = 0x70, },
2225        { .channel = 7, .freq = 2442, .data[0] = 0x6F, .data[1] = 0x2C,
2226          .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
2227          .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
2228          .data[10] = 0x80, .data[11] = 0x70, },
2229        { .channel = 8, .freq = 2447, .data[0] = 0x6F, .data[1] = 0x2C,
2230          .data[2] = 0x2C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
2231          .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
2232          .data[10] = 0x80, .data[11] = 0x70, },
2233        { .channel = 9, .freq = 2452, .data[0] = 0x6F, .data[1] = 0x1C,
2234          .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
2235          .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
2236          .data[10] = 0x80, .data[11] = 0x70, },
2237        { .channel = 10, .freq = 2457, .data[0] = 0x6F, .data[1] = 0x1C,
2238          .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
2239          .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
2240          .data[10] = 0x80, .data[11] = 0x70, },
2241        { .channel = 11, .freq = 2462, .data[0] = 0x6E, .data[1] = 0x1C,
2242          .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
2243          .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
2244          .data[10] = 0x80, .data[11] = 0x70, },
2245        { .channel = 12, .freq = 2467, .data[0] = 0x6E, .data[1] = 0x1C,
2246          .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
2247          .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
2248          .data[10] = 0x80, .data[11] = 0x70, },
2249        { .channel = 13, .freq = 2472, .data[0] = 0x6E, .data[1] = 0x1C,
2250          .data[2] = 0x1C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
2251          .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
2252          .data[10] = 0x80, .data[11] = 0x70, },
2253        { .channel = 14, .freq = 2484, .data[0] = 0x6E, .data[1] = 0x0C,
2254          .data[2] = 0x0C, .data[3] = 0x04, .data[4] = 0x05, .data[5] = 0x05,
2255          .data[6] = 0x05, .data[7] = 0x05, .data[8] = 0x77, .data[9] = 0x80,
2256          .data[10] = 0x80, .data[11] = 0x70, },
2257        { .channel = 34, .freq = 5170, .data[0] = 0x6A, .data[1] = 0x0C,
2258          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x02, .data[5] = 0x05,
2259          .data[6] = 0x0D, .data[7] = 0x0D, .data[8] = 0x77, .data[9] = 0x80,
2260          .data[10] = 0x20, .data[11] = 0x00, },
2261        { .channel = 36, .freq = 5180, .data[0] = 0x6A, .data[1] = 0x0C,
2262          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x05,
2263          .data[6] = 0x0D, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x80,
2264          .data[10] = 0x20, .data[11] = 0x00, },
2265        { .channel = 38, .freq = 5190, .data[0] = 0x6A, .data[1] = 0x0C,
2266          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04,
2267          .data[6] = 0x0C, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x80,
2268          .data[10] = 0x20, .data[11] = 0x00, },
2269        { .channel = 40, .freq = 5200, .data[0] = 0x69, .data[1] = 0x0C,
2270          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04,
2271          .data[6] = 0x0C, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x70,
2272          .data[10] = 0x20, .data[11] = 0x00, },
2273        { .channel = 42, .freq = 5210, .data[0] = 0x69, .data[1] = 0x0C,
2274          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x01, .data[5] = 0x04,
2275          .data[6] = 0x0B, .data[7] = 0x0C, .data[8] = 0x77, .data[9] = 0x70,
2276          .data[10] = 0x20, .data[11] = 0x00, },
2277        { .channel = 44, .freq = 5220, .data[0] = 0x69, .data[1] = 0x0C,
2278          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x04,
2279          .data[6] = 0x0B, .data[7] = 0x0B, .data[8] = 0x77, .data[9] = 0x60,
2280          .data[10] = 0x20, .data[11] = 0x00, },
2281        { .channel = 46, .freq = 5230, .data[0] = 0x69, .data[1] = 0x0C,
2282          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x03,
2283          .data[6] = 0x0A, .data[7] = 0x0B, .data[8] = 0x77, .data[9] = 0x60,
2284          .data[10] = 0x20, .data[11] = 0x00, },
2285        { .channel = 48, .freq = 5240, .data[0] = 0x69, .data[1] = 0x0C,
2286          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x03,
2287          .data[6] = 0x0A, .data[7] = 0x0A, .data[8] = 0x77, .data[9] = 0x60,
2288          .data[10] = 0x20, .data[11] = 0x00, },
2289        { .channel = 52, .freq = 5260, .data[0] = 0x68, .data[1] = 0x0C,
2290          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x02,
2291          .data[6] = 0x09, .data[7] = 0x09, .data[8] = 0x77, .data[9] = 0x60,
2292          .data[10] = 0x20, .data[11] = 0x00, },
2293        { .channel = 56, .freq = 5280, .data[0] = 0x68, .data[1] = 0x0C,
2294          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x01,
2295          .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50,
2296          .data[10] = 0x10, .data[11] = 0x00, },
2297        { .channel = 60, .freq = 5300, .data[0] = 0x68, .data[1] = 0x0C,
2298          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x01,
2299          .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50,
2300          .data[10] = 0x10, .data[11] = 0x00, },
2301        { .channel = 64, .freq = 5320, .data[0] = 0x67, .data[1] = 0x0C,
2302          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2303          .data[6] = 0x08, .data[7] = 0x08, .data[8] = 0x77, .data[9] = 0x50,
2304          .data[10] = 0x10, .data[11] = 0x00, },
2305        { .channel = 100, .freq = 5500, .data[0] = 0x64, .data[1] = 0x0C,
2306          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2307          .data[6] = 0x02, .data[7] = 0x01, .data[8] = 0x77, .data[9] = 0x20,
2308          .data[10] = 0x00, .data[11] = 0x00, },
2309        { .channel = 104, .freq = 5520, .data[0] = 0x64, .data[1] = 0x0C,
2310          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2311          .data[6] = 0x01, .data[7] = 0x01, .data[8] = 0x77, .data[9] = 0x20,
2312          .data[10] = 0x00, .data[11] = 0x00, },
2313        { .channel = 108, .freq = 5540, .data[0] = 0x63, .data[1] = 0x0C,
2314          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2315          .data[6] = 0x01, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10,
2316          .data[10] = 0x00, .data[11] = 0x00, },
2317        { .channel = 112, .freq = 5560, .data[0] = 0x63, .data[1] = 0x0C,
2318          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2319          .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10,
2320          .data[10] = 0x00, .data[11] = 0x00, },
2321        { .channel = 116, .freq = 5580, .data[0] = 0x62, .data[1] = 0x0C,
2322          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2323          .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x10,
2324          .data[10] = 0x00, .data[11] = 0x00, },
2325        { .channel = 120, .freq = 5600, .data[0] = 0x62, .data[1] = 0x0C,
2326          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2327          .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
2328          .data[10] = 0x00, .data[11] = 0x00, },
2329        { .channel = 124, .freq = 5620, .data[0] = 0x62, .data[1] = 0x0C,
2330          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2331          .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
2332          .data[10] = 0x00, .data[11] = 0x00, },
2333        { .channel = 128, .freq = 5640, .data[0] = 0x61, .data[1] = 0x0C,
2334          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2335          .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
2336          .data[10] = 0x00, .data[11] = 0x00, },
2337        { .channel = 132, .freq = 5660, .data[0] = 0x61, .data[1] = 0x0C,
2338          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2339          .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
2340          .data[10] = 0x00, .data[11] = 0x00, },
2341        { .channel = 136, .freq = 5680, .data[0] = 0x61, .data[1] = 0x0C,
2342          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2343          .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
2344          .data[10] = 0x00, .data[11] = 0x00, },
2345        { .channel = 140, .freq = 5700, .data[0] = 0x60, .data[1] = 0x0C,
2346          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2347          .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
2348          .data[10] = 0x00, .data[11] = 0x00, },
2349        { .channel = 149, .freq = 5745, .data[0] = 0x60, .data[1] = 0x0C,
2350          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2351          .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
2352          .data[10] = 0x00, .data[11] = 0x00, },
2353        { .channel = 153, .freq = 5765, .data[0] = 0x60, .data[1] = 0x0C,
2354          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2355          .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
2356          .data[10] = 0x00, .data[11] = 0x00, },
2357        { .channel = 157, .freq = 5785, .data[0] = 0x60, .data[1] = 0x0C,
2358          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2359          .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
2360          .data[10] = 0x00, .data[11] = 0x00, },
2361        { .channel = 161, .freq = 5805, .data[0] = 0x60, .data[1] = 0x0C,
2362          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2363          .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
2364          .data[10] = 0x00, .data[11] = 0x00, },
2365        { .channel = 165, .freq = 5825, .data[0] = 0x60, .data[1] = 0x0C,
2366          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x00, .data[5] = 0x00,
2367          .data[6] = 0x00, .data[7] = 0x00, .data[8] = 0x77, .data[9] = 0x00,
2368          .data[10] = 0x00, .data[11] = 0x00, },
2369        { .channel = 184, .freq = 4920, .data[0] = 0x6E, .data[1] = 0x0C,
2370          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x09, .data[5] = 0x0E,
2371          .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xC0,
2372          .data[10] = 0x50, .data[11] = 0x00, },
2373        { .channel = 188, .freq = 4940, .data[0] = 0x6E, .data[1] = 0x0C,
2374          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x09, .data[5] = 0x0D,
2375          .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xB0,
2376          .data[10] = 0x50, .data[11] = 0x00, },
2377        { .channel = 192, .freq = 4960, .data[0] = 0x6E, .data[1] = 0x0C,
2378          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0C,
2379          .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xB0,
2380          .data[10] = 0x50, .data[11] = 0x00, },
2381        { .channel = 196, .freq = 4980, .data[0] = 0x6D, .data[1] = 0x0C,
2382          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0C,
2383          .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0,
2384          .data[10] = 0x40, .data[11] = 0x00, },
2385        { .channel = 200, .freq = 5000, .data[0] = 0x6D, .data[1] = 0x0C,
2386          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0B,
2387          .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0,
2388          .data[10] = 0x40, .data[11] = 0x00, },
2389        { .channel = 204, .freq = 5020, .data[0] = 0x6D, .data[1] = 0x0C,
2390          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x08, .data[5] = 0x0A,
2391          .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0xA0,
2392          .data[10] = 0x40, .data[11] = 0x00, },
2393        { .channel = 208, .freq = 5040, .data[0] = 0x6C, .data[1] = 0x0C,
2394          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x07, .data[5] = 0x09,
2395          .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90,
2396          .data[10] = 0x40, .data[11] = 0x00, },
2397        { .channel = 212, .freq = 5060, .data[0] = 0x6C, .data[1] = 0x0C,
2398          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x06, .data[5] = 0x08,
2399          .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90,
2400          .data[10] = 0x40, .data[11] = 0x00, },
2401        { .channel = 216, .freq = 5080, .data[0] = 0x6C, .data[1] = 0x0C,
2402          .data[2] = 0x0C, .data[3] = 0x00, .data[4] = 0x05, .data[5] = 0x08,
2403          .data[6] = 0x0F, .data[7] = 0x0F, .data[8] = 0x77, .data[9] = 0x90,
2404          .data[10] = 0x40, .data[11] = 0x00, },
2405};
2406
2407static void lpphy_b2062_reset_pll_bias(struct b43_wldev *dev)
2408{
2409        b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0xFF);
2410        udelay(20);
2411        if (dev->dev->chip_id == 0x5354) {
2412                b43_radio_write(dev, B2062_N_COMM1, 4);
2413                b43_radio_write(dev, B2062_S_RFPLL_CTL2, 4);
2414        } else {
2415                b43_radio_write(dev, B2062_S_RFPLL_CTL2, 0);
2416        }
2417        udelay(5);
2418}
2419
2420static void lpphy_b2062_vco_calib(struct b43_wldev *dev)
2421{
2422        b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x42);
2423        b43_radio_write(dev, B2062_S_RFPLL_CTL21, 0x62);
2424        udelay(200);
2425}
2426
2427static int lpphy_b2062_tune(struct b43_wldev *dev,
2428                            unsigned int channel)
2429{
2430        struct b43_phy_lp *lpphy = dev->phy.lp;
2431        struct ssb_bus *bus = dev->dev->sdev->bus;
2432        const struct b206x_channel *chandata = NULL;
2433        u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
2434        u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6, tmp7, tmp8, tmp9;
2435        int i, err = 0;
2436
2437        for (i = 0; i < ARRAY_SIZE(b2062_chantbl); i++) {
2438                if (b2062_chantbl[i].channel == channel) {
2439                        chandata = &b2062_chantbl[i];
2440                        break;
2441                }
2442        }
2443
2444        if (B43_WARN_ON(!chandata))
2445                return -EINVAL;
2446
2447        b43_radio_set(dev, B2062_S_RFPLL_CTL14, 0x04);
2448        b43_radio_write(dev, B2062_N_LGENA_TUNE0, chandata->data[0]);
2449        b43_radio_write(dev, B2062_N_LGENA_TUNE2, chandata->data[1]);
2450        b43_radio_write(dev, B2062_N_LGENA_TUNE3, chandata->data[2]);
2451        b43_radio_write(dev, B2062_N_TX_TUNE, chandata->data[3]);
2452        b43_radio_write(dev, B2062_S_LGENG_CTL1, chandata->data[4]);
2453        b43_radio_write(dev, B2062_N_LGENA_CTL5, chandata->data[5]);
2454        b43_radio_write(dev, B2062_N_LGENA_CTL6, chandata->data[6]);
2455        b43_radio_write(dev, B2062_N_TX_PGA, chandata->data[7]);
2456        b43_radio_write(dev, B2062_N_TX_PAD, chandata->data[8]);
2457
2458        tmp1 = crystal_freq / 1000;
2459        tmp2 = lpphy->pdiv * 1000;
2460        b43_radio_write(dev, B2062_S_RFPLL_CTL33, 0xCC);
2461        b43_radio_write(dev, B2062_S_RFPLL_CTL34, 0x07);
2462        lpphy_b2062_reset_pll_bias(dev);
2463        tmp3 = tmp2 * channel2freq_lp(channel);
2464        if (channel2freq_lp(channel) < 4000)
2465                tmp3 *= 2;
2466        tmp4 = 48 * tmp1;
2467        tmp6 = tmp3 / tmp4;
2468        tmp7 = tmp3 % tmp4;
2469        b43_radio_write(dev, B2062_S_RFPLL_CTL26, tmp6);
2470        tmp5 = tmp7 * 0x100;
2471        tmp6 = tmp5 / tmp4;
2472        tmp7 = tmp5 % tmp4;
2473        b43_radio_write(dev, B2062_S_RFPLL_CTL27, tmp6);
2474        tmp5 = tmp7 * 0x100;
2475        tmp6 = tmp5 / tmp4;
2476        tmp7 = tmp5 % tmp4;
2477        b43_radio_write(dev, B2062_S_RFPLL_CTL28, tmp6);
2478        tmp5 = tmp7 * 0x100;
2479        tmp6 = tmp5 / tmp4;
2480        tmp7 = tmp5 % tmp4;
2481        b43_radio_write(dev, B2062_S_RFPLL_CTL29, tmp6 + ((2 * tmp7) / tmp4));
2482        tmp8 = b43_radio_read(dev, B2062_S_RFPLL_CTL19);
2483        tmp9 = ((2 * tmp3 * (tmp8 + 1)) + (3 * tmp1)) / (6 * tmp1);
2484        b43_radio_write(dev, B2062_S_RFPLL_CTL23, (tmp9 >> 8) + 16);
2485        b43_radio_write(dev, B2062_S_RFPLL_CTL24, tmp9 & 0xFF);
2486
2487        lpphy_b2062_vco_calib(dev);
2488        if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10) {
2489                b43_radio_write(dev, B2062_S_RFPLL_CTL33, 0xFC);
2490                b43_radio_write(dev, B2062_S_RFPLL_CTL34, 0);
2491                lpphy_b2062_reset_pll_bias(dev);
2492                lpphy_b2062_vco_calib(dev);
2493                if (b43_radio_read(dev, B2062_S_RFPLL_CTL3) & 0x10)
2494                        err = -EIO;
2495        }
2496
2497        b43_radio_mask(dev, B2062_S_RFPLL_CTL14, ~0x04);
2498        return err;
2499}
2500
2501static void lpphy_b2063_vco_calib(struct b43_wldev *dev)
2502{
2503        u16 tmp;
2504
2505        b43_radio_mask(dev, B2063_PLL_SP1, ~0x40);
2506        tmp = b43_radio_read(dev, B2063_PLL_JTAG_CALNRST) & 0xF8;
2507        b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp);
2508        udelay(1);
2509        b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x4);
2510        udelay(1);
2511        b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x6);
2512        udelay(1);
2513        b43_radio_write(dev, B2063_PLL_JTAG_CALNRST, tmp | 0x7);
2514        udelay(300);
2515        b43_radio_set(dev, B2063_PLL_SP1, 0x40);
2516}
2517
2518static int lpphy_b2063_tune(struct b43_wldev *dev,
2519                            unsigned int channel)
2520{
2521        struct ssb_bus *bus = dev->dev->sdev->bus;
2522
2523        static const struct b206x_channel *chandata = NULL;
2524        u32 crystal_freq = bus->chipco.pmu.crystalfreq * 1000;
2525        u32 freqref, vco_freq, val1, val2, val3, timeout, timeoutref, count;
2526        u16 old_comm15, scale;
2527        u32 tmp1, tmp2, tmp3, tmp4, tmp5, tmp6;
2528        int i, div = (crystal_freq <= 26000000 ? 1 : 2);
2529
2530        for (i = 0; i < ARRAY_SIZE(b2063_chantbl); i++) {
2531                if (b2063_chantbl[i].channel == channel) {
2532                        chandata = &b2063_chantbl[i];
2533                        break;
2534                }
2535        }
2536
2537        if (B43_WARN_ON(!chandata))
2538                return -EINVAL;
2539
2540        b43_radio_write(dev, B2063_LOGEN_VCOBUF1, chandata->data[0]);
2541        b43_radio_write(dev, B2063_LOGEN_MIXER2, chandata->data[1]);
2542        b43_radio_write(dev, B2063_LOGEN_BUF2, chandata->data[2]);
2543        b43_radio_write(dev, B2063_LOGEN_RCCR1, chandata->data[3]);
2544        b43_radio_write(dev, B2063_A_RX_1ST3, chandata->data[4]);
2545        b43_radio_write(dev, B2063_A_RX_2ND1, chandata->data[5]);
2546        b43_radio_write(dev, B2063_A_RX_2ND4, chandata->data[6]);
2547        b43_radio_write(dev, B2063_A_RX_2ND7, chandata->data[7]);
2548        b43_radio_write(dev, B2063_A_RX_PS6, chandata->data[8]);
2549        b43_radio_write(dev, B2063_TX_RF_CTL2, chandata->data[9]);
2550        b43_radio_write(dev, B2063_TX_RF_CTL5, chandata->data[10]);
2551        b43_radio_write(dev, B2063_PA_CTL11, chandata->data[11]);
2552
2553        old_comm15 = b43_radio_read(dev, B2063_COMM15);
2554        b43_radio_set(dev, B2063_COMM15, 0x1E);
2555
2556        if (chandata->freq > 4000) /* spec says 2484, but 4000 is safer */
2557                vco_freq = chandata->freq << 1;
2558        else
2559                vco_freq = chandata->freq << 2;
2560
2561        freqref = crystal_freq * 3;
2562        val1 = lpphy_qdiv_roundup(crystal_freq, 1000000, 16);
2563        val2 = lpphy_qdiv_roundup(crystal_freq, 1000000 * div, 16);
2564        val3 = lpphy_qdiv_roundup(vco_freq, 3, 16);
2565        timeout = ((((8 * crystal_freq) / (div * 5000000)) + 1) >> 1) - 1;
2566        b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB3, 0x2);
2567        b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB6,
2568                          0xFFF8, timeout >> 2);
2569        b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB7,
2570                          0xFF9F,timeout << 5);
2571
2572        timeoutref = ((((8 * crystal_freq) / (div * (timeout + 1))) +
2573                                                999999) / 1000000) + 1;
2574        b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB5, timeoutref);
2575
2576        count = lpphy_qdiv_roundup(val3, val2 + 16, 16);
2577        count *= (timeout + 1) * (timeoutref + 1);
2578        count--;
2579        b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_VCO_CALIB7,
2580                                                0xF0, count >> 8);
2581        b43_radio_write(dev, B2063_PLL_JTAG_PLL_VCO_CALIB8, count & 0xFF);
2582
2583        tmp1 = ((val3 * 62500) / freqref) << 4;
2584        tmp2 = ((val3 * 62500) % freqref) << 4;
2585        while (tmp2 >= freqref) {
2586                tmp1++;
2587                tmp2 -= freqref;
2588        }
2589        b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG1, 0xFFE0, tmp1 >> 4);
2590        b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG2, 0xFE0F, tmp1 << 4);
2591        b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_SG2, 0xFFF0, tmp1 >> 16);
2592        b43_radio_write(dev, B2063_PLL_JTAG_PLL_SG3, (tmp2 >> 8) & 0xFF);
2593        b43_radio_write(dev, B2063_PLL_JTAG_PLL_SG4, tmp2 & 0xFF);
2594
2595        b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF1, 0xB9);
2596        b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF2, 0x88);
2597        b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF3, 0x28);
2598        b43_radio_write(dev, B2063_PLL_JTAG_PLL_LF4, 0x63);
2599
2600        tmp3 = ((41 * (val3 - 3000)) /1200) + 27;
2601        tmp4 = lpphy_qdiv_roundup(132000 * tmp1, 8451, 16);
2602
2603        if ((tmp4 + tmp3 - 1) / tmp3 > 60) {
2604                scale = 1;
2605                tmp5 = ((tmp4 + tmp3) / (tmp3 << 1)) - 8;
2606        } else {
2607                scale = 0;
2608                tmp5 = ((tmp4 + (tmp3 >> 1)) / tmp3) - 8;
2609        }
2610        b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFC0, tmp5);
2611        b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP2, 0xFFBF, scale << 6);
2612
2613        tmp6 = lpphy_qdiv_roundup(100 * val1, val3, 16);
2614        tmp6 *= (tmp5 * 8) * (scale + 1);
2615        if (tmp6 > 150)
2616                tmp6 = 0;
2617
2618        b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFE0, tmp6);
2619        b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_CP3, 0xFFDF, scale << 5);
2620
2621        b43_radio_maskset(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFFFB, 0x4);
2622        if (crystal_freq > 26000000)
2623                b43_radio_set(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0x2);
2624        else
2625                b43_radio_mask(dev, B2063_PLL_JTAG_PLL_XTAL_12, 0xFD);
2626
2627        if (val1 == 45)
2628                b43_radio_set(dev, B2063_PLL_JTAG_PLL_VCO1, 0x2);
2629        else
2630                b43_radio_mask(dev, B2063_PLL_JTAG_PLL_VCO1, 0xFD);
2631
2632        b43_radio_set(dev, B2063_PLL_SP2, 0x3);
2633        udelay(1);
2634        b43_radio_mask(dev, B2063_PLL_SP2, 0xFFFC);
2635        lpphy_b2063_vco_calib(dev);
2636        b43_radio_write(dev, B2063_COMM15, old_comm15);
2637
2638        return 0;
2639}
2640
2641static int b43_lpphy_op_switch_channel(struct b43_wldev *dev,
2642                                       unsigned int new_channel)
2643{
2644        struct b43_phy_lp *lpphy = dev->phy.lp;
2645        int err;
2646
2647        if (dev->phy.radio_ver == 0x2063) {
2648                err = lpphy_b2063_tune(dev, new_channel);
2649                if (err)
2650                        return err;
2651        } else {
2652                err = lpphy_b2062_tune(dev, new_channel);
2653                if (err)
2654                        return err;
2655                lpphy_set_analog_filter(dev, new_channel);
2656                lpphy_adjust_gain_table(dev, channel2freq_lp(new_channel));
2657        }
2658
2659        lpphy->channel = new_channel;
2660        b43_write16(dev, B43_MMIO_CHANNEL, new_channel);
2661
2662        return 0;
2663}
2664
2665static int b43_lpphy_op_init(struct b43_wldev *dev)
2666{
2667        int err;
2668
2669        if (dev->dev->bus_type != B43_BUS_SSB) {
2670                b43err(dev->wl, "LP-PHY is supported only on SSB!\n");
2671                return -EOPNOTSUPP;
2672        }
2673
2674        lpphy_read_band_sprom(dev); //FIXME should this be in prepare_structs?
2675        lpphy_baseband_init(dev);
2676        lpphy_radio_init(dev);
2677        lpphy_calibrate_rc(dev);
2678        err = b43_lpphy_op_switch_channel(dev, 7);
2679        if (err) {
2680                b43dbg(dev->wl, "Switch to channel 7 failed, error = %d.\n",
2681                       err);
2682        }
2683        lpphy_tx_pctl_init(dev);
2684        lpphy_calibration(dev);
2685        //TODO ACI init
2686
2687        return 0;
2688}
2689
2690static void b43_lpphy_op_adjust_txpower(struct b43_wldev *dev)
2691{
2692        //TODO
2693}
2694
2695static enum b43_txpwr_result b43_lpphy_op_recalc_txpower(struct b43_wldev *dev,
2696                                                         bool ignore_tssi)
2697{
2698        //TODO
2699        return B43_TXPWR_RES_DONE;
2700}
2701
2702static void b43_lpphy_op_switch_analog(struct b43_wldev *dev, bool on)
2703{
2704       if (on) {
2705               b43_phy_mask(dev, B43_LPPHY_AFE_CTL_OVR, 0xfff8);
2706       } else {
2707               b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVRVAL, 0x0007);
2708               b43_phy_set(dev, B43_LPPHY_AFE_CTL_OVR, 0x0007);
2709       }
2710}
2711
2712static void b43_lpphy_op_pwork_15sec(struct b43_wldev *dev)
2713{
2714        //TODO
2715}
2716
2717const struct b43_phy_operations b43_phyops_lp = {
2718        .allocate               = b43_lpphy_op_allocate,
2719        .free                   = b43_lpphy_op_free,
2720        .prepare_structs        = b43_lpphy_op_prepare_structs,
2721        .init                   = b43_lpphy_op_init,
2722        .phy_read               = b43_lpphy_op_read,
2723        .phy_write              = b43_lpphy_op_write,
2724        .phy_maskset            = b43_lpphy_op_maskset,
2725        .radio_read             = b43_lpphy_op_radio_read,
2726        .radio_write            = b43_lpphy_op_radio_write,
2727        .software_rfkill        = b43_lpphy_op_software_rfkill,
2728        .switch_analog          = b43_lpphy_op_switch_analog,
2729        .switch_channel         = b43_lpphy_op_switch_channel,
2730        .get_default_chan       = b43_lpphy_op_get_default_chan,
2731        .set_rx_antenna         = b43_lpphy_op_set_rx_antenna,
2732        .recalc_txpower         = b43_lpphy_op_recalc_txpower,
2733        .adjust_txpower         = b43_lpphy_op_adjust_txpower,
2734        .pwork_15sec            = b43_lpphy_op_pwork_15sec,
2735        .pwork_60sec            = lpphy_calibration,
2736};
2737