• Home
  • Line#
  • Scopes#
  • Navigate#
  • Raw
  • Download
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 
fsg_led_wlan_set(struct led_classdev * led_cdev,enum led_brightness value)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 
fsg_led_wan_set(struct led_classdev * led_cdev,enum led_brightness value)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 
fsg_led_sata_set(struct led_classdev * led_cdev,enum led_brightness value)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 
fsg_led_usb_set(struct led_classdev * led_cdev,enum led_brightness value)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 
fsg_led_sync_set(struct led_classdev * led_cdev,enum led_brightness value)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 
fsg_led_ring_set(struct led_classdev * led_cdev,enum led_brightness value)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 
fsg_led_probe(struct platform_device * pdev)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 
fsg_led_remove(struct platform_device * pdev)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 
fsg_led_init(void)220 static int __init fsg_led_init(void)
221 {
222 	return platform_driver_register(&fsg_led_driver);
223 }
224 
fsg_led_exit(void)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");
237