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 22 static 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. */ 35 static 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 43 void 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 51 int 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