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