linux/drivers/net/wireless/brcm80211/brcmsmac/led.c
<<
>>
Prefs
   1#include <net/mac80211.h>
   2#include <linux/bcma/bcma_driver_chipcommon.h>
   3#include <linux/gpio.h>
   4
   5#include "mac80211_if.h"
   6#include "pub.h"
   7#include "main.h"
   8#include "led.h"
   9
  10        /* number of leds */
  11#define  BRCMS_LED_NO           4
  12        /* behavior mask */
  13#define  BRCMS_LED_BEH_MASK     0x7f
  14        /* activelow (polarity) bit */
  15#define  BRCMS_LED_AL_MASK      0x80
  16        /* radio enabled */
  17#define  BRCMS_LED_RADIO        3
  18
  19static void brcms_radio_led_ctrl(struct brcms_info *wl, bool state)
  20{
  21        if (wl->radio_led.gpio == -1)
  22                return;
  23
  24        if (wl->radio_led.active_low)
  25                state = !state;
  26
  27        if (state)
  28                gpio_set_value(wl->radio_led.gpio, 1);
  29        else
  30                gpio_set_value(wl->radio_led.gpio, 0);
  31}
  32
  33
  34/* Callback from the LED subsystem. */
  35static void brcms_led_brightness_set(struct led_classdev *led_dev,
  36                                   enum led_brightness brightness)
  37{
  38        struct brcms_info *wl = container_of(led_dev,
  39                struct brcms_info, led_dev);
  40        brcms_radio_led_ctrl(wl, brightness);
  41}
  42
  43void brcms_led_unregister(struct brcms_info *wl)
  44{
  45        if (wl->led_dev.dev)
  46                led_classdev_unregister(&wl->led_dev);
  47        if (wl->radio_led.gpio != -1)
  48                gpio_free(wl->radio_led.gpio);
  49}
  50
  51int brcms_led_register(struct brcms_info *wl)
  52{
  53        int i, err;
  54        struct brcms_led *radio_led = &wl->radio_led;
  55        /* get CC core */
  56        struct bcma_drv_cc *cc_drv  = &wl->wlc->hw->d11core->bus->drv_cc;
  57        struct gpio_chip *bcma_gpio = &cc_drv->gpio;
  58        struct ssb_sprom *sprom = &wl->wlc->hw->d11core->bus->sprom;
  59        u8 *leds[] = { &sprom->gpio0,
  60                &sprom->gpio1,
  61                &sprom->gpio2,
  62                &sprom->gpio3 };
  63        unsigned gpio = -1;
  64        bool active_low = false;
  65
  66        /* none by default */
  67        radio_led->gpio = -1;
  68        radio_led->active_low = false;
  69
  70        if (!bcma_gpio || !gpio_is_valid(bcma_gpio->base))
  71                return -ENODEV;
  72
  73        /* find radio enabled LED */
  74        for (i = 0; i < BRCMS_LED_NO; i++) {
  75                u8 led = *leds[i];
  76                if ((led & BRCMS_LED_BEH_MASK) == BRCMS_LED_RADIO) {
  77                        gpio = bcma_gpio->base + i;
  78                        if (led & BRCMS_LED_AL_MASK)
  79                                active_low = true;
  80                        break;
  81                }
  82        }
  83
  84        if (gpio == -1 || !gpio_is_valid(gpio))
  85                return -ENODEV;
  86
  87        /* request and configure LED gpio */
  88        err = gpio_request_one(gpio,
  89                                active_low ? GPIOF_OUT_INIT_HIGH
  90                                        : GPIOF_OUT_INIT_LOW,
  91                                "radio on");
  92        if (err) {
  93                wiphy_err(wl->wiphy, "requesting led gpio %d failed (err: %d)\n",
  94                          gpio, err);
  95                return err;
  96        }
  97        err = gpio_direction_output(gpio, 1);
  98        if (err) {
  99                wiphy_err(wl->wiphy, "cannot set led gpio %d to output (err: %d)\n",
 100                          gpio, err);
 101                return err;
 102        }
 103
 104        snprintf(wl->radio_led.name, sizeof(wl->radio_led.name),
 105                 "brcmsmac-%s:radio", wiphy_name(wl->wiphy));
 106
 107        wl->led_dev.name = wl->radio_led.name;
 108        wl->led_dev.default_trigger =
 109                ieee80211_get_radio_led_name(wl->pub->ieee_hw);
 110        wl->led_dev.brightness_set = brcms_led_brightness_set;
 111        err = led_classdev_register(wiphy_dev(wl->wiphy), &wl->led_dev);
 112
 113        if (err) {
 114                wiphy_err(wl->wiphy, "cannot register led device: %s (err: %d)\n",
 115                          wl->radio_led.name, err);
 116                return err;
 117        }
 118
 119        wiphy_info(wl->wiphy, "registered radio enabled led device: %s gpio: %d\n",
 120                   wl->radio_led.name,
 121                   gpio);
 122        radio_led->gpio = gpio;
 123        radio_led->active_low = active_low;
 124
 125        return 0;
 126}
 127