Linux Audio

Check our new training course

Linux debugging, profiling, tracing and performance analysis training

Mar 24-27, 2025, special US time zones
Register
Loading...
Note: File does not exist in v6.13.7.
  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 <linux/module.h>
 23#include <mach/hardware.h>
 24#include <asm/io.h>
 25
 26#define FSG_LED_WLAN_BIT	0
 27#define FSG_LED_WAN_BIT		1
 28#define FSG_LED_SATA_BIT	2
 29#define FSG_LED_USB_BIT		4
 30#define FSG_LED_RING_BIT	5
 31#define FSG_LED_SYNC_BIT	7
 32
 33static short __iomem *latch_address;
 34static unsigned short latch_value;
 35
 36
 37static void fsg_led_wlan_set(struct led_classdev *led_cdev,
 38			     enum led_brightness value)
 39{
 40	if (value) {
 41		latch_value &= ~(1 << FSG_LED_WLAN_BIT);
 42		*latch_address = latch_value;
 43	} else {
 44		latch_value |=  (1 << FSG_LED_WLAN_BIT);
 45		*latch_address = latch_value;
 46	}
 47}
 48
 49static void fsg_led_wan_set(struct led_classdev *led_cdev,
 50			    enum led_brightness value)
 51{
 52	if (value) {
 53		latch_value &= ~(1 << FSG_LED_WAN_BIT);
 54		*latch_address = latch_value;
 55	} else {
 56		latch_value |=  (1 << FSG_LED_WAN_BIT);
 57		*latch_address = latch_value;
 58	}
 59}
 60
 61static void fsg_led_sata_set(struct led_classdev *led_cdev,
 62			     enum led_brightness value)
 63{
 64	if (value) {
 65		latch_value &= ~(1 << FSG_LED_SATA_BIT);
 66		*latch_address = latch_value;
 67	} else {
 68		latch_value |=  (1 << FSG_LED_SATA_BIT);
 69		*latch_address = latch_value;
 70	}
 71}
 72
 73static void fsg_led_usb_set(struct led_classdev *led_cdev,
 74			    enum led_brightness value)
 75{
 76	if (value) {
 77		latch_value &= ~(1 << FSG_LED_USB_BIT);
 78		*latch_address = latch_value;
 79	} else {
 80		latch_value |=  (1 << FSG_LED_USB_BIT);
 81		*latch_address = latch_value;
 82	}
 83}
 84
 85static void fsg_led_sync_set(struct led_classdev *led_cdev,
 86			     enum led_brightness value)
 87{
 88	if (value) {
 89		latch_value &= ~(1 << FSG_LED_SYNC_BIT);
 90		*latch_address = latch_value;
 91	} else {
 92		latch_value |=  (1 << FSG_LED_SYNC_BIT);
 93		*latch_address = latch_value;
 94	}
 95}
 96
 97static void fsg_led_ring_set(struct led_classdev *led_cdev,
 98			     enum led_brightness value)
 99{
100	if (value) {
101		latch_value &= ~(1 << FSG_LED_RING_BIT);
102		*latch_address = latch_value;
103	} else {
104		latch_value |=  (1 << FSG_LED_RING_BIT);
105		*latch_address = latch_value;
106	}
107}
108
109
110static struct led_classdev fsg_wlan_led = {
111	.name			= "fsg:blue:wlan",
112	.brightness_set		= fsg_led_wlan_set,
113	.flags			= LED_CORE_SUSPENDRESUME,
114};
115
116static struct led_classdev fsg_wan_led = {
117	.name			= "fsg:blue:wan",
118	.brightness_set		= fsg_led_wan_set,
119	.flags			= LED_CORE_SUSPENDRESUME,
120};
121
122static struct led_classdev fsg_sata_led = {
123	.name			= "fsg:blue:sata",
124	.brightness_set		= fsg_led_sata_set,
125	.flags			= LED_CORE_SUSPENDRESUME,
126};
127
128static struct led_classdev fsg_usb_led = {
129	.name			= "fsg:blue:usb",
130	.brightness_set		= fsg_led_usb_set,
131	.flags			= LED_CORE_SUSPENDRESUME,
132};
133
134static struct led_classdev fsg_sync_led = {
135	.name			= "fsg:blue:sync",
136	.brightness_set		= fsg_led_sync_set,
137	.flags			= LED_CORE_SUSPENDRESUME,
138};
139
140static struct led_classdev fsg_ring_led = {
141	.name			= "fsg:blue:ring",
142	.brightness_set		= fsg_led_ring_set,
143	.flags			= LED_CORE_SUSPENDRESUME,
144};
145
146
147static int fsg_led_probe(struct platform_device *pdev)
148{
149	int ret;
150
151	/* Map the LED chip select address space */
152	latch_address = (unsigned short *) ioremap(IXP4XX_EXP_BUS_BASE(2), 512);
153	if (!latch_address) {
154		ret = -ENOMEM;
155		goto failremap;
156	}
157
158	latch_value = 0xffff;
159	*latch_address = latch_value;
160
161	ret = led_classdev_register(&pdev->dev, &fsg_wlan_led);
162	if (ret < 0)
163		goto failwlan;
164
165	ret = led_classdev_register(&pdev->dev, &fsg_wan_led);
166	if (ret < 0)
167		goto failwan;
168
169	ret = led_classdev_register(&pdev->dev, &fsg_sata_led);
170	if (ret < 0)
171		goto failsata;
172
173	ret = led_classdev_register(&pdev->dev, &fsg_usb_led);
174	if (ret < 0)
175		goto failusb;
176
177	ret = led_classdev_register(&pdev->dev, &fsg_sync_led);
178	if (ret < 0)
179		goto failsync;
180
181	ret = led_classdev_register(&pdev->dev, &fsg_ring_led);
182	if (ret < 0)
183		goto failring;
184
185	return ret;
186
187 failring:
188	led_classdev_unregister(&fsg_sync_led);
189 failsync:
190	led_classdev_unregister(&fsg_usb_led);
191 failusb:
192	led_classdev_unregister(&fsg_sata_led);
193 failsata:
194	led_classdev_unregister(&fsg_wan_led);
195 failwan:
196	led_classdev_unregister(&fsg_wlan_led);
197 failwlan:
198	iounmap(latch_address);
199 failremap:
200
201	return ret;
202}
203
204static int fsg_led_remove(struct platform_device *pdev)
205{
206	led_classdev_unregister(&fsg_wlan_led);
207	led_classdev_unregister(&fsg_wan_led);
208	led_classdev_unregister(&fsg_sata_led);
209	led_classdev_unregister(&fsg_usb_led);
210	led_classdev_unregister(&fsg_sync_led);
211	led_classdev_unregister(&fsg_ring_led);
212
213	iounmap(latch_address);
214
215	return 0;
216}
217
218
219static struct platform_driver fsg_led_driver = {
220	.probe		= fsg_led_probe,
221	.remove		= fsg_led_remove,
222	.driver		= {
223		.name		= "fsg-led",
224	},
225};
226
227module_platform_driver(fsg_led_driver);
228
229MODULE_AUTHOR("Rod Whitby <rod@whitby.id.au>");
230MODULE_DESCRIPTION("Freecom FSG-3 LED driver");
231MODULE_LICENSE("GPL");