1 /* 2 3 Broadcom B43legacy wireless driver 4 5 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>, 6 Stefano Brivio <stefano.brivio@polimi.it> 7 Michael Buesch <m@bues.ch> 8 Danny van Dyk <kugelfang@gentoo.org> 9 Andreas Jaggi <andreas.jaggi@waterwave.ch> 10 Copyright (c) 2007 Larry Finger <Larry.Finger@lwfinger.net> 11 12 Some parts of the code in this file are derived from the ipw2200 13 driver Copyright(c) 2003 - 2004 Intel Corporation. 14 15 This program is free software; you can redistribute it and/or modify 16 it under the terms of the GNU General Public License as published by 17 the Free Software Foundation; either version 2 of the License, or 18 (at your option) any later version. 19 20 This program is distributed in the hope that it will be useful, 21 but WITHOUT ANY WARRANTY; without even the implied warranty of 22 MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the 23 GNU General Public License for more details. 24 25 You should have received a copy of the GNU General Public License 26 along with this program; see the file COPYING. If not, write to 27 the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor, 28 Boston, MA 02110-1301, USA. 29 30 */ 31 32 #include <linux/delay.h> 33 34 #include "b43legacy.h" 35 #include "main.h" 36 #include "phy.h" 37 #include "radio.h" 38 #include "ilt.h" 39 40 41 /* Table for b43legacy_radio_calibrationvalue() */ 42 static const u16 rcc_table[16] = { 43 0x0002, 0x0003, 0x0001, 0x000F, 44 0x0006, 0x0007, 0x0005, 0x000F, 45 0x000A, 0x000B, 0x0009, 0x000F, 46 0x000E, 0x000F, 0x000D, 0x000F, 47 }; 48 49 /* Reverse the bits of a 4bit value. 50 * Example: 1101 is flipped 1011 51 */ 52 static u16 flip_4bit(u16 value) 53 { 54 u16 flipped = 0x0000; 55 56 B43legacy_BUG_ON(!((value & ~0x000F) == 0x0000)); 57 58 flipped |= (value & 0x0001) << 3; 59 flipped |= (value & 0x0002) << 1; 60 flipped |= (value & 0x0004) >> 1; 61 flipped |= (value & 0x0008) >> 3; 62 63 return flipped; 64 } 65 66 /* Get the freq, as it has to be written to the device. */ 67 static inline 68 u16 channel2freq_bg(u8 channel) 69 { 70 /* Frequencies are given as frequencies_bg[index] + 2.4GHz 71 * Starting with channel 1 72 */ 73 static const u16 frequencies_bg[14] = { 74 12, 17, 22, 27, 75 32, 37, 42, 47, 76 52, 57, 62, 67, 77 72, 84, 78 }; 79 80 if (unlikely(channel < 1 || channel > 14)) { 81 printk(KERN_INFO "b43legacy: Channel %d is out of range\n", 82 channel); 83 dump_stack(); 84 return 2412; 85 } 86 87 return frequencies_bg[channel - 1]; 88 } 89 90 void b43legacy_radio_lock(struct b43legacy_wldev *dev) 91 { 92 u32 status; 93 94 status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); 95 B43legacy_WARN_ON(status & B43legacy_MACCTL_RADIOLOCK); 96 status |= B43legacy_MACCTL_RADIOLOCK; 97 b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); 98 udelay(10); 99 } 100 101 void b43legacy_radio_unlock(struct b43legacy_wldev *dev) 102 { 103 u32 status; 104 105 b43legacy_read16(dev, B43legacy_MMIO_PHY_VER); /* dummy read */ 106 status = b43legacy_read32(dev, B43legacy_MMIO_MACCTL); 107 B43legacy_WARN_ON(!(status & B43legacy_MACCTL_RADIOLOCK)); 108 status &= ~B43legacy_MACCTL_RADIOLOCK; 109 b43legacy_write32(dev, B43legacy_MMIO_MACCTL, status); 110 } 111 112 u16 b43legacy_radio_read16(struct b43legacy_wldev *dev, u16 offset) 113 { 114 struct b43legacy_phy *phy = &dev->phy; 115 116 switch (phy->type) { 117 case B43legacy_PHYTYPE_B: 118 if (phy->radio_ver == 0x2053) { 119 if (offset < 0x70) 120 offset += 0x80; 121 else if (offset < 0x80) 122 offset += 0x70; 123 } else if (phy->radio_ver == 0x2050) 124 offset |= 0x80; 125 else 126 B43legacy_WARN_ON(1); 127 break; 128 case B43legacy_PHYTYPE_G: 129 offset |= 0x80; 130 break; 131 default: 132 B43legacy_BUG_ON(1); 133 } 134 135 b43legacy_write16(dev, B43legacy_MMIO_RADIO_CONTROL, offset); 136 return b43legacy_read16(dev, B43legacy_MMIO_RADIO_DATA_LOW); 137 } 138 139 void b43legacy_radio_write16(struct b43legacy_wldev *dev, u16 offset, u16 val) 140 { 141 b43legacy_write16(dev, B43legacy_MMIO_RADIO_CONTROL, offset); 142 b43legacy_write16(dev, B43legacy_MMIO_RADIO_DATA_LOW, val); 143 } 144 145 static void b43legacy_set_all_gains(struct b43legacy_wldev *dev, 146 s16 first, s16 second, s16 third) 147 { 148 struct b43legacy_phy *phy = &dev->phy; 149 u16 i; 150 u16 start = 0x08; 151 u16 end = 0x18; 152 u16 offset = 0x0400; 153 u16 tmp; 154 155 if (phy->rev <= 1) { 156 offset = 0x5000; 157 start = 0x10; 158 end = 0x20; 159 } 160 161 for (i = 0; i < 4; i++) 162 b43legacy_ilt_write(dev, offset + i, first); 163 164 for (i = start; i < end; i++) 165 b43legacy_ilt_write(dev, offset + i, second); 166 167 if (third != -1) { 168 tmp = ((u16)third << 14) | ((u16)third << 6); 169 b43legacy_phy_write(dev, 0x04A0, 170 (b43legacy_phy_read(dev, 0x04A0) & 0xBFBF) 171 | tmp); 172 b43legacy_phy_write(dev, 0x04A1, 173 (b43legacy_phy_read(dev, 0x04A1) & 0xBFBF) 174 | tmp); 175 b43legacy_phy_write(dev, 0x04A2, 176 (b43legacy_phy_read(dev, 0x04A2) & 0xBFBF) 177 | tmp); 178 } 179 b43legacy_dummy_transmission(dev); 180 } 181 182 static void b43legacy_set_original_gains(struct b43legacy_wldev *dev) 183 { 184 struct b43legacy_phy *phy = &dev->phy; 185 u16 i; 186 u16 tmp; 187 u16 offset = 0x0400; 188 u16 start = 0x0008; 189 u16 end = 0x0018; 190 191 if (phy->rev <= 1) { 192 offset = 0x5000; 193 start = 0x0010; 194 end = 0x0020; 195 } 196 197 for (i = 0; i < 4; i++) { 198 tmp = (i & 0xFFFC); 199 tmp |= (i & 0x0001) << 1; 200 tmp |= (i & 0x0002) >> 1; 201 202 b43legacy_ilt_write(dev, offset + i, tmp); 203 } 204 205 for (i = start; i < end; i++) 206 b43legacy_ilt_write(dev, offset + i, i - start); 207 208 b43legacy_phy_write(dev, 0x04A0, 209 (b43legacy_phy_read(dev, 0x04A0) & 0xBFBF) 210 | 0x4040); 211 b43legacy_phy_write(dev, 0x04A1, 212 (b43legacy_phy_read(dev, 0x04A1) & 0xBFBF) 213 | 0x4040); 214 b43legacy_phy_write(dev, 0x04A2, 215 (b43legacy_phy_read(dev, 0x04A2) & 0xBFBF) 216 | 0x4000); 217 b43legacy_dummy_transmission(dev); 218 } 219 220 /* Synthetic PU workaround */ 221 static void b43legacy_synth_pu_workaround(struct b43legacy_wldev *dev, 222 u8 channel) 223 { 224 struct b43legacy_phy *phy = &dev->phy; 225 226 might_sleep(); 227 228 if (phy->radio_ver != 0x2050 || phy->radio_rev >= 6) 229 /* We do not need the workaround. */ 230 return; 231 232 if (channel <= 10) 233 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL, 234 channel2freq_bg(channel + 4)); 235 else 236 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL, 237 channel2freq_bg(channel)); 238 msleep(1); 239 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL, 240 channel2freq_bg(channel)); 241 } 242 243 u8 b43legacy_radio_aci_detect(struct b43legacy_wldev *dev, u8 channel) 244 { 245 struct b43legacy_phy *phy = &dev->phy; 246 u8 ret = 0; 247 u16 saved; 248 u16 rssi; 249 u16 temp; 250 int i; 251 int j = 0; 252 253 saved = b43legacy_phy_read(dev, 0x0403); 254 b43legacy_radio_selectchannel(dev, channel, 0); 255 b43legacy_phy_write(dev, 0x0403, (saved & 0xFFF8) | 5); 256 if (phy->aci_hw_rssi) 257 rssi = b43legacy_phy_read(dev, 0x048A) & 0x3F; 258 else 259 rssi = saved & 0x3F; 260 /* clamp temp to signed 5bit */ 261 if (rssi > 32) 262 rssi -= 64; 263 for (i = 0; i < 100; i++) { 264 temp = (b43legacy_phy_read(dev, 0x047F) >> 8) & 0x3F; 265 if (temp > 32) 266 temp -= 64; 267 if (temp < rssi) 268 j++; 269 if (j >= 20) 270 ret = 1; 271 } 272 b43legacy_phy_write(dev, 0x0403, saved); 273 274 return ret; 275 } 276 277 u8 b43legacy_radio_aci_scan(struct b43legacy_wldev *dev) 278 { 279 struct b43legacy_phy *phy = &dev->phy; 280 u8 ret[13] = { 0 }; 281 unsigned int channel = phy->channel; 282 unsigned int i; 283 unsigned int j; 284 unsigned int start; 285 unsigned int end; 286 287 if (!((phy->type == B43legacy_PHYTYPE_G) && (phy->rev > 0))) 288 return 0; 289 290 b43legacy_phy_lock(dev); 291 b43legacy_radio_lock(dev); 292 b43legacy_phy_write(dev, 0x0802, 293 b43legacy_phy_read(dev, 0x0802) & 0xFFFC); 294 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, 295 b43legacy_phy_read(dev, B43legacy_PHY_G_CRS) 296 & 0x7FFF); 297 b43legacy_set_all_gains(dev, 3, 8, 1); 298 299 start = (channel - 5 > 0) ? channel - 5 : 1; 300 end = (channel + 5 < 14) ? channel + 5 : 13; 301 302 for (i = start; i <= end; i++) { 303 if (abs(channel - i) > 2) 304 ret[i-1] = b43legacy_radio_aci_detect(dev, i); 305 } 306 b43legacy_radio_selectchannel(dev, channel, 0); 307 b43legacy_phy_write(dev, 0x0802, 308 (b43legacy_phy_read(dev, 0x0802) & 0xFFFC) 309 | 0x0003); 310 b43legacy_phy_write(dev, 0x0403, 311 b43legacy_phy_read(dev, 0x0403) & 0xFFF8); 312 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, 313 b43legacy_phy_read(dev, B43legacy_PHY_G_CRS) 314 | 0x8000); 315 b43legacy_set_original_gains(dev); 316 for (i = 0; i < 13; i++) { 317 if (!ret[i]) 318 continue; 319 end = (i + 5 < 13) ? i + 5 : 13; 320 for (j = i; j < end; j++) 321 ret[j] = 1; 322 } 323 b43legacy_radio_unlock(dev); 324 b43legacy_phy_unlock(dev); 325 326 return ret[channel - 1]; 327 } 328 329 /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ 330 void b43legacy_nrssi_hw_write(struct b43legacy_wldev *dev, u16 offset, s16 val) 331 { 332 b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_CTRL, offset); 333 b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_DATA, (u16)val); 334 } 335 336 /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ 337 s16 b43legacy_nrssi_hw_read(struct b43legacy_wldev *dev, u16 offset) 338 { 339 u16 val; 340 341 b43legacy_phy_write(dev, B43legacy_PHY_NRSSILT_CTRL, offset); 342 val = b43legacy_phy_read(dev, B43legacy_PHY_NRSSILT_DATA); 343 344 return (s16)val; 345 } 346 347 /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ 348 void b43legacy_nrssi_hw_update(struct b43legacy_wldev *dev, u16 val) 349 { 350 u16 i; 351 s16 tmp; 352 353 for (i = 0; i < 64; i++) { 354 tmp = b43legacy_nrssi_hw_read(dev, i); 355 tmp -= val; 356 tmp = clamp_val(tmp, -32, 31); 357 b43legacy_nrssi_hw_write(dev, i, tmp); 358 } 359 } 360 361 /* http://bcm-specs.sipsolutions.net/NRSSILookupTable */ 362 void b43legacy_nrssi_mem_update(struct b43legacy_wldev *dev) 363 { 364 struct b43legacy_phy *phy = &dev->phy; 365 s16 i; 366 s16 delta; 367 s32 tmp; 368 369 delta = 0x1F - phy->nrssi[0]; 370 for (i = 0; i < 64; i++) { 371 tmp = (i - delta) * phy->nrssislope; 372 tmp /= 0x10000; 373 tmp += 0x3A; 374 tmp = clamp_val(tmp, 0, 0x3F); 375 phy->nrssi_lt[i] = tmp; 376 } 377 } 378 379 static void b43legacy_calc_nrssi_offset(struct b43legacy_wldev *dev) 380 { 381 struct b43legacy_phy *phy = &dev->phy; 382 u16 backup[20] = { 0 }; 383 s16 v47F; 384 u16 i; 385 u16 saved = 0xFFFF; 386 387 backup[0] = b43legacy_phy_read(dev, 0x0001); 388 backup[1] = b43legacy_phy_read(dev, 0x0811); 389 backup[2] = b43legacy_phy_read(dev, 0x0812); 390 backup[3] = b43legacy_phy_read(dev, 0x0814); 391 backup[4] = b43legacy_phy_read(dev, 0x0815); 392 backup[5] = b43legacy_phy_read(dev, 0x005A); 393 backup[6] = b43legacy_phy_read(dev, 0x0059); 394 backup[7] = b43legacy_phy_read(dev, 0x0058); 395 backup[8] = b43legacy_phy_read(dev, 0x000A); 396 backup[9] = b43legacy_phy_read(dev, 0x0003); 397 backup[10] = b43legacy_radio_read16(dev, 0x007A); 398 backup[11] = b43legacy_radio_read16(dev, 0x0043); 399 400 b43legacy_phy_write(dev, 0x0429, 401 b43legacy_phy_read(dev, 0x0429) & 0x7FFF); 402 b43legacy_phy_write(dev, 0x0001, 403 (b43legacy_phy_read(dev, 0x0001) & 0x3FFF) 404 | 0x4000); 405 b43legacy_phy_write(dev, 0x0811, 406 b43legacy_phy_read(dev, 0x0811) | 0x000C); 407 b43legacy_phy_write(dev, 0x0812, 408 (b43legacy_phy_read(dev, 0x0812) & 0xFFF3) 409 | 0x0004); 410 b43legacy_phy_write(dev, 0x0802, 411 b43legacy_phy_read(dev, 0x0802) & ~(0x1 | 0x2)); 412 if (phy->rev >= 6) { 413 backup[12] = b43legacy_phy_read(dev, 0x002E); 414 backup[13] = b43legacy_phy_read(dev, 0x002F); 415 backup[14] = b43legacy_phy_read(dev, 0x080F); 416 backup[15] = b43legacy_phy_read(dev, 0x0810); 417 backup[16] = b43legacy_phy_read(dev, 0x0801); 418 backup[17] = b43legacy_phy_read(dev, 0x0060); 419 backup[18] = b43legacy_phy_read(dev, 0x0014); 420 backup[19] = b43legacy_phy_read(dev, 0x0478); 421 422 b43legacy_phy_write(dev, 0x002E, 0); 423 b43legacy_phy_write(dev, 0x002F, 0); 424 b43legacy_phy_write(dev, 0x080F, 0); 425 b43legacy_phy_write(dev, 0x0810, 0); 426 b43legacy_phy_write(dev, 0x0478, 427 b43legacy_phy_read(dev, 0x0478) | 0x0100); 428 b43legacy_phy_write(dev, 0x0801, 429 b43legacy_phy_read(dev, 0x0801) | 0x0040); 430 b43legacy_phy_write(dev, 0x0060, 431 b43legacy_phy_read(dev, 0x0060) | 0x0040); 432 b43legacy_phy_write(dev, 0x0014, 433 b43legacy_phy_read(dev, 0x0014) | 0x0200); 434 } 435 b43legacy_radio_write16(dev, 0x007A, 436 b43legacy_radio_read16(dev, 0x007A) | 0x0070); 437 b43legacy_radio_write16(dev, 0x007A, 438 b43legacy_radio_read16(dev, 0x007A) | 0x0080); 439 udelay(30); 440 441 v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F); 442 if (v47F >= 0x20) 443 v47F -= 0x40; 444 if (v47F == 31) { 445 for (i = 7; i >= 4; i--) { 446 b43legacy_radio_write16(dev, 0x007B, i); 447 udelay(20); 448 v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) 449 & 0x003F); 450 if (v47F >= 0x20) 451 v47F -= 0x40; 452 if (v47F < 31 && saved == 0xFFFF) 453 saved = i; 454 } 455 if (saved == 0xFFFF) 456 saved = 4; 457 } else { 458 b43legacy_radio_write16(dev, 0x007A, 459 b43legacy_radio_read16(dev, 0x007A) 460 & 0x007F); 461 b43legacy_phy_write(dev, 0x0814, 462 b43legacy_phy_read(dev, 0x0814) | 0x0001); 463 b43legacy_phy_write(dev, 0x0815, 464 b43legacy_phy_read(dev, 0x0815) & 0xFFFE); 465 b43legacy_phy_write(dev, 0x0811, 466 b43legacy_phy_read(dev, 0x0811) | 0x000C); 467 b43legacy_phy_write(dev, 0x0812, 468 b43legacy_phy_read(dev, 0x0812) | 0x000C); 469 b43legacy_phy_write(dev, 0x0811, 470 b43legacy_phy_read(dev, 0x0811) | 0x0030); 471 b43legacy_phy_write(dev, 0x0812, 472 b43legacy_phy_read(dev, 0x0812) | 0x0030); 473 b43legacy_phy_write(dev, 0x005A, 0x0480); 474 b43legacy_phy_write(dev, 0x0059, 0x0810); 475 b43legacy_phy_write(dev, 0x0058, 0x000D); 476 if (phy->analog == 0) 477 b43legacy_phy_write(dev, 0x0003, 0x0122); 478 else 479 b43legacy_phy_write(dev, 0x000A, 480 b43legacy_phy_read(dev, 0x000A) 481 | 0x2000); 482 b43legacy_phy_write(dev, 0x0814, 483 b43legacy_phy_read(dev, 0x0814) | 0x0004); 484 b43legacy_phy_write(dev, 0x0815, 485 b43legacy_phy_read(dev, 0x0815) & 0xFFFB); 486 b43legacy_phy_write(dev, 0x0003, 487 (b43legacy_phy_read(dev, 0x0003) & 0xFF9F) 488 | 0x0040); 489 b43legacy_radio_write16(dev, 0x007A, 490 b43legacy_radio_read16(dev, 0x007A) 491 | 0x000F); 492 b43legacy_set_all_gains(dev, 3, 0, 1); 493 b43legacy_radio_write16(dev, 0x0043, 494 (b43legacy_radio_read16(dev, 0x0043) 495 & 0x00F0) | 0x000F); 496 udelay(30); 497 v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F); 498 if (v47F >= 0x20) 499 v47F -= 0x40; 500 if (v47F == -32) { 501 for (i = 0; i < 4; i++) { 502 b43legacy_radio_write16(dev, 0x007B, i); 503 udelay(20); 504 v47F = (s16)((b43legacy_phy_read(dev, 0x047F) >> 505 8) & 0x003F); 506 if (v47F >= 0x20) 507 v47F -= 0x40; 508 if (v47F > -31 && saved == 0xFFFF) 509 saved = i; 510 } 511 if (saved == 0xFFFF) 512 saved = 3; 513 } else 514 saved = 0; 515 } 516 b43legacy_radio_write16(dev, 0x007B, saved); 517 518 if (phy->rev >= 6) { 519 b43legacy_phy_write(dev, 0x002E, backup[12]); 520 b43legacy_phy_write(dev, 0x002F, backup[13]); 521 b43legacy_phy_write(dev, 0x080F, backup[14]); 522 b43legacy_phy_write(dev, 0x0810, backup[15]); 523 } 524 b43legacy_phy_write(dev, 0x0814, backup[3]); 525 b43legacy_phy_write(dev, 0x0815, backup[4]); 526 b43legacy_phy_write(dev, 0x005A, backup[5]); 527 b43legacy_phy_write(dev, 0x0059, backup[6]); 528 b43legacy_phy_write(dev, 0x0058, backup[7]); 529 b43legacy_phy_write(dev, 0x000A, backup[8]); 530 b43legacy_phy_write(dev, 0x0003, backup[9]); 531 b43legacy_radio_write16(dev, 0x0043, backup[11]); 532 b43legacy_radio_write16(dev, 0x007A, backup[10]); 533 b43legacy_phy_write(dev, 0x0802, 534 b43legacy_phy_read(dev, 0x0802) | 0x1 | 0x2); 535 b43legacy_phy_write(dev, 0x0429, 536 b43legacy_phy_read(dev, 0x0429) | 0x8000); 537 b43legacy_set_original_gains(dev); 538 if (phy->rev >= 6) { 539 b43legacy_phy_write(dev, 0x0801, backup[16]); 540 b43legacy_phy_write(dev, 0x0060, backup[17]); 541 b43legacy_phy_write(dev, 0x0014, backup[18]); 542 b43legacy_phy_write(dev, 0x0478, backup[19]); 543 } 544 b43legacy_phy_write(dev, 0x0001, backup[0]); 545 b43legacy_phy_write(dev, 0x0812, backup[2]); 546 b43legacy_phy_write(dev, 0x0811, backup[1]); 547 } 548 549 void b43legacy_calc_nrssi_slope(struct b43legacy_wldev *dev) 550 { 551 struct b43legacy_phy *phy = &dev->phy; 552 u16 backup[18] = { 0 }; 553 u16 tmp; 554 s16 nrssi0; 555 s16 nrssi1; 556 557 switch (phy->type) { 558 case B43legacy_PHYTYPE_B: 559 backup[0] = b43legacy_radio_read16(dev, 0x007A); 560 backup[1] = b43legacy_radio_read16(dev, 0x0052); 561 backup[2] = b43legacy_radio_read16(dev, 0x0043); 562 backup[3] = b43legacy_phy_read(dev, 0x0030); 563 backup[4] = b43legacy_phy_read(dev, 0x0026); 564 backup[5] = b43legacy_phy_read(dev, 0x0015); 565 backup[6] = b43legacy_phy_read(dev, 0x002A); 566 backup[7] = b43legacy_phy_read(dev, 0x0020); 567 backup[8] = b43legacy_phy_read(dev, 0x005A); 568 backup[9] = b43legacy_phy_read(dev, 0x0059); 569 backup[10] = b43legacy_phy_read(dev, 0x0058); 570 backup[11] = b43legacy_read16(dev, 0x03E2); 571 backup[12] = b43legacy_read16(dev, 0x03E6); 572 backup[13] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT); 573 574 tmp = b43legacy_radio_read16(dev, 0x007A); 575 tmp &= (phy->rev >= 5) ? 0x007F : 0x000F; 576 b43legacy_radio_write16(dev, 0x007A, tmp); 577 b43legacy_phy_write(dev, 0x0030, 0x00FF); 578 b43legacy_write16(dev, 0x03EC, 0x7F7F); 579 b43legacy_phy_write(dev, 0x0026, 0x0000); 580 b43legacy_phy_write(dev, 0x0015, 581 b43legacy_phy_read(dev, 0x0015) | 0x0020); 582 b43legacy_phy_write(dev, 0x002A, 0x08A3); 583 b43legacy_radio_write16(dev, 0x007A, 584 b43legacy_radio_read16(dev, 0x007A) 585 | 0x0080); 586 587 nrssi0 = (s16)b43legacy_phy_read(dev, 0x0027); 588 b43legacy_radio_write16(dev, 0x007A, 589 b43legacy_radio_read16(dev, 0x007A) 590 & 0x007F); 591 if (phy->analog >= 2) 592 b43legacy_write16(dev, 0x03E6, 0x0040); 593 else if (phy->analog == 0) 594 b43legacy_write16(dev, 0x03E6, 0x0122); 595 else 596 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 597 b43legacy_read16(dev, 598 B43legacy_MMIO_CHANNEL_EXT) & 0x2000); 599 b43legacy_phy_write(dev, 0x0020, 0x3F3F); 600 b43legacy_phy_write(dev, 0x0015, 0xF330); 601 b43legacy_radio_write16(dev, 0x005A, 0x0060); 602 b43legacy_radio_write16(dev, 0x0043, 603 b43legacy_radio_read16(dev, 0x0043) 604 & 0x00F0); 605 b43legacy_phy_write(dev, 0x005A, 0x0480); 606 b43legacy_phy_write(dev, 0x0059, 0x0810); 607 b43legacy_phy_write(dev, 0x0058, 0x000D); 608 udelay(20); 609 610 nrssi1 = (s16)b43legacy_phy_read(dev, 0x0027); 611 b43legacy_phy_write(dev, 0x0030, backup[3]); 612 b43legacy_radio_write16(dev, 0x007A, backup[0]); 613 b43legacy_write16(dev, 0x03E2, backup[11]); 614 b43legacy_phy_write(dev, 0x0026, backup[4]); 615 b43legacy_phy_write(dev, 0x0015, backup[5]); 616 b43legacy_phy_write(dev, 0x002A, backup[6]); 617 b43legacy_synth_pu_workaround(dev, phy->channel); 618 if (phy->analog != 0) 619 b43legacy_write16(dev, 0x03F4, backup[13]); 620 621 b43legacy_phy_write(dev, 0x0020, backup[7]); 622 b43legacy_phy_write(dev, 0x005A, backup[8]); 623 b43legacy_phy_write(dev, 0x0059, backup[9]); 624 b43legacy_phy_write(dev, 0x0058, backup[10]); 625 b43legacy_radio_write16(dev, 0x0052, backup[1]); 626 b43legacy_radio_write16(dev, 0x0043, backup[2]); 627 628 if (nrssi0 == nrssi1) 629 phy->nrssislope = 0x00010000; 630 else 631 phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1); 632 633 if (nrssi0 <= -4) { 634 phy->nrssi[0] = nrssi0; 635 phy->nrssi[1] = nrssi1; 636 } 637 break; 638 case B43legacy_PHYTYPE_G: 639 if (phy->radio_rev >= 9) 640 return; 641 if (phy->radio_rev == 8) 642 b43legacy_calc_nrssi_offset(dev); 643 644 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, 645 b43legacy_phy_read(dev, B43legacy_PHY_G_CRS) 646 & 0x7FFF); 647 b43legacy_phy_write(dev, 0x0802, 648 b43legacy_phy_read(dev, 0x0802) & 0xFFFC); 649 backup[7] = b43legacy_read16(dev, 0x03E2); 650 b43legacy_write16(dev, 0x03E2, 651 b43legacy_read16(dev, 0x03E2) | 0x8000); 652 backup[0] = b43legacy_radio_read16(dev, 0x007A); 653 backup[1] = b43legacy_radio_read16(dev, 0x0052); 654 backup[2] = b43legacy_radio_read16(dev, 0x0043); 655 backup[3] = b43legacy_phy_read(dev, 0x0015); 656 backup[4] = b43legacy_phy_read(dev, 0x005A); 657 backup[5] = b43legacy_phy_read(dev, 0x0059); 658 backup[6] = b43legacy_phy_read(dev, 0x0058); 659 backup[8] = b43legacy_read16(dev, 0x03E6); 660 backup[9] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT); 661 if (phy->rev >= 3) { 662 backup[10] = b43legacy_phy_read(dev, 0x002E); 663 backup[11] = b43legacy_phy_read(dev, 0x002F); 664 backup[12] = b43legacy_phy_read(dev, 0x080F); 665 backup[13] = b43legacy_phy_read(dev, 666 B43legacy_PHY_G_LO_CONTROL); 667 backup[14] = b43legacy_phy_read(dev, 0x0801); 668 backup[15] = b43legacy_phy_read(dev, 0x0060); 669 backup[16] = b43legacy_phy_read(dev, 0x0014); 670 backup[17] = b43legacy_phy_read(dev, 0x0478); 671 b43legacy_phy_write(dev, 0x002E, 0); 672 b43legacy_phy_write(dev, B43legacy_PHY_G_LO_CONTROL, 0); 673 switch (phy->rev) { 674 case 4: case 6: case 7: 675 b43legacy_phy_write(dev, 0x0478, 676 b43legacy_phy_read(dev, 677 0x0478) | 0x0100); 678 b43legacy_phy_write(dev, 0x0801, 679 b43legacy_phy_read(dev, 680 0x0801) | 0x0040); 681 break; 682 case 3: case 5: 683 b43legacy_phy_write(dev, 0x0801, 684 b43legacy_phy_read(dev, 685 0x0801) & 0xFFBF); 686 break; 687 } 688 b43legacy_phy_write(dev, 0x0060, 689 b43legacy_phy_read(dev, 0x0060) 690 | 0x0040); 691 b43legacy_phy_write(dev, 0x0014, 692 b43legacy_phy_read(dev, 0x0014) 693 | 0x0200); 694 } 695 b43legacy_radio_write16(dev, 0x007A, 696 b43legacy_radio_read16(dev, 0x007A) 697 | 0x0070); 698 b43legacy_set_all_gains(dev, 0, 8, 0); 699 b43legacy_radio_write16(dev, 0x007A, 700 b43legacy_radio_read16(dev, 0x007A) 701 & 0x00F7); 702 if (phy->rev >= 2) { 703 b43legacy_phy_write(dev, 0x0811, 704 (b43legacy_phy_read(dev, 0x0811) 705 & 0xFFCF) | 0x0030); 706 b43legacy_phy_write(dev, 0x0812, 707 (b43legacy_phy_read(dev, 0x0812) 708 & 0xFFCF) | 0x0010); 709 } 710 b43legacy_radio_write16(dev, 0x007A, 711 b43legacy_radio_read16(dev, 0x007A) 712 | 0x0080); 713 udelay(20); 714 715 nrssi0 = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F); 716 if (nrssi0 >= 0x0020) 717 nrssi0 -= 0x0040; 718 719 b43legacy_radio_write16(dev, 0x007A, 720 b43legacy_radio_read16(dev, 0x007A) 721 & 0x007F); 722 if (phy->analog >= 2) 723 b43legacy_phy_write(dev, 0x0003, 724 (b43legacy_phy_read(dev, 0x0003) 725 & 0xFF9F) | 0x0040); 726 727 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 728 b43legacy_read16(dev, 729 B43legacy_MMIO_CHANNEL_EXT) | 0x2000); 730 b43legacy_radio_write16(dev, 0x007A, 731 b43legacy_radio_read16(dev, 0x007A) 732 | 0x000F); 733 b43legacy_phy_write(dev, 0x0015, 0xF330); 734 if (phy->rev >= 2) { 735 b43legacy_phy_write(dev, 0x0812, 736 (b43legacy_phy_read(dev, 0x0812) 737 & 0xFFCF) | 0x0020); 738 b43legacy_phy_write(dev, 0x0811, 739 (b43legacy_phy_read(dev, 0x0811) 740 & 0xFFCF) | 0x0020); 741 } 742 743 b43legacy_set_all_gains(dev, 3, 0, 1); 744 if (phy->radio_rev == 8) 745 b43legacy_radio_write16(dev, 0x0043, 0x001F); 746 else { 747 tmp = b43legacy_radio_read16(dev, 0x0052) & 0xFF0F; 748 b43legacy_radio_write16(dev, 0x0052, tmp | 0x0060); 749 tmp = b43legacy_radio_read16(dev, 0x0043) & 0xFFF0; 750 b43legacy_radio_write16(dev, 0x0043, tmp | 0x0009); 751 } 752 b43legacy_phy_write(dev, 0x005A, 0x0480); 753 b43legacy_phy_write(dev, 0x0059, 0x0810); 754 b43legacy_phy_write(dev, 0x0058, 0x000D); 755 udelay(20); 756 nrssi1 = (s16)((b43legacy_phy_read(dev, 0x047F) >> 8) & 0x003F); 757 if (nrssi1 >= 0x0020) 758 nrssi1 -= 0x0040; 759 if (nrssi0 == nrssi1) 760 phy->nrssislope = 0x00010000; 761 else 762 phy->nrssislope = 0x00400000 / (nrssi0 - nrssi1); 763 if (nrssi0 >= -4) { 764 phy->nrssi[0] = nrssi1; 765 phy->nrssi[1] = nrssi0; 766 } 767 if (phy->rev >= 3) { 768 b43legacy_phy_write(dev, 0x002E, backup[10]); 769 b43legacy_phy_write(dev, 0x002F, backup[11]); 770 b43legacy_phy_write(dev, 0x080F, backup[12]); 771 b43legacy_phy_write(dev, B43legacy_PHY_G_LO_CONTROL, 772 backup[13]); 773 } 774 if (phy->rev >= 2) { 775 b43legacy_phy_write(dev, 0x0812, 776 b43legacy_phy_read(dev, 0x0812) 777 & 0xFFCF); 778 b43legacy_phy_write(dev, 0x0811, 779 b43legacy_phy_read(dev, 0x0811) 780 & 0xFFCF); 781 } 782 783 b43legacy_radio_write16(dev, 0x007A, backup[0]); 784 b43legacy_radio_write16(dev, 0x0052, backup[1]); 785 b43legacy_radio_write16(dev, 0x0043, backup[2]); 786 b43legacy_write16(dev, 0x03E2, backup[7]); 787 b43legacy_write16(dev, 0x03E6, backup[8]); 788 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, backup[9]); 789 b43legacy_phy_write(dev, 0x0015, backup[3]); 790 b43legacy_phy_write(dev, 0x005A, backup[4]); 791 b43legacy_phy_write(dev, 0x0059, backup[5]); 792 b43legacy_phy_write(dev, 0x0058, backup[6]); 793 b43legacy_synth_pu_workaround(dev, phy->channel); 794 b43legacy_phy_write(dev, 0x0802, 795 b43legacy_phy_read(dev, 0x0802) | 0x0003); 796 b43legacy_set_original_gains(dev); 797 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, 798 b43legacy_phy_read(dev, B43legacy_PHY_G_CRS) 799 | 0x8000); 800 if (phy->rev >= 3) { 801 b43legacy_phy_write(dev, 0x0801, backup[14]); 802 b43legacy_phy_write(dev, 0x0060, backup[15]); 803 b43legacy_phy_write(dev, 0x0014, backup[16]); 804 b43legacy_phy_write(dev, 0x0478, backup[17]); 805 } 806 b43legacy_nrssi_mem_update(dev); 807 b43legacy_calc_nrssi_threshold(dev); 808 break; 809 default: 810 B43legacy_BUG_ON(1); 811 } 812 } 813 814 void b43legacy_calc_nrssi_threshold(struct b43legacy_wldev *dev) 815 { 816 struct b43legacy_phy *phy = &dev->phy; 817 s32 threshold; 818 s32 a; 819 s32 b; 820 s16 tmp16; 821 u16 tmp_u16; 822 823 switch (phy->type) { 824 case B43legacy_PHYTYPE_B: { 825 if (phy->radio_ver != 0x2050) 826 return; 827 if (!(dev->dev->bus->sprom.boardflags_lo & 828 B43legacy_BFL_RSSI)) 829 return; 830 831 if (phy->radio_rev >= 6) { 832 threshold = (phy->nrssi[1] - phy->nrssi[0]) * 32; 833 threshold += 20 * (phy->nrssi[0] + 1); 834 threshold /= 40; 835 } else 836 threshold = phy->nrssi[1] - 5; 837 838 threshold = clamp_val(threshold, 0, 0x3E); 839 b43legacy_phy_read(dev, 0x0020); /* dummy read */ 840 b43legacy_phy_write(dev, 0x0020, (((u16)threshold) << 8) 841 | 0x001C); 842 843 if (phy->radio_rev >= 6) { 844 b43legacy_phy_write(dev, 0x0087, 0x0E0D); 845 b43legacy_phy_write(dev, 0x0086, 0x0C0B); 846 b43legacy_phy_write(dev, 0x0085, 0x0A09); 847 b43legacy_phy_write(dev, 0x0084, 0x0808); 848 b43legacy_phy_write(dev, 0x0083, 0x0808); 849 b43legacy_phy_write(dev, 0x0082, 0x0604); 850 b43legacy_phy_write(dev, 0x0081, 0x0302); 851 b43legacy_phy_write(dev, 0x0080, 0x0100); 852 } 853 break; 854 } 855 case B43legacy_PHYTYPE_G: 856 if (!phy->gmode || 857 !(dev->dev->bus->sprom.boardflags_lo & 858 B43legacy_BFL_RSSI)) { 859 tmp16 = b43legacy_nrssi_hw_read(dev, 0x20); 860 if (tmp16 >= 0x20) 861 tmp16 -= 0x40; 862 if (tmp16 < 3) 863 b43legacy_phy_write(dev, 0x048A, 864 (b43legacy_phy_read(dev, 865 0x048A) & 0xF000) | 0x09EB); 866 else 867 b43legacy_phy_write(dev, 0x048A, 868 (b43legacy_phy_read(dev, 869 0x048A) & 0xF000) | 0x0AED); 870 } else { 871 if (phy->interfmode == 872 B43legacy_RADIO_INTERFMODE_NONWLAN) { 873 a = 0xE; 874 b = 0xA; 875 } else if (!phy->aci_wlan_automatic && 876 phy->aci_enable) { 877 a = 0x13; 878 b = 0x12; 879 } else { 880 a = 0xE; 881 b = 0x11; 882 } 883 884 a = a * (phy->nrssi[1] - phy->nrssi[0]); 885 a += (phy->nrssi[0] << 6); 886 if (a < 32) 887 a += 31; 888 else 889 a += 32; 890 a = a >> 6; 891 a = clamp_val(a, -31, 31); 892 893 b = b * (phy->nrssi[1] - phy->nrssi[0]); 894 b += (phy->nrssi[0] << 6); 895 if (b < 32) 896 b += 31; 897 else 898 b += 32; 899 b = b >> 6; 900 b = clamp_val(b, -31, 31); 901 902 tmp_u16 = b43legacy_phy_read(dev, 0x048A) & 0xF000; 903 tmp_u16 |= ((u32)b & 0x0000003F); 904 tmp_u16 |= (((u32)a & 0x0000003F) << 6); 905 b43legacy_phy_write(dev, 0x048A, tmp_u16); 906 } 907 break; 908 default: 909 B43legacy_BUG_ON(1); 910 } 911 } 912 913 /* Stack implementation to save/restore values from the 914 * interference mitigation code. 915 * It is save to restore values in random order. 916 */ 917 static void _stack_save(u32 *_stackptr, size_t *stackidx, 918 u8 id, u16 offset, u16 value) 919 { 920 u32 *stackptr = &(_stackptr[*stackidx]); 921 922 B43legacy_WARN_ON(!((offset & 0xE000) == 0x0000)); 923 B43legacy_WARN_ON(!((id & 0xF8) == 0x00)); 924 *stackptr = offset; 925 *stackptr |= ((u32)id) << 13; 926 *stackptr |= ((u32)value) << 16; 927 (*stackidx)++; 928 B43legacy_WARN_ON(!(*stackidx < B43legacy_INTERFSTACK_SIZE)); 929 } 930 931 static u16 _stack_restore(u32 *stackptr, 932 u8 id, u16 offset) 933 { 934 size_t i; 935 936 B43legacy_WARN_ON(!((offset & 0xE000) == 0x0000)); 937 B43legacy_WARN_ON(!((id & 0xF8) == 0x00)); 938 for (i = 0; i < B43legacy_INTERFSTACK_SIZE; i++, stackptr++) { 939 if ((*stackptr & 0x00001FFF) != offset) 940 continue; 941 if (((*stackptr & 0x00007000) >> 13) != id) 942 continue; 943 return ((*stackptr & 0xFFFF0000) >> 16); 944 } 945 B43legacy_BUG_ON(1); 946 947 return 0; 948 } 949 950 #define phy_stacksave(offset) \ 951 do { \ 952 _stack_save(stack, &stackidx, 0x1, (offset), \ 953 b43legacy_phy_read(dev, (offset))); \ 954 } while (0) 955 #define phy_stackrestore(offset) \ 956 do { \ 957 b43legacy_phy_write(dev, (offset), \ 958 _stack_restore(stack, 0x1, \ 959 (offset))); \ 960 } while (0) 961 #define radio_stacksave(offset) \ 962 do { \ 963 _stack_save(stack, &stackidx, 0x2, (offset), \ 964 b43legacy_radio_read16(dev, (offset))); \ 965 } while (0) 966 #define radio_stackrestore(offset) \ 967 do { \ 968 b43legacy_radio_write16(dev, (offset), \ 969 _stack_restore(stack, 0x2, \ 970 (offset))); \ 971 } while (0) 972 #define ilt_stacksave(offset) \ 973 do { \ 974 _stack_save(stack, &stackidx, 0x3, (offset), \ 975 b43legacy_ilt_read(dev, (offset))); \ 976 } while (0) 977 #define ilt_stackrestore(offset) \ 978 do { \ 979 b43legacy_ilt_write(dev, (offset), \ 980 _stack_restore(stack, 0x3, \ 981 (offset))); \ 982 } while (0) 983 984 static void 985 b43legacy_radio_interference_mitigation_enable(struct b43legacy_wldev *dev, 986 int mode) 987 { 988 struct b43legacy_phy *phy = &dev->phy; 989 u16 tmp; 990 u16 flipped; 991 u32 tmp32; 992 size_t stackidx = 0; 993 u32 *stack = phy->interfstack; 994 995 switch (mode) { 996 case B43legacy_RADIO_INTERFMODE_NONWLAN: 997 if (phy->rev != 1) { 998 b43legacy_phy_write(dev, 0x042B, 999 b43legacy_phy_read(dev, 0x042B) 1000 | 0x0800); 1001 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, 1002 b43legacy_phy_read(dev, 1003 B43legacy_PHY_G_CRS) & ~0x4000); 1004 break; 1005 } 1006 radio_stacksave(0x0078); 1007 tmp = (b43legacy_radio_read16(dev, 0x0078) & 0x001E); 1008 flipped = flip_4bit(tmp); 1009 if (flipped < 10 && flipped >= 8) 1010 flipped = 7; 1011 else if (flipped >= 10) 1012 flipped -= 3; 1013 flipped = flip_4bit(flipped); 1014 flipped = (flipped << 1) | 0x0020; 1015 b43legacy_radio_write16(dev, 0x0078, flipped); 1016 1017 b43legacy_calc_nrssi_threshold(dev); 1018 1019 phy_stacksave(0x0406); 1020 b43legacy_phy_write(dev, 0x0406, 0x7E28); 1021 1022 b43legacy_phy_write(dev, 0x042B, 1023 b43legacy_phy_read(dev, 0x042B) | 0x0800); 1024 b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD, 1025 b43legacy_phy_read(dev, 1026 B43legacy_PHY_RADIO_BITFIELD) | 0x1000); 1027 1028 phy_stacksave(0x04A0); 1029 b43legacy_phy_write(dev, 0x04A0, 1030 (b43legacy_phy_read(dev, 0x04A0) & 0xC0C0) 1031 | 0x0008); 1032 phy_stacksave(0x04A1); 1033 b43legacy_phy_write(dev, 0x04A1, 1034 (b43legacy_phy_read(dev, 0x04A1) & 0xC0C0) 1035 | 0x0605); 1036 phy_stacksave(0x04A2); 1037 b43legacy_phy_write(dev, 0x04A2, 1038 (b43legacy_phy_read(dev, 0x04A2) & 0xC0C0) 1039 | 0x0204); 1040 phy_stacksave(0x04A8); 1041 b43legacy_phy_write(dev, 0x04A8, 1042 (b43legacy_phy_read(dev, 0x04A8) & 0xC0C0) 1043 | 0x0803); 1044 phy_stacksave(0x04AB); 1045 b43legacy_phy_write(dev, 0x04AB, 1046 (b43legacy_phy_read(dev, 0x04AB) & 0xC0C0) 1047 | 0x0605); 1048 1049 phy_stacksave(0x04A7); 1050 b43legacy_phy_write(dev, 0x04A7, 0x0002); 1051 phy_stacksave(0x04A3); 1052 b43legacy_phy_write(dev, 0x04A3, 0x287A); 1053 phy_stacksave(0x04A9); 1054 b43legacy_phy_write(dev, 0x04A9, 0x2027); 1055 phy_stacksave(0x0493); 1056 b43legacy_phy_write(dev, 0x0493, 0x32F5); 1057 phy_stacksave(0x04AA); 1058 b43legacy_phy_write(dev, 0x04AA, 0x2027); 1059 phy_stacksave(0x04AC); 1060 b43legacy_phy_write(dev, 0x04AC, 0x32F5); 1061 break; 1062 case B43legacy_RADIO_INTERFMODE_MANUALWLAN: 1063 if (b43legacy_phy_read(dev, 0x0033) & 0x0800) 1064 break; 1065 1066 phy->aci_enable = true; 1067 1068 phy_stacksave(B43legacy_PHY_RADIO_BITFIELD); 1069 phy_stacksave(B43legacy_PHY_G_CRS); 1070 if (phy->rev < 2) 1071 phy_stacksave(0x0406); 1072 else { 1073 phy_stacksave(0x04C0); 1074 phy_stacksave(0x04C1); 1075 } 1076 phy_stacksave(0x0033); 1077 phy_stacksave(0x04A7); 1078 phy_stacksave(0x04A3); 1079 phy_stacksave(0x04A9); 1080 phy_stacksave(0x04AA); 1081 phy_stacksave(0x04AC); 1082 phy_stacksave(0x0493); 1083 phy_stacksave(0x04A1); 1084 phy_stacksave(0x04A0); 1085 phy_stacksave(0x04A2); 1086 phy_stacksave(0x048A); 1087 phy_stacksave(0x04A8); 1088 phy_stacksave(0x04AB); 1089 if (phy->rev == 2) { 1090 phy_stacksave(0x04AD); 1091 phy_stacksave(0x04AE); 1092 } else if (phy->rev >= 3) { 1093 phy_stacksave(0x04AD); 1094 phy_stacksave(0x0415); 1095 phy_stacksave(0x0416); 1096 phy_stacksave(0x0417); 1097 ilt_stacksave(0x1A00 + 0x2); 1098 ilt_stacksave(0x1A00 + 0x3); 1099 } 1100 phy_stacksave(0x042B); 1101 phy_stacksave(0x048C); 1102 1103 b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD, 1104 b43legacy_phy_read(dev, 1105 B43legacy_PHY_RADIO_BITFIELD) & ~0x1000); 1106 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, 1107 (b43legacy_phy_read(dev, 1108 B43legacy_PHY_G_CRS) 1109 & 0xFFFC) | 0x0002); 1110 1111 b43legacy_phy_write(dev, 0x0033, 0x0800); 1112 b43legacy_phy_write(dev, 0x04A3, 0x2027); 1113 b43legacy_phy_write(dev, 0x04A9, 0x1CA8); 1114 b43legacy_phy_write(dev, 0x0493, 0x287A); 1115 b43legacy_phy_write(dev, 0x04AA, 0x1CA8); 1116 b43legacy_phy_write(dev, 0x04AC, 0x287A); 1117 1118 b43legacy_phy_write(dev, 0x04A0, 1119 (b43legacy_phy_read(dev, 0x04A0) 1120 & 0xFFC0) | 0x001A); 1121 b43legacy_phy_write(dev, 0x04A7, 0x000D); 1122 1123 if (phy->rev < 2) 1124 b43legacy_phy_write(dev, 0x0406, 0xFF0D); 1125 else if (phy->rev == 2) { 1126 b43legacy_phy_write(dev, 0x04C0, 0xFFFF); 1127 b43legacy_phy_write(dev, 0x04C1, 0x00A9); 1128 } else { 1129 b43legacy_phy_write(dev, 0x04C0, 0x00C1); 1130 b43legacy_phy_write(dev, 0x04C1, 0x0059); 1131 } 1132 1133 b43legacy_phy_write(dev, 0x04A1, 1134 (b43legacy_phy_read(dev, 0x04A1) 1135 & 0xC0FF) | 0x1800); 1136 b43legacy_phy_write(dev, 0x04A1, 1137 (b43legacy_phy_read(dev, 0x04A1) 1138 & 0xFFC0) | 0x0015); 1139 b43legacy_phy_write(dev, 0x04A8, 1140 (b43legacy_phy_read(dev, 0x04A8) 1141 & 0xCFFF) | 0x1000); 1142 b43legacy_phy_write(dev, 0x04A8, 1143 (b43legacy_phy_read(dev, 0x04A8) 1144 & 0xF0FF) | 0x0A00); 1145 b43legacy_phy_write(dev, 0x04AB, 1146 (b43legacy_phy_read(dev, 0x04AB) 1147 & 0xCFFF) | 0x1000); 1148 b43legacy_phy_write(dev, 0x04AB, 1149 (b43legacy_phy_read(dev, 0x04AB) 1150 & 0xF0FF) | 0x0800); 1151 b43legacy_phy_write(dev, 0x04AB, 1152 (b43legacy_phy_read(dev, 0x04AB) 1153 & 0xFFCF) | 0x0010); 1154 b43legacy_phy_write(dev, 0x04AB, 1155 (b43legacy_phy_read(dev, 0x04AB) 1156 & 0xFFF0) | 0x0005); 1157 b43legacy_phy_write(dev, 0x04A8, 1158 (b43legacy_phy_read(dev, 0x04A8) 1159 & 0xFFCF) | 0x0010); 1160 b43legacy_phy_write(dev, 0x04A8, 1161 (b43legacy_phy_read(dev, 0x04A8) 1162 & 0xFFF0) | 0x0006); 1163 b43legacy_phy_write(dev, 0x04A2, 1164 (b43legacy_phy_read(dev, 0x04A2) 1165 & 0xF0FF) | 0x0800); 1166 b43legacy_phy_write(dev, 0x04A0, 1167 (b43legacy_phy_read(dev, 0x04A0) 1168 & 0xF0FF) | 0x0500); 1169 b43legacy_phy_write(dev, 0x04A2, 1170 (b43legacy_phy_read(dev, 0x04A2) 1171 & 0xFFF0) | 0x000B); 1172 1173 if (phy->rev >= 3) { 1174 b43legacy_phy_write(dev, 0x048A, 1175 b43legacy_phy_read(dev, 0x048A) 1176 & ~0x8000); 1177 b43legacy_phy_write(dev, 0x0415, 1178 (b43legacy_phy_read(dev, 0x0415) 1179 & 0x8000) | 0x36D8); 1180 b43legacy_phy_write(dev, 0x0416, 1181 (b43legacy_phy_read(dev, 0x0416) 1182 & 0x8000) | 0x36D8); 1183 b43legacy_phy_write(dev, 0x0417, 1184 (b43legacy_phy_read(dev, 0x0417) 1185 & 0xFE00) | 0x016D); 1186 } else { 1187 b43legacy_phy_write(dev, 0x048A, 1188 b43legacy_phy_read(dev, 0x048A) 1189 | 0x1000); 1190 b43legacy_phy_write(dev, 0x048A, 1191 (b43legacy_phy_read(dev, 0x048A) 1192 & 0x9FFF) | 0x2000); 1193 tmp32 = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, 1194 B43legacy_UCODEFLAGS_OFFSET); 1195 if (!(tmp32 & 0x800)) { 1196 tmp32 |= 0x800; 1197 b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 1198 B43legacy_UCODEFLAGS_OFFSET, 1199 tmp32); 1200 } 1201 } 1202 if (phy->rev >= 2) 1203 b43legacy_phy_write(dev, 0x042B, 1204 b43legacy_phy_read(dev, 0x042B) 1205 | 0x0800); 1206 b43legacy_phy_write(dev, 0x048C, 1207 (b43legacy_phy_read(dev, 0x048C) 1208 & 0xF0FF) | 0x0200); 1209 if (phy->rev == 2) { 1210 b43legacy_phy_write(dev, 0x04AE, 1211 (b43legacy_phy_read(dev, 0x04AE) 1212 & 0xFF00) | 0x007F); 1213 b43legacy_phy_write(dev, 0x04AD, 1214 (b43legacy_phy_read(dev, 0x04AD) 1215 & 0x00FF) | 0x1300); 1216 } else if (phy->rev >= 6) { 1217 b43legacy_ilt_write(dev, 0x1A00 + 0x3, 0x007F); 1218 b43legacy_ilt_write(dev, 0x1A00 + 0x2, 0x007F); 1219 b43legacy_phy_write(dev, 0x04AD, 1220 b43legacy_phy_read(dev, 0x04AD) 1221 & 0x00FF); 1222 } 1223 b43legacy_calc_nrssi_slope(dev); 1224 break; 1225 default: 1226 B43legacy_BUG_ON(1); 1227 } 1228 } 1229 1230 static void 1231 b43legacy_radio_interference_mitigation_disable(struct b43legacy_wldev *dev, 1232 int mode) 1233 { 1234 struct b43legacy_phy *phy = &dev->phy; 1235 u32 tmp32; 1236 u32 *stack = phy->interfstack; 1237 1238 switch (mode) { 1239 case B43legacy_RADIO_INTERFMODE_NONWLAN: 1240 if (phy->rev != 1) { 1241 b43legacy_phy_write(dev, 0x042B, 1242 b43legacy_phy_read(dev, 0x042B) 1243 & ~0x0800); 1244 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, 1245 b43legacy_phy_read(dev, 1246 B43legacy_PHY_G_CRS) | 0x4000); 1247 break; 1248 } 1249 phy_stackrestore(0x0078); 1250 b43legacy_calc_nrssi_threshold(dev); 1251 phy_stackrestore(0x0406); 1252 b43legacy_phy_write(dev, 0x042B, 1253 b43legacy_phy_read(dev, 0x042B) & ~0x0800); 1254 if (!dev->bad_frames_preempt) 1255 b43legacy_phy_write(dev, B43legacy_PHY_RADIO_BITFIELD, 1256 b43legacy_phy_read(dev, 1257 B43legacy_PHY_RADIO_BITFIELD) 1258 & ~(1 << 11)); 1259 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, 1260 b43legacy_phy_read(dev, B43legacy_PHY_G_CRS) 1261 | 0x4000); 1262 phy_stackrestore(0x04A0); 1263 phy_stackrestore(0x04A1); 1264 phy_stackrestore(0x04A2); 1265 phy_stackrestore(0x04A8); 1266 phy_stackrestore(0x04AB); 1267 phy_stackrestore(0x04A7); 1268 phy_stackrestore(0x04A3); 1269 phy_stackrestore(0x04A9); 1270 phy_stackrestore(0x0493); 1271 phy_stackrestore(0x04AA); 1272 phy_stackrestore(0x04AC); 1273 break; 1274 case B43legacy_RADIO_INTERFMODE_MANUALWLAN: 1275 if (!(b43legacy_phy_read(dev, 0x0033) & 0x0800)) 1276 break; 1277 1278 phy->aci_enable = false; 1279 1280 phy_stackrestore(B43legacy_PHY_RADIO_BITFIELD); 1281 phy_stackrestore(B43legacy_PHY_G_CRS); 1282 phy_stackrestore(0x0033); 1283 phy_stackrestore(0x04A3); 1284 phy_stackrestore(0x04A9); 1285 phy_stackrestore(0x0493); 1286 phy_stackrestore(0x04AA); 1287 phy_stackrestore(0x04AC); 1288 phy_stackrestore(0x04A0); 1289 phy_stackrestore(0x04A7); 1290 if (phy->rev >= 2) { 1291 phy_stackrestore(0x04C0); 1292 phy_stackrestore(0x04C1); 1293 } else 1294 phy_stackrestore(0x0406); 1295 phy_stackrestore(0x04A1); 1296 phy_stackrestore(0x04AB); 1297 phy_stackrestore(0x04A8); 1298 if (phy->rev == 2) { 1299 phy_stackrestore(0x04AD); 1300 phy_stackrestore(0x04AE); 1301 } else if (phy->rev >= 3) { 1302 phy_stackrestore(0x04AD); 1303 phy_stackrestore(0x0415); 1304 phy_stackrestore(0x0416); 1305 phy_stackrestore(0x0417); 1306 ilt_stackrestore(0x1A00 + 0x2); 1307 ilt_stackrestore(0x1A00 + 0x3); 1308 } 1309 phy_stackrestore(0x04A2); 1310 phy_stackrestore(0x04A8); 1311 phy_stackrestore(0x042B); 1312 phy_stackrestore(0x048C); 1313 tmp32 = b43legacy_shm_read32(dev, B43legacy_SHM_SHARED, 1314 B43legacy_UCODEFLAGS_OFFSET); 1315 if (tmp32 & 0x800) { 1316 tmp32 &= ~0x800; 1317 b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 1318 B43legacy_UCODEFLAGS_OFFSET, 1319 tmp32); 1320 } 1321 b43legacy_calc_nrssi_slope(dev); 1322 break; 1323 default: 1324 B43legacy_BUG_ON(1); 1325 } 1326 } 1327 1328 #undef phy_stacksave 1329 #undef phy_stackrestore 1330 #undef radio_stacksave 1331 #undef radio_stackrestore 1332 #undef ilt_stacksave 1333 #undef ilt_stackrestore 1334 1335 int b43legacy_radio_set_interference_mitigation(struct b43legacy_wldev *dev, 1336 int mode) 1337 { 1338 struct b43legacy_phy *phy = &dev->phy; 1339 int currentmode; 1340 1341 if ((phy->type != B43legacy_PHYTYPE_G) || 1342 (phy->rev == 0) || (!phy->gmode)) 1343 return -ENODEV; 1344 1345 phy->aci_wlan_automatic = false; 1346 switch (mode) { 1347 case B43legacy_RADIO_INTERFMODE_AUTOWLAN: 1348 phy->aci_wlan_automatic = true; 1349 if (phy->aci_enable) 1350 mode = B43legacy_RADIO_INTERFMODE_MANUALWLAN; 1351 else 1352 mode = B43legacy_RADIO_INTERFMODE_NONE; 1353 break; 1354 case B43legacy_RADIO_INTERFMODE_NONE: 1355 case B43legacy_RADIO_INTERFMODE_NONWLAN: 1356 case B43legacy_RADIO_INTERFMODE_MANUALWLAN: 1357 break; 1358 default: 1359 return -EINVAL; 1360 } 1361 1362 currentmode = phy->interfmode; 1363 if (currentmode == mode) 1364 return 0; 1365 if (currentmode != B43legacy_RADIO_INTERFMODE_NONE) 1366 b43legacy_radio_interference_mitigation_disable(dev, 1367 currentmode); 1368 1369 if (mode == B43legacy_RADIO_INTERFMODE_NONE) { 1370 phy->aci_enable = false; 1371 phy->aci_hw_rssi = false; 1372 } else 1373 b43legacy_radio_interference_mitigation_enable(dev, mode); 1374 phy->interfmode = mode; 1375 1376 return 0; 1377 } 1378 1379 u16 b43legacy_radio_calibrationvalue(struct b43legacy_wldev *dev) 1380 { 1381 u16 reg; 1382 u16 index; 1383 u16 ret; 1384 1385 reg = b43legacy_radio_read16(dev, 0x0060); 1386 index = (reg & 0x001E) >> 1; 1387 ret = rcc_table[index] << 1; 1388 ret |= (reg & 0x0001); 1389 ret |= 0x0020; 1390 1391 return ret; 1392 } 1393 1394 #define LPD(L, P, D) (((L) << 2) | ((P) << 1) | ((D) << 0)) 1395 static u16 b43legacy_get_812_value(struct b43legacy_wldev *dev, u8 lpd) 1396 { 1397 struct b43legacy_phy *phy = &dev->phy; 1398 u16 loop_or = 0; 1399 u16 adj_loopback_gain = phy->loopback_gain[0]; 1400 u8 loop; 1401 u16 extern_lna_control; 1402 1403 if (!phy->gmode) 1404 return 0; 1405 if (!has_loopback_gain(phy)) { 1406 if (phy->rev < 7 || !(dev->dev->bus->sprom.boardflags_lo 1407 & B43legacy_BFL_EXTLNA)) { 1408 switch (lpd) { 1409 case LPD(0, 1, 1): 1410 return 0x0FB2; 1411 case LPD(0, 0, 1): 1412 return 0x00B2; 1413 case LPD(1, 0, 1): 1414 return 0x30B2; 1415 case LPD(1, 0, 0): 1416 return 0x30B3; 1417 default: 1418 B43legacy_BUG_ON(1); 1419 } 1420 } else { 1421 switch (lpd) { 1422 case LPD(0, 1, 1): 1423 return 0x8FB2; 1424 case LPD(0, 0, 1): 1425 return 0x80B2; 1426 case LPD(1, 0, 1): 1427 return 0x20B2; 1428 case LPD(1, 0, 0): 1429 return 0x20B3; 1430 default: 1431 B43legacy_BUG_ON(1); 1432 } 1433 } 1434 } else { 1435 if (phy->radio_rev == 8) 1436 adj_loopback_gain += 0x003E; 1437 else 1438 adj_loopback_gain += 0x0026; 1439 if (adj_loopback_gain >= 0x46) { 1440 adj_loopback_gain -= 0x46; 1441 extern_lna_control = 0x3000; 1442 } else if (adj_loopback_gain >= 0x3A) { 1443 adj_loopback_gain -= 0x3A; 1444 extern_lna_control = 0x2000; 1445 } else if (adj_loopback_gain >= 0x2E) { 1446 adj_loopback_gain -= 0x2E; 1447 extern_lna_control = 0x1000; 1448 } else { 1449 adj_loopback_gain -= 0x10; 1450 extern_lna_control = 0x0000; 1451 } 1452 for (loop = 0; loop < 16; loop++) { 1453 u16 tmp = adj_loopback_gain - 6 * loop; 1454 if (tmp < 6) 1455 break; 1456 } 1457 1458 loop_or = (loop << 8) | extern_lna_control; 1459 if (phy->rev >= 7 && dev->dev->bus->sprom.boardflags_lo 1460 & B43legacy_BFL_EXTLNA) { 1461 if (extern_lna_control) 1462 loop_or |= 0x8000; 1463 switch (lpd) { 1464 case LPD(0, 1, 1): 1465 return 0x8F92; 1466 case LPD(0, 0, 1): 1467 return (0x8092 | loop_or); 1468 case LPD(1, 0, 1): 1469 return (0x2092 | loop_or); 1470 case LPD(1, 0, 0): 1471 return (0x2093 | loop_or); 1472 default: 1473 B43legacy_BUG_ON(1); 1474 } 1475 } else { 1476 switch (lpd) { 1477 case LPD(0, 1, 1): 1478 return 0x0F92; 1479 case LPD(0, 0, 1): 1480 case LPD(1, 0, 1): 1481 return (0x0092 | loop_or); 1482 case LPD(1, 0, 0): 1483 return (0x0093 | loop_or); 1484 default: 1485 B43legacy_BUG_ON(1); 1486 } 1487 } 1488 } 1489 return 0; 1490 } 1491 1492 u16 b43legacy_radio_init2050(struct b43legacy_wldev *dev) 1493 { 1494 struct b43legacy_phy *phy = &dev->phy; 1495 u16 backup[21] = { 0 }; 1496 u16 ret; 1497 u16 i; 1498 u16 j; 1499 u32 tmp1 = 0; 1500 u32 tmp2 = 0; 1501 1502 backup[0] = b43legacy_radio_read16(dev, 0x0043); 1503 backup[14] = b43legacy_radio_read16(dev, 0x0051); 1504 backup[15] = b43legacy_radio_read16(dev, 0x0052); 1505 backup[1] = b43legacy_phy_read(dev, 0x0015); 1506 backup[16] = b43legacy_phy_read(dev, 0x005A); 1507 backup[17] = b43legacy_phy_read(dev, 0x0059); 1508 backup[18] = b43legacy_phy_read(dev, 0x0058); 1509 if (phy->type == B43legacy_PHYTYPE_B) { 1510 backup[2] = b43legacy_phy_read(dev, 0x0030); 1511 backup[3] = b43legacy_read16(dev, 0x03EC); 1512 b43legacy_phy_write(dev, 0x0030, 0x00FF); 1513 b43legacy_write16(dev, 0x03EC, 0x3F3F); 1514 } else { 1515 if (phy->gmode) { 1516 backup[4] = b43legacy_phy_read(dev, 0x0811); 1517 backup[5] = b43legacy_phy_read(dev, 0x0812); 1518 backup[6] = b43legacy_phy_read(dev, 0x0814); 1519 backup[7] = b43legacy_phy_read(dev, 0x0815); 1520 backup[8] = b43legacy_phy_read(dev, 1521 B43legacy_PHY_G_CRS); 1522 backup[9] = b43legacy_phy_read(dev, 0x0802); 1523 b43legacy_phy_write(dev, 0x0814, 1524 (b43legacy_phy_read(dev, 0x0814) 1525 | 0x0003)); 1526 b43legacy_phy_write(dev, 0x0815, 1527 (b43legacy_phy_read(dev, 0x0815) 1528 & 0xFFFC)); 1529 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, 1530 (b43legacy_phy_read(dev, 1531 B43legacy_PHY_G_CRS) & 0x7FFF)); 1532 b43legacy_phy_write(dev, 0x0802, 1533 (b43legacy_phy_read(dev, 0x0802) 1534 & 0xFFFC)); 1535 if (phy->rev > 1) { /* loopback gain enabled */ 1536 backup[19] = b43legacy_phy_read(dev, 0x080F); 1537 backup[20] = b43legacy_phy_read(dev, 0x0810); 1538 if (phy->rev >= 3) 1539 b43legacy_phy_write(dev, 0x080F, 1540 0xC020); 1541 else 1542 b43legacy_phy_write(dev, 0x080F, 1543 0x8020); 1544 b43legacy_phy_write(dev, 0x0810, 0x0000); 1545 } 1546 b43legacy_phy_write(dev, 0x0812, 1547 b43legacy_get_812_value(dev, 1548 LPD(0, 1, 1))); 1549 if (phy->rev < 7 || 1550 !(dev->dev->bus->sprom.boardflags_lo 1551 & B43legacy_BFL_EXTLNA)) 1552 b43legacy_phy_write(dev, 0x0811, 0x01B3); 1553 else 1554 b43legacy_phy_write(dev, 0x0811, 0x09B3); 1555 } 1556 } 1557 b43legacy_write16(dev, B43legacy_MMIO_PHY_RADIO, 1558 (b43legacy_read16(dev, B43legacy_MMIO_PHY_RADIO) 1559 | 0x8000)); 1560 backup[10] = b43legacy_phy_read(dev, 0x0035); 1561 b43legacy_phy_write(dev, 0x0035, 1562 (b43legacy_phy_read(dev, 0x0035) & 0xFF7F)); 1563 backup[11] = b43legacy_read16(dev, 0x03E6); 1564 backup[12] = b43legacy_read16(dev, B43legacy_MMIO_CHANNEL_EXT); 1565 1566 /* Initialization */ 1567 if (phy->analog == 0) 1568 b43legacy_write16(dev, 0x03E6, 0x0122); 1569 else { 1570 if (phy->analog >= 2) 1571 b43legacy_phy_write(dev, 0x0003, 1572 (b43legacy_phy_read(dev, 0x0003) 1573 & 0xFFBF) | 0x0040); 1574 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 1575 (b43legacy_read16(dev, 1576 B43legacy_MMIO_CHANNEL_EXT) | 0x2000)); 1577 } 1578 1579 ret = b43legacy_radio_calibrationvalue(dev); 1580 1581 if (phy->type == B43legacy_PHYTYPE_B) 1582 b43legacy_radio_write16(dev, 0x0078, 0x0026); 1583 1584 if (phy->gmode) 1585 b43legacy_phy_write(dev, 0x0812, 1586 b43legacy_get_812_value(dev, 1587 LPD(0, 1, 1))); 1588 b43legacy_phy_write(dev, 0x0015, 0xBFAF); 1589 b43legacy_phy_write(dev, 0x002B, 0x1403); 1590 if (phy->gmode) 1591 b43legacy_phy_write(dev, 0x0812, 1592 b43legacy_get_812_value(dev, 1593 LPD(0, 0, 1))); 1594 b43legacy_phy_write(dev, 0x0015, 0xBFA0); 1595 b43legacy_radio_write16(dev, 0x0051, 1596 (b43legacy_radio_read16(dev, 0x0051) 1597 | 0x0004)); 1598 if (phy->radio_rev == 8) 1599 b43legacy_radio_write16(dev, 0x0043, 0x001F); 1600 else { 1601 b43legacy_radio_write16(dev, 0x0052, 0x0000); 1602 b43legacy_radio_write16(dev, 0x0043, 1603 (b43legacy_radio_read16(dev, 0x0043) 1604 & 0xFFF0) | 0x0009); 1605 } 1606 b43legacy_phy_write(dev, 0x0058, 0x0000); 1607 1608 for (i = 0; i < 16; i++) { 1609 b43legacy_phy_write(dev, 0x005A, 0x0480); 1610 b43legacy_phy_write(dev, 0x0059, 0xC810); 1611 b43legacy_phy_write(dev, 0x0058, 0x000D); 1612 if (phy->gmode) 1613 b43legacy_phy_write(dev, 0x0812, 1614 b43legacy_get_812_value(dev, 1615 LPD(1, 0, 1))); 1616 b43legacy_phy_write(dev, 0x0015, 0xAFB0); 1617 udelay(10); 1618 if (phy->gmode) 1619 b43legacy_phy_write(dev, 0x0812, 1620 b43legacy_get_812_value(dev, 1621 LPD(1, 0, 1))); 1622 b43legacy_phy_write(dev, 0x0015, 0xEFB0); 1623 udelay(10); 1624 if (phy->gmode) 1625 b43legacy_phy_write(dev, 0x0812, 1626 b43legacy_get_812_value(dev, 1627 LPD(1, 0, 0))); 1628 b43legacy_phy_write(dev, 0x0015, 0xFFF0); 1629 udelay(20); 1630 tmp1 += b43legacy_phy_read(dev, 0x002D); 1631 b43legacy_phy_write(dev, 0x0058, 0x0000); 1632 if (phy->gmode) 1633 b43legacy_phy_write(dev, 0x0812, 1634 b43legacy_get_812_value(dev, 1635 LPD(1, 0, 1))); 1636 b43legacy_phy_write(dev, 0x0015, 0xAFB0); 1637 } 1638 1639 tmp1++; 1640 tmp1 >>= 9; 1641 udelay(10); 1642 b43legacy_phy_write(dev, 0x0058, 0x0000); 1643 1644 for (i = 0; i < 16; i++) { 1645 b43legacy_radio_write16(dev, 0x0078, (flip_4bit(i) << 1) 1646 | 0x0020); 1647 backup[13] = b43legacy_radio_read16(dev, 0x0078); 1648 udelay(10); 1649 for (j = 0; j < 16; j++) { 1650 b43legacy_phy_write(dev, 0x005A, 0x0D80); 1651 b43legacy_phy_write(dev, 0x0059, 0xC810); 1652 b43legacy_phy_write(dev, 0x0058, 0x000D); 1653 if (phy->gmode) 1654 b43legacy_phy_write(dev, 0x0812, 1655 b43legacy_get_812_value(dev, 1656 LPD(1, 0, 1))); 1657 b43legacy_phy_write(dev, 0x0015, 0xAFB0); 1658 udelay(10); 1659 if (phy->gmode) 1660 b43legacy_phy_write(dev, 0x0812, 1661 b43legacy_get_812_value(dev, 1662 LPD(1, 0, 1))); 1663 b43legacy_phy_write(dev, 0x0015, 0xEFB0); 1664 udelay(10); 1665 if (phy->gmode) 1666 b43legacy_phy_write(dev, 0x0812, 1667 b43legacy_get_812_value(dev, 1668 LPD(1, 0, 0))); 1669 b43legacy_phy_write(dev, 0x0015, 0xFFF0); 1670 udelay(10); 1671 tmp2 += b43legacy_phy_read(dev, 0x002D); 1672 b43legacy_phy_write(dev, 0x0058, 0x0000); 1673 if (phy->gmode) 1674 b43legacy_phy_write(dev, 0x0812, 1675 b43legacy_get_812_value(dev, 1676 LPD(1, 0, 1))); 1677 b43legacy_phy_write(dev, 0x0015, 0xAFB0); 1678 } 1679 tmp2++; 1680 tmp2 >>= 8; 1681 if (tmp1 < tmp2) 1682 break; 1683 } 1684 1685 /* Restore the registers */ 1686 b43legacy_phy_write(dev, 0x0015, backup[1]); 1687 b43legacy_radio_write16(dev, 0x0051, backup[14]); 1688 b43legacy_radio_write16(dev, 0x0052, backup[15]); 1689 b43legacy_radio_write16(dev, 0x0043, backup[0]); 1690 b43legacy_phy_write(dev, 0x005A, backup[16]); 1691 b43legacy_phy_write(dev, 0x0059, backup[17]); 1692 b43legacy_phy_write(dev, 0x0058, backup[18]); 1693 b43legacy_write16(dev, 0x03E6, backup[11]); 1694 if (phy->analog != 0) 1695 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, backup[12]); 1696 b43legacy_phy_write(dev, 0x0035, backup[10]); 1697 b43legacy_radio_selectchannel(dev, phy->channel, 1); 1698 if (phy->type == B43legacy_PHYTYPE_B) { 1699 b43legacy_phy_write(dev, 0x0030, backup[2]); 1700 b43legacy_write16(dev, 0x03EC, backup[3]); 1701 } else { 1702 if (phy->gmode) { 1703 b43legacy_write16(dev, B43legacy_MMIO_PHY_RADIO, 1704 (b43legacy_read16(dev, 1705 B43legacy_MMIO_PHY_RADIO) & 0x7FFF)); 1706 b43legacy_phy_write(dev, 0x0811, backup[4]); 1707 b43legacy_phy_write(dev, 0x0812, backup[5]); 1708 b43legacy_phy_write(dev, 0x0814, backup[6]); 1709 b43legacy_phy_write(dev, 0x0815, backup[7]); 1710 b43legacy_phy_write(dev, B43legacy_PHY_G_CRS, 1711 backup[8]); 1712 b43legacy_phy_write(dev, 0x0802, backup[9]); 1713 if (phy->rev > 1) { 1714 b43legacy_phy_write(dev, 0x080F, backup[19]); 1715 b43legacy_phy_write(dev, 0x0810, backup[20]); 1716 } 1717 } 1718 } 1719 if (i >= 15) 1720 ret = backup[13]; 1721 1722 return ret; 1723 } 1724 1725 static inline 1726 u16 freq_r3A_value(u16 frequency) 1727 { 1728 u16 value; 1729 1730 if (frequency < 5091) 1731 value = 0x0040; 1732 else if (frequency < 5321) 1733 value = 0x0000; 1734 else if (frequency < 5806) 1735 value = 0x0080; 1736 else 1737 value = 0x0040; 1738 1739 return value; 1740 } 1741 1742 int b43legacy_radio_selectchannel(struct b43legacy_wldev *dev, 1743 u8 channel, 1744 int synthetic_pu_workaround) 1745 { 1746 struct b43legacy_phy *phy = &dev->phy; 1747 1748 if (channel == 0xFF) { 1749 switch (phy->type) { 1750 case B43legacy_PHYTYPE_B: 1751 case B43legacy_PHYTYPE_G: 1752 channel = B43legacy_RADIO_DEFAULT_CHANNEL_BG; 1753 break; 1754 default: 1755 B43legacy_WARN_ON(1); 1756 } 1757 } 1758 1759 /* TODO: Check if channel is valid - return -EINVAL if not */ 1760 if (synthetic_pu_workaround) 1761 b43legacy_synth_pu_workaround(dev, channel); 1762 1763 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL, 1764 channel2freq_bg(channel)); 1765 1766 if (channel == 14) { 1767 if (dev->dev->bus->sprom.country_code == 5) /* JAPAN) */ 1768 b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 1769 B43legacy_UCODEFLAGS_OFFSET, 1770 b43legacy_shm_read32(dev, 1771 B43legacy_SHM_SHARED, 1772 B43legacy_UCODEFLAGS_OFFSET) 1773 & ~(1 << 7)); 1774 else 1775 b43legacy_shm_write32(dev, B43legacy_SHM_SHARED, 1776 B43legacy_UCODEFLAGS_OFFSET, 1777 b43legacy_shm_read32(dev, 1778 B43legacy_SHM_SHARED, 1779 B43legacy_UCODEFLAGS_OFFSET) 1780 | (1 << 7)); 1781 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 1782 b43legacy_read16(dev, 1783 B43legacy_MMIO_CHANNEL_EXT) | (1 << 11)); 1784 } else 1785 b43legacy_write16(dev, B43legacy_MMIO_CHANNEL_EXT, 1786 b43legacy_read16(dev, 1787 B43legacy_MMIO_CHANNEL_EXT) & 0xF7BF); 1788 1789 phy->channel = channel; 1790 /*XXX: Using the longer of 2 timeouts (8000 vs 2000 usecs). Specs states 1791 * that 2000 usecs might suffice. */ 1792 msleep(8); 1793 1794 return 0; 1795 } 1796 1797 void b43legacy_radio_set_txantenna(struct b43legacy_wldev *dev, u32 val) 1798 { 1799 u16 tmp; 1800 1801 val <<= 8; 1802 tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0022) & 0xFCFF; 1803 b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0022, tmp | val); 1804 tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x03A8) & 0xFCFF; 1805 b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x03A8, tmp | val); 1806 tmp = b43legacy_shm_read16(dev, B43legacy_SHM_SHARED, 0x0054) & 0xFCFF; 1807 b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0054, tmp | val); 1808 } 1809 1810 /* http://bcm-specs.sipsolutions.net/TX_Gain_Base_Band */ 1811 static u16 b43legacy_get_txgain_base_band(u16 txpower) 1812 { 1813 u16 ret; 1814 1815 B43legacy_WARN_ON(txpower > 63); 1816 1817 if (txpower >= 54) 1818 ret = 2; 1819 else if (txpower >= 49) 1820 ret = 4; 1821 else if (txpower >= 44) 1822 ret = 5; 1823 else 1824 ret = 6; 1825 1826 return ret; 1827 } 1828 1829 /* http://bcm-specs.sipsolutions.net/TX_Gain_Radio_Frequency_Power_Amplifier */ 1830 static u16 b43legacy_get_txgain_freq_power_amp(u16 txpower) 1831 { 1832 u16 ret; 1833 1834 B43legacy_WARN_ON(txpower > 63); 1835 1836 if (txpower >= 32) 1837 ret = 0; 1838 else if (txpower >= 25) 1839 ret = 1; 1840 else if (txpower >= 20) 1841 ret = 2; 1842 else if (txpower >= 12) 1843 ret = 3; 1844 else 1845 ret = 4; 1846 1847 return ret; 1848 } 1849 1850 /* http://bcm-specs.sipsolutions.net/TX_Gain_Digital_Analog_Converter */ 1851 static u16 b43legacy_get_txgain_dac(u16 txpower) 1852 { 1853 u16 ret; 1854 1855 B43legacy_WARN_ON(txpower > 63); 1856 1857 if (txpower >= 54) 1858 ret = txpower - 53; 1859 else if (txpower >= 49) 1860 ret = txpower - 42; 1861 else if (txpower >= 44) 1862 ret = txpower - 37; 1863 else if (txpower >= 32) 1864 ret = txpower - 32; 1865 else if (txpower >= 25) 1866 ret = txpower - 20; 1867 else if (txpower >= 20) 1868 ret = txpower - 13; 1869 else if (txpower >= 12) 1870 ret = txpower - 8; 1871 else 1872 ret = txpower; 1873 1874 return ret; 1875 } 1876 1877 void b43legacy_radio_set_txpower_a(struct b43legacy_wldev *dev, u16 txpower) 1878 { 1879 struct b43legacy_phy *phy = &dev->phy; 1880 u16 pamp; 1881 u16 base; 1882 u16 dac; 1883 u16 ilt; 1884 1885 txpower = clamp_val(txpower, 0, 63); 1886 1887 pamp = b43legacy_get_txgain_freq_power_amp(txpower); 1888 pamp <<= 5; 1889 pamp &= 0x00E0; 1890 b43legacy_phy_write(dev, 0x0019, pamp); 1891 1892 base = b43legacy_get_txgain_base_band(txpower); 1893 base &= 0x000F; 1894 b43legacy_phy_write(dev, 0x0017, base | 0x0020); 1895 1896 ilt = b43legacy_ilt_read(dev, 0x3001); 1897 ilt &= 0x0007; 1898 1899 dac = b43legacy_get_txgain_dac(txpower); 1900 dac <<= 3; 1901 dac |= ilt; 1902 1903 b43legacy_ilt_write(dev, 0x3001, dac); 1904 1905 phy->txpwr_offset = txpower; 1906 1907 /* TODO: FuncPlaceholder (Adjust BB loft cancel) */ 1908 } 1909 1910 void b43legacy_radio_set_txpower_bg(struct b43legacy_wldev *dev, 1911 u16 baseband_attenuation, 1912 u16 radio_attenuation, 1913 u16 txpower) 1914 { 1915 struct b43legacy_phy *phy = &dev->phy; 1916 1917 if (baseband_attenuation == 0xFFFF) 1918 baseband_attenuation = phy->bbatt; 1919 if (radio_attenuation == 0xFFFF) 1920 radio_attenuation = phy->rfatt; 1921 if (txpower == 0xFFFF) 1922 txpower = phy->txctl1; 1923 phy->bbatt = baseband_attenuation; 1924 phy->rfatt = radio_attenuation; 1925 phy->txctl1 = txpower; 1926 1927 B43legacy_WARN_ON(baseband_attenuation > 11); 1928 if (phy->radio_rev < 6) 1929 B43legacy_WARN_ON(radio_attenuation > 9); 1930 else 1931 B43legacy_WARN_ON(radio_attenuation > 31); 1932 B43legacy_WARN_ON(txpower > 7); 1933 1934 b43legacy_phy_set_baseband_attenuation(dev, baseband_attenuation); 1935 b43legacy_radio_write16(dev, 0x0043, radio_attenuation); 1936 b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0064, 1937 radio_attenuation); 1938 if (phy->radio_ver == 0x2050) 1939 b43legacy_radio_write16(dev, 0x0052, 1940 (b43legacy_radio_read16(dev, 0x0052) 1941 & ~0x0070) | ((txpower << 4) & 0x0070)); 1942 /* FIXME: The spec is very weird and unclear here. */ 1943 if (phy->type == B43legacy_PHYTYPE_G) 1944 b43legacy_phy_lo_adjust(dev, 0); 1945 } 1946 1947 u16 b43legacy_default_baseband_attenuation(struct b43legacy_wldev *dev) 1948 { 1949 struct b43legacy_phy *phy = &dev->phy; 1950 1951 if (phy->radio_ver == 0x2050 && phy->radio_rev < 6) 1952 return 0; 1953 return 2; 1954 } 1955 1956 u16 b43legacy_default_radio_attenuation(struct b43legacy_wldev *dev) 1957 { 1958 struct b43legacy_phy *phy = &dev->phy; 1959 u16 att = 0xFFFF; 1960 1961 switch (phy->radio_ver) { 1962 case 0x2053: 1963 switch (phy->radio_rev) { 1964 case 1: 1965 att = 6; 1966 break; 1967 } 1968 break; 1969 case 0x2050: 1970 switch (phy->radio_rev) { 1971 case 0: 1972 att = 5; 1973 break; 1974 case 1: 1975 if (phy->type == B43legacy_PHYTYPE_G) { 1976 if (is_bcm_board_vendor(dev) && 1977 dev->dev->bus->boardinfo.type == 0x421 && 1978 dev->dev->bus->sprom.board_rev >= 30) 1979 att = 3; 1980 else if (is_bcm_board_vendor(dev) && 1981 dev->dev->bus->boardinfo.type == 0x416) 1982 att = 3; 1983 else 1984 att = 1; 1985 } else { 1986 if (is_bcm_board_vendor(dev) && 1987 dev->dev->bus->boardinfo.type == 0x421 && 1988 dev->dev->bus->sprom.board_rev >= 30) 1989 att = 7; 1990 else 1991 att = 6; 1992 } 1993 break; 1994 case 2: 1995 if (phy->type == B43legacy_PHYTYPE_G) { 1996 if (is_bcm_board_vendor(dev) && 1997 dev->dev->bus->boardinfo.type == 0x421 && 1998 dev->dev->bus->sprom.board_rev >= 30) 1999 att = 3; 2000 else if (is_bcm_board_vendor(dev) && 2001 dev->dev->bus->boardinfo.type == 2002 0x416) 2003 att = 5; 2004 else if (dev->dev->bus->chip_id == 0x4320) 2005 att = 4; 2006 else 2007 att = 3; 2008 } else 2009 att = 6; 2010 break; 2011 case 3: 2012 att = 5; 2013 break; 2014 case 4: 2015 case 5: 2016 att = 1; 2017 break; 2018 case 6: 2019 case 7: 2020 att = 5; 2021 break; 2022 case 8: 2023 att = 0x1A; 2024 break; 2025 case 9: 2026 default: 2027 att = 5; 2028 } 2029 } 2030 if (is_bcm_board_vendor(dev) && 2031 dev->dev->bus->boardinfo.type == 0x421) { 2032 if (dev->dev->bus->sprom.board_rev < 0x43) 2033 att = 2; 2034 else if (dev->dev->bus->sprom.board_rev < 0x51) 2035 att = 3; 2036 } 2037 if (att == 0xFFFF) 2038 att = 5; 2039 2040 return att; 2041 } 2042 2043 u16 b43legacy_default_txctl1(struct b43legacy_wldev *dev) 2044 { 2045 struct b43legacy_phy *phy = &dev->phy; 2046 2047 if (phy->radio_ver != 0x2050) 2048 return 0; 2049 if (phy->radio_rev == 1) 2050 return 3; 2051 if (phy->radio_rev < 6) 2052 return 2; 2053 if (phy->radio_rev == 8) 2054 return 1; 2055 return 0; 2056 } 2057 2058 void b43legacy_radio_turn_on(struct b43legacy_wldev *dev) 2059 { 2060 struct b43legacy_phy *phy = &dev->phy; 2061 int err; 2062 u8 channel; 2063 2064 might_sleep(); 2065 2066 if (phy->radio_on) 2067 return; 2068 2069 switch (phy->type) { 2070 case B43legacy_PHYTYPE_B: 2071 case B43legacy_PHYTYPE_G: 2072 b43legacy_phy_write(dev, 0x0015, 0x8000); 2073 b43legacy_phy_write(dev, 0x0015, 0xCC00); 2074 b43legacy_phy_write(dev, 0x0015, 2075 (phy->gmode ? 0x00C0 : 0x0000)); 2076 if (phy->radio_off_context.valid) { 2077 /* Restore the RFover values. */ 2078 b43legacy_phy_write(dev, B43legacy_PHY_RFOVER, 2079 phy->radio_off_context.rfover); 2080 b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL, 2081 phy->radio_off_context.rfoverval); 2082 phy->radio_off_context.valid = false; 2083 } 2084 channel = phy->channel; 2085 err = b43legacy_radio_selectchannel(dev, 2086 B43legacy_RADIO_DEFAULT_CHANNEL_BG, 1); 2087 err |= b43legacy_radio_selectchannel(dev, channel, 0); 2088 B43legacy_WARN_ON(err); 2089 break; 2090 default: 2091 B43legacy_BUG_ON(1); 2092 } 2093 phy->radio_on = true; 2094 } 2095 2096 void b43legacy_radio_turn_off(struct b43legacy_wldev *dev, bool force) 2097 { 2098 struct b43legacy_phy *phy = &dev->phy; 2099 2100 if (!phy->radio_on && !force) 2101 return; 2102 2103 if (phy->type == B43legacy_PHYTYPE_G && dev->dev->id.revision >= 5) { 2104 u16 rfover, rfoverval; 2105 2106 rfover = b43legacy_phy_read(dev, B43legacy_PHY_RFOVER); 2107 rfoverval = b43legacy_phy_read(dev, B43legacy_PHY_RFOVERVAL); 2108 if (!force) { 2109 phy->radio_off_context.rfover = rfover; 2110 phy->radio_off_context.rfoverval = rfoverval; 2111 phy->radio_off_context.valid = true; 2112 } 2113 b43legacy_phy_write(dev, B43legacy_PHY_RFOVER, rfover | 0x008C); 2114 b43legacy_phy_write(dev, B43legacy_PHY_RFOVERVAL, 2115 rfoverval & 0xFF73); 2116 } else 2117 b43legacy_phy_write(dev, 0x0015, 0xAA00); 2118 phy->radio_on = false; 2119 b43legacydbg(dev->wl, "Radio initialized\n"); 2120 } 2121 2122 void b43legacy_radio_clear_tssi(struct b43legacy_wldev *dev) 2123 { 2124 struct b43legacy_phy *phy = &dev->phy; 2125 2126 switch (phy->type) { 2127 case B43legacy_PHYTYPE_B: 2128 case B43legacy_PHYTYPE_G: 2129 b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0058, 2130 0x7F7F); 2131 b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x005a, 2132 0x7F7F); 2133 b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0070, 2134 0x7F7F); 2135 b43legacy_shm_write16(dev, B43legacy_SHM_SHARED, 0x0072, 2136 0x7F7F); 2137 break; 2138 } 2139 } 2140