powerpc: Split exception handling out of head_64.S
[deliverable/linux.git] / drivers / leds / leds-fsg.c
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 <mach/hardware.h>
23 #include <asm/io.h>
24
25 static short __iomem *latch_address;
26 static unsigned short latch_value;
27
28
29 static 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
41 static 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
53 static 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
65 static 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
77 static 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
89 static 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 static struct led_classdev fsg_wlan_led = {
103 .name = "fsg:blue:wlan",
104 .brightness_set = fsg_led_wlan_set,
105 .flags = LED_CORE_SUSPENDRESUME,
106 };
107
108 static struct led_classdev fsg_wan_led = {
109 .name = "fsg:blue:wan",
110 .brightness_set = fsg_led_wan_set,
111 .flags = LED_CORE_SUSPENDRESUME,
112 };
113
114 static struct led_classdev fsg_sata_led = {
115 .name = "fsg:blue:sata",
116 .brightness_set = fsg_led_sata_set,
117 .flags = LED_CORE_SUSPENDRESUME,
118 };
119
120 static struct led_classdev fsg_usb_led = {
121 .name = "fsg:blue:usb",
122 .brightness_set = fsg_led_usb_set,
123 .flags = LED_CORE_SUSPENDRESUME,
124 };
125
126 static struct led_classdev fsg_sync_led = {
127 .name = "fsg:blue:sync",
128 .brightness_set = fsg_led_sync_set,
129 .flags = LED_CORE_SUSPENDRESUME,
130 };
131
132 static struct led_classdev fsg_ring_led = {
133 .name = "fsg:blue:ring",
134 .brightness_set = fsg_led_ring_set,
135 .flags = LED_CORE_SUSPENDRESUME,
136 };
137
138
139 static int fsg_led_probe(struct platform_device *pdev)
140 {
141 int ret;
142
143 /* Map the LED chip select address space */
144 latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
145 if (!latch_address) {
146 ret = -ENOMEM;
147 goto failremap;
148 }
149
150 latch_value = 0xffff;
151 *latch_address = latch_value;
152
153 ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
154 if (ret < 0)
155 goto failwlan;
156
157 ret = led_classdev_register(&pdev->dev, &fsg_wan_led);
158 if (ret < 0)
159 goto failwan;
160
161 ret = led_classdev_register(&pdev->dev, &fsg_sata_led);
162 if (ret < 0)
163 goto failsata;
164
165 ret = led_classdev_register(&pdev->dev, &fsg_usb_led);
166 if (ret < 0)
167 goto failusb;
168
169 ret = led_classdev_register(&pdev->dev, &fsg_sync_led);
170 if (ret < 0)
171 goto failsync;
172
173 ret = led_classdev_register(&pdev->dev, &fsg_ring_led);
174 if (ret < 0)
175 goto failring;
176
177 return ret;
178
179 failring:
180 led_classdev_unregister(&fsg_sync_led);
181 failsync:
182 led_classdev_unregister(&fsg_usb_led);
183 failusb:
184 led_classdev_unregister(&fsg_sata_led);
185 failsata:
186 led_classdev_unregister(&fsg_wan_led);
187 failwan:
188 led_classdev_unregister(&fsg_wlan_led);
189 failwlan:
190 iounmap(latch_address);
191 failremap:
192
193 return ret;
194 }
195
196 static int fsg_led_remove(struct platform_device *pdev)
197 {
198 led_classdev_unregister(&fsg_wlan_led);
199 led_classdev_unregister(&fsg_wan_led);
200 led_classdev_unregister(&fsg_sata_led);
201 led_classdev_unregister(&fsg_usb_led);
202 led_classdev_unregister(&fsg_sync_led);
203 led_classdev_unregister(&fsg_ring_led);
204
205 iounmap(latch_address);
206
207 return 0;
208 }
209
210
211 static struct platform_driver fsg_led_driver = {
212 .probe = fsg_led_probe,
213 .remove = fsg_led_remove,
214 .driver = {
215 .name = "fsg-led",
216 },
217 };
218
219
220 static int __init fsg_led_init(void)
221 {
222 return platform_driver_register(&fsg_led_driver);
223 }
224
225 static void __exit fsg_led_exit(void)
226 {
227 platform_driver_unregister(&fsg_led_driver);
228 }
229
230
231 module_init(fsg_led_init);
232 module_exit(fsg_led_exit);
233
234 MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>");
235 MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
236 MODULE_LICENSE("GPL");
This page took 0.040603 seconds and 5 git commands to generate.