root/drivers/net/wireless/broadcom/b43legacy/leds.c

/* [<][>][^][v][top][bottom][index][help] */

DEFINITIONS

This source file includes following definitions.
  1. b43legacy_led_turn_on
  2. b43legacy_led_turn_off
  3. b43legacy_led_brightness_set
  4. b43legacy_register_led
  5. b43legacy_unregister_led
  6. b43legacy_map_led
  7. b43legacy_leds_init
  8. b43legacy_leds_exit

   1 // SPDX-License-Identifier: GPL-2.0-or-later
   2 /*
   3 
   4   Broadcom B43 wireless driver
   5   LED control
   6 
   7   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
   8   Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
   9   Copyright (c) 2005-2007 Michael Buesch <m@bues.ch>
  10   Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
  11   Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
  12 
  13 
  14 */
  15 
  16 #include "b43legacy.h"
  17 #include "leds.h"
  18 #include "rfkill.h"
  19 
  20 
  21 static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index,
  22                             bool activelow)
  23 {
  24         struct b43legacy_wl *wl = dev->wl;
  25         unsigned long flags;
  26         u16 ctl;
  27 
  28         spin_lock_irqsave(&wl->leds_lock, flags);
  29         ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
  30         if (activelow)
  31                 ctl &= ~(1 << led_index);
  32         else
  33                 ctl |= (1 << led_index);
  34         b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
  35         spin_unlock_irqrestore(&wl->leds_lock, flags);
  36 }
  37 
  38 static void b43legacy_led_turn_off(struct b43legacy_wldev *dev, u8 led_index,
  39                              bool activelow)
  40 {
  41         struct b43legacy_wl *wl = dev->wl;
  42         unsigned long flags;
  43         u16 ctl;
  44 
  45         spin_lock_irqsave(&wl->leds_lock, flags);
  46         ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
  47         if (activelow)
  48                 ctl |= (1 << led_index);
  49         else
  50                 ctl &= ~(1 << led_index);
  51         b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
  52         spin_unlock_irqrestore(&wl->leds_lock, flags);
  53 }
  54 
  55 /* Callback from the LED subsystem. */
  56 static void b43legacy_led_brightness_set(struct led_classdev *led_dev,
  57                                    enum led_brightness brightness)
  58 {
  59         struct b43legacy_led *led = container_of(led_dev, struct b43legacy_led,
  60                                     led_dev);
  61         struct b43legacy_wldev *dev = led->dev;
  62         bool radio_enabled;
  63 
  64         /* Checking the radio-enabled status here is slightly racy,
  65          * but we want to avoid the locking overhead and we don't care
  66          * whether the LED has the wrong state for a second. */
  67         radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
  68 
  69         if (brightness == LED_OFF || !radio_enabled)
  70                 b43legacy_led_turn_off(dev, led->index, led->activelow);
  71         else
  72                 b43legacy_led_turn_on(dev, led->index, led->activelow);
  73 }
  74 
  75 static int b43legacy_register_led(struct b43legacy_wldev *dev,
  76                                   struct b43legacy_led *led,
  77                                   const char *name,
  78                                   const char *default_trigger,
  79                                   u8 led_index, bool activelow)
  80 {
  81         int err;
  82 
  83         b43legacy_led_turn_off(dev, led_index, activelow);
  84         if (led->dev)
  85                 return -EEXIST;
  86         if (!default_trigger)
  87                 return -EINVAL;
  88         led->dev = dev;
  89         led->index = led_index;
  90         led->activelow = activelow;
  91         strlcpy(led->name, name, sizeof(led->name));
  92 
  93         led->led_dev.name = led->name;
  94         led->led_dev.default_trigger = default_trigger;
  95         led->led_dev.brightness_set = b43legacy_led_brightness_set;
  96 
  97         err = led_classdev_register(dev->dev->dev, &led->led_dev);
  98         if (err) {
  99                 b43legacywarn(dev->wl, "LEDs: Failed to register %s\n", name);
 100                 led->dev = NULL;
 101                 return err;
 102         }
 103         return 0;
 104 }
 105 
 106 static void b43legacy_unregister_led(struct b43legacy_led *led)
 107 {
 108         if (!led->dev)
 109                 return;
 110         led_classdev_unregister(&led->led_dev);
 111         b43legacy_led_turn_off(led->dev, led->index, led->activelow);
 112         led->dev = NULL;
 113 }
 114 
 115 static void b43legacy_map_led(struct b43legacy_wldev *dev,
 116                         u8 led_index,
 117                         enum b43legacy_led_behaviour behaviour,
 118                         bool activelow)
 119 {
 120         struct ieee80211_hw *hw = dev->wl->hw;
 121         char name[B43legacy_LED_MAX_NAME_LEN + 1];
 122 
 123         /* Map the b43 specific LED behaviour value to the
 124          * generic LED triggers. */
 125         switch (behaviour) {
 126         case B43legacy_LED_INACTIVE:
 127                 break;
 128         case B43legacy_LED_OFF:
 129                 b43legacy_led_turn_off(dev, led_index, activelow);
 130                 break;
 131         case B43legacy_LED_ON:
 132                 b43legacy_led_turn_on(dev, led_index, activelow);
 133                 break;
 134         case B43legacy_LED_ACTIVITY:
 135         case B43legacy_LED_TRANSFER:
 136         case B43legacy_LED_APTRANSFER:
 137                 snprintf(name, sizeof(name),
 138                          "b43legacy-%s::tx", wiphy_name(hw->wiphy));
 139                 b43legacy_register_led(dev, &dev->led_tx, name,
 140                                  ieee80211_get_tx_led_name(hw),
 141                                  led_index, activelow);
 142                 snprintf(name, sizeof(name),
 143                          "b43legacy-%s::rx", wiphy_name(hw->wiphy));
 144                 b43legacy_register_led(dev, &dev->led_rx, name,
 145                                  ieee80211_get_rx_led_name(hw),
 146                                  led_index, activelow);
 147                 break;
 148         case B43legacy_LED_RADIO_ALL:
 149         case B43legacy_LED_RADIO_A:
 150         case B43legacy_LED_RADIO_B:
 151         case B43legacy_LED_MODE_BG:
 152                 snprintf(name, sizeof(name),
 153                          "b43legacy-%s::radio", wiphy_name(hw->wiphy));
 154                 b43legacy_register_led(dev, &dev->led_radio, name,
 155                                  ieee80211_get_radio_led_name(hw),
 156                                  led_index, activelow);
 157                 /* Sync the RF-kill LED state with radio and switch states. */
 158                 if (dev->phy.radio_on && b43legacy_is_hw_radio_enabled(dev))
 159                         b43legacy_led_turn_on(dev, led_index, activelow);
 160                 break;
 161         case B43legacy_LED_WEIRD:
 162         case B43legacy_LED_ASSOC:
 163                 snprintf(name, sizeof(name),
 164                          "b43legacy-%s::assoc", wiphy_name(hw->wiphy));
 165                 b43legacy_register_led(dev, &dev->led_assoc, name,
 166                                  ieee80211_get_assoc_led_name(hw),
 167                                  led_index, activelow);
 168                 break;
 169         default:
 170                 b43legacywarn(dev->wl, "LEDs: Unknown behaviour 0x%02X\n",
 171                         behaviour);
 172                 break;
 173         }
 174 }
 175 
 176 void b43legacy_leds_init(struct b43legacy_wldev *dev)
 177 {
 178         struct ssb_bus *bus = dev->dev->bus;
 179         u8 sprom[4];
 180         int i;
 181         enum b43legacy_led_behaviour behaviour;
 182         bool activelow;
 183 
 184         sprom[0] = bus->sprom.gpio0;
 185         sprom[1] = bus->sprom.gpio1;
 186         sprom[2] = bus->sprom.gpio2;
 187         sprom[3] = bus->sprom.gpio3;
 188 
 189         for (i = 0; i < 4; i++) {
 190                 if (sprom[i] == 0xFF) {
 191                         /* There is no LED information in the SPROM
 192                          * for this LED. Hardcode it here. */
 193                         activelow = false;
 194                         switch (i) {
 195                         case 0:
 196                                 behaviour = B43legacy_LED_ACTIVITY;
 197                                 activelow = true;
 198                                 if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
 199                                         behaviour = B43legacy_LED_RADIO_ALL;
 200                                 break;
 201                         case 1:
 202                                 behaviour = B43legacy_LED_RADIO_B;
 203                                 if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
 204                                         behaviour = B43legacy_LED_ASSOC;
 205                                 break;
 206                         case 2:
 207                                 behaviour = B43legacy_LED_RADIO_A;
 208                                 break;
 209                         case 3:
 210                                 behaviour = B43legacy_LED_OFF;
 211                                 break;
 212                         default:
 213                                 B43legacy_WARN_ON(1);
 214                                 return;
 215                         }
 216                 } else {
 217                         behaviour = sprom[i] & B43legacy_LED_BEHAVIOUR;
 218                         activelow = !!(sprom[i] & B43legacy_LED_ACTIVELOW);
 219                 }
 220                 b43legacy_map_led(dev, i, behaviour, activelow);
 221         }
 222 }
 223 
 224 void b43legacy_leds_exit(struct b43legacy_wldev *dev)
 225 {
 226         b43legacy_unregister_led(&dev->led_tx);
 227         b43legacy_unregister_led(&dev->led_rx);
 228         b43legacy_unregister_led(&dev->led_assoc);
 229         b43legacy_unregister_led(&dev->led_radio);
 230 }

/* [<][>][^][v][top][bottom][index][help] */