1 | // SPDX-License-Identifier: GPL-2.0-or-later |
2 | /* |
3 | |
4 | Broadcom B43 wireless driver |
5 | RFKILL support |
6 | |
7 | Copyright (c) 2007 Michael Buesch <m@bues.ch> |
8 | |
9 | |
10 | */ |
11 | |
12 | #include "radio.h" |
13 | #include "b43legacy.h" |
14 | |
15 | |
16 | /* Returns TRUE, if the radio is enabled in hardware. */ |
17 | bool b43legacy_is_hw_radio_enabled(struct b43legacy_wldev *dev) |
18 | { |
19 | if (dev->dev->id.revision >= 3) { |
20 | if (!(b43legacy_read32(dev, B43legacy_MMIO_RADIO_HWENABLED_HI) |
21 | & B43legacy_MMIO_RADIO_HWENABLED_HI_MASK)) |
22 | return true; |
23 | } else { |
24 | /* To prevent CPU fault on PPC, do not read a register |
25 | * unless the interface is started; however, on resume |
26 | * for hibernation, this routine is entered early. When |
27 | * that happens, unconditionally return TRUE. |
28 | */ |
29 | if (b43legacy_status(dev) < B43legacy_STAT_STARTED) |
30 | return true; |
31 | if (b43legacy_read16(dev, B43legacy_MMIO_RADIO_HWENABLED_LO) |
32 | & B43legacy_MMIO_RADIO_HWENABLED_LO_MASK) |
33 | return true; |
34 | } |
35 | return false; |
36 | } |
37 | |
38 | /* The poll callback for the hardware button. */ |
39 | void b43legacy_rfkill_poll(struct ieee80211_hw *hw) |
40 | { |
41 | struct b43legacy_wl *wl = hw_to_b43legacy_wl(hw); |
42 | struct b43legacy_wldev *dev = wl->current_dev; |
43 | struct ssb_bus *bus = dev->dev->bus; |
44 | bool enabled; |
45 | bool brought_up = false; |
46 | |
47 | mutex_lock(&wl->mutex); |
48 | if (unlikely(b43legacy_status(dev) < B43legacy_STAT_INITIALIZED)) { |
49 | if (ssb_bus_powerup(bus, dynamic_pctl: 0)) { |
50 | mutex_unlock(lock: &wl->mutex); |
51 | return; |
52 | } |
53 | ssb_device_enable(dev: dev->dev, core_specific_flags: 0); |
54 | brought_up = true; |
55 | } |
56 | |
57 | enabled = b43legacy_is_hw_radio_enabled(dev); |
58 | |
59 | if (unlikely(enabled != dev->radio_hw_enable)) { |
60 | dev->radio_hw_enable = enabled; |
61 | b43legacyinfo(wl, fmt: "Radio hardware status changed to %s\n" , |
62 | enabled ? "ENABLED" : "DISABLED" ); |
63 | wiphy_rfkill_set_hw_state(wiphy: hw->wiphy, blocked: !enabled); |
64 | if (enabled != dev->phy.radio_on) { |
65 | if (enabled) |
66 | b43legacy_radio_turn_on(dev); |
67 | else |
68 | b43legacy_radio_turn_off(dev, force: 0); |
69 | } |
70 | } |
71 | |
72 | if (brought_up) { |
73 | ssb_device_disable(dev: dev->dev, core_specific_flags: 0); |
74 | ssb_bus_may_powerdown(bus); |
75 | } |
76 | |
77 | mutex_unlock(lock: &wl->mutex); |
78 | } |
79 | |