Blame view

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