3   Broadcom B43 wireless driver
 
   6   Copyright (c) 2005 Martin Langer <martin-langer@gmx.de>,
 
   7   Copyright (c) 2005 Stefano Brivio <stefano.brivio@polimi.it>
 
   8   Copyright (c) 2005-2007 Michael Buesch <mb@bu3sch.de>
 
   9   Copyright (c) 2005 Danny van Dyk <kugelfang@gentoo.org>
 
  10   Copyright (c) 2005 Andreas Jaggi <andreas.jaggi@waterwave.ch>
 
  12   This program is free software; you can redistribute it and/or modify
 
  13   it under the terms of the GNU General Public License as published by
 
  14   the Free Software Foundation; either version 2 of the License, or
 
  15   (at your option) any later version.
 
  17   This program is distributed in the hope that it will be useful,
 
  18   but WITHOUT ANY WARRANTY; without even the implied warranty of
 
  19   MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
 
  20   GNU General Public License for more details.
 
  22   You should have received a copy of the GNU General Public License
 
  23   along with this program; see the file COPYING.  If not, write to
 
  24   the Free Software Foundation, Inc., 51 Franklin Steet, Fifth Floor,
 
  25   Boston, MA 02110-1301, USA.
 
  29 #include "b43legacy.h"
 
  33 static void b43legacy_led_turn_on(struct b43legacy_wldev *dev, u8 led_index,
 
  36         struct b43legacy_wl *wl = dev->wl;
 
  40         spin_lock_irqsave(&wl->leds_lock, flags);
 
  41         ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
 
  43                 ctl &= ~(1 << led_index);
 
  45                 ctl |= (1 << led_index);
 
  46         b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
 
  47         spin_unlock_irqrestore(&wl->leds_lock, flags);
 
  50 static void b43legacy_led_turn_off(struct b43legacy_wldev *dev, u8 led_index,
 
  53         struct b43legacy_wl *wl = dev->wl;
 
  57         spin_lock_irqsave(&wl->leds_lock, flags);
 
  58         ctl = b43legacy_read16(dev, B43legacy_MMIO_GPIO_CONTROL);
 
  60                 ctl |= (1 << led_index);
 
  62                 ctl &= ~(1 << led_index);
 
  63         b43legacy_write16(dev, B43legacy_MMIO_GPIO_CONTROL, ctl);
 
  64         spin_unlock_irqrestore(&wl->leds_lock, flags);
 
  67 /* Callback from the LED subsystem. */
 
  68 static void b43legacy_led_brightness_set(struct led_classdev *led_dev,
 
  69                                    enum led_brightness brightness)
 
  71         struct b43legacy_led *led = container_of(led_dev, struct b43legacy_led,
 
  73         struct b43legacy_wldev *dev = led->dev;
 
  76         /* Checking the radio-enabled status here is slightly racy,
 
  77          * but we want to avoid the locking overhead and we don't care
 
  78          * whether the LED has the wrong state for a second. */
 
  79         radio_enabled = (dev->phy.radio_on && dev->radio_hw_enable);
 
  81         if (brightness == LED_OFF || !radio_enabled)
 
  82                 b43legacy_led_turn_off(dev, led->index, led->activelow);
 
  84                 b43legacy_led_turn_on(dev, led->index, led->activelow);
 
  87 static int b43legacy_register_led(struct b43legacy_wldev *dev,
 
  88                                   struct b43legacy_led *led,
 
  89                                   const char *name, char *default_trigger,
 
  90                                   u8 led_index, bool activelow)
 
  94         b43legacy_led_turn_off(dev, led_index, activelow);
 
 100         led->index = led_index;
 
 101         led->activelow = activelow;
 
 102         strncpy(led->name, name, sizeof(led->name));
 
 104         led->led_dev.name = led->name;
 
 105         led->led_dev.default_trigger = default_trigger;
 
 106         led->led_dev.brightness_set = b43legacy_led_brightness_set;
 
 108         err = led_classdev_register(dev->dev->dev, &led->led_dev);
 
 110                 b43legacywarn(dev->wl, "LEDs: Failed to register %s\n", name);
 
 117 static void b43legacy_unregister_led(struct b43legacy_led *led)
 
 121         led_classdev_unregister(&led->led_dev);
 
 122         b43legacy_led_turn_off(led->dev, led->index, led->activelow);
 
 126 static void b43legacy_map_led(struct b43legacy_wldev *dev,
 
 128                         enum b43legacy_led_behaviour behaviour,
 
 131         struct ieee80211_hw *hw = dev->wl->hw;
 
 132         char name[B43legacy_LED_MAX_NAME_LEN + 1];
 
 134         /* Map the b43 specific LED behaviour value to the
 
 135          * generic LED triggers. */
 
 137         case B43legacy_LED_INACTIVE:
 
 139         case B43legacy_LED_OFF:
 
 140                 b43legacy_led_turn_off(dev, led_index, activelow);
 
 142         case B43legacy_LED_ON:
 
 143                 b43legacy_led_turn_on(dev, led_index, activelow);
 
 145         case B43legacy_LED_ACTIVITY:
 
 146         case B43legacy_LED_TRANSFER:
 
 147         case B43legacy_LED_APTRANSFER:
 
 148                 snprintf(name, sizeof(name),
 
 149                          "b43legacy-%s:tx", wiphy_name(hw->wiphy));
 
 150                 b43legacy_register_led(dev, &dev->led_tx, name,
 
 151                                  ieee80211_get_tx_led_name(hw),
 
 152                                  led_index, activelow);
 
 153                 snprintf(name, sizeof(name),
 
 154                          "b43legacy-%s:rx", wiphy_name(hw->wiphy));
 
 155                 b43legacy_register_led(dev, &dev->led_rx, name,
 
 156                                  ieee80211_get_rx_led_name(hw),
 
 157                                  led_index, activelow);
 
 159         case B43legacy_LED_RADIO_ALL:
 
 160         case B43legacy_LED_RADIO_A:
 
 161         case B43legacy_LED_RADIO_B:
 
 162         case B43legacy_LED_MODE_BG:
 
 163                 snprintf(name, sizeof(name),
 
 164                          "b43legacy-%s:radio", wiphy_name(hw->wiphy));
 
 165                 b43legacy_register_led(dev, &dev->led_radio, name,
 
 166                                  b43legacy_rfkill_led_name(dev),
 
 167                                  led_index, activelow);
 
 168                 /* Sync the RF-kill LED state with the switch state. */
 
 169                 if (dev->radio_hw_enable)
 
 170                         b43legacy_led_turn_on(dev, led_index, activelow);
 
 172         case B43legacy_LED_WEIRD:
 
 173         case B43legacy_LED_ASSOC:
 
 174                 snprintf(name, sizeof(name),
 
 175                          "b43legacy-%s:assoc", wiphy_name(hw->wiphy));
 
 176                 b43legacy_register_led(dev, &dev->led_assoc, name,
 
 177                                  ieee80211_get_assoc_led_name(hw),
 
 178                                  led_index, activelow);
 
 181                 b43legacywarn(dev->wl, "LEDs: Unknown behaviour 0x%02X\n",
 
 187 void b43legacy_leds_init(struct b43legacy_wldev *dev)
 
 189         struct ssb_bus *bus = dev->dev->bus;
 
 192         enum b43legacy_led_behaviour behaviour;
 
 195         sprom[0] = bus->sprom.gpio0;
 
 196         sprom[1] = bus->sprom.gpio1;
 
 197         sprom[2] = bus->sprom.gpio2;
 
 198         sprom[3] = bus->sprom.gpio3;
 
 200         for (i = 0; i < 4; i++) {
 
 201                 if (sprom[i] == 0xFF) {
 
 202                         /* There is no LED information in the SPROM
 
 203                          * for this LED. Hardcode it here. */
 
 207                                 behaviour = B43legacy_LED_ACTIVITY;
 
 209                                 if (bus->boardinfo.vendor == PCI_VENDOR_ID_COMPAQ)
 
 210                                         behaviour = B43legacy_LED_RADIO_ALL;
 
 213                                 behaviour = B43legacy_LED_RADIO_B;
 
 214                                 if (bus->boardinfo.vendor == PCI_VENDOR_ID_ASUSTEK)
 
 215                                         behaviour = B43legacy_LED_ASSOC;
 
 218                                 behaviour = B43legacy_LED_RADIO_A;
 
 221                                 behaviour = B43legacy_LED_OFF;
 
 224                                 B43legacy_WARN_ON(1);
 
 228                         behaviour = sprom[i] & B43legacy_LED_BEHAVIOUR;
 
 229                         activelow = !!(sprom[i] & B43legacy_LED_ACTIVELOW);
 
 231                 b43legacy_map_led(dev, i, behaviour, activelow);
 
 235 void b43legacy_leds_exit(struct b43legacy_wldev *dev)
 
 237         b43legacy_unregister_led(&dev->led_tx);
 
 238         b43legacy_unregister_led(&dev->led_rx);
 
 239         b43legacy_unregister_led(&dev->led_assoc);
 
 240         b43legacy_unregister_led(&dev->led_radio);