wa.c (10890B)
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}