aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorRod Whitby <rod@whitby.id.au>2008-04-24 18:43:09 -0400
committerRichard Purdie <rpurdie@rpsys.net>2008-04-24 18:43:09 -0400
commit3b2e46f8c4a5f2d7856c490ab5f0c46b65e2cb99 (patch)
treecb884fc9b35eff8554d5028a27cfc37e9a8ce653
parent29d76dfa29fe22583aefddccda0bc56aa81035dc (diff)
leds: Add new driver for the LEDs on the Freecom FSG-3
The LEDs on the Freecom FSG-3 are connected to an external memory-mapped latch on the ixp4xx expansion bus, and therefore cannot be supported by any of the existing LEDs drivers. Signed-off-by: Rod Whitby <rod@whitby.id.au> Signed-off-by: Richard Purdie <rpurdie@rpsys.net>
-rw-r--r--drivers/leds/Kconfig6
-rw-r--r--drivers/leds/Makefile1
-rw-r--r--drivers/leds/leds-fsg.c261
3 files changed, 268 insertions, 0 deletions
diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
index 4f56248fed4e..2d5ea8a05338 100644
--- a/drivers/leds/Kconfig
+++ b/drivers/leds/Kconfig
@@ -65,6 +65,12 @@ config LEDS_NET48XX
65 This option enables support for the Soekris net4801 and net4826 error 65 This option enables support for the Soekris net4801 and net4826 error
66 LED. 66 LED.
67 67
68config LEDS_FSG
69 tristate "LED Support for the Freecom FSG-3"
70 depends on LEDS_CLASS && MACH_FSG
71 help
72 This option enables support for the LEDs on the Freecom FSG-3.
73
68config LEDS_WRAP 74config LEDS_WRAP
69 tristate "LED Support for the WRAP series LEDs" 75 tristate "LED Support for the WRAP series LEDs"
70 depends on LEDS_CLASS && SCx200_GPIO 76 depends on LEDS_CLASS && SCx200_GPIO
diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
index e54f42da21a2..9adfa2fe37d4 100644
--- a/drivers/leds/Makefile
+++ b/drivers/leds/Makefile
@@ -20,6 +20,7 @@ obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
20obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o 20obj-$(CONFIG_LEDS_CM_X270) += leds-cm-x270.o
21obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o 21obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
22obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o 22obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
23obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
23 24
24# LED Triggers 25# LED Triggers
25obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o 26obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o
diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
new file mode 100644
index 000000000000..a7421b8c47d8
--- /dev/null
+++ b/drivers/leds/leds-fsg.c
@@ -0,0 +1,261 @@
1/*
2 * LED Driver for the Freecom FSG-3
3 *
4 * Copyright (c) 2008 Rod Whitby <rod@whitby.id.au>
5 *
6 * Author: Rod Whitby <rod@whitby.id.au>
7 *
8 * Based on leds-spitz.c
9 * Copyright 2005-2006 Openedhand Ltd.
10 * Author: Richard Purdie <rpurdie@openedhand.com>
11 *
12 * This program is free software; you can redistribute it and/or modify
13 * it under the terms of the GNU General Public License version 2 as
14 * published by the Free Software Foundation.
15 *
16 */
17
18#include <linux/kernel.h>
19#include <linux/init.h>
20#include <linux/platform_device.h>
21#include <linux/leds.h>
22#include <asm/arch/hardware.h>
23#include <asm/io.h>
24
25static short __iomem *latch_address;
26static unsigned short latch_value;
27
28
29static void fsg_led_wlan_set(struct led_classdev *led_cdev,
30 enum led_brightness value)
31{
32 if (value) {
33 latch_value &= ~(1 << FSG_LED_WLAN_BIT);
34 *latch_address = latch_value;
35 } else {
36 latch_value |= (1 << FSG_LED_WLAN_BIT);
37 *latch_address = latch_value;
38 }
39}
40
41static void fsg_led_wan_set(struct led_classdev *led_cdev,
42 enum led_brightness value)
43{
44 if (value) {
45 latch_value &= ~(1 << FSG_LED_WAN_BIT);
46 *latch_address = latch_value;
47 } else {
48 latch_value |= (1 << FSG_LED_WAN_BIT);
49 *latch_address = latch_value;
50 }
51}
52
53static void fsg_led_sata_set(struct led_classdev *led_cdev,
54 enum led_brightness value)
55{
56 if (value) {
57 latch_value &= ~(1 << FSG_LED_SATA_BIT);
58 *latch_address = latch_value;
59 } else {
60 latch_value |= (1 << FSG_LED_SATA_BIT);
61 *latch_address = latch_value;
62 }
63}
64
65static void fsg_led_usb_set(struct led_classdev *led_cdev,
66 enum led_brightness value)
67{
68 if (value) {
69 latch_value &= ~(1 << FSG_LED_USB_BIT);
70 *latch_address = latch_value;
71 } else {
72 latch_value |= (1 << FSG_LED_USB_BIT);
73 *latch_address = latch_value;
74 }
75}
76
77static void fsg_led_sync_set(struct led_classdev *led_cdev,
78 enum led_brightness value)
79{
80 if (value) {
81 latch_value &= ~(1 << FSG_LED_SYNC_BIT);
82 *latch_address = latch_value;
83 } else {
84 latch_value |= (1 << FSG_LED_SYNC_BIT);
85 *latch_address = latch_value;
86 }
87}
88
89static void fsg_led_ring_set(struct led_classdev *led_cdev,
90 enum led_brightness value)
91{
92 if (value) {
93 latch_value &= ~(1 << FSG_LED_RING_BIT);
94 *latch_address = latch_value;
95 } else {
96 latch_value |= (1 << FSG_LED_RING_BIT);
97 *latch_address = latch_value;
98 }
99}
100
101
102
103static struct led_classdev fsg_wlan_led = {
104 .name = "fsg:blue:wlan",
105 .brightness_set = fsg_led_wlan_set,
106};
107
108static struct led_classdev fsg_wan_led = {
109 .name = "fsg:blue:wan",
110 .brightness_set = fsg_led_wan_set,
111};
112
113static struct led_classdev fsg_sata_led = {
114 .name = "fsg:blue:sata",
115 .brightness_set = fsg_led_sata_set,
116};
117
118static struct led_classdev fsg_usb_led = {
119 .name = "fsg:blue:usb",
120 .brightness_set = fsg_led_usb_set,
121};
122
123static struct led_classdev fsg_sync_led = {
124 .name = "fsg:blue:sync",
125 .brightness_set = fsg_led_sync_set,
126};
127
128static struct led_classdev fsg_ring_led = {
129 .name = "fsg:blue:ring",
130 .brightness_set = fsg_led_ring_set,
131};
132
133
134
135#ifdef CONFIG_PM
136static int fsg_led_suspend(struct platform_device *dev, pm_message_t state)
137{
138 led_classdev_suspend(&fsg_wlan_led);
139 led_classdev_suspend(&fsg_wan_led);
140 led_classdev_suspend(&fsg_sata_led);
141 led_classdev_suspend(&fsg_usb_led);
142 led_classdev_suspend(&fsg_sync_led);
143 led_classdev_suspend(&fsg_ring_led);
144 return 0;
145}
146
147static int fsg_led_resume(struct platform_device *dev)
148{
149 led_classdev_resume(&fsg_wlan_led);
150 led_classdev_resume(&fsg_wan_led);
151 led_classdev_resume(&fsg_sata_led);
152 led_classdev_resume(&fsg_usb_led);
153 led_classdev_resume(&fsg_sync_led);
154 led_classdev_resume(&fsg_ring_led);
155 return 0;
156}
157#endif
158
159
160static int fsg_led_probe(struct platform_device *pdev)
161{
162 int ret;
163
164 ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
165 if (ret < 0)
166 goto failwlan;
167
168 ret = led_classdev_register(&pdev->dev, &fsg_wan_led);
169 if (ret < 0)
170 goto failwan;
171
172 ret = led_classdev_register(&pdev->dev, &fsg_sata_led);
173 if (ret < 0)
174 goto failsata;
175
176 ret = led_classdev_register(&pdev->dev, &fsg_usb_led);
177 if (ret < 0)
178 goto failusb;
179
180 ret = led_classdev_register(&pdev->dev, &fsg_sync_led);
181 if (ret < 0)
182 goto failsync;
183
184 ret = led_classdev_register(&pdev->dev, &fsg_ring_led);
185 if (ret < 0)
186 goto failring;
187
188 /* Map the LED chip select address space */
189 latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
190 if (!latch_address) {
191 ret = -ENOMEM;
192 goto failremap;
193 }
194
195 latch_value = 0xffff;
196 *latch_address = latch_value;
197
198 return ret;
199
200 failremap:
201 led_classdev_unregister(&fsg_ring_led);
202 failring:
203 led_classdev_unregister(&fsg_sync_led);
204 failsync:
205 led_classdev_unregister(&fsg_usb_led);
206 failusb:
207 led_classdev_unregister(&fsg_sata_led);
208 failsata:
209 led_classdev_unregister(&fsg_wan_led);
210 failwan:
211 led_classdev_unregister(&fsg_wlan_led);
212 failwlan:
213
214 return ret;
215}
216
217static int fsg_led_remove(struct platform_device *pdev)
218{
219 iounmap(latch_address);
220
221 led_classdev_unregister(&fsg_wlan_led);
222 led_classdev_unregister(&fsg_wan_led);
223 led_classdev_unregister(&fsg_sata_led);
224 led_classdev_unregister(&fsg_usb_led);
225 led_classdev_unregister(&fsg_sync_led);
226 led_classdev_unregister(&fsg_ring_led);
227
228 return 0;
229}
230
231
232static struct platform_driver fsg_led_driver = {
233 .probe = fsg_led_probe,
234 .remove = fsg_led_remove,
235#ifdef CONFIG_PM
236 .suspend = fsg_led_suspend,
237 .resume = fsg_led_resume,
238#endif
239 .driver = {
240 .name = "fsg-led",
241 },
242};
243
244
245static int __init fsg_led_init(void)
246{
247 return platform_driver_register(&fsg_led_driver);
248}
249
250static void __exit fsg_led_exit(void)
251{
252 platform_driver_unregister(&fsg_led_driver);
253}
254
255
256module_init(fsg_led_init);
257module_exit(fsg_led_exit);
258
259MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>");
260MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
261MODULE_LICENSE("GPL");