Root/target/linux/ixp4xx/patches-2.6.33/295-latch_led_driver.patch

1--- a/drivers/leds/Kconfig
2+++ b/drivers/leds/Kconfig
3@@ -157,6 +157,13 @@ config LEDS_LP3944
4       To compile this driver as a module, choose M here: the
5       module will be called leds-lp3944.
6 
7+config LEDS_LATCH
8+ tristate "LED Support for Memory Latched LEDs"
9+ depends on LEDS_CLASS
10+ help
11+ -- To Do --
12+
13+
14 config LEDS_CLEVO_MAIL
15     tristate "Mail LED on Clevo notebook"
16     depends on LEDS_CLASS && X86 && SERIO_I8042 && DMI
17--- /dev/null
18+++ b/drivers/leds/leds-latch.c
19@@ -0,0 +1,149 @@
20+/*
21+ * LEDs driver for Memory Latched Devices
22+ *
23+ * Copyright (C) 2008 Gateworks Corp.
24+ * Chris Lang <clang@gateworks.com>
25+ *
26+ * This program is free software; you can redistribute it and/or modify
27+ * it under the terms of the GNU General Public License version 2 as
28+ * published by the Free Software Foundation.
29+ *
30+ */
31+#include <linux/kernel.h>
32+#include <linux/init.h>
33+#include <linux/platform_device.h>
34+#include <linux/leds.h>
35+#include <linux/workqueue.h>
36+#include <asm/io.h>
37+#include <linux/spinlock.h>
38+
39+static unsigned int mem_keep = 0xFF;
40+static spinlock_t mem_lock;
41+static unsigned char *iobase;
42+
43+struct latch_led_data {
44+ struct led_classdev cdev;
45+ struct work_struct work;
46+ u8 new_level;
47+ u8 bit;
48+ void (*set_led)(u8 bit, enum led_brightness value);
49+};
50+
51+static void latch_set_led(u8 bit, enum led_brightness value)
52+{
53+ if (value == LED_OFF)
54+ mem_keep |= (0x1 << bit);
55+ else
56+ mem_keep &= ~(0x1 << bit);
57+
58+ writeb(mem_keep, iobase);
59+}
60+
61+static void latch_led_set(struct led_classdev *led_cdev,
62+ enum led_brightness value)
63+{
64+ struct latch_led_data *led_dat =
65+ container_of(led_cdev, struct latch_led_data, cdev);
66+
67+ raw_spin_lock(mem_lock);
68+
69+ led_dat->set_led(led_dat->bit, value);
70+
71+ raw_spin_unlock(mem_lock);
72+}
73+
74+static int latch_led_probe(struct platform_device *pdev)
75+{
76+ struct latch_led_platform_data *pdata = pdev->dev.platform_data;
77+ struct latch_led *cur_led;
78+ struct latch_led_data *leds_data, *led_dat;
79+ int i, ret = 0;
80+
81+ if (!pdata)
82+ return -EBUSY;
83+
84+ leds_data = kzalloc(sizeof(struct latch_led_data) * pdata->num_leds,
85+ GFP_KERNEL);
86+ if (!leds_data)
87+ return -ENOMEM;
88+
89+ for (i = 0; i < pdata->num_leds; i++) {
90+ cur_led = &pdata->leds[i];
91+ led_dat = &leds_data[i];
92+
93+ led_dat->cdev.name = cur_led->name;
94+ led_dat->cdev.default_trigger = cur_led->default_trigger;
95+ led_dat->cdev.brightness_set = latch_led_set;
96+ led_dat->cdev.brightness = LED_OFF;
97+ led_dat->bit = cur_led->bit;
98+ led_dat->set_led = pdata->set_led ? pdata->set_led : latch_set_led;
99+
100+ ret = led_classdev_register(&pdev->dev, &led_dat->cdev);
101+ if (ret < 0) {
102+ goto err;
103+ }
104+ }
105+
106+ if (!pdata->set_led) {
107+ iobase = ioremap_nocache(pdata->mem, 0x1000);
108+ writeb(0xFF, iobase);
109+ }
110+ platform_set_drvdata(pdev, leds_data);
111+
112+ return 0;
113+
114+err:
115+ if (i > 0) {
116+ for (i = i - 1; i >= 0; i--) {
117+ led_classdev_unregister(&leds_data[i].cdev);
118+ }
119+ }
120+
121+ kfree(leds_data);
122+
123+ return ret;
124+}
125+
126+static int __devexit latch_led_remove(struct platform_device *pdev)
127+{
128+ int i;
129+ struct latch_led_platform_data *pdata = pdev->dev.platform_data;
130+ struct latch_led_data *leds_data;
131+
132+ leds_data = platform_get_drvdata(pdev);
133+
134+ for (i = 0; i < pdata->num_leds; i++) {
135+ led_classdev_unregister(&leds_data[i].cdev);
136+ cancel_work_sync(&leds_data[i].work);
137+ }
138+
139+ kfree(leds_data);
140+
141+ return 0;
142+}
143+
144+static struct platform_driver latch_led_driver = {
145+ .probe = latch_led_probe,
146+ .remove = __devexit_p(latch_led_remove),
147+ .driver = {
148+ .name = "leds-latch",
149+ .owner = THIS_MODULE,
150+ },
151+};
152+
153+static int __init latch_led_init(void)
154+{
155+ return platform_driver_register(&latch_led_driver);
156+}
157+
158+static void __exit latch_led_exit(void)
159+{
160+ platform_driver_unregister(&latch_led_driver);
161+}
162+
163+module_init(latch_led_init);
164+module_exit(latch_led_exit);
165+
166+MODULE_AUTHOR("Chris Lang <clang@gateworks.com>");
167+MODULE_DESCRIPTION("Latch LED driver");
168+MODULE_LICENSE("GPL");
169--- a/drivers/leds/Makefile
170+++ b/drivers/leds/Makefile
171@@ -20,6 +20,7 @@ obj-$(CONFIG_LEDS_COBALT_RAQ) += leds-c
172 obj-$(CONFIG_LEDS_SUNFIRE) += leds-sunfire.o
173 obj-$(CONFIG_LEDS_PCA9532) += leds-pca9532.o
174 obj-$(CONFIG_LEDS_GPIO) += leds-gpio.o
175+obj-$(CONFIG_LEDS_LATCH) += leds-latch.o
176 obj-$(CONFIG_LEDS_LP3944) += leds-lp3944.o
177 obj-$(CONFIG_LEDS_CLEVO_MAIL) += leds-clevo-mail.o
178 obj-$(CONFIG_LEDS_HP6XX) += leds-hp6xx.o
179--- a/include/linux/leds.h
180+++ b/include/linux/leds.h
181@@ -161,5 +161,19 @@ struct gpio_led_platform_data {
182                     unsigned long *delay_off);
183 };
184 
185+/* For the leds-latch driver */
186+struct latch_led {
187+ const char *name;
188+ char *default_trigger;
189+ unsigned bit;
190+};
191+
192+struct latch_led_platform_data {
193+ int num_leds;
194+ u32 mem;
195+ struct latch_led *leds;
196+ void (*set_led)(u8 bit, enum led_brightness value);
197+};
198+
199 
200 #endif /* __LINUX_LEDS_H_INCLUDED */
201

Archive Download this file



interactive