rename patch
[openwrt.git] / target / linux / ixp4xx / patches-2.6.25 / 031-ixp4xx_fsg_led_driver.patch
1 From a66e34fefb3f8142d7f16808563eb610225f6e77 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: [PATCH] leds: Add new driver for the LEDs on the Freecom FSG-3
5
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.
9
10 Signed-off-by: Rod Whitby <rod@whitby.id.au>
11 --
12 PATCH FOLLOWS
13 KernelVersion: v2.6.25-rc6-117-g457fb60
14 ---
15  drivers/leds/Kconfig    |    6 +
16  drivers/leds/Makefile   |    1 +
17  drivers/leds/leds-fsg.c |  261 +++++++++++++++++++++++++++++++++++++++++++++++
18  3 files changed, 268 insertions(+), 0 deletions(-)
19  create mode 100644 drivers/leds/leds-fsg.c
20
21 --- a/drivers/leds/Kconfig
22 +++ b/drivers/leds/Kconfig
23 @@ -46,6 +46,12 @@
24           This option enables support for the LEDs on Sharp Zaurus
25           SL-Cxx00 series (C1000, C3000, C3100).
26  
27 +config LEDS_FSG
28 +       tristate "LED Support for the Freecom FSG-3"
29 +       depends on LEDS_CLASS && MACH_FSG
30 +       help
31 +         This option enables support for the LEDs on the Freecom FSG-3.
32 +
33  config LEDS_TOSA
34         tristate "LED Support for the Sharp SL-6000 series"
35         depends on LEDS_CLASS && PXA_SHARPSL
36 --- a/drivers/leds/Makefile
37 +++ b/drivers/leds/Makefile
38 @@ -22,6 +22,7 @@
39  obj-$(CONFIG_LEDS_CM_X270)              += leds-cm-x270.o
40  obj-$(CONFIG_LEDS_CLEVO_MAIL)          += leds-clevo-mail.o
41  obj-$(CONFIG_LEDS_HP6XX)               += leds-hp6xx.o
42 +obj-$(CONFIG_LEDS_FSG)                 += leds-fsg.o
43  
44  # LED Triggers
45  obj-$(CONFIG_LEDS_TRIGGER_TIMER)       += ledtrig-timer.o
46 --- /dev/null
47 +++ b/drivers/leds/leds-fsg.c
48 @@ -0,0 +1,261 @@
49 +/*
50 + * LED Driver for the Freecom FSG-3
51 + *
52 + * Copyright (c) 2008 Rod Whitby <rod@whitby.id.au>
53 + *
54 + * Author: Rod Whitby <rod@whitby.id.au>
55 + *
56 + * Based on leds-spitz.c
57 + * Copyright 2005-2006 Openedhand Ltd.
58 + * Author: Richard Purdie <rpurdie@openedhand.com>
59 + *
60 + * This program is free software; you can redistribute it and/or modify
61 + * it under the terms of the GNU General Public License version 2 as
62 + * published by the Free Software Foundation.
63 + *
64 + */
65 +
66 +#include <linux/kernel.h>
67 +#include <linux/init.h>
68 +#include <linux/platform_device.h>
69 +#include <linux/leds.h>
70 +#include <asm/arch/hardware.h>
71 +#include <asm/io.h>
72 +
73 +static short __iomem *latch_address;
74 +static unsigned short latch_value;
75 +
76 +
77 +static void fsg_led_wlan_set(struct led_classdev *led_cdev,
78 +                            enum led_brightness value)
79 +{
80 +       if (value) {
81 +               latch_value &= ~(1 << FSG_LED_WLAN_BIT);
82 +               *latch_address = latch_value;
83 +       } else {
84 +               latch_value |=  (1 << FSG_LED_WLAN_BIT);
85 +               *latch_address = latch_value;
86 +       }
87 +}
88 +
89 +static void fsg_led_wan_set(struct led_classdev *led_cdev,
90 +                           enum led_brightness value)
91 +{
92 +       if (value) {
93 +               latch_value &= ~(1 << FSG_LED_WAN_BIT);
94 +               *latch_address = latch_value;
95 +       } else {
96 +               latch_value |=  (1 << FSG_LED_WAN_BIT);
97 +               *latch_address = latch_value;
98 +       }
99 +}
100 +
101 +static void fsg_led_sata_set(struct led_classdev *led_cdev,
102 +                            enum led_brightness value)
103 +{
104 +       if (value) {
105 +               latch_value &= ~(1 << FSG_LED_SATA_BIT);
106 +               *latch_address = latch_value;
107 +       } else {
108 +               latch_value |=  (1 << FSG_LED_SATA_BIT);
109 +               *latch_address = latch_value;
110 +       }
111 +}
112 +
113 +static void fsg_led_usb_set(struct led_classdev *led_cdev,
114 +                           enum led_brightness value)
115 +{
116 +       if (value) {
117 +               latch_value &= ~(1 << FSG_LED_USB_BIT);
118 +               *latch_address = latch_value;
119 +       } else {
120 +               latch_value |=  (1 << FSG_LED_USB_BIT);
121 +               *latch_address = latch_value;
122 +       }
123 +}
124 +
125 +static void fsg_led_sync_set(struct led_classdev *led_cdev,
126 +                            enum led_brightness value)
127 +{
128 +       if (value) {
129 +               latch_value &= ~(1 << FSG_LED_SYNC_BIT);
130 +               *latch_address = latch_value;
131 +       } else {
132 +               latch_value |=  (1 << FSG_LED_SYNC_BIT);
133 +               *latch_address = latch_value;
134 +       }
135 +}
136 +
137 +static void fsg_led_ring_set(struct led_classdev *led_cdev,
138 +                            enum led_brightness value)
139 +{
140 +       if (value) {
141 +               latch_value &= ~(1 << FSG_LED_RING_BIT);
142 +               *latch_address = latch_value;
143 +       } else {
144 +               latch_value |=  (1 << FSG_LED_RING_BIT);
145 +               *latch_address = latch_value;
146 +       }
147 +}
148 +
149 +
150 +
151 +static struct led_classdev fsg_wlan_led = {
152 +       .name                   = "fsg:blue:wlan",
153 +       .brightness_set         = fsg_led_wlan_set,
154 +};
155 +
156 +static struct led_classdev fsg_wan_led = {
157 +       .name                   = "fsg:blue:wan",
158 +       .brightness_set         = fsg_led_wan_set,
159 +};
160 +
161 +static struct led_classdev fsg_sata_led = {
162 +       .name                   = "fsg:blue:sata",
163 +       .brightness_set         = fsg_led_sata_set,
164 +};
165 +
166 +static struct led_classdev fsg_usb_led = {
167 +       .name                   = "fsg:blue:usb",
168 +       .brightness_set         = fsg_led_usb_set,
169 +};
170 +
171 +static struct led_classdev fsg_sync_led = {
172 +       .name                   = "fsg:blue:sync",
173 +       .brightness_set         = fsg_led_sync_set,
174 +};
175 +
176 +static struct led_classdev fsg_ring_led = {
177 +       .name                   = "fsg:blue:ring",
178 +       .brightness_set         = fsg_led_ring_set,
179 +};
180 +
181 +
182 +
183 +#ifdef CONFIG_PM
184 +static int fsg_led_suspend(struct platform_device *dev, pm_message_t state)
185 +{
186 +       led_classdev_suspend(&fsg_wlan_led);
187 +       led_classdev_suspend(&fsg_wan_led);
188 +       led_classdev_suspend(&fsg_sata_led);
189 +       led_classdev_suspend(&fsg_usb_led);
190 +       led_classdev_suspend(&fsg_sync_led);
191 +       led_classdev_suspend(&fsg_ring_led);
192 +       return 0;
193 +}
194 +
195 +static int fsg_led_resume(struct platform_device *dev)
196 +{
197 +       led_classdev_resume(&fsg_wlan_led);
198 +       led_classdev_resume(&fsg_wan_led);
199 +       led_classdev_resume(&fsg_sata_led);
200 +       led_classdev_resume(&fsg_usb_led);
201 +       led_classdev_resume(&fsg_sync_led);
202 +       led_classdev_resume(&fsg_ring_led);
203 +       return 0;
204 +}
205 +#endif
206 +
207 +
208 +static int fsg_led_probe(struct platform_device *pdev)
209 +{
210 +       int ret;
211 +
212 +       ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
213 +       if (ret < 0)
214 +               goto failwlan;
215 +
216 +       ret = led_classdev_register(&pdev->dev, &fsg_wan_led);
217 +       if (ret < 0)
218 +               goto failwan;
219 +
220 +       ret = led_classdev_register(&pdev->dev, &fsg_sata_led);
221 +       if (ret < 0)
222 +               goto failsata;
223 +
224 +       ret = led_classdev_register(&pdev->dev, &fsg_usb_led);
225 +       if (ret < 0)
226 +               goto failusb;
227 +
228 +       ret = led_classdev_register(&pdev->dev, &fsg_sync_led);
229 +       if (ret < 0)
230 +               goto failsync;
231 +
232 +       ret = led_classdev_register(&pdev->dev, &fsg_ring_led);
233 +       if (ret < 0)
234 +               goto failring;
235 +
236 +       /* Map the LED chip select address space */
237 +       latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
238 +       if (!latch_address) {
239 +               ret = -ENOMEM;
240 +               goto failremap;
241 +       }
242 +
243 +       latch_value = 0xffff;
244 +       *latch_address = latch_value;
245 +
246 +       return ret;
247 +
248 + failremap:
249 +       led_classdev_unregister(&fsg_ring_led);
250 + failring:
251 +       led_classdev_unregister(&fsg_sync_led);
252 + failsync:
253 +       led_classdev_unregister(&fsg_usb_led);
254 + failusb:
255 +       led_classdev_unregister(&fsg_sata_led);
256 + failsata:
257 +       led_classdev_unregister(&fsg_wan_led);
258 + failwan:
259 +       led_classdev_unregister(&fsg_wlan_led);
260 + failwlan:
261 +
262 +       return ret;
263 +}
264 +
265 +static int fsg_led_remove(struct platform_device *pdev)
266 +{
267 +       iounmap(latch_address);
268 +
269 +       led_classdev_unregister(&fsg_wlan_led);
270 +       led_classdev_unregister(&fsg_wan_led);
271 +       led_classdev_unregister(&fsg_sata_led);
272 +       led_classdev_unregister(&fsg_usb_led);
273 +       led_classdev_unregister(&fsg_sync_led);
274 +       led_classdev_unregister(&fsg_ring_led);
275 +
276 +       return 0;
277 +}
278 +
279 +
280 +static struct platform_driver fsg_led_driver = {
281 +       .probe          = fsg_led_probe,
282 +       .remove         = fsg_led_remove,
283 +#ifdef CONFIG_PM
284 +       .suspend        = fsg_led_suspend,
285 +       .resume         = fsg_led_resume,
286 +#endif
287 +       .driver         = {
288 +               .name           = "fsg-led",
289 +       },
290 +};
291 +
292 +
293 +static int __init fsg_led_init(void)
294 +{
295 +       return platform_driver_register(&fsg_led_driver);
296 +}
297 +
298 +static void __exit fsg_led_exit(void)
299 +{
300 +       platform_driver_unregister(&fsg_led_driver);
301 +}
302 +
303 +
304 +module_init(fsg_led_init);
305 +module_exit(fsg_led_exit);
306 +
307 +MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>");
308 +MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
309 +MODULE_LICENSE("GPL");