aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/leds/leds-fsg.c
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 /drivers/leds/leds-fsg.c
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>
Diffstat (limited to 'drivers/leds/leds-fsg.c')
-rw-r--r--drivers/leds/leds-fsg.c261
1 files changed, 261 insertions, 0 deletions
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");