Reordered patches prior to upstream submission (power patches before a new board...
[nslu2-linux/kernel.git] / patches / 2.6.24 / ixp4xx-fsg-led-driver.patch
blobe13fee1fc7d6972cafaffe6cacd8e7e1d3808ed3
1 From bc47cc117084370cb6b22c95ae826a0654a37218 Mon Sep 17 00:00:00 2001
2 From: Rod Whitby <rod@whitby.id.au>
3 Date: Tue, 29 Jan 2008 23:17:42 +1030
4 Subject: leds: Add new driver for the LEDs on the Freecom FSG-3
6 The LEDs on the Freecom FSG-3 are connected to an external
7 memory-mapped latch on the ixp4xx expansion bus, and therefore cannot
8 be supported by any of the existing LEDs drivers.
10 Signed-off-by: Rod Whitby <rod@whitby.id.au>
12 PATCH FOLLOWS
13 KernelVersion: 2.6.24-git6
15 diff --git a/drivers/leds/Kconfig b/drivers/leds/Kconfig
16 index ec568fa..1bda273 100644
17 --- a/drivers/leds/Kconfig
18 +++ b/drivers/leds/Kconfig
19 @@ -48,6 +48,12 @@ config LEDS_IXP4XX
20 particular board must have LEDs and they must be connected
21 to the GPIO lines. If unsure, say Y.
23 +config LEDS_FSG
24 + tristate "LED Support for the Freecom FSG-3"
25 + depends on LEDS_CLASS && MACH_FSG
26 + help
27 + This option enables support for the LEDs on the Freecom FSG-3.
29 config LEDS_TOSA
30 tristate "LED Support for the Sharp SL-6000 series"
31 depends on LEDS_CLASS && PXA_SHARPSL
32 diff --git a/drivers/leds/Makefile b/drivers/leds/Makefile
33 index a60de1b..acacfee 100644
34 --- a/drivers/leds/Makefile
35 +++ b/drivers/leds/Makefile
36 @@ -9,6 +9,7 @@ obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o
37 obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o
38 obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o
39 obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o
40 +obj-$(CONFIG_LEDS_FSG) += leds-fsg.o
41 obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o
42 obj-$(CONFIG_LEDS_S3C24XX) += leds-s3c24xx.o
43 obj-$(CONFIG_LEDS_AMS_DELTA) += leds-ams-delta.o
44 diff --git a/drivers/leds/leds-fsg.c b/drivers/leds/leds-fsg.c
45 new file mode 100644
46 index 0000000..8de714c
47 --- /dev/null
48 +++ b/drivers/leds/leds-fsg.c
49 @@ -0,0 +1,262 @@
50 +/*
51 + * LED Driver for the Freecom FSG-3
52 + *
53 + * Copyright (c) 2008 Rod Whitby <rod@whitby.id.au>
54 + *
55 + * Author: Rod Whitby <rod@whitby.id.au>
56 + *
57 + * Based on leds-spitz.c
58 + * Copyright 2005-2006 Openedhand Ltd.
59 + * Author: Richard Purdie <rpurdie@openedhand.com>
60 + *
61 + * This program is free software; you can redistribute it and/or modify
62 + * it under the terms of the GNU General Public License version 2 as
63 + * published by the Free Software Foundation.
64 + *
65 + */
67 +#include <linux/kernel.h>
68 +#include <linux/init.h>
69 +#include <linux/platform_device.h>
70 +#include <linux/leds.h>
71 +#include <asm/arch/hardware.h>
72 +#include <asm/io.h>
74 +static short __iomem *latch_address;
75 +static unsigned short latch_value;
78 +static void fsg_led_wlan_set(struct led_classdev *led_cdev,
79 + enum led_brightness value)
81 + if (value) {
82 + latch_value &= ~(1 << FSG_LED_WLAN_BIT);
83 + *latch_address = latch_value;
84 + } else {
85 + latch_value |= (1 << FSG_LED_WLAN_BIT);
86 + *latch_address = latch_value;
87 + }
90 +static void fsg_led_wan_set(struct led_classdev *led_cdev,
91 + enum led_brightness value)
93 + if (value) {
94 + latch_value &= ~(1 << FSG_LED_WAN_BIT);
95 + *latch_address = latch_value;
96 + } else {
97 + latch_value |= (1 << FSG_LED_WAN_BIT);
98 + *latch_address = latch_value;
99 + }
102 +static void fsg_led_sata_set(struct led_classdev *led_cdev,
103 + enum led_brightness value)
105 + if (value) {
106 + latch_value &= ~(1 << FSG_LED_SATA_BIT);
107 + *latch_address = latch_value;
108 + } else {
109 + latch_value |= (1 << FSG_LED_SATA_BIT);
110 + *latch_address = latch_value;
114 +static void fsg_led_usb_set(struct led_classdev *led_cdev,
115 + enum led_brightness value)
117 + if (value) {
118 + latch_value &= ~(1 << FSG_LED_USB_BIT);
119 + *latch_address = latch_value;
120 + } else {
121 + latch_value |= (1 << FSG_LED_USB_BIT);
122 + *latch_address = latch_value;
126 +static void fsg_led_sync_set(struct led_classdev *led_cdev,
127 + enum led_brightness value)
129 + if (value) {
130 + latch_value &= ~(1 << FSG_LED_SYNC_BIT);
131 + *latch_address = latch_value;
132 + } else {
133 + latch_value |= (1 << FSG_LED_SYNC_BIT);
134 + *latch_address = latch_value;
138 +static void fsg_led_ring_set(struct led_classdev *led_cdev,
139 + enum led_brightness value)
141 + if (value) {
142 + latch_value &= ~(1 << FSG_LED_RING_BIT);
143 + *latch_address = latch_value;
144 + } else {
145 + latch_value |= (1 << FSG_LED_RING_BIT);
146 + *latch_address = latch_value;
152 +static struct led_classdev fsg_wlan_led = {
153 + .name = "fsg:blue:wlan",
154 + .brightness_set = fsg_led_wlan_set,
157 +static struct led_classdev fsg_wan_led = {
158 + .name = "fsg:blue:wan",
159 + .brightness_set = fsg_led_wan_set,
162 +static struct led_classdev fsg_sata_led = {
163 + .name = "fsg:blue:sata",
164 + .brightness_set = fsg_led_sata_set,
167 +static struct led_classdev fsg_usb_led = {
168 + .name = "fsg:blue:usb",
169 + .brightness_set = fsg_led_usb_set,
172 +static struct led_classdev fsg_sync_led = {
173 + .name = "fsg:blue:sync",
174 + .brightness_set = fsg_led_sync_set,
177 +static struct led_classdev fsg_ring_led = {
178 + .name = "fsg:blue:ring",
179 + .brightness_set = fsg_led_ring_set,
184 +#ifdef CONFIG_PM
185 +static int fsg_led_suspend(struct platform_device *dev, pm_message_t state)
187 + led_classdev_suspend(&fsg_wlan_led);
188 + led_classdev_suspend(&fsg_wan_led);
189 + led_classdev_suspend(&fsg_sata_led);
190 + led_classdev_suspend(&fsg_usb_led);
191 + led_classdev_suspend(&fsg_sync_led);
192 + led_classdev_suspend(&fsg_ring_led);
193 + return 0;
196 +static int fsg_led_resume(struct platform_device *dev)
198 + led_classdev_resume(&fsg_wlan_led);
199 + led_classdev_resume(&fsg_wan_led);
200 + led_classdev_resume(&fsg_sata_led);
201 + led_classdev_resume(&fsg_usb_led);
202 + led_classdev_resume(&fsg_sync_led);
203 + led_classdev_resume(&fsg_ring_led);
204 + return 0;
206 +#endif
209 +static int fsg_led_probe(struct platform_device *pdev)
211 + int ret;
213 + ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
214 + if (ret < 0)
215 + goto failwlan;
217 + ret = led_classdev_register(&pdev->dev, &fsg_wan_led);
218 + if (ret < 0)
219 + goto failwan;
221 + ret = led_classdev_register(&pdev->dev, &fsg_sata_led);
222 + if (ret < 0)
223 + goto failsata;
225 + ret = led_classdev_register(&pdev->dev, &fsg_usb_led);
226 + if (ret < 0)
227 + goto failusb;
229 + ret = led_classdev_register(&pdev->dev, &fsg_sync_led);
230 + if (ret < 0)
231 + goto failsync;
233 + ret = led_classdev_register(&pdev->dev, &fsg_ring_led);
234 + if (ret < 0)
235 + goto failring;
237 + return ret;
239 + failring:
240 + led_classdev_unregister(&fsg_sync_led);
241 + failsync:
242 + led_classdev_unregister(&fsg_usb_led);
243 + failusb:
244 + led_classdev_unregister(&fsg_sata_led);
245 + failsata:
246 + led_classdev_unregister(&fsg_wan_led);
247 + failwan:
248 + led_classdev_unregister(&fsg_wlan_led);
249 + failwlan:
251 + return ret;
254 +static int fsg_led_remove(struct platform_device *pdev)
256 + led_classdev_unregister(&fsg_wlan_led);
257 + led_classdev_unregister(&fsg_wan_led);
258 + led_classdev_unregister(&fsg_sata_led);
259 + led_classdev_unregister(&fsg_usb_led);
260 + led_classdev_unregister(&fsg_sync_led);
261 + led_classdev_unregister(&fsg_ring_led);
263 + return 0;
267 +static struct platform_driver fsg_led_driver = {
268 + .probe = fsg_led_probe,
269 + .remove = fsg_led_remove,
270 +#ifdef CONFIG_PM
271 + .suspend = fsg_led_suspend,
272 + .resume = fsg_led_resume,
273 +#endif
274 + .driver = {
275 + .name = "fsg-led",
276 + },
280 +static int __init fsg_led_init(void)
282 + int ret;
284 + /* Map the LED chip select address space */
285 + latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
286 + if (!latch_address)
287 + return -ENOMEM;
288 + latch_value = 0xffff;
289 + *latch_address = latch_value;
291 + ret = platform_driver_register(&fsg_led_driver);
292 + if (ret == 0)
293 + return ret;
295 + iounmap(latch_address);
296 + return ret;
299 +static void __exit fsg_led_exit(void)
301 + platform_driver_unregister(&fsg_led_driver);
302 + iounmap(latch_address);
306 +module_init(fsg_led_init);
307 +module_exit(fsg_led_exit);
309 +MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>");
310 +MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
311 +MODULE_LICENSE("GPL");
313 1.5.2.5