377 lines · c
1// SPDX-License-Identifier: GPL-2.0-or-later2/*3 4 Broadcom B43 wireless driver5 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 else92 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 else121 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 rev1339 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