linux/drivers/net/wireless/broadcom/b43/wa.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0-or-later
   2/*
   3
   4  Broadcom B43 wireless driver
   5
   6  PHY workarounds.
   7
   8  Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it>
   9  Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
  10
  11
  12*/
  13
  14#include "b43.h"
  15#include "main.h"
  16#include "tables.h"
  17#include "phy_common.h"
  18#include "wa.h"
  19
  20void b43_wa_initgains(struct b43_wldev *dev)
  21{
  22        struct b43_phy *phy = &dev->phy;
  23
  24        b43_phy_write(dev, B43_PHY_LNAHPFCTL, 0x1FF9);
  25        b43_phy_mask(dev, B43_PHY_LPFGAINCTL, 0xFF0F);
  26        if (phy->rev <= 2)
  27                b43_ofdmtab_write16(dev, B43_OFDMTAB_LPFGAIN, 0, 0x1FBF);
  28        b43_radio_write16(dev, 0x0002, 0x1FBF);
  29
  30        b43_phy_write(dev, 0x0024, 0x4680);
  31        b43_phy_write(dev, 0x0020, 0x0003);
  32        b43_phy_write(dev, 0x001D, 0x0F40);
  33        b43_phy_write(dev, 0x001F, 0x1C00);
  34        if (phy->rev <= 3)
  35                b43_phy_maskset(dev, 0x002A, 0x00FF, 0x0400);
  36        else if (phy->rev == 5) {
  37                b43_phy_maskset(dev, 0x002A, 0x00FF, 0x1A00);
  38                b43_phy_write(dev, 0x00CC, 0x2121);
  39        }
  40        if (phy->rev >= 3)
  41                b43_phy_write(dev, 0x00BA, 0x3ED5);
  42}
  43
  44static void b43_wa_rssi_lt(struct b43_wldev *dev) /* RSSI lookup table */
  45{
  46        int i;
  47
  48        if (0 /* FIXME: For APHY.rev=2 this might be needed */) {
  49                for (i = 0; i < 8; i++)
  50                        b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i + 8);
  51                for (i = 8; i < 16; i++)
  52                        b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i - 8);
  53        } else {
  54                for (i = 0; i < 64; i++)
  55                        b43_ofdmtab_write16(dev, B43_OFDMTAB_RSSI, i, i);
  56        }
  57}
  58
  59static void b43_wa_analog(struct b43_wldev *dev)
  60{
  61        u16 ofdmrev;
  62
  63        ofdmrev = b43_phy_read(dev, B43_PHY_VERSION_OFDM) & B43_PHYVER_VERSION;
  64        if (ofdmrev > 2) {
  65                b43_phy_write(dev, B43_PHY_PWRDOWN, 0x1000);
  66        } else {
  67                b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 3, 0x1044);
  68                b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 4, 0x7201);
  69                b43_ofdmtab_write16(dev, B43_OFDMTAB_DAC, 6, 0x0040);
  70        }
  71}
  72
  73static void b43_wa_fft(struct b43_wldev *dev) /* Fine frequency table */
  74{
  75        int i;
  76
  77        for (i = 0; i < B43_TAB_FINEFREQG_SIZE; i++)
  78                b43_ofdmtab_write16(dev, B43_OFDMTAB_DACRFPABB, i,
  79                                    b43_tab_finefreqg[i]);
  80}
  81
  82static void b43_wa_nft(struct b43_wldev *dev) /* Noise figure table */
  83{
  84        struct b43_phy *phy = &dev->phy;
  85        int i;
  86
  87        if (phy->rev == 1)
  88                for (i = 0; i < B43_TAB_NOISEG1_SIZE; i++)
  89                        b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i,
  90                                            b43_tab_noiseg1[i]);
  91        else
  92                for (i = 0; i < B43_TAB_NOISEG2_SIZE; i++)
  93                        b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, i,
  94                                            b43_tab_noiseg2[i]);
  95}
  96
  97static void b43_wa_rt(struct b43_wldev *dev) /* Rotor table */
  98{
  99        int i;
 100
 101        for (i = 0; i < B43_TAB_ROTOR_SIZE; i++)
 102                b43_ofdmtab_write32(dev, B43_OFDMTAB_ROTOR, i, b43_tab_rotor[i]);
 103}
 104
 105static void b43_write_nst(struct b43_wldev *dev, const u16 *nst)
 106{
 107        int i;
 108
 109        for (i = 0; i < B43_TAB_NOISESCALE_SIZE; i++)
 110                b43_ofdmtab_write16(dev, B43_OFDMTAB_NOISESCALE, i, nst[i]);
 111}
 112
 113static void b43_wa_nst(struct b43_wldev *dev) /* Noise scale table */
 114{
 115        struct b43_phy *phy = &dev->phy;
 116
 117        if (phy->rev >= 6) {
 118                if (b43_phy_read(dev, B43_PHY_ENCORE) & B43_PHY_ENCORE_EN)
 119                        b43_write_nst(dev, b43_tab_noisescaleg3);
 120                else
 121                        b43_write_nst(dev, b43_tab_noisescaleg2);
 122        } else {
 123                b43_write_nst(dev, b43_tab_noisescaleg1);
 124        }
 125}
 126
 127static void b43_wa_art(struct b43_wldev *dev) /* ADV retard table */
 128{
 129        int i;
 130
 131        for (i = 0; i < B43_TAB_RETARD_SIZE; i++)
 132                        b43_ofdmtab_write32(dev, B43_OFDMTAB_ADVRETARD,
 133                                i, b43_tab_retard[i]);
 134}
 135
 136static void b43_wa_msst(struct b43_wldev *dev) /* Min sigma square table */
 137{
 138        struct b43_phy *phy = &dev->phy;
 139        int i;
 140        const u16 *tab;
 141
 142        if (phy->type == B43_PHYTYPE_G) {
 143                tab = b43_tab_sigmasqr2;
 144        } else {
 145                B43_WARN_ON(1);
 146                return;
 147        }
 148
 149        for (i = 0; i < B43_TAB_SIGMASQR_SIZE; i++) {
 150                b43_ofdmtab_write16(dev, B43_OFDMTAB_MINSIGSQ,
 151                                        i, tab[i]);
 152        }
 153}
 154
 155static void b43_wa_crs_ed(struct b43_wldev *dev)
 156{
 157        struct b43_phy *phy = &dev->phy;
 158
 159        if (phy->rev == 1) {
 160                b43_phy_write(dev, B43_PHY_CRSTHRES1_R1, 0x4F19);
 161        } else if (phy->rev == 2) {
 162                b43_phy_write(dev, B43_PHY_CRSTHRES1, 0x1861);
 163                b43_phy_write(dev, B43_PHY_CRSTHRES2, 0x0271);
 164                b43_phy_set(dev, B43_PHY_ANTDWELL, 0x0800);
 165        } else {
 166                b43_phy_write(dev, B43_PHY_CRSTHRES1, 0x0098);
 167                b43_phy_write(dev, B43_PHY_CRSTHRES2, 0x0070);
 168                b43_phy_write(dev, B43_PHY_OFDM(0xC9), 0x0080);
 169                b43_phy_set(dev, B43_PHY_ANTDWELL, 0x0800);
 170        }
 171}
 172
 173static void b43_wa_crs_thr(struct b43_wldev *dev)
 174{
 175        b43_phy_maskset(dev, B43_PHY_CRS0, ~0x03C0, 0xD000);
 176}
 177
 178static void b43_wa_crs_blank(struct b43_wldev *dev)
 179{
 180        b43_phy_write(dev, B43_PHY_OFDM(0x2C), 0x005A);
 181}
 182
 183static void b43_wa_cck_shiftbits(struct b43_wldev *dev)
 184{
 185        b43_phy_write(dev, B43_PHY_CCKSHIFTBITS, 0x0026);
 186}
 187
 188static void b43_wa_wrssi_offset(struct b43_wldev *dev)
 189{
 190        int i;
 191
 192        if (dev->phy.rev == 1) {
 193                for (i = 0; i < 16; i++) {
 194                        b43_ofdmtab_write16(dev, B43_OFDMTAB_WRSSI_R1,
 195                                                i, 0x0020);
 196                }
 197        } else {
 198                for (i = 0; i < 32; i++) {
 199                        b43_ofdmtab_write16(dev, B43_OFDMTAB_WRSSI,
 200                                                i, 0x0820);
 201                }
 202        }
 203}
 204
 205static void b43_wa_txpuoff_rxpuon(struct b43_wldev *dev)
 206{
 207        b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_0F, 2, 15);
 208        b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_0F, 3, 20);
 209}
 210
 211static void b43_wa_altagc(struct b43_wldev *dev)
 212{
 213        struct b43_phy *phy = &dev->phy;
 214
 215        if (phy->rev == 1) {
 216                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 0, 254);
 217                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 1, 13);
 218                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 2, 19);
 219                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1_R1, 3, 25);
 220                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 0, 0x2710);
 221                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 1, 0x9B83);
 222                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 2, 0x9B83);
 223                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC2, 3, 0x0F8D);
 224                b43_phy_write(dev, B43_PHY_LMS, 4);
 225        } else {
 226                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 0, 254);
 227                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 1, 13);
 228                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 2, 19);
 229                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC1, 3, 25);
 230        }
 231
 232        b43_phy_maskset(dev, B43_PHY_CCKSHIFTBITS_WA, 0x00FF, 0x5700);
 233        b43_phy_maskset(dev, B43_PHY_OFDM(0x1A), ~0x007F, 0x000F);
 234        b43_phy_maskset(dev, B43_PHY_OFDM(0x1A), ~0x3F80, 0x2B80);
 235        b43_phy_maskset(dev, B43_PHY_ANTWRSETT, 0xF0FF, 0x0300);
 236        b43_radio_set(dev, 0x7A, 0x0008);
 237        b43_phy_maskset(dev, B43_PHY_N1P1GAIN, ~0x000F, 0x0008);
 238        b43_phy_maskset(dev, B43_PHY_P1P2GAIN, ~0x0F00, 0x0600);
 239        b43_phy_maskset(dev, B43_PHY_N1N2GAIN, ~0x0F00, 0x0700);
 240        b43_phy_maskset(dev, B43_PHY_N1P1GAIN, ~0x0F00, 0x0100);
 241        if (phy->rev == 1) {
 242                b43_phy_maskset(dev, B43_PHY_N1N2GAIN, ~0x000F, 0x0007);
 243        }
 244        b43_phy_maskset(dev, B43_PHY_OFDM(0x88), ~0x00FF, 0x001C);
 245        b43_phy_maskset(dev, B43_PHY_OFDM(0x88), ~0x3F00, 0x0200);
 246        b43_phy_maskset(dev, B43_PHY_OFDM(0x96), ~0x00FF, 0x001C);
 247        b43_phy_maskset(dev, B43_PHY_OFDM(0x89), ~0x00FF, 0x0020);
 248        b43_phy_maskset(dev, B43_PHY_OFDM(0x89), ~0x3F00, 0x0200);
 249        b43_phy_maskset(dev, B43_PHY_OFDM(0x82), ~0x00FF, 0x002E);
 250        b43_phy_maskset(dev, B43_PHY_OFDM(0x96), 0x00FF, 0x1A00);
 251        b43_phy_maskset(dev, B43_PHY_OFDM(0x81), ~0x00FF, 0x0028);
 252        b43_phy_maskset(dev, B43_PHY_OFDM(0x81), 0x00FF, 0x2C00);
 253        if (phy->rev == 1) {
 254                b43_phy_write(dev, B43_PHY_PEAK_COUNT, 0x092B);
 255                b43_phy_maskset(dev, B43_PHY_OFDM(0x1B), ~0x001E, 0x0002);
 256        } else {
 257                b43_phy_mask(dev, B43_PHY_OFDM(0x1B), ~0x001E);
 258                b43_phy_write(dev, B43_PHY_OFDM(0x1F), 0x287A);
 259                b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, ~0x000F, 0x0004);
 260                if (phy->rev >= 6) {
 261                        b43_phy_write(dev, B43_PHY_OFDM(0x22), 0x287A);
 262                        b43_phy_maskset(dev, B43_PHY_LPFGAINCTL, 0x0FFF, 0x3000);
 263                }
 264        }
 265        b43_phy_maskset(dev, B43_PHY_DIVSRCHIDX, 0x8080, 0x7874);
 266        b43_phy_write(dev, B43_PHY_OFDM(0x8E), 0x1C00);
 267        if (phy->rev == 1) {
 268                b43_phy_maskset(dev, B43_PHY_DIVP1P2GAIN, ~0x0F00, 0x0600);
 269                b43_phy_write(dev, B43_PHY_OFDM(0x8B), 0x005E);
 270                b43_phy_maskset(dev, B43_PHY_ANTWRSETT, ~0x00FF, 0x001E);
 271                b43_phy_write(dev, B43_PHY_OFDM(0x8D), 0x0002);
 272                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 0, 0);
 273                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 1, 7);
 274                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 2, 16);
 275                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3_R1, 3, 28);
 276        } else {
 277                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 0, 0);
 278                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 1, 7);
 279                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 2, 16);
 280                b43_ofdmtab_write16(dev, B43_OFDMTAB_AGC3, 3, 28);
 281        }
 282        if (phy->rev >= 6) {
 283                b43_phy_mask(dev, B43_PHY_OFDM(0x26), ~0x0003);
 284                b43_phy_mask(dev, B43_PHY_OFDM(0x26), ~0x1000);
 285        }
 286        b43_phy_read(dev, B43_PHY_VERSION_OFDM); /* Dummy read */
 287}
 288
 289static void b43_wa_tr_ltov(struct b43_wldev *dev) /* TR Lookup Table Original Values */
 290{
 291        b43_gtab_write(dev, B43_GTAB_ORIGTR, 0, 0x7654);
 292}
 293
 294static void b43_wa_cpll_nonpilot(struct b43_wldev *dev)
 295{
 296        b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_11, 0, 0);
 297        b43_ofdmtab_write16(dev, B43_OFDMTAB_UNKNOWN_11, 1, 0);
 298}
 299
 300static void b43_wa_boards_g(struct b43_wldev *dev)
 301{
 302        struct ssb_sprom *sprom = dev->dev->bus_sprom;
 303        struct b43_phy *phy = &dev->phy;
 304
 305        if (dev->dev->board_vendor != SSB_BOARDVENDOR_BCM ||
 306            dev->dev->board_type != SSB_BOARD_BU4306 ||
 307            dev->dev->board_rev != 0x17) {
 308                if (phy->rev < 2) {
 309                        b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 1, 0x0002);
 310                        b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX_R1, 2, 0x0001);
 311                } else {
 312                        b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 1, 0x0002);
 313                        b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 2, 0x0001);
 314                        if ((sprom->boardflags_lo & B43_BFL_EXTLNA) &&
 315                            (phy->rev >= 7)) {
 316                                b43_phy_mask(dev, B43_PHY_EXTG(0x11), 0xF7FF);
 317                                b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0020, 0x0001);
 318                                b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0021, 0x0001);
 319                                b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0022, 0x0001);
 320                                b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0023, 0x0000);
 321                                b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0000, 0x0000);
 322                                b43_ofdmtab_write16(dev, B43_OFDMTAB_GAINX, 0x0003, 0x0002);
 323                        }
 324                }
 325        }
 326        if (sprom->boardflags_lo & B43_BFL_FEM) {
 327                b43_phy_write(dev, B43_PHY_GTABCTL, 0x3120);
 328                b43_phy_write(dev, B43_PHY_GTABDATA, 0xC480);
 329        }
 330}
 331
 332void b43_wa_all(struct b43_wldev *dev)
 333{
 334        struct b43_phy *phy = &dev->phy;
 335
 336        if (phy->type == B43_PHYTYPE_G) {
 337                switch (phy->rev) {
 338                case 1://XXX review rev1
 339                        b43_wa_crs_ed(dev);
 340                        b43_wa_crs_thr(dev);
 341                        b43_wa_crs_blank(dev);
 342                        b43_wa_cck_shiftbits(dev);
 343                        b43_wa_fft(dev);
 344                        b43_wa_nft(dev);
 345                        b43_wa_rt(dev);
 346                        b43_wa_nst(dev);
 347                        b43_wa_art(dev);
 348                        b43_wa_wrssi_offset(dev);
 349                        b43_wa_altagc(dev);
 350                        break;
 351                case 2:
 352                case 6:
 353                case 7:
 354                case 8:
 355                case 9:
 356                        b43_wa_tr_ltov(dev);
 357                        b43_wa_crs_ed(dev);
 358                        b43_wa_rssi_lt(dev);
 359                        b43_wa_nft(dev);
 360                        b43_wa_nst(dev);
 361                        b43_wa_msst(dev);
 362                        b43_wa_wrssi_offset(dev);
 363                        b43_wa_altagc(dev);
 364                        b43_wa_analog(dev);
 365                        b43_wa_txpuoff_rxpuon(dev);
 366                        break;
 367                default:
 368                        B43_WARN_ON(1);
 369                }
 370                b43_wa_boards_g(dev);
 371        } else { /* No N PHY support so far, LP PHY is in phy_lp.c */
 372                B43_WARN_ON(1);
 373        }
 374
 375        b43_wa_cpll_nonpilot(dev);
 376}
 377