aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/net/wireless/brcm80211/brcmsmac
diff options
context:
space:
mode:
authorPiotr Haber <phaber@broadcom.com>2013-03-03 06:45:20 -0500
committerJohn W. Linville <linville@tuxdriver.com>2013-03-06 16:28:20 -0500
commitcd864522b349cfe88903cf6f3415293c39856b6c (patch)
treeaf4f249a27c55053f59b6cded29b641535ced413 /drivers/net/wireless/brcm80211/brcmsmac
parent98929824eec490984e42ac9dc3b96f7f12033996 (diff)
brcmsmac: radio on led support
Add support for radio on led indicator. Control led via BCMA gpio driver. Reviewed-by: Pieter-Paul Giesberts <pieterpg@broadcom.com> Reviewed-by: Hante Meuleman <meuleman@broadcom.com> Reviewed-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: Piotr Haber <phaber@broadcom.com> [arend@broadcom.com: modify Makefile for conditional compile led.c] Signed-off-by: Arend van Spriel <arend@broadcom.com> Signed-off-by: John W. Linville <linville@tuxdriver.com>
Diffstat (limited to 'drivers/net/wireless/brcm80211/brcmsmac')
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/Makefile4
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/led.c126
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/led.h36
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c4
-rw-r--r--drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h4
5 files changed, 174 insertions, 0 deletions
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/Makefile b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
index d3d4151c3eda..cba19d839b77 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/Makefile
+++ b/drivers/net/wireless/brcm80211/brcmsmac/Makefile
@@ -43,6 +43,10 @@ BRCMSMAC_OFILES := \
43 brcms_trace_events.o \ 43 brcms_trace_events.o \
44 debug.o 44 debug.o
45 45
46ifdef CONFIG_BCMA_DRIVER_GPIO
47BRCMSMAC_OFILES += led.o
48endif
49
46MODULEPFX := brcmsmac 50MODULEPFX := brcmsmac
47 51
48obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o 52obj-$(CONFIG_BRCMSMAC) += $(MODULEPFX).o
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/led.c b/drivers/net/wireless/brcm80211/brcmsmac/led.c
new file mode 100644
index 000000000000..74b17cecb189
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/led.c
@@ -0,0 +1,126 @@
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}
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/led.h b/drivers/net/wireless/brcm80211/brcmsmac/led.h
new file mode 100644
index 000000000000..17a0b1f5dbcf
--- /dev/null
+++ b/drivers/net/wireless/brcm80211/brcmsmac/led.h
@@ -0,0 +1,36 @@
1/*
2 * Copyright (c) 2012 Broadcom Corporation
3 *
4 * Permission to use, copy, modify, and/or distribute this software for any
5 * purpose with or without fee is hereby granted, provided that the above
6 * copyright notice and this permission notice appear in all copies.
7 *
8 * THE SOFTWARE IS PROVIDED "AS IS" AND THE AUTHOR DISCLAIMS ALL WARRANTIES
9 * WITH REGARD TO THIS SOFTWARE INCLUDING ALL IMPLIED WARRANTIES OF
10 * MERCHANTABILITY AND FITNESS. IN NO EVENT SHALL THE AUTHOR BE LIABLE FOR ANY
11 * SPECIAL, DIRECT, INDIRECT, OR CONSEQUENTIAL DAMAGES OR ANY DAMAGES
12 * WHATSOEVER RESULTING FROM LOSS OF USE, DATA OR PROFITS, WHETHER IN AN ACTION
13 * OF CONTRACT, NEGLIGENCE OR OTHER TORTIOUS ACTION, ARISING OUT OF OR IN
14 * CONNECTION WITH THE USE OR PERFORMANCE OF THIS SOFTWARE.
15 */
16
17#ifndef _BRCM_LED_H_
18#define _BRCM_LED_H_
19struct brcms_led {
20 char name[32];
21 unsigned gpio;
22 bool active_low;
23};
24
25#ifdef CONFIG_BCMA_DRIVER_GPIO
26void brcms_led_unregister(struct brcms_info *wl);
27int brcms_led_register(struct brcms_info *wl);
28#else
29static inline void brcms_led_unregister(struct brcms_info *wl) {};
30static inline int brcms_led_register(struct brcms_info *wl)
31{
32 return -ENOTSUPP;
33};
34#endif
35
36#endif /* _BRCM_LED_H_ */
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
index c6451c61407a..c70cf7b654cd 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.c
@@ -34,6 +34,7 @@
34#include "mac80211_if.h" 34#include "mac80211_if.h"
35#include "main.h" 35#include "main.h"
36#include "debug.h" 36#include "debug.h"
37#include "led.h"
37 38
38#define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */ 39#define N_TX_QUEUES 4 /* #tx queues on mac80211<->driver interface */
39#define BRCMS_FLUSH_TIMEOUT 500 /* msec */ 40#define BRCMS_FLUSH_TIMEOUT 500 /* msec */
@@ -904,6 +905,7 @@ static void brcms_remove(struct bcma_device *pdev)
904 struct brcms_info *wl = hw->priv; 905 struct brcms_info *wl = hw->priv;
905 906
906 if (wl->wlc) { 907 if (wl->wlc) {
908 brcms_led_unregister(wl);
907 wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false); 909 wiphy_rfkill_set_hw_state(wl->pub->ieee_hw->wiphy, false);
908 wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy); 910 wiphy_rfkill_stop_polling(wl->pub->ieee_hw->wiphy);
909 ieee80211_unregister_hw(hw); 911 ieee80211_unregister_hw(hw);
@@ -1151,6 +1153,8 @@ static int brcms_bcma_probe(struct bcma_device *pdev)
1151 pr_err("%s: brcms_attach failed!\n", __func__); 1153 pr_err("%s: brcms_attach failed!\n", __func__);
1152 return -ENODEV; 1154 return -ENODEV;
1153 } 1155 }
1156 brcms_led_register(wl);
1157
1154 return 0; 1158 return 0;
1155} 1159}
1156 1160
diff --git a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
index 947ccacf43e6..4090032e81a2 100644
--- a/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
+++ b/drivers/net/wireless/brcm80211/brcmsmac/mac80211_if.h
@@ -20,8 +20,10 @@
20#include <linux/timer.h> 20#include <linux/timer.h>
21#include <linux/interrupt.h> 21#include <linux/interrupt.h>
22#include <linux/workqueue.h> 22#include <linux/workqueue.h>
23#include <linux/leds.h>
23 24
24#include "ucode_loader.h" 25#include "ucode_loader.h"
26#include "led.h"
25/* 27/*
26 * Starting index for 5G rates in the 28 * Starting index for 5G rates in the
27 * legacy rate table. 29 * legacy rate table.
@@ -81,6 +83,8 @@ struct brcms_info {
81 struct wiphy *wiphy; 83 struct wiphy *wiphy;
82 struct brcms_ucode ucode; 84 struct brcms_ucode ucode;
83 bool mute_tx; 85 bool mute_tx;
86 struct brcms_led radio_led;
87 struct led_classdev led_dev;
84}; 88};
85 89
86/* misc callbacks */ 90/* misc callbacks */