linux/drivers/net/wireless/broadcom/brcm80211/brcmsmac/led.c
<<
>>
Prefs
   1// SPDX-License-Identifier: GPL-2.0
   2#include <net/mac80211.h>
   3#include <linux/bcma/bcma_driver_chipcommon.h>
   4#include <linux/gpio/driver.h>
   5#include <linux/gpio/machine.h>
   6#include <linux/gpio/consumer.h>
   7
   8#include "mac80211_if.h"
   9#include "pub.h"
  10#include "main.h"
  11#include "led.h"
  12
  13        /* number of leds */
  14#define  BRCMS_LED_NO           4
  15        /* behavior mask */
  16#define  BRCMS_LED_BEH_MASK     0x7f
  17        /* activelow (polarity) bit */
  18#define  BRCMS_LED_AL_MASK      0x80
  19        /* radio enabled */
  20#define  BRCMS_LED_RADIO        3
  21
  22static void brcms_radio_led_ctrl(struct brcms_info *wl, bool state)
  23{
  24        if (!wl->radio_led.gpiod)
  25                return;
  26
  27        if (state)
  28                gpiod_set_value(wl->radio_led.gpiod, 1);
  29        else
  30                gpiod_set_value(wl->radio_led.gpiod, 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.gpiod)
  48                gpiochip_free_own_desc(wl->radio_led.gpiod);
  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        int hwnum = -1;
  64        enum gpio_lookup_flags lflags = GPIO_ACTIVE_HIGH;
  65
  66        if (!bcma_gpio || !gpio_is_valid(bcma_gpio->base))
  67                return -ENODEV;
  68
  69        /* find radio enabled LED */
  70        for (i = 0; i < BRCMS_LED_NO; i++) {
  71                u8 led = *leds[i];
  72                if ((led & BRCMS_LED_BEH_MASK) == BRCMS_LED_RADIO) {
  73                        hwnum = i;
  74                        if (led & BRCMS_LED_AL_MASK)
  75                                lflags = GPIO_ACTIVE_LOW;
  76                        break;
  77                }
  78        }
  79
  80        /* No LED, bail out */
  81        if (hwnum == -1)
  82                return -ENODEV;
  83
  84        /* Try to obtain this LED GPIO line */
  85        radio_led->gpiod = gpiochip_request_own_desc(bcma_gpio, hwnum,
  86                                                     "radio on", lflags,
  87                                                     GPIOD_OUT_LOW);
  88
  89        if (IS_ERR(radio_led->gpiod)) {
  90                err = PTR_ERR(radio_led->gpiod);
  91                wiphy_err(wl->wiphy, "requesting led GPIO failed (err: %d)\n",
  92                          err);
  93                return err;
  94        }
  95
  96        snprintf(wl->radio_led.name, sizeof(wl->radio_led.name),
  97                 "brcmsmac-%s:radio", wiphy_name(wl->wiphy));
  98
  99        wl->led_dev.name = wl->radio_led.name;
 100        wl->led_dev.default_trigger =
 101                ieee80211_get_radio_led_name(wl->pub->ieee_hw);
 102        wl->led_dev.brightness_set = brcms_led_brightness_set;
 103        err = led_classdev_register(wiphy_dev(wl->wiphy), &wl->led_dev);
 104
 105        if (err) {
 106                wiphy_err(wl->wiphy, "cannot register led device: %s (err: %d)\n",
 107                          wl->radio_led.name, err);
 108                return err;
 109        }
 110
 111        wiphy_info(wl->wiphy, "registered radio enabled led device: %s\n",
 112                   wl->radio_led.name);
 113
 114        return 0;
 115}
 116