1 // SPDX-License-Identifier: GPL-2.0-or-later
4 Broadcom B43 wireless driver
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>
16 #include "phy_common.h"
28 int b43_phy_allocate(struct b43_wldev
*dev
)
30 struct b43_phy
*phy
= &(dev
->phy
);
37 #ifdef CONFIG_B43_PHY_G
38 phy
->ops
= &b43_phyops_g
;
42 #ifdef CONFIG_B43_PHY_N
43 phy
->ops
= &b43_phyops_n
;
47 #ifdef CONFIG_B43_PHY_LP
48 phy
->ops
= &b43_phyops_lp
;
52 #ifdef CONFIG_B43_PHY_HT
53 phy
->ops
= &b43_phyops_ht
;
57 #ifdef CONFIG_B43_PHY_LCN
58 phy
->ops
= &b43_phyops_lcn
;
62 #ifdef CONFIG_B43_PHY_AC
63 phy
->ops
= &b43_phyops_ac
;
67 if (B43_WARN_ON(!phy
->ops
))
70 err
= phy
->ops
->allocate(dev
);
77 void b43_phy_free(struct b43_wldev
*dev
)
79 dev
->phy
.ops
->free(dev
);
83 int b43_phy_init(struct b43_wldev
*dev
)
85 struct b43_phy
*phy
= &dev
->phy
;
86 const struct b43_phy_operations
*ops
= phy
->ops
;
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.
93 phy
->chandef
= &dev
->wl
->hw
->conf
.chandef
;
94 phy
->channel
= phy
->chandef
->chan
->hw_value
;
97 phy
->ops
->switch_analog(dev
, true);
98 b43_software_rfkill(dev
, false);
100 err
= ops
->init(dev
);
102 b43err(dev
->wl
, "PHY init failed\n");
105 phy
->do_full_init
= false;
107 err
= b43_switch_channel(dev
, phy
->channel
);
109 b43err(dev
->wl
, "PHY init: Channel switch to default failed\n");
116 phy
->do_full_init
= true;
120 b43_software_rfkill(dev
, true);
125 void b43_phy_exit(struct b43_wldev
*dev
)
127 const struct b43_phy_operations
*ops
= dev
->phy
.ops
;
129 b43_software_rfkill(dev
, true);
130 dev
->phy
.do_full_init
= true;
135 bool b43_has_hardware_pctl(struct b43_wldev
*dev
)
137 if (!dev
->phy
.hardware_power_control
)
139 if (!dev
->phy
.ops
->supports_hwpctl
)
141 return dev
->phy
.ops
->supports_hwpctl(dev
);
144 void b43_radio_lock(struct b43_wldev
*dev
)
149 B43_WARN_ON(dev
->phy
.radio_locked
);
150 dev
->phy
.radio_locked
= true;
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
);
162 void b43_radio_unlock(struct b43_wldev
*dev
)
167 B43_WARN_ON(!dev
->phy
.radio_locked
);
168 dev
->phy
.radio_locked
= false;
171 /* Commit any write */
172 b43_read16(dev
, B43_MMIO_PHY_VER
);
174 macctl
= b43_read32(dev
, B43_MMIO_MACCTL
);
175 macctl
&= ~B43_MACCTL_RADIOLOCK
;
176 b43_write32(dev
, B43_MMIO_MACCTL
, macctl
);
179 void b43_phy_lock(struct b43_wldev
*dev
)
182 B43_WARN_ON(dev
->phy
.phy_locked
);
183 dev
->phy
.phy_locked
= true;
185 B43_WARN_ON(dev
->dev
->core_rev
< 3);
187 if (!b43_is_mode(dev
->wl
, NL80211_IFTYPE_AP
))
188 b43_power_saving_ctl_bits(dev
, B43_PS_AWAKE
);
191 void b43_phy_unlock(struct b43_wldev
*dev
)
194 B43_WARN_ON(!dev
->phy
.phy_locked
);
195 dev
->phy
.phy_locked
= false;
197 B43_WARN_ON(dev
->dev
->core_rev
< 3);
199 if (!b43_is_mode(dev
->wl
, NL80211_IFTYPE_AP
))
200 b43_power_saving_ctl_bits(dev
, 0);
203 static inline void assert_mac_suspended(struct b43_wldev
*dev
)
207 if ((b43_status(dev
) >= B43_STAT_INITIALIZED
) &&
208 (dev
->mac_suspended
<= 0)) {
209 b43dbg(dev
->wl
, "PHY/RADIO register access with "
215 u16
b43_radio_read(struct b43_wldev
*dev
, u16 reg
)
217 assert_mac_suspended(dev
);
218 dev
->phy
.writes_counter
= 0;
219 return dev
->phy
.ops
->radio_read(dev
, reg
);
222 void b43_radio_write(struct b43_wldev
*dev
, u16 reg
, u16 value
)
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;
230 dev
->phy
.ops
->radio_write(dev
, reg
, value
);
233 void b43_radio_mask(struct b43_wldev
*dev
, u16 offset
, u16 mask
)
235 b43_radio_write16(dev
, offset
,
236 b43_radio_read16(dev
, offset
) & mask
);
239 void b43_radio_set(struct b43_wldev
*dev
, u16 offset
, u16 set
)
241 b43_radio_write16(dev
, offset
,
242 b43_radio_read16(dev
, offset
) | set
);
245 void b43_radio_maskset(struct b43_wldev
*dev
, u16 offset
, u16 mask
, u16 set
)
247 b43_radio_write16(dev
, offset
,
248 (b43_radio_read16(dev
, offset
) & mask
) | set
);
251 bool b43_radio_wait_value(struct b43_wldev
*dev
, u16 offset
, u16 mask
,
252 u16 value
, int delay
, int timeout
)
257 for (i
= 0; i
< timeout
; i
+= delay
) {
258 val
= b43_radio_read(dev
, offset
);
259 if ((val
& mask
) == value
)
266 u16
b43_phy_read(struct b43_wldev
*dev
, u16 reg
)
268 assert_mac_suspended(dev
);
269 dev
->phy
.writes_counter
= 0;
271 if (dev
->phy
.ops
->phy_read
)
272 return dev
->phy
.ops
->phy_read(dev
, reg
);
274 b43_write16f(dev
, B43_MMIO_PHY_CONTROL
, reg
);
275 return b43_read16(dev
, B43_MMIO_PHY_DATA
);
278 void b43_phy_write(struct b43_wldev
*dev
, u16 reg
, u16 value
)
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;
287 if (dev
->phy
.ops
->phy_write
)
288 return dev
->phy
.ops
->phy_write(dev
, reg
, value
);
290 b43_write16f(dev
, B43_MMIO_PHY_CONTROL
, reg
);
291 b43_write16(dev
, B43_MMIO_PHY_DATA
, value
);
294 void b43_phy_copy(struct b43_wldev
*dev
, u16 destreg
, u16 srcreg
)
296 b43_phy_write(dev
, destreg
, b43_phy_read(dev
, srcreg
));
299 void b43_phy_mask(struct b43_wldev
*dev
, u16 offset
, u16 mask
)
301 if (dev
->phy
.ops
->phy_maskset
) {
302 assert_mac_suspended(dev
);
303 dev
->phy
.ops
->phy_maskset(dev
, offset
, mask
, 0);
305 b43_phy_write(dev
, offset
,
306 b43_phy_read(dev
, offset
) & mask
);
310 void b43_phy_set(struct b43_wldev
*dev
, u16 offset
, u16 set
)
312 if (dev
->phy
.ops
->phy_maskset
) {
313 assert_mac_suspended(dev
);
314 dev
->phy
.ops
->phy_maskset(dev
, offset
, 0xFFFF, set
);
316 b43_phy_write(dev
, offset
,
317 b43_phy_read(dev
, offset
) | set
);
321 void b43_phy_maskset(struct b43_wldev
*dev
, u16 offset
, u16 mask
, u16 set
)
323 if (dev
->phy
.ops
->phy_maskset
) {
324 assert_mac_suspended(dev
);
325 dev
->phy
.ops
->phy_maskset(dev
, offset
, mask
, set
);
327 b43_phy_write(dev
, offset
,
328 (b43_phy_read(dev
, offset
) & mask
) | set
);
332 void b43_phy_put_into_reset(struct b43_wldev
*dev
)
336 switch (dev
->dev
->bus_type
) {
337 #ifdef CONFIG_B43_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
);
346 tmp
= bcma_aread32(dev
->dev
->bdev
, BCMA_IOCTL
);
347 tmp
&= ~BCMA_IOCTL_FGC
;
348 bcma_awrite32(dev
->dev
->bdev
, BCMA_IOCTL
, tmp
);
352 #ifdef CONFIG_B43_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);
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);
371 void b43_phy_take_out_of_reset(struct b43_wldev
*dev
)
375 switch (dev
->dev
->bus_type
) {
376 #ifdef CONFIG_B43_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
);
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
);
394 #ifdef CONFIG_B43_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);
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);
416 int b43_switch_channel(struct b43_wldev
*dev
, unsigned int new_channel
)
418 struct b43_phy
*phy
= &(dev
->phy
);
419 u16 channelcookie
, savedcookie
;
422 /* First we set the channel radio code to prevent the
423 * firmware from sending ghost packets.
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 */
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
);
434 /* Now try to switch the PHY hardware channel. */
435 err
= phy
->ops
->switch_channel(dev
, new_channel
);
437 goto err_restore_cookie
;
439 /* Wait for the radio to tune to the channel and stabilize. */
445 b43_shm_write16(dev
, B43_SHM_SHARED
,
446 B43_SHM_SH_CHAN
, savedcookie
);
451 void b43_software_rfkill(struct b43_wldev
*dev
, bool blocked
)
453 struct b43_phy
*phy
= &dev
->phy
;
455 b43_mac_suspend(dev
);
456 phy
->ops
->software_rfkill(dev
, blocked
);
457 phy
->radio_on
= !blocked
;
462 * b43_phy_txpower_adjust_work - TX power workqueue.
464 * Workqueue for updating the TX power parameters in hardware.
466 void b43_phy_txpower_adjust_work(struct work_struct
*work
)
468 struct b43_wl
*wl
= container_of(work
, struct b43_wl
,
469 txpower_adjust_work
);
470 struct b43_wldev
*dev
;
472 mutex_lock(&wl
->mutex
);
473 dev
= wl
->current_dev
;
475 if (likely(dev
&& (b43_status(dev
) >= B43_STAT_STARTED
)))
476 dev
->phy
.ops
->adjust_txpower(dev
);
478 mutex_unlock(&wl
->mutex
);
481 void b43_phy_txpower_check(struct b43_wldev
*dev
, unsigned int flags
)
483 struct b43_phy
*phy
= &dev
->phy
;
484 unsigned long now
= jiffies
;
485 enum b43_txpwr_result result
;
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 */
492 /* The next check will be needed in two seconds, or later. */
493 phy
->next_txpwr_check_time
= round_jiffies(now
+ (HZ
* 2));
495 if ((dev
->dev
->board_vendor
== SSB_BOARDVENDOR_BCM
) &&
496 (dev
->dev
->board_type
== SSB_BOARD_BU4306
))
497 return; /* No software txpower adjustment needed */
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
);
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
);
510 int b43_phy_shm_tssi_read(struct b43_wldev
*dev
, u16 shm_offset
)
512 const bool is_ofdm
= (shm_offset
!= B43_SHM_SH_TSSI_CCK
);
513 unsigned int a
, b
, c
, d
;
514 unsigned int average
;
517 tmp
= b43_shm_read32(dev
, B43_SHM_SHARED
, shm_offset
);
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
)
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
);
539 /* Get the average of the values with 0.5 added to each value. */
540 average
= (a
+ b
+ c
+ d
+ 2) / 4;
542 /* Adjust for CCK-boost */
543 if (b43_shm_read16(dev
, B43_SHM_SHARED
, B43_SHM_SH_HOSTF1
)
545 average
= (average
>= 13) ? (average
- 13) : 0;
551 void b43_phyop_switch_analog_generic(struct b43_wldev
*dev
, bool on
)
553 b43_write16(dev
, B43_MMIO_PHY0
, on
? 0 : 0xF4);
557 bool b43_is_40mhz(struct b43_wldev
*dev
)
559 return dev
->phy
.chandef
->width
== NL80211_CHAN_WIDTH_40
;
562 /* http://bcm-v4.sipsolutions.net/802.11/PHY/N/BmacPhyClkFgc */
563 void b43_phy_force_clock(struct b43_wldev
*dev
, bool force
)
567 WARN_ON(dev
->phy
.type
!= B43_PHYTYPE_N
&&
568 dev
->phy
.type
!= B43_PHYTYPE_HT
&&
569 dev
->phy
.type
!= B43_PHYTYPE_AC
);
571 switch (dev
->dev
->bus_type
) {
572 #ifdef CONFIG_B43_BCMA
574 tmp
= bcma_aread32(dev
->dev
->bdev
, BCMA_IOCTL
);
576 tmp
|= BCMA_IOCTL_FGC
;
578 tmp
&= ~BCMA_IOCTL_FGC
;
579 bcma_awrite32(dev
->dev
->bdev
, BCMA_IOCTL
, tmp
);
582 #ifdef CONFIG_B43_SSB
584 tmp
= ssb_read32(dev
->dev
->sdev
, SSB_TMSLOW
);
586 tmp
|= SSB_TMSLOW_FGC
;
588 tmp
&= ~SSB_TMSLOW_FGC
;
589 ssb_write32(dev
->dev
->sdev
, SSB_TMSLOW
, tmp
);