Linux Kernel  3.7.1
 All Data Structures Namespaces Files Functions Variables Typedefs Enumerations Enumerator Macros Groups Pages
leds.c
Go to the documentation of this file.
1 /*
2  * Linux LED driver for RTL8187
3  *
4  * Copyright 2009 Larry Finger <[email protected]>
5  *
6  * Based on the LED handling in the r8187 driver, which is:
7  * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
8  *
9  * Thanks to Realtek for their support!
10  *
11  * This program is free software; you can redistribute it and/or modify
12  * it under the terms of the GNU General Public License version 2 as
13  * published by the Free Software Foundation.
14  */
15 
16 #ifdef CONFIG_RTL8187_LEDS
17 
18 #include <net/mac80211.h>
19 #include <linux/usb.h>
20 #include <linux/eeprom_93cx6.h>
21 
22 #include "rtl8187.h"
23 #include "leds.h"
24 
25 static void led_turn_on(struct work_struct *work)
26 {
27  /* As this routine does read/write operations on the hardware, it must
28  * be run from a work queue.
29  */
30  u8 reg;
31  struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
32  led_on.work);
33  struct rtl8187_led *led = &priv->led_tx;
34 
35  /* Don't change the LED, when the device is down. */
36  if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED)
37  return ;
38 
39  /* Skip if the LED is not registered. */
40  if (!led->dev)
41  return;
42  mutex_lock(&priv->conf_mutex);
43  switch (led->ledpin) {
44  case LED_PIN_GPIO0:
45  rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01);
46  rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x00);
47  break;
48  case LED_PIN_LED0:
49  reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 4);
50  rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
51  break;
52  case LED_PIN_LED1:
53  reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) & ~(1 << 5);
54  rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
55  break;
56  case LED_PIN_HW:
57  default:
58  break;
59  }
60  mutex_unlock(&priv->conf_mutex);
61 }
62 
63 static void led_turn_off(struct work_struct *work)
64 {
65  /* As this routine does read/write operations on the hardware, it must
66  * be run from a work queue.
67  */
68  u8 reg;
69  struct rtl8187_priv *priv = container_of(work, struct rtl8187_priv,
70  led_off.work);
71  struct rtl8187_led *led = &priv->led_tx;
72 
73  /* Don't change the LED, when the device is down. */
74  if (!priv->vif || priv->vif->type == NL80211_IFTYPE_UNSPECIFIED)
75  return ;
76 
77  /* Skip if the LED is not registered. */
78  if (!led->dev)
79  return;
80  mutex_lock(&priv->conf_mutex);
81  switch (led->ledpin) {
82  case LED_PIN_GPIO0:
83  rtl818x_iowrite8(priv, &priv->map->GPIO0, 0x01);
84  rtl818x_iowrite8(priv, &priv->map->GP_ENABLE, 0x01);
85  break;
86  case LED_PIN_LED0:
87  reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 4);
88  rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
89  break;
90  case LED_PIN_LED1:
91  reg = rtl818x_ioread8(priv, &priv->map->PGSELECT) | (1 << 5);
92  rtl818x_iowrite8(priv, &priv->map->PGSELECT, reg);
93  break;
94  case LED_PIN_HW:
95  default:
96  break;
97  }
98  mutex_unlock(&priv->conf_mutex);
99 }
100 
101 /* Callback from the LED subsystem. */
102 static void rtl8187_led_brightness_set(struct led_classdev *led_dev,
104 {
105  struct rtl8187_led *led = container_of(led_dev, struct rtl8187_led,
106  led_dev);
107  struct ieee80211_hw *hw = led->dev;
108  struct rtl8187_priv *priv;
109  static bool radio_on;
110 
111  if (!hw)
112  return;
113  priv = hw->priv;
114  if (led->is_radio) {
115  if (brightness == LED_FULL) {
116  ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
117  radio_on = true;
118  } else if (radio_on) {
119  radio_on = false;
120  cancel_delayed_work(&priv->led_on);
121  ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
122  }
123  } else if (radio_on) {
124  if (brightness == LED_OFF) {
125  ieee80211_queue_delayed_work(hw, &priv->led_off, 0);
126  /* The LED is off for 1/20 sec - it just blinks. */
127  ieee80211_queue_delayed_work(hw, &priv->led_on,
128  HZ / 20);
129  } else
130  ieee80211_queue_delayed_work(hw, &priv->led_on, 0);
131  }
132 }
133 
134 static int rtl8187_register_led(struct ieee80211_hw *dev,
135  struct rtl8187_led *led, const char *name,
136  const char *default_trigger, u8 ledpin,
137  bool is_radio)
138 {
139  int err;
140  struct rtl8187_priv *priv = dev->priv;
141 
142  if (led->dev)
143  return -EEXIST;
144  if (!default_trigger)
145  return -EINVAL;
146  led->dev = dev;
147  led->ledpin = ledpin;
148  led->is_radio = is_radio;
149  strncpy(led->name, name, sizeof(led->name));
150 
151  led->led_dev.name = led->name;
152  led->led_dev.default_trigger = default_trigger;
153  led->led_dev.brightness_set = rtl8187_led_brightness_set;
154 
155  err = led_classdev_register(&priv->udev->dev, &led->led_dev);
156  if (err) {
157  printk(KERN_INFO "LEDs: Failed to register %s\n", name);
158  led->dev = NULL;
159  return err;
160  }
161  return 0;
162 }
163 
164 static void rtl8187_unregister_led(struct rtl8187_led *led)
165 {
166  struct ieee80211_hw *hw = led->dev;
167  struct rtl8187_priv *priv = hw->priv;
168 
169  led_classdev_unregister(&led->led_dev);
170  flush_delayed_work(&priv->led_off);
171  led->dev = NULL;
172 }
173 
174 void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid)
175 {
176  struct rtl8187_priv *priv = dev->priv;
177  char name[RTL8187_LED_MAX_NAME_LEN + 1];
178  u8 ledpin;
179  int err;
180 
181  /* According to the vendor driver, the LED operation depends on the
182  * customer ID encoded in the EEPROM
183  */
184  printk(KERN_INFO "rtl8187: Customer ID is 0x%02X\n", custid);
185  switch (custid) {
186  case EEPROM_CID_RSVD0:
187  case EEPROM_CID_RSVD1:
188  case EEPROM_CID_SERCOMM_PS:
189  case EEPROM_CID_QMI:
190  case EEPROM_CID_DELL:
191  case EEPROM_CID_TOSHIBA:
192  ledpin = LED_PIN_GPIO0;
193  break;
194  case EEPROM_CID_ALPHA0:
195  ledpin = LED_PIN_LED0;
196  break;
197  case EEPROM_CID_HW:
198  ledpin = LED_PIN_HW;
199  break;
200  default:
201  ledpin = LED_PIN_GPIO0;
202  }
203 
204  INIT_DELAYED_WORK(&priv->led_on, led_turn_on);
205  INIT_DELAYED_WORK(&priv->led_off, led_turn_off);
206 
207  snprintf(name, sizeof(name),
208  "rtl8187-%s::radio", wiphy_name(dev->wiphy));
209  err = rtl8187_register_led(dev, &priv->led_radio, name,
210  ieee80211_get_radio_led_name(dev), ledpin, true);
211  if (err)
212  return;
213 
214  snprintf(name, sizeof(name),
215  "rtl8187-%s::tx", wiphy_name(dev->wiphy));
216  err = rtl8187_register_led(dev, &priv->led_tx, name,
217  ieee80211_get_tx_led_name(dev), ledpin, false);
218  if (err)
219  goto err_tx;
220 
221  snprintf(name, sizeof(name),
222  "rtl8187-%s::rx", wiphy_name(dev->wiphy));
223  err = rtl8187_register_led(dev, &priv->led_rx, name,
224  ieee80211_get_rx_led_name(dev), ledpin, false);
225  if (!err)
226  return;
227 
228  /* registration of RX LED failed - unregister */
229  rtl8187_unregister_led(&priv->led_tx);
230 err_tx:
231  rtl8187_unregister_led(&priv->led_radio);
232 }
233 
234 void rtl8187_leds_exit(struct ieee80211_hw *dev)
235 {
236  struct rtl8187_priv *priv = dev->priv;
237 
238  rtl8187_unregister_led(&priv->led_radio);
239  rtl8187_unregister_led(&priv->led_rx);
240  rtl8187_unregister_led(&priv->led_tx);
241  cancel_delayed_work_sync(&priv->led_off);
242  cancel_delayed_work_sync(&priv->led_on);
243 }
244 #endif /* def CONFIG_RTL8187_LEDS */
245