aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/net/wireless/Kconfig7
-rw-r--r--drivers/net/wireless/rtl818x/Makefile2
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187.h7
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_dev.c18
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_leds.c218
-rw-r--r--drivers/net/wireless/rtl818x/rtl8187_leds.h57
6 files changed, 305 insertions, 4 deletions
diff --git a/drivers/net/wireless/Kconfig b/drivers/net/wireless/Kconfig
index ad99470ae92d..11c248180982 100644
--- a/drivers/net/wireless/Kconfig
+++ b/drivers/net/wireless/Kconfig
@@ -433,6 +433,13 @@ config RTL8187
433 433
434 Thanks to Realtek for their support! 434 Thanks to Realtek for their support!
435 435
436# If possible, automatically enable LEDs for RTL8187.
437
438config RTL8187_LEDS
439 bool
440 depends on RTL8187 && MAC80211_LEDS && (LEDS_CLASS = y || LEDS_CLASS = RTL8187)
441 default y
442
436config ADM8211 443config ADM8211
437 tristate "ADMtek ADM8211 support" 444 tristate "ADMtek ADM8211 support"
438 depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL 445 depends on MAC80211 && PCI && WLAN_80211 && EXPERIMENTAL
diff --git a/drivers/net/wireless/rtl818x/Makefile b/drivers/net/wireless/rtl818x/Makefile
index c113b3e69046..37e3d4db0c40 100644
--- a/drivers/net/wireless/rtl818x/Makefile
+++ b/drivers/net/wireless/rtl818x/Makefile
@@ -1,5 +1,5 @@
1rtl8180-objs := rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o 1rtl8180-objs := rtl8180_dev.o rtl8180_rtl8225.o rtl8180_sa2400.o rtl8180_max2820.o rtl8180_grf5101.o
2rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o 2rtl8187-objs := rtl8187_dev.o rtl8187_rtl8225.o rtl8187_leds.o
3 3
4obj-$(CONFIG_RTL8180) += rtl8180.o 4obj-$(CONFIG_RTL8180) += rtl8180.o
5obj-$(CONFIG_RTL8187) += rtl8187.o 5obj-$(CONFIG_RTL8187) += rtl8187.o
diff --git a/drivers/net/wireless/rtl818x/rtl8187.h b/drivers/net/wireless/rtl818x/rtl8187.h
index 9718f61809cf..622196dc078e 100644
--- a/drivers/net/wireless/rtl818x/rtl8187.h
+++ b/drivers/net/wireless/rtl818x/rtl8187.h
@@ -16,6 +16,7 @@
16#define RTL8187_H 16#define RTL8187_H
17 17
18#include "rtl818x.h" 18#include "rtl818x.h"
19#include "rtl8187_leds.h"
19 20
20#define RTL8187_EEPROM_TXPWR_BASE 0x05 21#define RTL8187_EEPROM_TXPWR_BASE 0x05
21#define RTL8187_EEPROM_MAC_ADDR 0x07 22#define RTL8187_EEPROM_MAC_ADDR 0x07
@@ -102,6 +103,12 @@ struct rtl8187_priv {
102 struct usb_anchor anchored; 103 struct usb_anchor anchored;
103 struct delayed_work work; 104 struct delayed_work work;
104 struct ieee80211_hw *dev; 105 struct ieee80211_hw *dev;
106#ifdef CONFIG_RTL8187_LEDS
107 struct rtl8187_led led_tx;
108 struct rtl8187_led led_rx;
109 struct delayed_work led_on;
110 struct delayed_work led_off;
111#endif
105 u16 txpwr_base; 112 u16 txpwr_base;
106 u8 asic_rev; 113 u8 asic_rev;
107 u8 is_rtl8187b; 114 u8 is_rtl8187b;
diff --git a/drivers/net/wireless/rtl818x/rtl8187_dev.c b/drivers/net/wireless/rtl818x/rtl8187_dev.c
index d6d4001812a7..ac558da92aac 100644
--- a/drivers/net/wireless/rtl818x/rtl8187_dev.c
+++ b/drivers/net/wireless/rtl818x/rtl8187_dev.c
@@ -29,6 +29,9 @@
29 29
30#include "rtl8187.h" 30#include "rtl8187.h"
31#include "rtl8187_rtl8225.h" 31#include "rtl8187_rtl8225.h"
32#ifdef CONFIG_RTL8187_LEDS
33#include "rtl8187_leds.h"
34#endif
32 35
33MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>"); 36MODULE_AUTHOR("Michael Wu <flamingice@sourmilk.net>");
34MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>"); 37MODULE_AUTHOR("Andrea Merello <andreamrl@tiscali.it>");
@@ -734,10 +737,10 @@ static const u8 rtl8187b_reg_table[][3] = {
734 {0x85, 0x24, 0}, {0x88, 0x54, 0}, {0x8B, 0xB8, 0}, {0x8C, 0x07, 0}, 737 {0x85, 0x24, 0}, {0x88, 0x54, 0}, {0x8B, 0xB8, 0}, {0x8C, 0x07, 0},
735 {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, {0x95, 0x12, 0}, {0x96, 0x00, 0}, 738 {0x8D, 0x00, 0}, {0x94, 0x1B, 0}, {0x95, 0x12, 0}, {0x96, 0x00, 0},
736 {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, {0x9F, 0x10, 0}, {0xB4, 0x22, 0}, 739 {0x97, 0x06, 0}, {0x9D, 0x1A, 0}, {0x9F, 0x10, 0}, {0xB4, 0x22, 0},
737 {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x91, 0x03, 0}, 740 {0xBE, 0x80, 0}, {0xDB, 0x00, 0}, {0xEE, 0x00, 0}, {0x4C, 0x00, 2},
738 741
739 {0x4C, 0x00, 2}, {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, 742 {0x9F, 0x00, 3}, {0x8C, 0x01, 0}, {0x8D, 0x10, 0}, {0x8E, 0x08, 0},
740 {0x8E, 0x08, 0}, {0x8F, 0x00, 0} 743 {0x8F, 0x00, 0}
741}; 744};
742 745
743static int rtl8187b_init_hw(struct ieee80211_hw *dev) 746static int rtl8187b_init_hw(struct ieee80211_hw *dev)
@@ -1501,6 +1504,12 @@ static int __devinit rtl8187_probe(struct usb_interface *intf,
1501 wiphy_name(dev->wiphy), dev->wiphy->perm_addr, 1504 wiphy_name(dev->wiphy), dev->wiphy->perm_addr,
1502 chip_name, priv->asic_rev, priv->rf->name); 1505 chip_name, priv->asic_rev, priv->rf->name);
1503 1506
1507#ifdef CONFIG_RTL8187_LEDS
1508 eeprom_93cx6_read(&eeprom, 0x3F, &reg);
1509 reg &= 0xFF;
1510 rtl8187_leds_init(dev, reg);
1511#endif
1512
1504 return 0; 1513 return 0;
1505 1514
1506 err_free_dev: 1515 err_free_dev:
@@ -1518,6 +1527,9 @@ static void __devexit rtl8187_disconnect(struct usb_interface *intf)
1518 if (!dev) 1527 if (!dev)
1519 return; 1528 return;
1520 1529
1530#ifdef CONFIG_RTL8187_LEDS
1531 rtl8187_leds_exit(dev);
1532#endif
1521 ieee80211_unregister_hw(dev); 1533 ieee80211_unregister_hw(dev);
1522 1534
1523 priv = dev->priv; 1535 priv = dev->priv;
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.c b/drivers/net/wireless/rtl818x/rtl8187_leds.c
new file mode 100644
index 000000000000..b44253592243
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/rtl8187_leds.c
@@ -0,0 +1,218 @@
1/*
2 * Linux LED driver for RTL8187
3 *
4 * Copyright 2009 Larry Finger <Larry.Finger@lwfinger.net>
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 "rtl8187_leds.h"
24
25static 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->mode == 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->GPIO, 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
63static 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->mode == 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->GPIO, 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. */
102static void rtl8187_led_brightness_set(struct led_classdev *led_dev,
103 enum led_brightness brightness)
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 = hw->priv;
109
110 if (brightness == LED_OFF) {
111 queue_delayed_work(hw->workqueue, &priv->led_off, 0);
112 /* The LED is off for 1/20 sec so that it just blinks. */
113 queue_delayed_work(hw->workqueue, &priv->led_on, HZ / 20);
114 } else
115 queue_delayed_work(hw->workqueue, &priv->led_on, 0);
116}
117
118static int rtl8187_register_led(struct ieee80211_hw *dev,
119 struct rtl8187_led *led, const char *name,
120 const char *default_trigger, u8 ledpin)
121{
122 int err;
123 struct rtl8187_priv *priv = dev->priv;
124
125 if (led->dev)
126 return -EEXIST;
127 if (!default_trigger)
128 return -EINVAL;
129 led->dev = dev;
130 led->ledpin = ledpin;
131 strncpy(led->name, name, sizeof(led->name));
132
133 led->led_dev.name = led->name;
134 led->led_dev.default_trigger = default_trigger;
135 led->led_dev.brightness_set = rtl8187_led_brightness_set;
136
137 err = led_classdev_register(&priv->udev->dev, &led->led_dev);
138 if (err) {
139 printk(KERN_INFO "LEDs: Failed to register %s\n", name);
140 led->dev = NULL;
141 return err;
142 }
143 return 0;
144}
145
146static void rtl8187_unregister_led(struct rtl8187_led *led)
147{
148 led_classdev_unregister(&led->led_dev);
149 led->dev = NULL;
150}
151
152void rtl8187_leds_init(struct ieee80211_hw *dev, u16 custid)
153{
154 struct rtl8187_priv *priv = dev->priv;
155 char name[RTL8187_LED_MAX_NAME_LEN + 1];
156 u8 ledpin;
157 int err;
158
159 /* According to the vendor driver, the LED operation depends on the
160 * customer ID encoded in the EEPROM
161 */
162 printk(KERN_INFO "rtl8187: Customer ID is 0x%02X\n", custid);
163 switch (custid) {
164 case EEPROM_CID_RSVD0:
165 case EEPROM_CID_RSVD1:
166 case EEPROM_CID_SERCOMM_PS:
167 case EEPROM_CID_QMI:
168 case EEPROM_CID_DELL:
169 case EEPROM_CID_TOSHIBA:
170 ledpin = LED_PIN_GPIO0;
171 break;
172 case EEPROM_CID_ALPHA0:
173 ledpin = LED_PIN_LED0;
174 break;
175 case EEPROM_CID_HW:
176 ledpin = LED_PIN_HW;
177 break;
178 default:
179 ledpin = LED_PIN_GPIO0;
180 }
181
182 INIT_DELAYED_WORK(&priv->led_on, led_turn_on);
183 INIT_DELAYED_WORK(&priv->led_off, led_turn_off);
184
185 snprintf(name, sizeof(name),
186 "rtl8187-%s::tx", wiphy_name(dev->wiphy));
187 err = rtl8187_register_led(dev, &priv->led_tx, name,
188 ieee80211_get_tx_led_name(dev), ledpin);
189 if (err)
190 goto error;
191 snprintf(name, sizeof(name),
192 "rtl8187-%s::rx", wiphy_name(dev->wiphy));
193 err = rtl8187_register_led(dev, &priv->led_rx, name,
194 ieee80211_get_rx_led_name(dev), ledpin);
195 if (!err) {
196 queue_delayed_work(dev->workqueue, &priv->led_on, 0);
197 return;
198 }
199 /* registration of RX LED failed - unregister TX */
200 rtl8187_unregister_led(&priv->led_tx);
201error:
202 /* If registration of either failed, cancel delayed work */
203 cancel_delayed_work_sync(&priv->led_off);
204 cancel_delayed_work_sync(&priv->led_on);
205}
206
207void rtl8187_leds_exit(struct ieee80211_hw *dev)
208{
209 struct rtl8187_priv *priv = dev->priv;
210
211 rtl8187_unregister_led(&priv->led_tx);
212 /* turn the LED off before exiting */
213 queue_delayed_work(dev->workqueue, &priv->led_off, 0);
214 cancel_delayed_work_sync(&priv->led_off);
215 rtl8187_unregister_led(&priv->led_rx);
216}
217#endif /* def CONFIG_RTL8187_LED */
218
diff --git a/drivers/net/wireless/rtl818x/rtl8187_leds.h b/drivers/net/wireless/rtl818x/rtl8187_leds.h
new file mode 100644
index 000000000000..a0332027aead
--- /dev/null
+++ b/drivers/net/wireless/rtl818x/rtl8187_leds.h
@@ -0,0 +1,57 @@
1/*
2 * Definitions for RTL8187 leds
3 *
4 * Copyright 2009 Larry Finger <Larry.Finger@lwfinger.net>
5 *
6 * Based on the LED handling in the r8187 driver, which is:
7 * Copyright (c) Realtek Semiconductor Corp. All rights reserved.
8 *
9 * This program is free software; you can redistribute it and/or modify
10 * it under the terms of the GNU General Public License version 2 as
11 * published by the Free Software Foundation.
12 */
13
14#ifndef RTL8187_LED_H
15#define RTL8187_LED_H
16
17#ifdef CONFIG_RTL8187_LEDS
18
19#define RTL8187_LED_MAX_NAME_LEN 21
20
21#include <linux/leds.h>
22#include <linux/types.h>
23
24enum {
25 LED_PIN_LED0,
26 LED_PIN_LED1,
27 LED_PIN_GPIO0,
28 LED_PIN_HW
29};
30
31enum {
32 EEPROM_CID_RSVD0 = 0x00,
33 EEPROM_CID_RSVD1 = 0xFF,
34 EEPROM_CID_ALPHA0 = 0x01,
35 EEPROM_CID_SERCOMM_PS = 0x02,
36 EEPROM_CID_HW = 0x03,
37 EEPROM_CID_TOSHIBA = 0x04,
38 EEPROM_CID_QMI = 0x07,
39 EEPROM_CID_DELL = 0x08
40};
41
42struct rtl8187_led {
43 struct ieee80211_hw *dev;
44 /* The LED class device */
45 struct led_classdev led_dev;
46 /* The pin/method used to control the led */
47 u8 ledpin;
48 /* The unique name string for this LED device. */
49 char name[RTL8187_LED_MAX_NAME_LEN + 1];
50};
51
52void rtl8187_leds_init(struct ieee80211_hw *dev, u16 code);
53void rtl8187_leds_exit(struct ieee80211_hw *dev);
54
55#endif /* def CONFIG_RTL8187_LED */
56
57#endif /* RTL8187_LED_H */