phy.c (65200B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 4 Broadcom B43legacy wireless driver 5 6 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>, 7 Stefano Brivio <stefano.brivio@polimi.it> 8 Michael Buesch <m@bues.ch> 9 Danny van Dyk <kugelfang@gentoo.org> 10 Andreas Jaggi <andreas.jaggi@waterwave.ch> 11 Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net> 12 13 Some parts of the code in this file are derived from the ipw2200 14 driver Copyright(c) 2003 - 2004 Intel Corporation. 15 16 17*/ 18 19#include <linux/delay.h> 20#include <linux/pci.h> 21#include <linux/sched.h> 22#include <linux/slab.h> 23#include <linux/types.h> 24 25#include "b43legacy.h" 26#include "phy.h" 27#include "main.h" 28#include "radio.h" 29#include "ilt.h" 30 31 32static const s8 b43legacy_tssi2dbm_b_table[] = { 33 0x4D, 0x4C, 0x4B, 0x4A, 34 0x4A, 0x49, 0x48, 0x47, 35 0x47, 0x46, 0x45, 0x45, 36 0x44, 0x43, 0x42, 0x42, 37 0x41, 0x40, 0x3F, 0x3E, 38 0x3D, 0x3C, 0x3B, 0x3A, 39 0x39, 0x38, 0x37, 0x36, 40 0x35, 0x34, 0x32, 0x31, 41 0x30, 0x2F, 0x2D, 0x2C, 42 0x2B, 0x29, 0x28, 0x26, 43 0x25, 0x23, 0x21, 0x1F, 44 0x1D, 0x1A, 0x17, 0x14, 45 0x10, 0x0C, 0x06, 0x00, 46 -7, -7, -7, -7, 47 -7, -7, -7, -7, 48 -7, -7, -7, -7, 49}; 50 51static const s8 b43legacy_tssi2dbm_g_table[] = { 52 77, 77, 77, 76, 53 76, 76, 75, 75, 54 74, 74, 73, 73, 55 73, 72, 72, 71, 56 71, 70, 70, 69, 57 68, 68, 67, 67, 58 66, 65, 65, 64, 59 63, 63, 62, 61, 60 60, 59, 58, 57, 61 56, 55, 54, 53, 62 52, 50, 49, 47, 63 45, 43, 40, 37, 64 33, 28, 22, 14, 65 5, -7, -20, -20, 66 -20, -20, -20, -20, 67 -20, -20, -20, -20, 68}; 69 70static void b43legacy_phy_initg(struct b43legacy_wldev *dev); 71 72/* Lock the PHY registers against concurrent access from the microcode. 73 * This lock is nonrecursive. */ 74void b43legacy_phy_lock(struct b43legacy_wldev *dev) 75{ 76#if B43legacy_DEBUG 77 B43legacy_WARN_ON(dev->phy.phy_locked); 78 dev->phy.phy_locked = 1; 79#endif 80 81 if (dev->dev->id.revision < 3) { 82 b43legacy_mac_suspend(dev); 83 } else { 84 if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP)) 85 b43legacy_power_saving_ctl_bits(dev, -1, 1); 86 } 87} 88 89void b43legacy_phy_unlock(struct b43legacy_wldev *dev) 90{ 91#if B43legacy_DEBUG 92 B43legacy_WARN_ON(!dev->phy.phy_locked); 93 dev->phy.phy_locked = 0; 94#endif 95 96 if (dev->dev->id.revision < 3) { 97 b43legacy_mac_enable(dev); 98 } else { 99 if (!b43legacy_is_mode(dev->wl, NL80211_IFTYPE_AP)) 100 b43legacy_power_saving_ctl_bits(dev, -1, -1); 101 } 102} 103 104u16 b43legacy_phy_read(struct b43legacy_wldev *dev, u16 offset) 105{ 106 b43legacy_write16(dev, B43legacy_MMIO_PHY_CONTROL, offset); 107 return b43legacy_read16(dev, B43legacy_MMIO_PHY_DATA); 108} 109 110void b43legacy_phy_write(struct b43legacy_wldev *dev, u16 offset, u16 val) 111{ 112 b43legacy_write16(dev, B43legacy_MMIO_PHY_CONTROL, offset); 113 b43legacy_write16(dev, B43legacy_MMIO_PHY_DATA, val); 114} 115 116void b43legacy_phy_calibrate(struct b43legacy_wldev *dev) 117{ 118 struct b43legacy_phy *phy = &dev->phy; 119 120 b43legacy_read32(dev, B43legacy_MMIO_MACCTL); /* Dummy read. */ 121 if (phy->calibrated) 122 return; 123 if (phy->type == B43legacy_PHYTYPE_G && phy->rev == 1) { 124 b43legacy_wireless_core_reset(dev, 0); 125 b43legacy_phy_initg(dev); 126 b43legacy_wireless_core_reset(dev, B43legacy_TMSLOW_GMODE); 127 } 128 phy->calibrated = 1; 129} 130 131/* initialize B PHY power control 132 * as described in https://bcm-specs.sipsolutions.net/InitPowerControl 133 */ 134static void b43legacy_phy_init_pctl(struct b43legacy_wldev *dev) 135{ 136 struct b43legacy_phy *phy = &dev->phy; 137 u16 saved_batt = 0; 138 u16 saved_ratt = 0; 139 u16 saved_txctl1 = 0; 140 int must_reset_txpower = 0; 141 142 B43legacy_BUG_ON(!(phy->type == B43legacy_PHYTYPE_B || 143 phy->type == B43legacy_PHYTYPE_G)); 144 if (is_bcm_board_vendor(dev) && 145 (dev->dev->bus->boardinfo.type == 0x0416)) 146 return; 147 148 b43legacy_phy_write(dev, 0x0028, 0x8018); 149 b43legacy_write16(dev, 0x03E6, b43legacy_read16(dev, 0x03E6) & 0xFFDF); 150 151 if (phy->type == B43legacy_PHYTYPE_G) { 152 if (!phy->gmode) 153 return; 154 b43legacy_phy_write(dev, 0x047A, 0xC111); 155 } 156 if (phy->savedpctlreg != 0xFFFF) 157 return; 158#ifdef CONFIG_B43LEGACY_DEBUG 159 if (phy->manual_txpower_control) 160 return; 161#endif 162 163 if (phy->type == B43legacy_PHYTYPE_B && 164 phy->rev >= 2 && 165 phy->radio_ver == 0x2050) 166 b43legacy_radio_write16(dev, 0x0076, 167 b43legacy_radio_read16(dev, 0x0076) 168 | 0x0084); 169 else { 170 saved_batt = phy->bbatt; 171 saved_ratt = phy->rfatt; 172 saved_txctl1 = phy->txctl1; 173 if ((phy->radio_rev >= 6) && (phy->radio_rev <= 8) 174 && /*FIXME: incomplete specs for 5 < revision < 9 */ 0) 175 b43legacy_radio_set_txpower_bg(dev, 0xB, 0x1F, 0); 176 else 177 b43legacy_radio_set_txpower_bg(dev, 0xB, 9, 0); 178 must_reset_txpower = 1; 179 } 180 b43legacy_dummy_transmission(dev); 181 182 phy->savedpctlreg = b43legacy_phy_read(dev, B43legacy_PHY_G_PCTL); 183 184 if (must_reset_txpower) 185 b43legacy_radio_set_txpower_bg(dev, saved_batt, saved_ratt, 186 saved_txctl1); 187 else 188 b43legacy_radio_write16(dev, 0x0076, b43legacy_radio_read16(dev, 189 0x0076) & 0xFF7B); 190 b43legacy_radio_clear_tssi(dev); 191} 192 193static void b43legacy_phy_agcsetup(struct b43legacy_wldev *dev) 194{ 195 struct b43legacy_phy *phy = &dev->phy; 196 u16 offset = 0x0000; 197 198 if (phy->rev == 1) 199 offset = 0x4C00; 200 201 b43legacy_ilt_write(dev, offset, 0x00FE); 202 b43legacy_ilt_write(dev, offset + 1, 0x000D); 203 b43legacy_ilt_write(dev, offset + 2, 0x0013); 204 b43legacy_ilt_write(dev, offset + 3, 0x0019); 205 206 if (phy->rev == 1) { 207 b43legacy_ilt_write(dev, 0x1800, 0x2710); 208 b43legacy_ilt_write(dev, 0x1801, 0x9B83); 209 b43legacy_ilt_write(dev, 0x1802, 0x9B83); 210 b43legacy_ilt_write(dev, 0x1803, 0x0F8D); 211 b43legacy_phy_write(dev, 0x0455, 0x0004); 212 } 213 214 b43legacy_phy_write(dev, 0x04A5, (b43legacy_phy_read(dev, 0x04A5) 215 & 0x00FF) | 0x5700); 216 b43legacy_phy_write(dev, 0x041A, (b43legacy_phy_read(dev, 0x041A) 217 & 0xFF80) | 0x000F); 218 b43legacy_phy_write(dev, 0x041A, (b43legacy_phy_read(dev, 0x041A) 219 & 0xC07F) | 0x2B80); 220 b43legacy_phy_write(dev, 0x048C, (b43legacy_phy_read(dev, 0x048C) 221 & 0xF0FF) | 0x0300); 222 223 b43legacy_radio_write16(dev, 0x007A, 224 b43legacy_radio_read16(dev, 0x007A) 225 | 0x0008); 226 227 b43legacy_phy_write(dev, 0x04A0, (b43legacy_phy_read(dev, 0x04A0) 228 & 0xFFF0) | 0x0008); 229 b43legacy_phy_write(dev, 0x04A1, (b43legacy_phy_read(dev, 0x04A1) 230 & 0xF0FF) | 0x0600); 231 b43legacy_phy_write(dev, 0x04A2, (b43legacy_phy_read(dev, 0x04A2) 232 & 0xF0FF) | 0x0700); 233 b43legacy_phy_write(dev, 0x04A0, (b43legacy_phy_read(dev, 0x04A0) 234 & 0xF0FF) | 0x0100); 235 236 if (phy->rev == 1) 237 b43legacy_phy_write(dev, 0x04A2, 238 (b43legacy_phy_read(dev, 0x04A2) 239 & 0xFFF0) | 0x0007); 240 241 b43legacy_phy_write(dev, 0x0488, (b43legacy_phy_read(dev, 0x0488) 242 & 0xFF00) | 0x001C); 243 b43legacy_phy_write(dev, 0x0488, (b43legacy_phy_read(dev, 0x0488) 244 & 0xC0FF) | 0x0200); 245 b43legacy_phy_write(dev, 0x0496, (b43legacy_phy_read(dev, 0x0496) 246 & 0xFF00) | 0x001C); 247 b43legacy_phy_write(dev, 0x0489, (b43legacy_phy_read(dev, 0x0489) 248 & 0xFF00) | 0x0020); 249 b43legacy_phy_write(dev, 0x0489, (b43legacy_phy_read(dev, 0x0489) 250 & 0xC0FF) | 0x0200); 251 b43legacy_phy_write(dev, 0x0482, (b43legacy_phy_read(dev, 0x0482) 252 & 0xFF00) | 0x002E); 253 b43legacy_phy_write(dev, 0x0496, (b43legacy_phy_read(dev, 0x0496) 254 & 0x00FF) | 0x1A00); 255 b43legacy_phy_write(dev, 0x0481, (b43legacy_phy_read(dev, 0x0481) 256 & 0xFF00) | 0x0028); 257 b43legacy_phy_write(dev, 0x0481, (b43legacy_phy_read(dev, 0x0481) 258 & 0x00FF) | 0x2C00); 259 260 if (phy->rev == 1) { 261 b43legacy_phy_write(dev, 0x0430, 0x092B); 262 b43legacy_phy_write(dev, 0x041B, 263 (b43legacy_phy_read(dev, 0x041B) 264 & 0xFFE1) | 0x0002); 265 } else { 266 b43legacy_phy_write(dev, 0x041B, 267 b43legacy_phy_read(dev, 0x041B) & 0xFFE1); 268 b43legacy_phy_write(dev, 0x041F, 0x287A); 269 b43legacy_phy_write(dev, 0x0420, 270 (b43legacy_phy_read(dev, 0x0420) 271 & 0xFFF0) | 0x0004); 272 } 273 274 if (phy->rev > 2) { 275 b43legacy_phy_write(dev, 0x0422, 0x287A); 276 b43legacy_phy_write(dev, 0x0420, 277 (b43legacy_phy_read(dev, 0x0420) 278 & 0x0FFF) | 0x3000); 279 } 280 281 b43legacy_phy_write(dev, 0x04A8, (b43legacy_phy_read(dev, 0x04A8) 282 & 0x8080) | 0x7874); 283 b43legacy_phy_write(dev, 0x048E, 0x1C00); 284 285 if (phy->rev == 1) { 286 b43legacy_phy_write(dev, 0x04AB, 287 (b43legacy_phy_read(dev, 0x04AB) 288 & 0xF0FF) | 0x0600); 289 b43legacy_phy_write(dev, 0x048B, 0x005E); 290 b43legacy_phy_write(dev, 0x048C, 291 (b43legacy_phy_read(dev, 0x048C) & 0xFF00) 292 | 0x001E); 293 b43legacy_phy_write(dev, 0x048D, 0x0002); 294 } 295 296 b43legacy_ilt_write(dev, offset + 0x0800, 0); 297 b43legacy_ilt_write(dev, offset + 0x0801, 7); 298 b43legacy_ilt_write(dev, offset + 0x0802, 16); 299 b43legacy_ilt_write(dev, offset + 0x0803, 28); 300 301 if (phy->rev >= 6) { 302 b43legacy_phy_write(dev, 0x0426, 303 (b43legacy_phy_read(dev, 0x0426) & 0xFFFC)); 304 b43legacy_phy_write(dev, 0x0426, 305 (b43legacy_phy_read(dev, 0x0426) & 0xEFFF)); 306 } 307} 308 309static void b43legacy_phy_setupg(struct b43legacy_wldev *dev) 310{ 311 struct b43legacy_phy *phy = &dev->phy; 312 u16 i; 313 314 B43legacy_BUG_ON(phy->type != B43legacy_PHYTYPE_G); 315 if (phy->rev == 1) { 316 b43legacy_phy_write(dev, 0x0406, 0x4F19); 317 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, 318 (b43legacy_phy_read(dev, 319 B43legacy_PHY_G_CRS) & 0xFC3F) | 0x0340); 320 b43legacy_phy_write(dev, 0x042C, 0x005A); 321 b43legacy_phy_write(dev, 0x0427, 0x001A); 322 323 for (i = 0; i < B43legacy_ILT_FINEFREQG_SIZE; i++) 324 b43legacy_ilt_write(dev, 0x5800 + i, 325 b43legacy_ilt_finefreqg[i]); 326 for (i = 0; i < B43legacy_ILT_NOISEG1_SIZE; i++) 327 b43legacy_ilt_write(dev, 0x1800 + i, 328 b43legacy_ilt_noiseg1[i]); 329 for (i = 0; i < B43legacy_ILT_ROTOR_SIZE; i++) 330 b43legacy_ilt_write32(dev, 0x2000 + i, 331 b43legacy_ilt_rotor[i]); 332 } else { 333 /* nrssi values are signed 6-bit values. Why 0x7654 here? */ 334 b43legacy_nrssi_hw_write(dev, 0xBA98, (s16)0x7654); 335 336 if (phy->rev == 2) { 337 b43legacy_phy_write(dev, 0x04C0, 0x1861); 338 b43legacy_phy_write(dev, 0x04C1, 0x0271); 339 } else if (phy->rev > 2) { 340 b43legacy_phy_write(dev, 0x04C0, 0x0098); 341 b43legacy_phy_write(dev, 0x04C1, 0x0070); 342 b43legacy_phy_write(dev, 0x04C9, 0x0080); 343 } 344 b43legacy_phy_write(dev, 0x042B, b43legacy_phy_read(dev, 345 0x042B) | 0x800); 346 347 for (i = 0; i < 64; i++) 348 b43legacy_ilt_write(dev, 0x4000 + i, i); 349 for (i = 0; i < B43legacy_ILT_NOISEG2_SIZE; i++) 350 b43legacy_ilt_write(dev, 0x1800 + i, 351 b43legacy_ilt_noiseg2[i]); 352 } 353 354 if (phy->rev <= 2) 355 for (i = 0; i < B43legacy_ILT_NOISESCALEG_SIZE; i++) 356 b43legacy_ilt_write(dev, 0x1400 + i, 357 b43legacy_ilt_noisescaleg1[i]); 358 else if ((phy->rev >= 7) && (b43legacy_phy_read(dev, 0x0449) & 0x0200)) 359 for (i = 0; i < B43legacy_ILT_NOISESCALEG_SIZE; i++) 360 b43legacy_ilt_write(dev, 0x1400 + i, 361 b43legacy_ilt_noisescaleg3[i]); 362 else 363 for (i = 0; i < B43legacy_ILT_NOISESCALEG_SIZE; i++) 364 b43legacy_ilt_write(dev, 0x1400 + i, 365 b43legacy_ilt_noisescaleg2[i]); 366 367 if (phy->rev == 2) 368 for (i = 0; i < B43legacy_ILT_SIGMASQR_SIZE; i++) 369 b43legacy_ilt_write(dev, 0x5000 + i, 370 b43legacy_ilt_sigmasqr1[i]); 371 else if ((phy->rev > 2) && (phy->rev <= 8)) 372 for (i = 0; i < B43legacy_ILT_SIGMASQR_SIZE; i++) 373 b43legacy_ilt_write(dev, 0x5000 + i, 374 b43legacy_ilt_sigmasqr2[i]); 375 376 if (phy->rev == 1) { 377 for (i = 0; i < B43legacy_ILT_RETARD_SIZE; i++) 378 b43legacy_ilt_write32(dev, 0x2400 + i, 379 b43legacy_ilt_retard[i]); 380 for (i = 4; i < 20; i++) 381 b43legacy_ilt_write(dev, 0x5400 + i, 0x0020); 382 b43legacy_phy_agcsetup(dev); 383 384 if (is_bcm_board_vendor(dev) && 385 (dev->dev->bus->boardinfo.type == 0x0416) && 386 (dev->dev->bus->sprom.board_rev == 0x0017)) 387 return; 388 389 b43legacy_ilt_write(dev, 0x5001, 0x0002); 390 b43legacy_ilt_write(dev, 0x5002, 0x0001); 391 } else { 392 for (i = 0; i <= 0x20; i++) 393 b43legacy_ilt_write(dev, 0x1000 + i, 0x0820); 394 b43legacy_phy_agcsetup(dev); 395 b43legacy_phy_read(dev, 0x0400); /* dummy read */ 396 b43legacy_phy_write(dev, 0x0403, 0x1000); 397 b43legacy_ilt_write(dev, 0x3C02, 0x000F); 398 b43legacy_ilt_write(dev, 0x3C03, 0x0014); 399 400 if (is_bcm_board_vendor(dev) && 401 (dev->dev->bus->boardinfo.type == 0x0416) && 402 (dev->dev->bus->sprom.board_rev == 0x0017)) 403 return; 404 405 b43legacy_ilt_write(dev, 0x0401, 0x0002); 406 b43legacy_ilt_write(dev, 0x0402, 0x0001); 407 } 408} 409 410/* Initialize the APHY portion of a GPHY. */ 411static void b43legacy_phy_inita(struct b43legacy_wldev *dev) 412{ 413 414 might_sleep(); 415 416 b43legacy_phy_setupg(dev); 417 if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_PACTRL) 418 b43legacy_phy_write(dev, 0x046E, 0x03CF); 419} 420 421static void b43legacy_phy_initb2(struct b43legacy_wldev *dev) 422{ 423 struct b43legacy_phy *phy = &dev->phy; 424 u16 offset; 425 int val; 426 427 b43legacy_write16(dev, 0x03EC, 0x3F22); 428 b43legacy_phy_write(dev, 0x0020, 0x301C); 429 b43legacy_phy_write(dev, 0x0026, 0x0000); 430 b43legacy_phy_write(dev, 0x0030, 0x00C6); 431 b43legacy_phy_write(dev, 0x0088, 0x3E00); 432 val = 0x3C3D; 433 for (offset = 0x0089; offset < 0x00A7; offset++) { 434 b43legacy_phy_write(dev, offset, val); 435 val -= 0x0202; 436 } 437 b43legacy_phy_write(dev, 0x03E4, 0x3000); 438 b43legacy_radio_selectchannel(dev, phy->channel, 0); 439 if (phy->radio_ver != 0x2050) { 440 b43legacy_radio_write16(dev, 0x0075, 0x0080); 441 b43legacy_radio_write16(dev, 0x0079, 0x0081); 442 } 443 b43legacy_radio_write16(dev, 0x0050, 0x0020); 444 b43legacy_radio_write16(dev, 0x0050, 0x0023); 445 if (phy->radio_ver == 0x2050) { 446 b43legacy_radio_write16(dev, 0x0050, 0x0020); 447 b43legacy_radio_write16(dev, 0x005A, 0x0070); 448 b43legacy_radio_write16(dev, 0x005B, 0x007B); 449 b43legacy_radio_write16(dev, 0x005C, 0x00B0); 450 b43legacy_radio_write16(dev, 0x007A, 0x000F); 451 b43legacy_phy_write(dev, 0x0038, 0x0677); 452 b43legacy_radio_init2050(dev); 453 } 454 b43legacy_phy_write(dev, 0x0014, 0x0080); 455 b43legacy_phy_write(dev, 0x0032, 0x00CA); 456 b43legacy_phy_write(dev, 0x0032, 0x00CC); 457 b43legacy_phy_write(dev, 0x0035, 0x07C2); 458 b43legacy_phy_lo_b_measure(dev); 459 b43legacy_phy_write(dev, 0x0026, 0xCC00); 460 if (phy->radio_ver != 0x2050) 461 b43legacy_phy_write(dev, 0x0026, 0xCE00); 462 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 0x1000); 463 b43legacy_phy_write(dev, 0x002A, 0x88A3); 464 if (phy->radio_ver != 0x2050) 465 b43legacy_phy_write(dev, 0x002A, 0x88C2); 466 b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF); 467 b43legacy_phy_init_pctl(dev); 468} 469 470static void b43legacy_phy_initb4(struct b43legacy_wldev *dev) 471{ 472 struct b43legacy_phy *phy = &dev->phy; 473 u16 offset; 474 u16 val; 475 476 b43legacy_write16(dev, 0x03EC, 0x3F22); 477 b43legacy_phy_write(dev, 0x0020, 0x301C); 478 b43legacy_phy_write(dev, 0x0026, 0x0000); 479 b43legacy_phy_write(dev, 0x0030, 0x00C6); 480 b43legacy_phy_write(dev, 0x0088, 0x3E00); 481 val = 0x3C3D; 482 for (offset = 0x0089; offset < 0x00A7; offset++) { 483 b43legacy_phy_write(dev, offset, val); 484 val -= 0x0202; 485 } 486 b43legacy_phy_write(dev, 0x03E4, 0x3000); 487 b43legacy_radio_selectchannel(dev, phy->channel, 0); 488 if (phy->radio_ver != 0x2050) { 489 b43legacy_radio_write16(dev, 0x0075, 0x0080); 490 b43legacy_radio_write16(dev, 0x0079, 0x0081); 491 } 492 b43legacy_radio_write16(dev, 0x0050, 0x0020); 493 b43legacy_radio_write16(dev, 0x0050, 0x0023); 494 if (phy->radio_ver == 0x2050) { 495 b43legacy_radio_write16(dev, 0x0050, 0x0020); 496 b43legacy_radio_write16(dev, 0x005A, 0x0070); 497 b43legacy_radio_write16(dev, 0x005B, 0x007B); 498 b43legacy_radio_write16(dev, 0x005C, 0x00B0); 499 b43legacy_radio_write16(dev, 0x007A, 0x000F); 500 b43legacy_phy_write(dev, 0x0038, 0x0677); 501 b43legacy_radio_init2050(dev); 502 } 503 b43legacy_phy_write(dev, 0x0014, 0x0080); 504 b43legacy_phy_write(dev, 0x0032, 0x00CA); 505 if (phy->radio_ver == 0x2050) 506 b43legacy_phy_write(dev, 0x0032, 0x00E0); 507 b43legacy_phy_write(dev, 0x0035, 0x07C2); 508 509 b43legacy_phy_lo_b_measure(dev); 510 511 b43legacy_phy_write(dev, 0x0026, 0xCC00); 512 if (phy->radio_ver == 0x2050) 513 b43legacy_phy_write(dev, 0x0026, 0xCE00); 514 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 0x1100); 515 b43legacy_phy_write(dev, 0x002A, 0x88A3); 516 if (phy->radio_ver == 0x2050) 517 b43legacy_phy_write(dev, 0x002A, 0x88C2); 518 b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF); 519 if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI) { 520 b43legacy_calc_nrssi_slope(dev); 521 b43legacy_calc_nrssi_threshold(dev); 522 } 523 b43legacy_phy_init_pctl(dev); 524} 525 526static void b43legacy_phy_initb5(struct b43legacy_wldev *dev) 527{ 528 struct b43legacy_phy *phy = &dev->phy; 529 u16 offset; 530 u16 value; 531 u8 old_channel; 532 533 if (phy->analog == 1) 534 b43legacy_radio_write16(dev, 0x007A, 535 b43legacy_radio_read16(dev, 0x007A) 536 | 0x0050); 537 if (!is_bcm_board_vendor(dev) && 538 (dev->dev->bus->boardinfo.type != 0x0416)) { 539 value = 0x2120; 540 for (offset = 0x00A8 ; offset < 0x00C7; offset++) { 541 b43legacy_phy_write(dev, offset, value); 542 value += 0x0202; 543 } 544 } 545 b43legacy_phy_write(dev, 0x0035, 546 (b43legacy_phy_read(dev, 0x0035) & 0xF0FF) 547 | 0x0700); 548 if (phy->radio_ver == 0x2050) 549 b43legacy_phy_write(dev, 0x0038, 0x0667); 550 551 if (phy->gmode) { 552 if (phy->radio_ver == 0x2050) { 553 b43legacy_radio_write16(dev, 0x007A, 554 b43legacy_radio_read16(dev, 0x007A) 555 | 0x0020); 556 b43legacy_radio_write16(dev, 0x0051, 557 b43legacy_radio_read16(dev, 0x0051) 558 | 0x0004); 559 } 560 b43legacy_write16(dev, B43legacy_MMIO_PHY_RADIO, 0x0000); 561 562 b43legacy_phy_write(dev, 0x0802, b43legacy_phy_read(dev, 0x0802) 563 | 0x0100); 564 b43legacy_phy_write(dev, 0x042B, b43legacy_phy_read(dev, 0x042B) 565 | 0x2000); 566 567 b43legacy_phy_write(dev, 0x001C, 0x186A); 568 569 b43legacy_phy_write(dev, 0x0013, (b43legacy_phy_read(dev, 570 0x0013) & 0x00FF) | 0x1900); 571 b43legacy_phy_write(dev, 0x0035, (b43legacy_phy_read(dev, 572 0x0035) & 0xFFC0) | 0x0064); 573 b43legacy_phy_write(dev, 0x005D, (b43legacy_phy_read(dev, 574 0x005D) & 0xFF80) | 0x000A); 575 b43legacy_phy_write(dev, 0x5B, 0x0000); 576 b43legacy_phy_write(dev, 0x5C, 0x0000); 577 } 578 579 if (dev->bad_frames_preempt) 580 b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD, 581 b43legacy_phy_read(dev, 582 B43legacy_PHY_RADIO_BITFIELD) | (1 << 12)); 583 584 if (phy->analog == 1) { 585 b43legacy_phy_write(dev, 0x0026, 0xCE00); 586 b43legacy_phy_write(dev, 0x0021, 0x3763); 587 b43legacy_phy_write(dev, 0x0022, 0x1BC3); 588 b43legacy_phy_write(dev, 0x0023, 0x06F9); 589 b43legacy_phy_write(dev, 0x0024, 0x037E); 590 } else 591 b43legacy_phy_write(dev, 0x0026, 0xCC00); 592 b43legacy_phy_write(dev, 0x0030, 0x00C6); 593 b43legacy_write16(dev, 0x03EC, 0x3F22); 594 595 if (phy->analog == 1) 596 b43legacy_phy_write(dev, 0x0020, 0x3E1C); 597 else 598 b43legacy_phy_write(dev, 0x0020, 0x301C); 599 600 if (phy->analog == 0) 601 b43legacy_write16(dev, 0x03E4, 0x3000); 602 603 old_channel = (phy->channel == 0xFF) ? 1 : phy->channel; 604 /* Force to channel 7, even if not supported. */ 605 b43legacy_radio_selectchannel(dev, 7, 0); 606 607 if (phy->radio_ver != 0x2050) { 608 b43legacy_radio_write16(dev, 0x0075, 0x0080); 609 b43legacy_radio_write16(dev, 0x0079, 0x0081); 610 } 611 612 b43legacy_radio_write16(dev, 0x0050, 0x0020); 613 b43legacy_radio_write16(dev, 0x0050, 0x0023); 614 615 if (phy->radio_ver == 0x2050) { 616 b43legacy_radio_write16(dev, 0x0050, 0x0020); 617 b43legacy_radio_write16(dev, 0x005A, 0x0070); 618 } 619 620 b43legacy_radio_write16(dev, 0x005B, 0x007B); 621 b43legacy_radio_write16(dev, 0x005C, 0x00B0); 622 623 b43legacy_radio_write16(dev, 0x007A, b43legacy_radio_read16(dev, 624 0x007A) | 0x0007); 625 626 b43legacy_radio_selectchannel(dev, old_channel, 0); 627 628 b43legacy_phy_write(dev, 0x0014, 0x0080); 629 b43legacy_phy_write(dev, 0x0032, 0x00CA); 630 b43legacy_phy_write(dev, 0x002A, 0x88A3); 631 632 b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF); 633 634 if (phy->radio_ver == 0x2050) 635 b43legacy_radio_write16(dev, 0x005D, 0x000D); 636 637 b43legacy_write16(dev, 0x03E4, (b43legacy_read16(dev, 0x03E4) & 638 0xFFC0) | 0x0004); 639} 640 641static void b43legacy_phy_initb6(struct b43legacy_wldev *dev) 642{ 643 struct b43legacy_phy *phy = &dev->phy; 644 u16 offset; 645 u16 val; 646 u8 old_channel; 647 648 b43legacy_phy_write(dev, 0x003E, 0x817A); 649 b43legacy_radio_write16(dev, 0x007A, 650 (b43legacy_radio_read16(dev, 0x007A) | 0x0058)); 651 if (phy->radio_rev == 4 || 652 phy->radio_rev == 5) { 653 b43legacy_radio_write16(dev, 0x0051, 0x0037); 654 b43legacy_radio_write16(dev, 0x0052, 0x0070); 655 b43legacy_radio_write16(dev, 0x0053, 0x00B3); 656 b43legacy_radio_write16(dev, 0x0054, 0x009B); 657 b43legacy_radio_write16(dev, 0x005A, 0x0088); 658 b43legacy_radio_write16(dev, 0x005B, 0x0088); 659 b43legacy_radio_write16(dev, 0x005D, 0x0088); 660 b43legacy_radio_write16(dev, 0x005E, 0x0088); 661 b43legacy_radio_write16(dev, 0x007D, 0x0088); 662 b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 663 B43legacy_UCODEFLAGS_OFFSET, 664 (b43legacy_shm_read32(dev, 665 B43legacy_SHM_SHARED, 666 B43legacy_UCODEFLAGS_OFFSET) 667 | 0x00000200)); 668 } 669 if (phy->radio_rev == 8) { 670 b43legacy_radio_write16(dev, 0x0051, 0x0000); 671 b43legacy_radio_write16(dev, 0x0052, 0x0040); 672 b43legacy_radio_write16(dev, 0x0053, 0x00B7); 673 b43legacy_radio_write16(dev, 0x0054, 0x0098); 674 b43legacy_radio_write16(dev, 0x005A, 0x0088); 675 b43legacy_radio_write16(dev, 0x005B, 0x006B); 676 b43legacy_radio_write16(dev, 0x005C, 0x000F); 677 if (dev->dev->bus->sprom.boardflags_lo & 0x8000) { 678 b43legacy_radio_write16(dev, 0x005D, 0x00FA); 679 b43legacy_radio_write16(dev, 0x005E, 0x00D8); 680 } else { 681 b43legacy_radio_write16(dev, 0x005D, 0x00F5); 682 b43legacy_radio_write16(dev, 0x005E, 0x00B8); 683 } 684 b43legacy_radio_write16(dev, 0x0073, 0x0003); 685 b43legacy_radio_write16(dev, 0x007D, 0x00A8); 686 b43legacy_radio_write16(dev, 0x007C, 0x0001); 687 b43legacy_radio_write16(dev, 0x007E, 0x0008); 688 } 689 val = 0x1E1F; 690 for (offset = 0x0088; offset < 0x0098; offset++) { 691 b43legacy_phy_write(dev, offset, val); 692 val -= 0x0202; 693 } 694 val = 0x3E3F; 695 for (offset = 0x0098; offset < 0x00A8; offset++) { 696 b43legacy_phy_write(dev, offset, val); 697 val -= 0x0202; 698 } 699 val = 0x2120; 700 for (offset = 0x00A8; offset < 0x00C8; offset++) { 701 b43legacy_phy_write(dev, offset, (val & 0x3F3F)); 702 val += 0x0202; 703 } 704 if (phy->type == B43legacy_PHYTYPE_G) { 705 b43legacy_radio_write16(dev, 0x007A, 706 b43legacy_radio_read16(dev, 0x007A) | 707 0x0020); 708 b43legacy_radio_write16(dev, 0x0051, 709 b43legacy_radio_read16(dev, 0x0051) | 710 0x0004); 711 b43legacy_phy_write(dev, 0x0802, 712 b43legacy_phy_read(dev, 0x0802) | 0x0100); 713 b43legacy_phy_write(dev, 0x042B, 714 b43legacy_phy_read(dev, 0x042B) | 0x2000); 715 b43legacy_phy_write(dev, 0x5B, 0x0000); 716 b43legacy_phy_write(dev, 0x5C, 0x0000); 717 } 718 719 old_channel = phy->channel; 720 if (old_channel >= 8) 721 b43legacy_radio_selectchannel(dev, 1, 0); 722 else 723 b43legacy_radio_selectchannel(dev, 13, 0); 724 725 b43legacy_radio_write16(dev, 0x0050, 0x0020); 726 b43legacy_radio_write16(dev, 0x0050, 0x0023); 727 udelay(40); 728 if (phy->radio_rev < 6 || phy->radio_rev == 8) { 729 b43legacy_radio_write16(dev, 0x007C, 730 (b43legacy_radio_read16(dev, 0x007C) 731 | 0x0002)); 732 b43legacy_radio_write16(dev, 0x0050, 0x0020); 733 } 734 if (phy->radio_rev <= 2) { 735 b43legacy_radio_write16(dev, 0x0050, 0x0020); 736 b43legacy_radio_write16(dev, 0x005A, 0x0070); 737 b43legacy_radio_write16(dev, 0x005B, 0x007B); 738 b43legacy_radio_write16(dev, 0x005C, 0x00B0); 739 } 740 b43legacy_radio_write16(dev, 0x007A, 741 (b43legacy_radio_read16(dev, 742 0x007A) & 0x00F8) | 0x0007); 743 744 b43legacy_radio_selectchannel(dev, old_channel, 0); 745 746 b43legacy_phy_write(dev, 0x0014, 0x0200); 747 if (phy->radio_rev >= 6) 748 b43legacy_phy_write(dev, 0x002A, 0x88C2); 749 else 750 b43legacy_phy_write(dev, 0x002A, 0x8AC0); 751 b43legacy_phy_write(dev, 0x0038, 0x0668); 752 b43legacy_radio_set_txpower_bg(dev, 0xFFFF, 0xFFFF, 0xFFFF); 753 if (phy->radio_rev == 4 || phy->radio_rev == 5) 754 b43legacy_phy_write(dev, 0x005D, (b43legacy_phy_read(dev, 755 0x005D) & 0xFF80) | 0x0003); 756 if (phy->radio_rev <= 2) 757 b43legacy_radio_write16(dev, 0x005D, 0x000D); 758 759 if (phy->analog == 4) { 760 b43legacy_write16(dev, 0x03E4, 0x0009); 761 b43legacy_phy_write(dev, 0x61, b43legacy_phy_read(dev, 0x61) 762 & 0xFFF); 763 } else 764 b43legacy_phy_write(dev, 0x0002, (b43legacy_phy_read(dev, 765 0x0002) & 0xFFC0) | 0x0004); 766 if (phy->type == B43legacy_PHYTYPE_G) 767 b43legacy_write16(dev, 0x03E6, 0x0); 768 if (phy->type == B43legacy_PHYTYPE_B) { 769 b43legacy_write16(dev, 0x03E6, 0x8140); 770 b43legacy_phy_write(dev, 0x0016, 0x0410); 771 b43legacy_phy_write(dev, 0x0017, 0x0820); 772 b43legacy_phy_write(dev, 0x0062, 0x0007); 773 b43legacy_radio_init2050(dev); 774 b43legacy_phy_lo_g_measure(dev); 775 if (dev->dev->bus->sprom.boardflags_lo & 776 B43legacy_BFL_RSSI) { 777 b43legacy_calc_nrssi_slope(dev); 778 b43legacy_calc_nrssi_threshold(dev); 779 } 780 b43legacy_phy_init_pctl(dev); 781 } 782} 783 784static void b43legacy_calc_loopback_gain(struct b43legacy_wldev *dev) 785{ 786 struct b43legacy_phy *phy = &dev->phy; 787 u16 backup_phy[15] = {0}; 788 u16 backup_radio[3]; 789 u16 backup_bband; 790 u16 i; 791 u16 loop1_cnt; 792 u16 loop1_done; 793 u16 loop1_omitted; 794 u16 loop2_done; 795 796 backup_phy[0] = b43legacy_phy_read(dev, 0x0429); 797 backup_phy[1] = b43legacy_phy_read(dev, 0x0001); 798 backup_phy[2] = b43legacy_phy_read(dev, 0x0811); 799 backup_phy[3] = b43legacy_phy_read(dev, 0x0812); 800 if (phy->rev != 1) { 801 backup_phy[4] = b43legacy_phy_read(dev, 0x0814); 802 backup_phy[5] = b43legacy_phy_read(dev, 0x0815); 803 } 804 backup_phy[6] = b43legacy_phy_read(dev, 0x005A); 805 backup_phy[7] = b43legacy_phy_read(dev, 0x0059); 806 backup_phy[8] = b43legacy_phy_read(dev, 0x0058); 807 backup_phy[9] = b43legacy_phy_read(dev, 0x000A); 808 backup_phy[10] = b43legacy_phy_read(dev, 0x0003); 809 backup_phy[11] = b43legacy_phy_read(dev, 0x080F); 810 backup_phy[12] = b43legacy_phy_read(dev, 0x0810); 811 backup_phy[13] = b43legacy_phy_read(dev, 0x002B); 812 backup_phy[14] = b43legacy_phy_read(dev, 0x0015); 813 b43legacy_phy_read(dev, 0x002D); /* dummy read */ 814 backup_bband = phy->bbatt; 815 backup_radio[0] = b43legacy_radio_read16(dev, 0x0052); 816 backup_radio[1] = b43legacy_radio_read16(dev, 0x0043); 817 backup_radio[2] = b43legacy_radio_read16(dev, 0x007A); 818 819 b43legacy_phy_write(dev, 0x0429, 820 b43legacy_phy_read(dev, 0x0429) & 0x3FFF); 821 b43legacy_phy_write(dev, 0x0001, 822 b43legacy_phy_read(dev, 0x0001) & 0x8000); 823 b43legacy_phy_write(dev, 0x0811, 824 b43legacy_phy_read(dev, 0x0811) | 0x0002); 825 b43legacy_phy_write(dev, 0x0812, 826 b43legacy_phy_read(dev, 0x0812) & 0xFFFD); 827 b43legacy_phy_write(dev, 0x0811, 828 b43legacy_phy_read(dev, 0x0811) | 0x0001); 829 b43legacy_phy_write(dev, 0x0812, 830 b43legacy_phy_read(dev, 0x0812) & 0xFFFE); 831 if (phy->rev != 1) { 832 b43legacy_phy_write(dev, 0x0814, 833 b43legacy_phy_read(dev, 0x0814) | 0x0001); 834 b43legacy_phy_write(dev, 0x0815, 835 b43legacy_phy_read(dev, 0x0815) & 0xFFFE); 836 b43legacy_phy_write(dev, 0x0814, 837 b43legacy_phy_read(dev, 0x0814) | 0x0002); 838 b43legacy_phy_write(dev, 0x0815, 839 b43legacy_phy_read(dev, 0x0815) & 0xFFFD); 840 } 841 b43legacy_phy_write(dev, 0x0811, b43legacy_phy_read(dev, 0x0811) | 842 0x000C); 843 b43legacy_phy_write(dev, 0x0812, b43legacy_phy_read(dev, 0x0812) | 844 0x000C); 845 846 b43legacy_phy_write(dev, 0x0811, (b43legacy_phy_read(dev, 0x0811) 847 & 0xFFCF) | 0x0030); 848 b43legacy_phy_write(dev, 0x0812, (b43legacy_phy_read(dev, 0x0812) 849 & 0xFFCF) | 0x0010); 850 851 b43legacy_phy_write(dev, 0x005A, 0x0780); 852 b43legacy_phy_write(dev, 0x0059, 0xC810); 853 b43legacy_phy_write(dev, 0x0058, 0x000D); 854 if (phy->analog == 0) 855 b43legacy_phy_write(dev, 0x0003, 0x0122); 856 else 857 b43legacy_phy_write(dev, 0x000A, 858 b43legacy_phy_read(dev, 0x000A) 859 | 0x2000); 860 if (phy->rev != 1) { 861 b43legacy_phy_write(dev, 0x0814, 862 b43legacy_phy_read(dev, 0x0814) | 0x0004); 863 b43legacy_phy_write(dev, 0x0815, 864 b43legacy_phy_read(dev, 0x0815) & 0xFFFB); 865 } 866 b43legacy_phy_write(dev, 0x0003, 867 (b43legacy_phy_read(dev, 0x0003) 868 & 0xFF9F) | 0x0040); 869 if (phy->radio_ver == 0x2050 && phy->radio_rev == 2) { 870 b43legacy_radio_write16(dev, 0x0052, 0x0000); 871 b43legacy_radio_write16(dev, 0x0043, 872 (b43legacy_radio_read16(dev, 0x0043) 873 & 0xFFF0) | 0x0009); 874 loop1_cnt = 9; 875 } else if (phy->radio_rev == 8) { 876 b43legacy_radio_write16(dev, 0x0043, 0x000F); 877 loop1_cnt = 15; 878 } else 879 loop1_cnt = 0; 880 881 b43legacy_phy_set_baseband_attenuation(dev, 11); 882 883 if (phy->rev >= 3) 884 b43legacy_phy_write(dev, 0x080F, 0xC020); 885 else 886 b43legacy_phy_write(dev, 0x080F, 0x8020); 887 b43legacy_phy_write(dev, 0x0810, 0x0000); 888 889 b43legacy_phy_write(dev, 0x002B, 890 (b43legacy_phy_read(dev, 0x002B) 891 & 0xFFC0) | 0x0001); 892 b43legacy_phy_write(dev, 0x002B, 893 (b43legacy_phy_read(dev, 0x002B) 894 & 0xC0FF) | 0x0800); 895 b43legacy_phy_write(dev, 0x0811, 896 b43legacy_phy_read(dev, 0x0811) | 0x0100); 897 b43legacy_phy_write(dev, 0x0812, 898 b43legacy_phy_read(dev, 0x0812) & 0xCFFF); 899 if (dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_EXTLNA) { 900 if (phy->rev >= 7) { 901 b43legacy_phy_write(dev, 0x0811, 902 b43legacy_phy_read(dev, 0x0811) 903 | 0x0800); 904 b43legacy_phy_write(dev, 0x0812, 905 b43legacy_phy_read(dev, 0x0812) 906 | 0x8000); 907 } 908 } 909 b43legacy_radio_write16(dev, 0x007A, 910 b43legacy_radio_read16(dev, 0x007A) 911 & 0x00F7); 912 913 for (i = 0; i < loop1_cnt; i++) { 914 b43legacy_radio_write16(dev, 0x0043, loop1_cnt); 915 b43legacy_phy_write(dev, 0x0812, 916 (b43legacy_phy_read(dev, 0x0812) 917 & 0xF0FF) | (i << 8)); 918 b43legacy_phy_write(dev, 0x0015, 919 (b43legacy_phy_read(dev, 0x0015) 920 & 0x0FFF) | 0xA000); 921 b43legacy_phy_write(dev, 0x0015, 922 (b43legacy_phy_read(dev, 0x0015) 923 & 0x0FFF) | 0xF000); 924 udelay(20); 925 if (b43legacy_phy_read(dev, 0x002D) >= 0x0DFC) 926 break; 927 } 928 loop1_done = i; 929 loop1_omitted = loop1_cnt - loop1_done; 930 931 loop2_done = 0; 932 if (loop1_done >= 8) { 933 b43legacy_phy_write(dev, 0x0812, 934 b43legacy_phy_read(dev, 0x0812) 935 | 0x0030); 936 for (i = loop1_done - 8; i < 16; i++) { 937 b43legacy_phy_write(dev, 0x0812, 938 (b43legacy_phy_read(dev, 0x0812) 939 & 0xF0FF) | (i << 8)); 940 b43legacy_phy_write(dev, 0x0015, 941 (b43legacy_phy_read(dev, 0x0015) 942 & 0x0FFF) | 0xA000); 943 b43legacy_phy_write(dev, 0x0015, 944 (b43legacy_phy_read(dev, 0x0015) 945 & 0x0FFF) | 0xF000); 946 udelay(20); 947 if (b43legacy_phy_read(dev, 0x002D) >= 0x0DFC) 948 break; 949 } 950 } 951 952 if (phy->rev != 1) { 953 b43legacy_phy_write(dev, 0x0814, backup_phy[4]); 954 b43legacy_phy_write(dev, 0x0815, backup_phy[5]); 955 } 956 b43legacy_phy_write(dev, 0x005A, backup_phy[6]); 957 b43legacy_phy_write(dev, 0x0059, backup_phy[7]); 958 b43legacy_phy_write(dev, 0x0058, backup_phy[8]); 959 b43legacy_phy_write(dev, 0x000A, backup_phy[9]); 960 b43legacy_phy_write(dev, 0x0003, backup_phy[10]); 961 b43legacy_phy_write(dev, 0x080F, backup_phy[11]); 962 b43legacy_phy_write(dev, 0x0810, backup_phy[12]); 963 b43legacy_phy_write(dev, 0x002B, backup_phy[13]); 964 b43legacy_phy_write(dev, 0x0015, backup_phy[14]); 965 966 b43legacy_phy_set_baseband_attenuation(dev, backup_bband); 967 968 b43legacy_radio_write16(dev, 0x0052, backup_radio[0]); 969 b43legacy_radio_write16(dev, 0x0043, backup_radio[1]); 970 b43legacy_radio_write16(dev, 0x007A, backup_radio[2]); 971 972 b43legacy_phy_write(dev, 0x0811, backup_phy[2] | 0x0003); 973 udelay(10); 974 b43legacy_phy_write(dev, 0x0811, backup_phy[2]); 975 b43legacy_phy_write(dev, 0x0812, backup_phy[3]); 976 b43legacy_phy_write(dev, 0x0429, backup_phy[0]); 977 b43legacy_phy_write(dev, 0x0001, backup_phy[1]); 978 979 phy->loopback_gain[0] = ((loop1_done * 6) - (loop1_omitted * 4)) - 11; 980 phy->loopback_gain[1] = (24 - (3 * loop2_done)) * 2; 981} 982 983static void b43legacy_phy_initg(struct b43legacy_wldev *dev) 984{ 985 struct b43legacy_phy *phy = &dev->phy; 986 u16 tmp; 987 988 if (phy->rev == 1) 989 b43legacy_phy_initb5(dev); 990 else 991 b43legacy_phy_initb6(dev); 992 if (phy->rev >= 2 && phy->gmode) 993 b43legacy_phy_inita(dev); 994 995 if (phy->rev >= 2) { 996 b43legacy_phy_write(dev, 0x0814, 0x0000); 997 b43legacy_phy_write(dev, 0x0815, 0x0000); 998 } 999 if (phy->rev == 2) { 1000 b43legacy_phy_write(dev, 0x0811, 0x0000); 1001 b43legacy_phy_write(dev, 0x0015, 0x00C0); 1002 } 1003 if (phy->rev > 5) { 1004 b43legacy_phy_write(dev, 0x0811, 0x0400); 1005 b43legacy_phy_write(dev, 0x0015, 0x00C0); 1006 } 1007 if (phy->gmode) { 1008 tmp = b43legacy_phy_read(dev, 0x0400) & 0xFF; 1009 if (tmp == 3) { 1010 b43legacy_phy_write(dev, 0x04C2, 0x1816); 1011 b43legacy_phy_write(dev, 0x04C3, 0x8606); 1012 } 1013 if (tmp == 4 || tmp == 5) { 1014 b43legacy_phy_write(dev, 0x04C2, 0x1816); 1015 b43legacy_phy_write(dev, 0x04C3, 0x8006); 1016 b43legacy_phy_write(dev, 0x04CC, 1017 (b43legacy_phy_read(dev, 1018 0x04CC) & 0x00FF) | 1019 0x1F00); 1020 } 1021 if (phy->rev >= 2) 1022 b43legacy_phy_write(dev, 0x047E, 0x0078); 1023 } 1024 if (phy->radio_rev == 8) { 1025 b43legacy_phy_write(dev, 0x0801, b43legacy_phy_read(dev, 0x0801) 1026 | 0x0080); 1027 b43legacy_phy_write(dev, 0x043E, b43legacy_phy_read(dev, 0x043E) 1028 | 0x0004); 1029 } 1030 if (phy->rev >= 2 && phy->gmode) 1031 b43legacy_calc_loopback_gain(dev); 1032 if (phy->radio_rev != 8) { 1033 if (phy->initval == 0xFFFF) 1034 phy->initval = b43legacy_radio_init2050(dev); 1035 else 1036 b43legacy_radio_write16(dev, 0x0078, phy->initval); 1037 } 1038 if (phy->txctl2 == 0xFFFF) 1039 b43legacy_phy_lo_g_measure(dev); 1040 else { 1041 if (phy->radio_ver == 0x2050 && phy->radio_rev == 8) 1042 b43legacy_radio_write16(dev, 0x0052, 1043 (phy->txctl1 << 4) | 1044 phy->txctl2); 1045 else 1046 b43legacy_radio_write16(dev, 0x0052, 1047 (b43legacy_radio_read16(dev, 1048 0x0052) & 0xFFF0) | 1049 phy->txctl1); 1050 if (phy->rev >= 6) 1051 b43legacy_phy_write(dev, 0x0036, 1052 (b43legacy_phy_read(dev, 0x0036) 1053 & 0x0FFF) | (phy->txctl2 << 12)); 1054 if (dev->dev->bus->sprom.boardflags_lo & 1055 B43legacy_BFL_PACTRL) 1056 b43legacy_phy_write(dev, 0x002E, 0x8075); 1057 else 1058 b43legacy_phy_write(dev, 0x002E, 0x807F); 1059 if (phy->rev < 2) 1060 b43legacy_phy_write(dev, 0x002F, 0x0101); 1061 else 1062 b43legacy_phy_write(dev, 0x002F, 0x0202); 1063 } 1064 if (phy->gmode) { 1065 b43legacy_phy_lo_adjust(dev, 0); 1066 b43legacy_phy_write(dev, 0x080F, 0x8078); 1067 } 1068 1069 if (!(dev->dev->bus->sprom.boardflags_lo & B43legacy_BFL_RSSI)) { 1070 /* The specs state to update the NRSSI LT with 1071 * the value 0x7FFFFFFF here. I think that is some weird 1072 * compiler optimization in the original driver. 1073 * Essentially, what we do here is resetting all NRSSI LT 1074 * entries to -32 (see the clamp_val() in nrssi_hw_update()) 1075 */ 1076 b43legacy_nrssi_hw_update(dev, 0xFFFF); 1077 b43legacy_calc_nrssi_threshold(dev); 1078 } else if (phy->gmode || phy->rev >= 2) { 1079 if (phy->nrssi[0] == -1000) { 1080 B43legacy_WARN_ON(phy->nrssi[1] != -1000); 1081 b43legacy_calc_nrssi_slope(dev); 1082 } else { 1083 B43legacy_WARN_ON(phy->nrssi[1] == -1000); 1084 b43legacy_calc_nrssi_threshold(dev); 1085 } 1086 } 1087 if (phy->radio_rev == 8) 1088 b43legacy_phy_write(dev, 0x0805, 0x3230); 1089 b43legacy_phy_init_pctl(dev); 1090 if (dev->dev->bus->chip_id == 0x4306 1091 && dev->dev->bus->chip_package == 2) { 1092 b43legacy_phy_write(dev, 0x0429, 1093 b43legacy_phy_read(dev, 0x0429) & 0xBFFF); 1094 b43legacy_phy_write(dev, 0x04C3, 1095 b43legacy_phy_read(dev, 0x04C3) & 0x7FFF); 1096 } 1097} 1098 1099static u16 b43legacy_phy_lo_b_r15_loop(struct b43legacy_wldev *dev) 1100{ 1101 int i; 1102 u16 ret = 0; 1103 unsigned long flags; 1104 1105 local_irq_save(flags); 1106 for (i = 0; i < 10; i++) { 1107 b43legacy_phy_write(dev, 0x0015, 0xAFA0); 1108 udelay(1); 1109 b43legacy_phy_write(dev, 0x0015, 0xEFA0); 1110 udelay(10); 1111 b43legacy_phy_write(dev, 0x0015, 0xFFA0); 1112 udelay(40); 1113 ret += b43legacy_phy_read(dev, 0x002C); 1114 } 1115 local_irq_restore(flags); 1116 cond_resched(); 1117 1118 return ret; 1119} 1120 1121void b43legacy_phy_lo_b_measure(struct b43legacy_wldev *dev) 1122{ 1123 struct b43legacy_phy *phy = &dev->phy; 1124 u16 regstack[12] = { 0 }; 1125 u16 mls; 1126 s16 fval; 1127 int i; 1128 int j; 1129 1130 regstack[0] = b43legacy_phy_read(dev, 0x0015); 1131 regstack[1] = b43legacy_radio_read16(dev, 0x0052) & 0xFFF0; 1132 1133 if (phy->radio_ver == 0x2053) { 1134 regstack[2] = b43legacy_phy_read(dev, 0x000A); 1135 regstack[3] = b43legacy_phy_read(dev, 0x002A); 1136 regstack[4] = b43legacy_phy_read(dev, 0x0035); 1137 regstack[5] = b43legacy_phy_read(dev, 0x0003); 1138 regstack[6] = b43legacy_phy_read(dev, 0x0001); 1139 regstack[7] = b43legacy_phy_read(dev, 0x0030); 1140 1141 regstack[8] = b43legacy_radio_read16(dev, 0x0043); 1142 regstack[9] = b43legacy_radio_read16(dev, 0x007A); 1143 regstack[10] = b43legacy_read16(dev, 0x03EC); 1144 regstack[11] = b43legacy_radio_read16(dev, 0x0052) & 0x00F0; 1145 1146 b43legacy_phy_write(dev, 0x0030, 0x00FF); 1147 b43legacy_write16(dev, 0x03EC, 0x3F3F); 1148 b43legacy_phy_write(dev, 0x0035, regstack[4] & 0xFF7F); 1149 b43legacy_radio_write16(dev, 0x007A, regstack[9] & 0xFFF0); 1150 } 1151 b43legacy_phy_write(dev, 0x0015, 0xB000); 1152 b43legacy_phy_write(dev, 0x002B, 0x0004); 1153 1154 if (phy->radio_ver == 0x2053) { 1155 b43legacy_phy_write(dev, 0x002B, 0x0203); 1156 b43legacy_phy_write(dev, 0x002A, 0x08A3); 1157 } 1158 1159 phy->minlowsig[0] = 0xFFFF; 1160 1161 for (i = 0; i < 4; i++) { 1162 b43legacy_radio_write16(dev, 0x0052, regstack[1] | i); 1163 b43legacy_phy_lo_b_r15_loop(dev); 1164 } 1165 for (i = 0; i < 10; i++) { 1166 b43legacy_radio_write16(dev, 0x0052, regstack[1] | i); 1167 mls = b43legacy_phy_lo_b_r15_loop(dev) / 10; 1168 if (mls < phy->minlowsig[0]) { 1169 phy->minlowsig[0] = mls; 1170 phy->minlowsigpos[0] = i; 1171 } 1172 } 1173 b43legacy_radio_write16(dev, 0x0052, regstack[1] 1174 | phy->minlowsigpos[0]); 1175 1176 phy->minlowsig[1] = 0xFFFF; 1177 1178 for (i = -4; i < 5; i += 2) { 1179 for (j = -4; j < 5; j += 2) { 1180 if (j < 0) 1181 fval = (0x0100 * i) + j + 0x0100; 1182 else 1183 fval = (0x0100 * i) + j; 1184 b43legacy_phy_write(dev, 0x002F, fval); 1185 mls = b43legacy_phy_lo_b_r15_loop(dev) / 10; 1186 if (mls < phy->minlowsig[1]) { 1187 phy->minlowsig[1] = mls; 1188 phy->minlowsigpos[1] = fval; 1189 } 1190 } 1191 } 1192 phy->minlowsigpos[1] += 0x0101; 1193 1194 b43legacy_phy_write(dev, 0x002F, phy->minlowsigpos[1]); 1195 if (phy->radio_ver == 0x2053) { 1196 b43legacy_phy_write(dev, 0x000A, regstack[2]); 1197 b43legacy_phy_write(dev, 0x002A, regstack[3]); 1198 b43legacy_phy_write(dev, 0x0035, regstack[4]); 1199 b43legacy_phy_write(dev, 0x0003, regstack[5]); 1200 b43legacy_phy_write(dev, 0x0001, regstack[6]); 1201 b43legacy_phy_write(dev, 0x0030, regstack[7]); 1202 1203 b43legacy_radio_write16(dev, 0x0043, regstack[8]); 1204 b43legacy_radio_write16(dev, 0x007A, regstack[9]); 1205 1206 b43legacy_radio_write16(dev, 0x0052, 1207 (b43legacy_radio_read16(dev, 0x0052) 1208 & 0x000F) | regstack[11]); 1209 1210 b43legacy_write16(dev, 0x03EC, regstack[10]); 1211 } 1212 b43legacy_phy_write(dev, 0x0015, regstack[0]); 1213} 1214 1215static inline 1216u16 b43legacy_phy_lo_g_deviation_subval(struct b43legacy_wldev *dev, 1217 u16 control) 1218{ 1219 struct b43legacy_phy *phy = &dev->phy; 1220 u16 ret; 1221 unsigned long flags; 1222 1223 local_irq_save(flags); 1224 if (phy->gmode) { 1225 b43legacy_phy_write(dev, 0x15, 0xE300); 1226 control <<= 8; 1227 b43legacy_phy_write(dev, 0x0812, control | 0x00B0); 1228 udelay(5); 1229 b43legacy_phy_write(dev, 0x0812, control | 0x00B2); 1230 udelay(2); 1231 b43legacy_phy_write(dev, 0x0812, control | 0x00B3); 1232 udelay(4); 1233 b43legacy_phy_write(dev, 0x0015, 0xF300); 1234 udelay(8); 1235 } else { 1236 b43legacy_phy_write(dev, 0x0015, control | 0xEFA0); 1237 udelay(2); 1238 b43legacy_phy_write(dev, 0x0015, control | 0xEFE0); 1239 udelay(4); 1240 b43legacy_phy_write(dev, 0x0015, control | 0xFFE0); 1241 udelay(8); 1242 } 1243 ret = b43legacy_phy_read(dev, 0x002D); 1244 local_irq_restore(flags); 1245 cond_resched(); 1246 1247 return ret; 1248} 1249 1250static u32 b43legacy_phy_lo_g_singledeviation(struct b43legacy_wldev *dev, 1251 u16 control) 1252{ 1253 int i; 1254 u32 ret = 0; 1255 1256 for (i = 0; i < 8; i++) 1257 ret += b43legacy_phy_lo_g_deviation_subval(dev, control); 1258 1259 return ret; 1260} 1261 1262/* Write the LocalOscillator CONTROL */ 1263static inline 1264void b43legacy_lo_write(struct b43legacy_wldev *dev, 1265 struct b43legacy_lopair *pair) 1266{ 1267 u16 value; 1268 1269 value = (u8)(pair->low); 1270 value |= ((u8)(pair->high)) << 8; 1271 1272#ifdef CONFIG_B43LEGACY_DEBUG 1273 /* Sanity check. */ 1274 if (pair->low < -8 || pair->low > 8 || 1275 pair->high < -8 || pair->high > 8) { 1276 b43legacydbg(dev->wl, 1277 "WARNING: Writing invalid LOpair " 1278 "(low: %d, high: %d)\n", 1279 pair->low, pair->high); 1280 dump_stack(); 1281 } 1282#endif 1283 1284 b43legacy_phy_write(dev, B43legacy_PHY_G_LO_CONTROL, value); 1285} 1286 1287static inline 1288struct b43legacy_lopair *b43legacy_find_lopair(struct b43legacy_wldev *dev, 1289 u16 bbatt, 1290 u16 rfatt, 1291 u16 tx) 1292{ 1293 static const u8 dict[10] = { 11, 10, 11, 12, 13, 12, 13, 12, 13, 12 }; 1294 struct b43legacy_phy *phy = &dev->phy; 1295 1296 if (bbatt > 6) 1297 bbatt = 6; 1298 B43legacy_WARN_ON(rfatt >= 10); 1299 1300 if (tx == 3) 1301 return b43legacy_get_lopair(phy, rfatt, bbatt); 1302 return b43legacy_get_lopair(phy, dict[rfatt], bbatt); 1303} 1304 1305static inline 1306struct b43legacy_lopair *b43legacy_current_lopair(struct b43legacy_wldev *dev) 1307{ 1308 struct b43legacy_phy *phy = &dev->phy; 1309 1310 return b43legacy_find_lopair(dev, phy->bbatt, 1311 phy->rfatt, phy->txctl1); 1312} 1313 1314/* Adjust B/G LO */ 1315void b43legacy_phy_lo_adjust(struct b43legacy_wldev *dev, int fixed) 1316{ 1317 struct b43legacy_lopair *pair; 1318 1319 if (fixed) { 1320 /* Use fixed values. Only for initialization. */ 1321 pair = b43legacy_find_lopair(dev, 2, 3, 0); 1322 } else 1323 pair = b43legacy_current_lopair(dev); 1324 b43legacy_lo_write(dev, pair); 1325} 1326 1327static void b43legacy_phy_lo_g_measure_txctl2(struct b43legacy_wldev *dev) 1328{ 1329 struct b43legacy_phy *phy = &dev->phy; 1330 u16 txctl2 = 0; 1331 u16 i; 1332 u32 smallest; 1333 u32 tmp; 1334 1335 b43legacy_radio_write16(dev, 0x0052, 0x0000); 1336 udelay(10); 1337 smallest = b43legacy_phy_lo_g_singledeviation(dev, 0); 1338 for (i = 0; i < 16; i++) { 1339 b43legacy_radio_write16(dev, 0x0052, i); 1340 udelay(10); 1341 tmp = b43legacy_phy_lo_g_singledeviation(dev, 0); 1342 if (tmp < smallest) { 1343 smallest = tmp; 1344 txctl2 = i; 1345 } 1346 } 1347 phy->txctl2 = txctl2; 1348} 1349 1350static 1351void b43legacy_phy_lo_g_state(struct b43legacy_wldev *dev, 1352 const struct b43legacy_lopair *in_pair, 1353 struct b43legacy_lopair *out_pair, 1354 u16 r27) 1355{ 1356 static const struct b43legacy_lopair transitions[8] = { 1357 { .high = 1, .low = 1, }, 1358 { .high = 1, .low = 0, }, 1359 { .high = 1, .low = -1, }, 1360 { .high = 0, .low = -1, }, 1361 { .high = -1, .low = -1, }, 1362 { .high = -1, .low = 0, }, 1363 { .high = -1, .low = 1, }, 1364 { .high = 0, .low = 1, }, 1365 }; 1366 struct b43legacy_lopair lowest_transition = { 1367 .high = in_pair->high, 1368 .low = in_pair->low, 1369 }; 1370 struct b43legacy_lopair tmp_pair; 1371 struct b43legacy_lopair transition; 1372 int i = 12; 1373 int state = 0; 1374 int found_lower; 1375 int j; 1376 int begin; 1377 int end; 1378 u32 lowest_deviation; 1379 u32 tmp; 1380 1381 /* Note that in_pair and out_pair can point to the same pair. 1382 * Be careful. */ 1383 1384 b43legacy_lo_write(dev, &lowest_transition); 1385 lowest_deviation = b43legacy_phy_lo_g_singledeviation(dev, r27); 1386 do { 1387 found_lower = 0; 1388 B43legacy_WARN_ON(!(state >= 0 && state <= 8)); 1389 if (state == 0) { 1390 begin = 1; 1391 end = 8; 1392 } else if (state % 2 == 0) { 1393 begin = state - 1; 1394 end = state + 1; 1395 } else { 1396 begin = state - 2; 1397 end = state + 2; 1398 } 1399 if (begin < 1) 1400 begin += 8; 1401 if (end > 8) 1402 end -= 8; 1403 1404 j = begin; 1405 tmp_pair.high = lowest_transition.high; 1406 tmp_pair.low = lowest_transition.low; 1407 while (1) { 1408 B43legacy_WARN_ON(!(j >= 1 && j <= 8)); 1409 transition.high = tmp_pair.high + 1410 transitions[j - 1].high; 1411 transition.low = tmp_pair.low + transitions[j - 1].low; 1412 if ((abs(transition.low) < 9) 1413 && (abs(transition.high) < 9)) { 1414 b43legacy_lo_write(dev, &transition); 1415 tmp = b43legacy_phy_lo_g_singledeviation(dev, 1416 r27); 1417 if (tmp < lowest_deviation) { 1418 lowest_deviation = tmp; 1419 state = j; 1420 found_lower = 1; 1421 1422 lowest_transition.high = 1423 transition.high; 1424 lowest_transition.low = transition.low; 1425 } 1426 } 1427 if (j == end) 1428 break; 1429 if (j == 8) 1430 j = 1; 1431 else 1432 j++; 1433 } 1434 } while (i-- && found_lower); 1435 1436 out_pair->high = lowest_transition.high; 1437 out_pair->low = lowest_transition.low; 1438} 1439 1440/* Set the baseband attenuation value on chip. */ 1441void b43legacy_phy_set_baseband_attenuation(struct b43legacy_wldev *dev, 1442 u16 bbatt) 1443{ 1444 struct b43legacy_phy *phy = &dev->phy; 1445 u16 value; 1446 1447 if (phy->analog == 0) { 1448 value = (b43legacy_read16(dev, 0x03E6) & 0xFFF0); 1449 value |= (bbatt & 0x000F); 1450 b43legacy_write16(dev, 0x03E6, value); 1451 return; 1452 } 1453 1454 if (phy->analog > 1) { 1455 value = b43legacy_phy_read(dev, 0x0060) & 0xFFC3; 1456 value |= (bbatt << 2) & 0x003C; 1457 } else { 1458 value = b43legacy_phy_read(dev, 0x0060) & 0xFF87; 1459 value |= (bbatt << 3) & 0x0078; 1460 } 1461 b43legacy_phy_write(dev, 0x0060, value); 1462} 1463 1464/* https://bcm-specs.sipsolutions.net/LocalOscillator/Measure */ 1465void b43legacy_phy_lo_g_measure(struct b43legacy_wldev *dev) 1466{ 1467 static const u8 pairorder[10] = { 3, 1, 5, 7, 9, 2, 0, 4, 6, 8 }; 1468 const int is_initializing = (b43legacy_status(dev) 1469 < B43legacy_STAT_STARTED); 1470 struct b43legacy_phy *phy = &dev->phy; 1471 u16 h; 1472 u16 i; 1473 u16 oldi = 0; 1474 u16 j; 1475 struct b43legacy_lopair control; 1476 struct b43legacy_lopair *tmp_control; 1477 u16 tmp; 1478 u16 regstack[16] = { 0 }; 1479 u8 oldchannel; 1480 1481 /* XXX: What are these? */ 1482 u8 r27 = 0; 1483 u16 r31; 1484 1485 oldchannel = phy->channel; 1486 /* Setup */ 1487 if (phy->gmode) { 1488 regstack[0] = b43legacy_phy_read(dev, B43legacy_PHY_G_CRS); 1489 regstack[1] = b43legacy_phy_read(dev, 0x0802); 1490 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, regstack[0] 1491 & 0x7FFF); 1492 b43legacy_phy_write(dev, 0x0802, regstack[1] & 0xFFFC); 1493 } 1494 regstack[3] = b43legacy_read16(dev, 0x03E2); 1495 b43legacy_write16(dev, 0x03E2, regstack[3] | 0x8000); 1496 regstack[4] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT); 1497 regstack[5] = b43legacy_phy_read(dev, 0x15); 1498 regstack[6] = b43legacy_phy_read(dev, 0x2A); 1499 regstack[7] = b43legacy_phy_read(dev, 0x35); 1500 regstack[8] = b43legacy_phy_read(dev, 0x60); 1501 regstack[9] = b43legacy_radio_read16(dev, 0x43); 1502 regstack[10] = b43legacy_radio_read16(dev, 0x7A); 1503 regstack[11] = b43legacy_radio_read16(dev, 0x52); 1504 if (phy->gmode) { 1505 regstack[12] = b43legacy_phy_read(dev, 0x0811); 1506 regstack[13] = b43legacy_phy_read(dev, 0x0812); 1507 regstack[14] = b43legacy_phy_read(dev, 0x0814); 1508 regstack[15] = b43legacy_phy_read(dev, 0x0815); 1509 } 1510 b43legacy_radio_selectchannel(dev, 6, 0); 1511 if (phy->gmode) { 1512 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, regstack[0] 1513 & 0x7FFF); 1514 b43legacy_phy_write(dev, 0x0802, regstack[1] & 0xFFFC); 1515 b43legacy_dummy_transmission(dev); 1516 } 1517 b43legacy_radio_write16(dev, 0x0043, 0x0006); 1518 1519 b43legacy_phy_set_baseband_attenuation(dev, 2); 1520 1521 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 0x0000); 1522 b43legacy_phy_write(dev, 0x002E, 0x007F); 1523 b43legacy_phy_write(dev, 0x080F, 0x0078); 1524 b43legacy_phy_write(dev, 0x0035, regstack[7] & ~(1 << 7)); 1525 b43legacy_radio_write16(dev, 0x007A, regstack[10] & 0xFFF0); 1526 b43legacy_phy_write(dev, 0x002B, 0x0203); 1527 b43legacy_phy_write(dev, 0x002A, 0x08A3); 1528 if (phy->gmode) { 1529 b43legacy_phy_write(dev, 0x0814, regstack[14] | 0x0003); 1530 b43legacy_phy_write(dev, 0x0815, regstack[15] & 0xFFFC); 1531 b43legacy_phy_write(dev, 0x0811, 0x01B3); 1532 b43legacy_phy_write(dev, 0x0812, 0x00B2); 1533 } 1534 if (is_initializing) 1535 b43legacy_phy_lo_g_measure_txctl2(dev); 1536 b43legacy_phy_write(dev, 0x080F, 0x8078); 1537 1538 /* Measure */ 1539 control.low = 0; 1540 control.high = 0; 1541 for (h = 0; h < 10; h++) { 1542 /* Loop over each possible RadioAttenuation (0-9) */ 1543 i = pairorder[h]; 1544 if (is_initializing) { 1545 if (i == 3) { 1546 control.low = 0; 1547 control.high = 0; 1548 } else if (((i % 2 == 1) && (oldi % 2 == 1)) || 1549 ((i % 2 == 0) && (oldi % 2 == 0))) { 1550 tmp_control = b43legacy_get_lopair(phy, oldi, 1551 0); 1552 memcpy(&control, tmp_control, sizeof(control)); 1553 } else { 1554 tmp_control = b43legacy_get_lopair(phy, 3, 0); 1555 memcpy(&control, tmp_control, sizeof(control)); 1556 } 1557 } 1558 /* Loop over each possible BasebandAttenuation/2 */ 1559 for (j = 0; j < 4; j++) { 1560 if (is_initializing) { 1561 tmp = i * 2 + j; 1562 r27 = 0; 1563 r31 = 0; 1564 if (tmp > 14) { 1565 r31 = 1; 1566 if (tmp > 17) 1567 r27 = 1; 1568 if (tmp > 19) 1569 r27 = 2; 1570 } 1571 } else { 1572 tmp_control = b43legacy_get_lopair(phy, i, 1573 j * 2); 1574 if (!tmp_control->used) 1575 continue; 1576 memcpy(&control, tmp_control, sizeof(control)); 1577 r27 = 3; 1578 r31 = 0; 1579 } 1580 b43legacy_radio_write16(dev, 0x43, i); 1581 b43legacy_radio_write16(dev, 0x52, phy->txctl2); 1582 udelay(10); 1583 cond_resched(); 1584 1585 b43legacy_phy_set_baseband_attenuation(dev, j * 2); 1586 1587 tmp = (regstack[10] & 0xFFF0); 1588 if (r31) 1589 tmp |= 0x0008; 1590 b43legacy_radio_write16(dev, 0x007A, tmp); 1591 1592 tmp_control = b43legacy_get_lopair(phy, i, j * 2); 1593 b43legacy_phy_lo_g_state(dev, &control, tmp_control, 1594 r27); 1595 } 1596 oldi = i; 1597 } 1598 /* Loop over each possible RadioAttenuation (10-13) */ 1599 for (i = 10; i < 14; i++) { 1600 /* Loop over each possible BasebandAttenuation/2 */ 1601 for (j = 0; j < 4; j++) { 1602 if (is_initializing) { 1603 tmp_control = b43legacy_get_lopair(phy, i - 9, 1604 j * 2); 1605 memcpy(&control, tmp_control, sizeof(control)); 1606 /* FIXME: The next line is wrong, as the 1607 * following if statement can never trigger. */ 1608 tmp = (i - 9) * 2 + j - 5; 1609 r27 = 0; 1610 r31 = 0; 1611 if (tmp > 14) { 1612 r31 = 1; 1613 if (tmp > 17) 1614 r27 = 1; 1615 if (tmp > 19) 1616 r27 = 2; 1617 } 1618 } else { 1619 tmp_control = b43legacy_get_lopair(phy, i - 9, 1620 j * 2); 1621 if (!tmp_control->used) 1622 continue; 1623 memcpy(&control, tmp_control, sizeof(control)); 1624 r27 = 3; 1625 r31 = 0; 1626 } 1627 b43legacy_radio_write16(dev, 0x43, i - 9); 1628 /* FIXME: shouldn't txctl1 be zero in the next line 1629 * and 3 in the loop above? */ 1630 b43legacy_radio_write16(dev, 0x52, 1631 phy->txctl2 1632 | (3/*txctl1*/ << 4)); 1633 udelay(10); 1634 cond_resched(); 1635 1636 b43legacy_phy_set_baseband_attenuation(dev, j * 2); 1637 1638 tmp = (regstack[10] & 0xFFF0); 1639 if (r31) 1640 tmp |= 0x0008; 1641 b43legacy_radio_write16(dev, 0x7A, tmp); 1642 1643 tmp_control = b43legacy_get_lopair(phy, i, j * 2); 1644 b43legacy_phy_lo_g_state(dev, &control, tmp_control, 1645 r27); 1646 } 1647 } 1648 1649 /* Restoration */ 1650 if (phy->gmode) { 1651 b43legacy_phy_write(dev, 0x0015, 0xE300); 1652 b43legacy_phy_write(dev, 0x0812, (r27 << 8) | 0xA0); 1653 udelay(5); 1654 b43legacy_phy_write(dev, 0x0812, (r27 << 8) | 0xA2); 1655 udelay(2); 1656 b43legacy_phy_write(dev, 0x0812, (r27 << 8) | 0xA3); 1657 cond_resched(); 1658 } else 1659 b43legacy_phy_write(dev, 0x0015, r27 | 0xEFA0); 1660 b43legacy_phy_lo_adjust(dev, is_initializing); 1661 b43legacy_phy_write(dev, 0x002E, 0x807F); 1662 if (phy->gmode) 1663 b43legacy_phy_write(dev, 0x002F, 0x0202); 1664 else 1665 b43legacy_phy_write(dev, 0x002F, 0x0101); 1666 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, regstack[4]); 1667 b43legacy_phy_write(dev, 0x0015, regstack[5]); 1668 b43legacy_phy_write(dev, 0x002A, regstack[6]); 1669 b43legacy_phy_write(dev, 0x0035, regstack[7]); 1670 b43legacy_phy_write(dev, 0x0060, regstack[8]); 1671 b43legacy_radio_write16(dev, 0x0043, regstack[9]); 1672 b43legacy_radio_write16(dev, 0x007A, regstack[10]); 1673 regstack[11] &= 0x00F0; 1674 regstack[11] |= (b43legacy_radio_read16(dev, 0x52) & 0x000F); 1675 b43legacy_radio_write16(dev, 0x52, regstack[11]); 1676 b43legacy_write16(dev, 0x03E2, regstack[3]); 1677 if (phy->gmode) { 1678 b43legacy_phy_write(dev, 0x0811, regstack[12]); 1679 b43legacy_phy_write(dev, 0x0812, regstack[13]); 1680 b43legacy_phy_write(dev, 0x0814, regstack[14]); 1681 b43legacy_phy_write(dev, 0x0815, regstack[15]); 1682 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, regstack[0]); 1683 b43legacy_phy_write(dev, 0x0802, regstack[1]); 1684 } 1685 b43legacy_radio_selectchannel(dev, oldchannel, 1); 1686 1687#ifdef CONFIG_B43LEGACY_DEBUG 1688 { 1689 /* Sanity check for all lopairs. */ 1690 for (i = 0; i < B43legacy_LO_COUNT; i++) { 1691 tmp_control = phy->_lo_pairs + i; 1692 if (tmp_control->low < -8 || tmp_control->low > 8 || 1693 tmp_control->high < -8 || tmp_control->high > 8) 1694 b43legacywarn(dev->wl, 1695 "WARNING: Invalid LOpair (low: %d, high:" 1696 " %d, index: %d)\n", 1697 tmp_control->low, tmp_control->high, i); 1698 } 1699 } 1700#endif /* CONFIG_B43LEGACY_DEBUG */ 1701} 1702 1703static 1704void b43legacy_phy_lo_mark_current_used(struct b43legacy_wldev *dev) 1705{ 1706 struct b43legacy_lopair *pair; 1707 1708 pair = b43legacy_current_lopair(dev); 1709 pair->used = 1; 1710} 1711 1712void b43legacy_phy_lo_mark_all_unused(struct b43legacy_wldev *dev) 1713{ 1714 struct b43legacy_phy *phy = &dev->phy; 1715 struct b43legacy_lopair *pair; 1716 int i; 1717 1718 for (i = 0; i < B43legacy_LO_COUNT; i++) { 1719 pair = phy->_lo_pairs + i; 1720 pair->used = 0; 1721 } 1722} 1723 1724/* https://bcm-specs.sipsolutions.net/EstimatePowerOut 1725 * This function converts a TSSI value to dBm in Q5.2 1726 */ 1727static s8 b43legacy_phy_estimate_power_out(struct b43legacy_wldev *dev, s8 tssi) 1728{ 1729 struct b43legacy_phy *phy = &dev->phy; 1730 s8 dbm = 0; 1731 s32 tmp; 1732 1733 tmp = phy->idle_tssi; 1734 tmp += tssi; 1735 tmp -= phy->savedpctlreg; 1736 1737 switch (phy->type) { 1738 case B43legacy_PHYTYPE_B: 1739 case B43legacy_PHYTYPE_G: 1740 tmp = clamp_val(tmp, 0x00, 0x3F); 1741 dbm = phy->tssi2dbm[tmp]; 1742 break; 1743 default: 1744 B43legacy_BUG_ON(1); 1745 } 1746 1747 return dbm; 1748} 1749 1750/* https://bcm-specs.sipsolutions.net/RecalculateTransmissionPower */ 1751void b43legacy_phy_xmitpower(struct b43legacy_wldev *dev) 1752{ 1753 struct b43legacy_phy *phy = &dev->phy; 1754 u16 tmp; 1755 u16 txpower; 1756 s8 v0; 1757 s8 v1; 1758 s8 v2; 1759 s8 v3; 1760 s8 average; 1761 int max_pwr; 1762 s16 desired_pwr; 1763 s16 estimated_pwr; 1764 s16 pwr_adjust; 1765 s16 radio_att_delta; 1766 s16 baseband_att_delta; 1767 s16 radio_attenuation; 1768 s16 baseband_attenuation; 1769 1770 if (phy->savedpctlreg == 0xFFFF) 1771 return; 1772 if ((dev->dev->bus->boardinfo.type == 0x0416) && 1773 is_bcm_board_vendor(dev)) 1774 return; 1775#ifdef CONFIG_B43LEGACY_DEBUG 1776 if (phy->manual_txpower_control) 1777 return; 1778#endif 1779 1780 B43legacy_BUG_ON(!(phy->type == B43legacy_PHYTYPE_B || 1781 phy->type == B43legacy_PHYTYPE_G)); 1782 tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0058); 1783 v0 = (s8)(tmp & 0x00FF); 1784 v1 = (s8)((tmp & 0xFF00) >> 8); 1785 tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x005A); 1786 v2 = (s8)(tmp & 0x00FF); 1787 v3 = (s8)((tmp & 0xFF00) >> 8); 1788 tmp = 0; 1789 1790 if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) { 1791 tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 1792 0x0070); 1793 v0 = (s8)(tmp & 0x00FF); 1794 v1 = (s8)((tmp & 0xFF00) >> 8); 1795 tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 1796 0x0072); 1797 v2 = (s8)(tmp & 0x00FF); 1798 v3 = (s8)((tmp & 0xFF00) >> 8); 1799 if (v0 == 0x7F || v1 == 0x7F || v2 == 0x7F || v3 == 0x7F) 1800 return; 1801 v0 = (v0 + 0x20) & 0x3F; 1802 v1 = (v1 + 0x20) & 0x3F; 1803 v2 = (v2 + 0x20) & 0x3F; 1804 v3 = (v3 + 0x20) & 0x3F; 1805 tmp = 1; 1806 } 1807 b43legacy_radio_clear_tssi(dev); 1808 1809 average = (v0 + v1 + v2 + v3 + 2) / 4; 1810 1811 if (tmp && (b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x005E) 1812 & 0x8)) 1813 average -= 13; 1814 1815 estimated_pwr = b43legacy_phy_estimate_power_out(dev, average); 1816 1817 max_pwr = dev->dev->bus->sprom.maxpwr_bg; 1818 1819 if ((dev->dev->bus->sprom.boardflags_lo 1820 & B43legacy_BFL_PACTRL) && 1821 (phy->type == B43legacy_PHYTYPE_G)) 1822 max_pwr -= 0x3; 1823 if (unlikely(max_pwr <= 0)) { 1824 b43legacywarn(dev->wl, "Invalid max-TX-power value in SPROM." 1825 "\n"); 1826 max_pwr = 74; /* fake it */ 1827 dev->dev->bus->sprom.maxpwr_bg = max_pwr; 1828 } 1829 1830 /* Use regulatory information to get the maximum power. 1831 * In the absence of such data from mac80211, we will use 20 dBm, which 1832 * is the value for the EU, US, Canada, and most of the world. 1833 * The regulatory maximum is reduced by the antenna gain (from sprom) 1834 * and 1.5 dBm (a safety factor??). The result is in Q5.2 format 1835 * which accounts for the factor of 4 */ 1836#define REG_MAX_PWR 20 1837 max_pwr = min(REG_MAX_PWR * 4 1838 - dev->dev->bus->sprom.antenna_gain.a0 1839 - 0x6, max_pwr); 1840 1841 /* find the desired power in Q5.2 - power_level is in dBm 1842 * and limit it - max_pwr is already in Q5.2 */ 1843 desired_pwr = clamp_val(phy->power_level << 2, 0, max_pwr); 1844 if (b43legacy_debug(dev, B43legacy_DBG_XMITPOWER)) 1845 b43legacydbg(dev->wl, "Current TX power output: " Q52_FMT 1846 " dBm, Desired TX power output: " Q52_FMT 1847 " dBm\n", Q52_ARG(estimated_pwr), 1848 Q52_ARG(desired_pwr)); 1849 /* Check if we need to adjust the current power. The factor of 2 is 1850 * for damping */ 1851 pwr_adjust = (desired_pwr - estimated_pwr) / 2; 1852 /* RF attenuation delta 1853 * The minus sign is because lower attenuation => more power */ 1854 radio_att_delta = -(pwr_adjust + 7) >> 3; 1855 /* Baseband attenuation delta */ 1856 baseband_att_delta = -(pwr_adjust >> 1) - (4 * radio_att_delta); 1857 /* Do we need to adjust anything? */ 1858 if ((radio_att_delta == 0) && (baseband_att_delta == 0)) { 1859 b43legacy_phy_lo_mark_current_used(dev); 1860 return; 1861 } 1862 1863 /* Calculate the new attenuation values. */ 1864 baseband_attenuation = phy->bbatt; 1865 baseband_attenuation += baseband_att_delta; 1866 radio_attenuation = phy->rfatt; 1867 radio_attenuation += radio_att_delta; 1868 1869 /* Get baseband and radio attenuation values into permitted ranges. 1870 * baseband 0-11, radio 0-9. 1871 * Radio attenuation affects power level 4 times as much as baseband. 1872 */ 1873 if (radio_attenuation < 0) { 1874 baseband_attenuation -= (4 * -radio_attenuation); 1875 radio_attenuation = 0; 1876 } else if (radio_attenuation > 9) { 1877 baseband_attenuation += (4 * (radio_attenuation - 9)); 1878 radio_attenuation = 9; 1879 } else { 1880 while (baseband_attenuation < 0 && radio_attenuation > 0) { 1881 baseband_attenuation += 4; 1882 radio_attenuation--; 1883 } 1884 while (baseband_attenuation > 11 && radio_attenuation < 9) { 1885 baseband_attenuation -= 4; 1886 radio_attenuation++; 1887 } 1888 } 1889 baseband_attenuation = clamp_val(baseband_attenuation, 0, 11); 1890 1891 txpower = phy->txctl1; 1892 if ((phy->radio_ver == 0x2050) && (phy->radio_rev == 2)) { 1893 if (radio_attenuation <= 1) { 1894 if (txpower == 0) { 1895 txpower = 3; 1896 radio_attenuation += 2; 1897 baseband_attenuation += 2; 1898 } else if (dev->dev->bus->sprom.boardflags_lo 1899 & B43legacy_BFL_PACTRL) { 1900 baseband_attenuation += 4 * 1901 (radio_attenuation - 2); 1902 radio_attenuation = 2; 1903 } 1904 } else if (radio_attenuation > 4 && txpower != 0) { 1905 txpower = 0; 1906 if (baseband_attenuation < 3) { 1907 radio_attenuation -= 3; 1908 baseband_attenuation += 2; 1909 } else { 1910 radio_attenuation -= 2; 1911 baseband_attenuation -= 2; 1912 } 1913 } 1914 } 1915 /* Save the control values */ 1916 phy->txctl1 = txpower; 1917 baseband_attenuation = clamp_val(baseband_attenuation, 0, 11); 1918 radio_attenuation = clamp_val(radio_attenuation, 0, 9); 1919 phy->rfatt = radio_attenuation; 1920 phy->bbatt = baseband_attenuation; 1921 1922 /* Adjust the hardware */ 1923 b43legacy_phy_lock(dev); 1924 b43legacy_radio_lock(dev); 1925 b43legacy_radio_set_txpower_bg(dev, baseband_attenuation, 1926 radio_attenuation, txpower); 1927 b43legacy_phy_lo_mark_current_used(dev); 1928 b43legacy_radio_unlock(dev); 1929 b43legacy_phy_unlock(dev); 1930} 1931 1932static inline 1933s32 b43legacy_tssi2dbm_ad(s32 num, s32 den) 1934{ 1935 if (num < 0) 1936 return num/den; 1937 else 1938 return (num+den/2)/den; 1939} 1940 1941static inline 1942s8 b43legacy_tssi2dbm_entry(s8 entry [], u8 index, s16 pab0, s16 pab1, s16 pab2) 1943{ 1944 s32 m1; 1945 s32 m2; 1946 s32 f = 256; 1947 s32 q; 1948 s32 delta; 1949 s8 i = 0; 1950 1951 m1 = b43legacy_tssi2dbm_ad(16 * pab0 + index * pab1, 32); 1952 m2 = max(b43legacy_tssi2dbm_ad(32768 + index * pab2, 256), 1); 1953 do { 1954 if (i > 15) 1955 return -EINVAL; 1956 q = b43legacy_tssi2dbm_ad(f * 4096 - 1957 b43legacy_tssi2dbm_ad(m2 * f, 16) * 1958 f, 2048); 1959 delta = abs(q - f); 1960 f = q; 1961 i++; 1962 } while (delta >= 2); 1963 entry[index] = clamp_val(b43legacy_tssi2dbm_ad(m1 * f, 8192), 1964 -127, 128); 1965 return 0; 1966} 1967 1968/* http://bcm-specs.sipsolutions.net/TSSI_to_DBM_Table */ 1969int b43legacy_phy_init_tssi2dbm_table(struct b43legacy_wldev *dev) 1970{ 1971 struct b43legacy_phy *phy = &dev->phy; 1972 s16 pab0; 1973 s16 pab1; 1974 s16 pab2; 1975 u8 idx; 1976 s8 *dyn_tssi2dbm; 1977 1978 B43legacy_WARN_ON(!(phy->type == B43legacy_PHYTYPE_B || 1979 phy->type == B43legacy_PHYTYPE_G)); 1980 pab0 = (s16)(dev->dev->bus->sprom.pa0b0); 1981 pab1 = (s16)(dev->dev->bus->sprom.pa0b1); 1982 pab2 = (s16)(dev->dev->bus->sprom.pa0b2); 1983 1984 if ((dev->dev->bus->chip_id == 0x4301) && (phy->radio_ver != 0x2050)) { 1985 phy->idle_tssi = 0x34; 1986 phy->tssi2dbm = b43legacy_tssi2dbm_b_table; 1987 return 0; 1988 } 1989 1990 if (pab0 != 0 && pab1 != 0 && pab2 != 0 && 1991 pab0 != -1 && pab1 != -1 && pab2 != -1) { 1992 /* The pabX values are set in SPROM. Use them. */ 1993 if ((s8)dev->dev->bus->sprom.itssi_bg != 0 && 1994 (s8)dev->dev->bus->sprom.itssi_bg != -1) 1995 phy->idle_tssi = (s8)(dev->dev->bus->sprom. 1996 itssi_bg); 1997 else 1998 phy->idle_tssi = 62; 1999 dyn_tssi2dbm = kmalloc(64, GFP_KERNEL); 2000 if (dyn_tssi2dbm == NULL) { 2001 b43legacyerr(dev->wl, "Could not allocate memory " 2002 "for tssi2dbm table\n"); 2003 return -ENOMEM; 2004 } 2005 for (idx = 0; idx < 64; idx++) 2006 if (b43legacy_tssi2dbm_entry(dyn_tssi2dbm, idx, pab0, 2007 pab1, pab2)) { 2008 phy->tssi2dbm = NULL; 2009 b43legacyerr(dev->wl, "Could not generate " 2010 "tssi2dBm table\n"); 2011 kfree(dyn_tssi2dbm); 2012 return -ENODEV; 2013 } 2014 phy->tssi2dbm = dyn_tssi2dbm; 2015 phy->dyn_tssi_tbl = 1; 2016 } else { 2017 /* pabX values not set in SPROM. */ 2018 switch (phy->type) { 2019 case B43legacy_PHYTYPE_B: 2020 phy->idle_tssi = 0x34; 2021 phy->tssi2dbm = b43legacy_tssi2dbm_b_table; 2022 break; 2023 case B43legacy_PHYTYPE_G: 2024 phy->idle_tssi = 0x34; 2025 phy->tssi2dbm = b43legacy_tssi2dbm_g_table; 2026 break; 2027 } 2028 } 2029 2030 return 0; 2031} 2032 2033int b43legacy_phy_init(struct b43legacy_wldev *dev) 2034{ 2035 struct b43legacy_phy *phy = &dev->phy; 2036 int err = -ENODEV; 2037 2038 switch (phy->type) { 2039 case B43legacy_PHYTYPE_B: 2040 switch (phy->rev) { 2041 case 2: 2042 b43legacy_phy_initb2(dev); 2043 err = 0; 2044 break; 2045 case 4: 2046 b43legacy_phy_initb4(dev); 2047 err = 0; 2048 break; 2049 case 5: 2050 b43legacy_phy_initb5(dev); 2051 err = 0; 2052 break; 2053 case 6: 2054 b43legacy_phy_initb6(dev); 2055 err = 0; 2056 break; 2057 } 2058 break; 2059 case B43legacy_PHYTYPE_G: 2060 b43legacy_phy_initg(dev); 2061 err = 0; 2062 break; 2063 } 2064 if (err) 2065 b43legacyerr(dev->wl, "Unknown PHYTYPE found\n"); 2066 2067 return err; 2068} 2069 2070void b43legacy_phy_set_antenna_diversity(struct b43legacy_wldev *dev) 2071{ 2072 struct b43legacy_phy *phy = &dev->phy; 2073 u16 antennadiv; 2074 u16 offset; 2075 u16 value; 2076 u32 ucodeflags; 2077 2078 antennadiv = phy->antenna_diversity; 2079 2080 if (antennadiv == 0xFFFF) 2081 antennadiv = 3; 2082 B43legacy_WARN_ON(antennadiv > 3); 2083 2084 ucodeflags = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, 2085 B43legacy_UCODEFLAGS_OFFSET); 2086 b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 2087 B43legacy_UCODEFLAGS_OFFSET, 2088 ucodeflags & ~B43legacy_UCODEFLAG_AUTODIV); 2089 2090 switch (phy->type) { 2091 case B43legacy_PHYTYPE_G: 2092 offset = 0x0400; 2093 2094 if (antennadiv == 2) 2095 value = (3/*automatic*/ << 7); 2096 else 2097 value = (antennadiv << 7); 2098 b43legacy_phy_write(dev, offset + 1, 2099 (b43legacy_phy_read(dev, offset + 1) 2100 & 0x7E7F) | value); 2101 2102 if (antennadiv >= 2) { 2103 if (antennadiv == 2) 2104 value = (antennadiv << 7); 2105 else 2106 value = (0/*force0*/ << 7); 2107 b43legacy_phy_write(dev, offset + 0x2B, 2108 (b43legacy_phy_read(dev, 2109 offset + 0x2B) 2110 & 0xFEFF) | value); 2111 } 2112 2113 if (phy->type == B43legacy_PHYTYPE_G) { 2114 if (antennadiv >= 2) 2115 b43legacy_phy_write(dev, 0x048C, 2116 b43legacy_phy_read(dev, 2117 0x048C) | 0x2000); 2118 else 2119 b43legacy_phy_write(dev, 0x048C, 2120 b43legacy_phy_read(dev, 2121 0x048C) & ~0x2000); 2122 if (phy->rev >= 2) { 2123 b43legacy_phy_write(dev, 0x0461, 2124 b43legacy_phy_read(dev, 2125 0x0461) | 0x0010); 2126 b43legacy_phy_write(dev, 0x04AD, 2127 (b43legacy_phy_read(dev, 2128 0x04AD) 2129 & 0x00FF) | 0x0015); 2130 if (phy->rev == 2) 2131 b43legacy_phy_write(dev, 0x0427, 2132 0x0008); 2133 else 2134 b43legacy_phy_write(dev, 0x0427, 2135 (b43legacy_phy_read(dev, 0x0427) 2136 & 0x00FF) | 0x0008); 2137 } else if (phy->rev >= 6) 2138 b43legacy_phy_write(dev, 0x049B, 0x00DC); 2139 } else { 2140 if (phy->rev < 3) 2141 b43legacy_phy_write(dev, 0x002B, 2142 (b43legacy_phy_read(dev, 2143 0x002B) & 0x00FF) 2144 | 0x0024); 2145 else { 2146 b43legacy_phy_write(dev, 0x0061, 2147 b43legacy_phy_read(dev, 2148 0x0061) | 0x0010); 2149 if (phy->rev == 3) { 2150 b43legacy_phy_write(dev, 0x0093, 2151 0x001D); 2152 b43legacy_phy_write(dev, 0x0027, 2153 0x0008); 2154 } else { 2155 b43legacy_phy_write(dev, 0x0093, 2156 0x003A); 2157 b43legacy_phy_write(dev, 0x0027, 2158 (b43legacy_phy_read(dev, 0x0027) 2159 & 0x00FF) | 0x0008); 2160 } 2161 } 2162 } 2163 break; 2164 case B43legacy_PHYTYPE_B: 2165 if (dev->dev->id.revision == 2) 2166 value = (3/*automatic*/ << 7); 2167 else 2168 value = (antennadiv << 7); 2169 b43legacy_phy_write(dev, 0x03E2, 2170 (b43legacy_phy_read(dev, 0x03E2) 2171 & 0xFE7F) | value); 2172 break; 2173 default: 2174 B43legacy_WARN_ON(1); 2175 } 2176 2177 if (antennadiv >= 2) { 2178 ucodeflags = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, 2179 B43legacy_UCODEFLAGS_OFFSET); 2180 b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 2181 B43legacy_UCODEFLAGS_OFFSET, 2182 ucodeflags | B43legacy_UCODEFLAG_AUTODIV); 2183 } 2184 2185 phy->antenna_diversity = antennadiv; 2186} 2187 2188/* Set the PowerSavingControlBits. 2189 * Bitvalues: 2190 * 0 => unset the bit 2191 * 1 => set the bit 2192 * -1 => calculate the bit 2193 */ 2194void b43legacy_power_saving_ctl_bits(struct b43legacy_wldev *dev, 2195 int bit25, int bit26) 2196{ 2197 int i; 2198 u32 status; 2199 2200/* FIXME: Force 25 to off and 26 to on for now: */ 2201bit25 = 0; 2202bit26 = 1; 2203 2204 if (bit25 == -1) { 2205 /* TODO: If powersave is not off and FIXME is not set and we 2206 * are not in adhoc and thus is not an AP and we arei 2207 * associated, set bit 25 */ 2208 } 2209 if (bit26 == -1) { 2210 /* TODO: If the device is awake or this is an AP, or we are 2211 * scanning, or FIXME, or we are associated, or FIXME, 2212 * or the latest PS-Poll packet sent was successful, 2213 * set bit26 */ 2214 } 2215 status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); 2216 if (bit25) 2217 status |= B43legacy_MACCTL_HWPS; 2218 else 2219 status &= ~B43legacy_MACCTL_HWPS; 2220 if (bit26) 2221 status |= B43legacy_MACCTL_AWAKE; 2222 else 2223 status &= ~B43legacy_MACCTL_AWAKE; 2224 b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); 2225 if (bit26 && dev->dev->id.revision >= 5) { 2226 for (i = 0; i < 100; i++) { 2227 if (b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, 2228 0x0040) != 4) 2229 break; 2230 udelay(10); 2231 } 2232 } 2233}