phy_common.c (14189B)
1// SPDX-License-Identifier: GPL-2.0-or-later 2/* 3 4 Broadcom B43 wireless driver 5 Common PHY routines 6 7 Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>, 8 Copyright (c) 2005-2007 Stefano Brivio <stefano.brivio@polimi.it> 9 Copyright (c) 2005-2008 Michael Buesch <m@bues.ch> 10 Copyright (c) 2005, 2006 Danny van Dyk <kugelfang@gentoo.org> 11 Copyright (c) 2005, 2006 Andreas Jaggi <andreas.jaggi@waterwave.ch> 12 13 14*/ 15 16#include "phy_common.h" 17#include "phy_g.h" 18#include "phy_a.h" 19#include "phy_n.h" 20#include "phy_lp.h" 21#include "phy_ht.h" 22#include "phy_lcn.h" 23#include "phy_ac.h" 24#include "b43.h" 25#include "main.h" 26 27 28int b43_phy_allocate(struct b43_wldev *dev) 29{ 30 struct b43_phy *phy = &(dev->phy); 31 int err; 32 33 phy->ops = NULL; 34 35 switch (phy->type) { 36 case B43_PHYTYPE_G: 37#ifdef CONFIG_B43_PHY_G 38 phy->ops = &b43_phyops_g; 39#endif 40 break; 41 case B43_PHYTYPE_N: 42#ifdef CONFIG_B43_PHY_N 43 phy->ops = &b43_phyops_n; 44#endif 45 break; 46 case B43_PHYTYPE_LP: 47#ifdef CONFIG_B43_PHY_LP 48 phy->ops = &b43_phyops_lp; 49#endif 50 break; 51 case B43_PHYTYPE_HT: 52#ifdef CONFIG_B43_PHY_HT 53 phy->ops = &b43_phyops_ht; 54#endif 55 break; 56 case B43_PHYTYPE_LCN: 57#ifdef CONFIG_B43_PHY_LCN 58 phy->ops = &b43_phyops_lcn; 59#endif 60 break; 61 case B43_PHYTYPE_AC: 62#ifdef CONFIG_B43_PHY_AC 63 phy->ops = &b43_phyops_ac; 64#endif 65 break; 66 } 67 if (B43_WARN_ON(!phy->ops)) 68 return -ENODEV; 69 70 err = phy->ops->allocate(dev); 71 if (err) 72 phy->ops = NULL; 73 74 return err; 75} 76 77void b43_phy_free(struct b43_wldev *dev) 78{ 79 dev->phy.ops->free(dev); 80 dev->phy.ops = NULL; 81} 82 83int b43_phy_init(struct b43_wldev *dev) 84{ 85 struct b43_phy *phy = &dev->phy; 86 const struct b43_phy_operations *ops = phy->ops; 87 int err; 88 89 /* During PHY init we need to use some channel. On the first init this 90 * function is called *before* b43_op_config, so our pointer is NULL. 91 */ 92 if (!phy->chandef) { 93 phy->chandef = &dev->wl->hw->conf.chandef; 94 phy->channel = phy->chandef->chan->hw_value; 95 } 96 97 phy->ops->switch_analog(dev, true); 98 b43_software_rfkill(dev, false); 99 100 err = ops->init(dev); 101 if (err) { 102 b43err(dev->wl, "PHY init failed\n"); 103 goto err_block_rf; 104 } 105 phy->do_full_init = false; 106 107 err = b43_switch_channel(dev, phy->channel); 108 if (err) { 109 b43err(dev->wl, "PHY init: Channel switch to default failed\n"); 110 goto err_phy_exit; 111 } 112 113 return 0; 114 115err_phy_exit: 116 phy->do_full_init = true; 117 if (ops->exit) 118 ops->exit(dev); 119err_block_rf: 120 b43_software_rfkill(dev, true); 121 122 return err; 123} 124 125void b43_phy_exit(struct b43_wldev *dev) 126{ 127 const struct b43_phy_operations *ops = dev->phy.ops; 128 129 b43_software_rfkill(dev, true); 130 dev->phy.do_full_init = true; 131 if (ops->exit) 132 ops->exit(dev); 133} 134 135bool b43_has_hardware_pctl(struct b43_wldev *dev) 136{ 137 if (!dev->phy.hardware_power_control) 138 return false; 139 if (!dev->phy.ops->supports_hwpctl) 140 return false; 141 return dev->phy.ops->supports_hwpctl(dev); 142} 143 144void b43_radio_lock(struct b43_wldev *dev) 145{ 146 u32 macctl; 147 148#if B43_DEBUG 149 B43_WARN_ON(dev->phy.radio_locked); 150 dev->phy.radio_locked = true; 151#endif 152 153 macctl = b43_read32(dev, B43_MMIO_MACCTL); 154 macctl |= B43_MACCTL_RADIOLOCK; 155 b43_write32(dev, B43_MMIO_MACCTL, macctl); 156 /* Commit the write and wait for the firmware 157 * to finish any radio register access. */ 158 b43_read32(dev, B43_MMIO_MACCTL); 159 udelay(10); 160} 161 162void b43_radio_unlock(struct b43_wldev *dev) 163{ 164 u32 macctl; 165 166#if B43_DEBUG 167 B43_WARN_ON(!dev->phy.radio_locked); 168 dev->phy.radio_locked = false; 169#endif 170 171 /* Commit any write */ 172 b43_read16(dev, B43_MMIO_PHY_VER); 173 /* unlock */ 174 macctl = b43_read32(dev, B43_MMIO_MACCTL); 175 macctl &= ~B43_MACCTL_RADIOLOCK; 176 b43_write32(dev, B43_MMIO_MACCTL, macctl); 177} 178 179void b43_phy_lock(struct b43_wldev *dev) 180{ 181#if B43_DEBUG 182 B43_WARN_ON(dev->phy.phy_locked); 183 dev->phy.phy_locked = true; 184#endif 185 B43_WARN_ON(dev->dev->core_rev < 3); 186 187 if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) 188 b43_power_saving_ctl_bits(dev, B43_PS_AWAKE); 189} 190 191void b43_phy_unlock(struct b43_wldev *dev) 192{ 193#if B43_DEBUG 194 B43_WARN_ON(!dev->phy.phy_locked); 195 dev->phy.phy_locked = false; 196#endif 197 B43_WARN_ON(dev->dev->core_rev < 3); 198 199 if (!b43_is_mode(dev->wl, NL80211_IFTYPE_AP)) 200 b43_power_saving_ctl_bits(dev, 0); 201} 202 203static inline void assert_mac_suspended(struct b43_wldev *dev) 204{ 205 if (!B43_DEBUG) 206 return; 207 if ((b43_status(dev) >= B43_STAT_INITIALIZED) && 208 (dev->mac_suspended <= 0)) { 209 b43dbg(dev->wl, "PHY/RADIO register access with " 210 "enabled MAC.\n"); 211 dump_stack(); 212 } 213} 214 215u16 b43_radio_read(struct b43_wldev *dev, u16 reg) 216{ 217 assert_mac_suspended(dev); 218 dev->phy.writes_counter = 0; 219 return dev->phy.ops->radio_read(dev, reg); 220} 221 222void b43_radio_write(struct b43_wldev *dev, u16 reg, u16 value) 223{ 224 assert_mac_suspended(dev); 225 if (b43_bus_host_is_pci(dev->dev) && 226 ++dev->phy.writes_counter > B43_MAX_WRITES_IN_ROW) { 227 b43_read32(dev, B43_MMIO_MACCTL); 228 dev->phy.writes_counter = 1; 229 } 230 dev->phy.ops->radio_write(dev, reg, value); 231} 232 233void b43_radio_mask(struct b43_wldev *dev, u16 offset, u16 mask) 234{ 235 b43_radio_write16(dev, offset, 236 b43_radio_read16(dev, offset) & mask); 237} 238 239void b43_radio_set(struct b43_wldev *dev, u16 offset, u16 set) 240{ 241 b43_radio_write16(dev, offset, 242 b43_radio_read16(dev, offset) | set); 243} 244 245void b43_radio_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) 246{ 247 b43_radio_write16(dev, offset, 248 (b43_radio_read16(dev, offset) & mask) | set); 249} 250 251bool b43_radio_wait_value(struct b43_wldev *dev, u16 offset, u16 mask, 252 u16 value, int delay, int timeout) 253{ 254 u16 val; 255 int i; 256 257 for (i = 0; i < timeout; i += delay) { 258 val = b43_radio_read(dev, offset); 259 if ((val & mask) == value) 260 return true; 261 udelay(delay); 262 } 263 return false; 264} 265 266u16 b43_phy_read(struct b43_wldev *dev, u16 reg) 267{ 268 assert_mac_suspended(dev); 269 dev->phy.writes_counter = 0; 270 271 if (dev->phy.ops->phy_read) 272 return dev->phy.ops->phy_read(dev, reg); 273 274 b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 275 return b43_read16(dev, B43_MMIO_PHY_DATA); 276} 277 278void b43_phy_write(struct b43_wldev *dev, u16 reg, u16 value) 279{ 280 assert_mac_suspended(dev); 281 if (b43_bus_host_is_pci(dev->dev) && 282 ++dev->phy.writes_counter > B43_MAX_WRITES_IN_ROW) { 283 b43_read16(dev, B43_MMIO_PHY_VER); 284 dev->phy.writes_counter = 1; 285 } 286 287 if (dev->phy.ops->phy_write) 288 return dev->phy.ops->phy_write(dev, reg, value); 289 290 b43_write16f(dev, B43_MMIO_PHY_CONTROL, reg); 291 b43_write16(dev, B43_MMIO_PHY_DATA, value); 292} 293 294void b43_phy_copy(struct b43_wldev *dev, u16 destreg, u16 srcreg) 295{ 296 b43_phy_write(dev, destreg, b43_phy_read(dev, srcreg)); 297} 298 299void b43_phy_mask(struct b43_wldev *dev, u16 offset, u16 mask) 300{ 301 if (dev->phy.ops->phy_maskset) { 302 assert_mac_suspended(dev); 303 dev->phy.ops->phy_maskset(dev, offset, mask, 0); 304 } else { 305 b43_phy_write(dev, offset, 306 b43_phy_read(dev, offset) & mask); 307 } 308} 309 310void b43_phy_set(struct b43_wldev *dev, u16 offset, u16 set) 311{ 312 if (dev->phy.ops->phy_maskset) { 313 assert_mac_suspended(dev); 314 dev->phy.ops->phy_maskset(dev, offset, 0xFFFF, set); 315 } else { 316 b43_phy_write(dev, offset, 317 b43_phy_read(dev, offset) | set); 318 } 319} 320 321void b43_phy_maskset(struct b43_wldev *dev, u16 offset, u16 mask, u16 set) 322{ 323 if (dev->phy.ops->phy_maskset) { 324 assert_mac_suspended(dev); 325 dev->phy.ops->phy_maskset(dev, offset, mask, set); 326 } else { 327 b43_phy_write(dev, offset, 328 (b43_phy_read(dev, offset) & mask) | set); 329 } 330} 331 332void b43_phy_put_into_reset(struct b43_wldev *dev) 333{ 334 u32 tmp; 335 336 switch (dev->dev->bus_type) { 337#ifdef CONFIG_B43_BCMA 338 case B43_BUS_BCMA: 339 tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); 340 tmp &= ~B43_BCMA_IOCTL_GMODE; 341 tmp |= B43_BCMA_IOCTL_PHY_RESET; 342 tmp |= BCMA_IOCTL_FGC; 343 bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); 344 udelay(1); 345 346 tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); 347 tmp &= ~BCMA_IOCTL_FGC; 348 bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); 349 udelay(1); 350 break; 351#endif 352#ifdef CONFIG_B43_SSB 353 case B43_BUS_SSB: 354 tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); 355 tmp &= ~B43_TMSLOW_GMODE; 356 tmp |= B43_TMSLOW_PHYRESET; 357 tmp |= SSB_TMSLOW_FGC; 358 ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); 359 usleep_range(1000, 2000); 360 361 tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); 362 tmp &= ~SSB_TMSLOW_FGC; 363 ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); 364 usleep_range(1000, 2000); 365 366 break; 367#endif 368 } 369} 370 371void b43_phy_take_out_of_reset(struct b43_wldev *dev) 372{ 373 u32 tmp; 374 375 switch (dev->dev->bus_type) { 376#ifdef CONFIG_B43_BCMA 377 case B43_BUS_BCMA: 378 /* Unset reset bit (with forcing clock) */ 379 tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); 380 tmp &= ~B43_BCMA_IOCTL_PHY_RESET; 381 tmp &= ~B43_BCMA_IOCTL_PHY_CLKEN; 382 tmp |= BCMA_IOCTL_FGC; 383 bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); 384 udelay(1); 385 386 /* Do not force clock anymore */ 387 tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); 388 tmp &= ~BCMA_IOCTL_FGC; 389 tmp |= B43_BCMA_IOCTL_PHY_CLKEN; 390 bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); 391 udelay(1); 392 break; 393#endif 394#ifdef CONFIG_B43_SSB 395 case B43_BUS_SSB: 396 /* Unset reset bit (with forcing clock) */ 397 tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); 398 tmp &= ~B43_TMSLOW_PHYRESET; 399 tmp &= ~B43_TMSLOW_PHYCLKEN; 400 tmp |= SSB_TMSLOW_FGC; 401 ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); 402 ssb_read32(dev->dev->sdev, SSB_TMSLOW); /* flush */ 403 usleep_range(1000, 2000); 404 405 tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); 406 tmp &= ~SSB_TMSLOW_FGC; 407 tmp |= B43_TMSLOW_PHYCLKEN; 408 ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); 409 ssb_read32(dev->dev->sdev, SSB_TMSLOW); /* flush */ 410 usleep_range(1000, 2000); 411 break; 412#endif 413 } 414} 415 416int b43_switch_channel(struct b43_wldev *dev, unsigned int new_channel) 417{ 418 struct b43_phy *phy = &(dev->phy); 419 u16 channelcookie, savedcookie; 420 int err; 421 422 /* First we set the channel radio code to prevent the 423 * firmware from sending ghost packets. 424 */ 425 channelcookie = new_channel; 426 if (b43_current_band(dev->wl) == NL80211_BAND_5GHZ) 427 channelcookie |= B43_SHM_SH_CHAN_5GHZ; 428 /* FIXME: set 40Mhz flag if required */ 429 if (0) 430 channelcookie |= B43_SHM_SH_CHAN_40MHZ; 431 savedcookie = b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN); 432 b43_shm_write16(dev, B43_SHM_SHARED, B43_SHM_SH_CHAN, channelcookie); 433 434 /* Now try to switch the PHY hardware channel. */ 435 err = phy->ops->switch_channel(dev, new_channel); 436 if (err) 437 goto err_restore_cookie; 438 439 /* Wait for the radio to tune to the channel and stabilize. */ 440 msleep(8); 441 442 return 0; 443 444err_restore_cookie: 445 b43_shm_write16(dev, B43_SHM_SHARED, 446 B43_SHM_SH_CHAN, savedcookie); 447 448 return err; 449} 450 451void b43_software_rfkill(struct b43_wldev *dev, bool blocked) 452{ 453 struct b43_phy *phy = &dev->phy; 454 455 b43_mac_suspend(dev); 456 phy->ops->software_rfkill(dev, blocked); 457 phy->radio_on = !blocked; 458 b43_mac_enable(dev); 459} 460 461/* 462 * b43_phy_txpower_adjust_work - TX power workqueue. 463 * 464 * Workqueue for updating the TX power parameters in hardware. 465 */ 466void b43_phy_txpower_adjust_work(struct work_struct *work) 467{ 468 struct b43_wl *wl = container_of(work, struct b43_wl, 469 txpower_adjust_work); 470 struct b43_wldev *dev; 471 472 mutex_lock(&wl->mutex); 473 dev = wl->current_dev; 474 475 if (likely(dev && (b43_status(dev) >= B43_STAT_STARTED))) 476 dev->phy.ops->adjust_txpower(dev); 477 478 mutex_unlock(&wl->mutex); 479} 480 481void b43_phy_txpower_check(struct b43_wldev *dev, unsigned int flags) 482{ 483 struct b43_phy *phy = &dev->phy; 484 unsigned long now = jiffies; 485 enum b43_txpwr_result result; 486 487 if (!(flags & B43_TXPWR_IGNORE_TIME)) { 488 /* Check if it's time for a TXpower check. */ 489 if (time_before(now, phy->next_txpwr_check_time)) 490 return; /* Not yet */ 491 } 492 /* The next check will be needed in two seconds, or later. */ 493 phy->next_txpwr_check_time = round_jiffies(now + (HZ * 2)); 494 495 if ((dev->dev->board_vendor == SSB_BOARDVENDOR_BCM) && 496 (dev->dev->board_type == SSB_BOARD_BU4306)) 497 return; /* No software txpower adjustment needed */ 498 499 result = phy->ops->recalc_txpower(dev, !!(flags & B43_TXPWR_IGNORE_TSSI)); 500 if (result == B43_TXPWR_RES_DONE) 501 return; /* We are done. */ 502 B43_WARN_ON(result != B43_TXPWR_RES_NEED_ADJUST); 503 B43_WARN_ON(phy->ops->adjust_txpower == NULL); 504 505 /* We must adjust the transmission power in hardware. 506 * Schedule b43_phy_txpower_adjust_work(). */ 507 ieee80211_queue_work(dev->wl->hw, &dev->wl->txpower_adjust_work); 508} 509 510int b43_phy_shm_tssi_read(struct b43_wldev *dev, u16 shm_offset) 511{ 512 const bool is_ofdm = (shm_offset != B43_SHM_SH_TSSI_CCK); 513 unsigned int a, b, c, d; 514 unsigned int average; 515 u32 tmp; 516 517 tmp = b43_shm_read32(dev, B43_SHM_SHARED, shm_offset); 518 a = tmp & 0xFF; 519 b = (tmp >> 8) & 0xFF; 520 c = (tmp >> 16) & 0xFF; 521 d = (tmp >> 24) & 0xFF; 522 if (a == 0 || a == B43_TSSI_MAX || 523 b == 0 || b == B43_TSSI_MAX || 524 c == 0 || c == B43_TSSI_MAX || 525 d == 0 || d == B43_TSSI_MAX) 526 return -ENOENT; 527 /* The values are OK. Clear them. */ 528 tmp = B43_TSSI_MAX | (B43_TSSI_MAX << 8) | 529 (B43_TSSI_MAX << 16) | (B43_TSSI_MAX << 24); 530 b43_shm_write32(dev, B43_SHM_SHARED, shm_offset, tmp); 531 532 if (is_ofdm) { 533 a = (a + 32) & 0x3F; 534 b = (b + 32) & 0x3F; 535 c = (c + 32) & 0x3F; 536 d = (d + 32) & 0x3F; 537 } 538 539 /* Get the average of the values with 0.5 added to each value. */ 540 average = (a + b + c + d + 2) / 4; 541 if (is_ofdm) { 542 /* Adjust for CCK-boost */ 543 if (b43_shm_read16(dev, B43_SHM_SHARED, B43_SHM_SH_HOSTF1) 544 & B43_HF_CCKBOOST) 545 average = (average >= 13) ? (average - 13) : 0; 546 } 547 548 return average; 549} 550 551void b43_phyop_switch_analog_generic(struct b43_wldev *dev, bool on) 552{ 553 b43_write16(dev, B43_MMIO_PHY0, on ? 0 : 0xF4); 554} 555 556 557bool b43_is_40mhz(struct b43_wldev *dev) 558{ 559 return dev->phy.chandef->width == NL80211_CHAN_WIDTH_40; 560} 561 562/* https://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */ 563void b43_phy_force_clock(struct b43_wldev *dev, bool force) 564{ 565 u32 tmp; 566 567 WARN_ON(dev->phy.type != B43_PHYTYPE_N && 568 dev->phy.type != B43_PHYTYPE_HT && 569 dev->phy.type != B43_PHYTYPE_AC); 570 571 switch (dev->dev->bus_type) { 572#ifdef CONFIG_B43_BCMA 573 case B43_BUS_BCMA: 574 tmp = bcma_aread32(dev->dev->bdev, BCMA_IOCTL); 575 if (force) 576 tmp |= BCMA_IOCTL_FGC; 577 else 578 tmp &= ~BCMA_IOCTL_FGC; 579 bcma_awrite32(dev->dev->bdev, BCMA_IOCTL, tmp); 580 break; 581#endif 582#ifdef CONFIG_B43_SSB 583 case B43_BUS_SSB: 584 tmp = ssb_read32(dev->dev->sdev, SSB_TMSLOW); 585 if (force) 586 tmp |= SSB_TMSLOW_FGC; 587 else 588 tmp &= ~SSB_TMSLOW_FGC; 589 ssb_write32(dev->dev->sdev, SSB_TMSLOW, tmp); 590 break; 591#endif 592 } 593}