diff options
Diffstat (limited to 'packages/linux/ixp4xx-kernel/2.6.16/leds-class.patch')
-rw-r--r-- | packages/linux/ixp4xx-kernel/2.6.16/leds-class.patch | 1862 |
1 files changed, 0 insertions, 1862 deletions
diff --git a/packages/linux/ixp4xx-kernel/2.6.16/leds-class.patch b/packages/linux/ixp4xx-kernel/2.6.16/leds-class.patch deleted file mode 100644 index c0146b6fe4..0000000000 --- a/packages/linux/ixp4xx-kernel/2.6.16/leds-class.patch +++ /dev/null @@ -1,1862 +0,0 @@ - -From: Richard Purdie <rpurdie@rpsys.net> - -Add the foundations of a new LEDs subsystem. This patch adds a class which -presents LED devices within sysfs and allows their brightness to be -controlled. - -Signed-off-by: Richard Purdie <rpurdie@rpsys.net> -Cc: Russell King <rmk@arm.linux.org.uk> -Cc: Greg KH <greg@kroah.com> -Signed-off-by: Andrew Morton <akpm@osdl.org> ---- - - arch/arm/Kconfig | 2 - arch/arm/mach-pxa/corgi.c | 9 + - arch/arm/mach-pxa/spitz.c | 9 + - arch/arm/mach-pxa/tosa.c | 9 + - drivers/Kconfig | 2 - drivers/Makefile | 1 - drivers/ide/ide-disk.c | 22 +++ - drivers/leds/Kconfig | 70 +++++++++++ - drivers/leds/Makefile | 15 ++ - drivers/leds/led-class.c | 174 +++++++++++++++++++++++++++++ - drivers/leds/led-core.c | 25 ++++ - drivers/leds/led-triggers.c | 239 ++++++++++++++++++++++++++++++++++++++++ - drivers/leds/leds-corgi.c | 121 ++++++++++++++++++++ - drivers/leds/leds-ixp4xx-gpio.c | 215 +++++++++++++++++++++++++++++++++++ - drivers/leds/leds-locomo.c | 95 +++++++++++++++ - drivers/leds/leds-spitz.c | 125 ++++++++++++++++++++ - drivers/leds/leds-tosa.c | 131 +++++++++++++++++++++ - drivers/leds/leds.h | 45 +++++++ - drivers/leds/ledtrig-timer.c | 174 +++++++++++++++++++++++++++++ - drivers/mtd/nand/nand_base.c | 26 ++++ - include/linux/leds.h | 105 +++++++++++++++++ - 21 files changed, 1610 insertions(+), 4 deletions(-) - ---- linux-ixp4xx.orig/arch/arm/Kconfig 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/arch/arm/Kconfig 2006-03-07 22:59:04.000000000 +0100 -@@ -807,6 +807,8 @@ source "drivers/misc/Kconfig" - - source "drivers/mfd/Kconfig" - -+source "drivers/leds/Kconfig" -+ - source "drivers/media/Kconfig" - - source "drivers/video/Kconfig" ---- linux-ixp4xx.orig/drivers/Kconfig 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/drivers/Kconfig 2006-03-07 22:59:04.000000000 +0100 -@@ -64,6 +64,8 @@ source "drivers/usb/Kconfig" - - source "drivers/mmc/Kconfig" - -+source "drivers/leds/Kconfig" -+ - source "drivers/infiniband/Kconfig" - - source "drivers/sn/Kconfig" ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/Kconfig 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,70 @@ -+ -+menu "LED devices" -+ -+config NEW_LEDS -+ bool "LED Support" -+ help -+ Say Y to enable Linux LED support. This is not related to standard -+ keyboard LEDs which are controlled via the input system. -+ -+config LEDS_CLASS -+ tristate "LED Class Support" -+ depends NEW_LEDS -+ help -+ This option enables the led sysfs class in /sys/class/leds. You'll -+ need this to do anything useful with LEDs. If unsure, say N. -+ -+config LEDS_TRIGGERS -+ bool "LED Trigger support" -+ depends NEW_LEDS -+ help -+ This option enables trigger support for the leds class. -+ These triggers allow kernel events to drive the LEDs and can -+ be configured via sysfs. If unsure, say Y. -+ -+config LEDS_CORGI -+ tristate "LED Support for the Sharp SL-C7x0 series" -+ depends LEDS_CLASS && PXA_SHARP_C7xx -+ help -+ This option enables support for the LEDs on Sharp Zaurus -+ SL-C7x0 series (C700, C750, C760, C860). -+ -+config LEDS_LOCOMO -+ tristate "LED Support for Locomo device" -+ depends LEDS_CLASS && SHARP_LOCOMO -+ help -+ This option enables support for the LEDs on Sharp Locomo. -+ Zaurus models SL-5500 and SL-5600. -+ -+config LEDS_SPITZ -+ tristate "LED Support for the Sharp SL-Cxx00 series" -+ depends LEDS_CLASS && PXA_SHARP_Cxx00 -+ help -+ This option enables support for the LEDs on Sharp Zaurus -+ SL-Cxx00 series (C1000, C3000, C3100). -+ -+config LEDS_IXP4XX -+ tristate "LED Support for GPIO connected LEDs on IXP4XX processors" -+ depends LEDS_CLASS && ARCH_IXP4XX -+ help -+ This option enables support for the LEDs connected to GPIO -+ outputs of the Intel IXP4XX processors. To be useful the -+ particular board must have LEDs and they must be connected -+ to the GPIO lines. If unsure, say Y. -+ -+config LEDS_TOSA -+ tristate "LED Support for the Sharp SL-6000 series" -+ depends LEDS_CLASS && PXA_SHARPSL -+ help -+ This option enables support for the LEDs on Sharp Zaurus -+ SL-6000 series. -+ -+config LEDS_TRIGGER_TIMER -+ tristate "LED Timer Trigger" -+ depends LEDS_TRIGGERS -+ help -+ This allows LEDs to be controlled by a programmable timer -+ via sysfs. If unsure, say Y. -+ -+endmenu -+ ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/led-class.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,174 @@ -+/* -+ * LED Class Core -+ * -+ * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu> -+ * Copyright (C) 2005-2006 Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include <linux/config.h> -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/list.h> -+#include <linux/spinlock.h> -+#include <linux/device.h> -+#include <linux/sysdev.h> -+#include <linux/timer.h> -+#include <linux/err.h> -+#include <linux/leds.h> -+#include "leds.h" -+ -+static struct class *leds_class; -+ -+static ssize_t led_brightness_show(struct class_device *dev, char *buf) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ ssize_t ret = 0; -+ -+ /* no lock needed for this */ -+ sprintf(buf, "%u\n", led_cdev->brightness); -+ ret = strlen(buf) + 1; -+ -+ return ret; -+} -+ -+static ssize_t led_brightness_store(struct class_device *dev, -+ const char *buf, size_t size) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ ssize_t ret = -EINVAL; -+ char *after; -+ unsigned long state = simple_strtoul(buf, &after, 10); -+ -+ if (after - buf > 0) { -+ ret = after - buf; -+ write_lock(&led_cdev->lock); -+ led_set_brightness(led_cdev, state); -+ write_unlock(&led_cdev->lock); -+ } -+ -+ return ret; -+} -+ -+static CLASS_DEVICE_ATTR(brightness, 0644, led_brightness_show, -+ led_brightness_store); -+#ifdef CONFIG_LEDS_TRIGGERS -+static CLASS_DEVICE_ATTR(trigger, 0644, led_trigger_show, led_trigger_store); -+#endif -+ -+/** -+ * led_classdev_suspend - suspend an led_classdev. -+ * @led_cdev: the led_classdev to suspend. -+ */ -+void led_classdev_suspend(struct led_classdev *led_cdev) -+{ -+ write_lock(&led_cdev->lock); -+ led_cdev->flags |= LED_SUSPENDED; -+ led_cdev->brightness_set(led_cdev, 0); -+ write_unlock(&led_cdev->lock); -+} -+EXPORT_SYMBOL_GPL(led_classdev_suspend); -+ -+/** -+ * led_classdev_resume - resume an led_classdev. -+ * @led_cdev: the led_classdev to resume. -+ */ -+void led_classdev_resume(struct led_classdev *led_cdev) -+{ -+ write_lock(&led_cdev->lock); -+ led_cdev->flags &= ~LED_SUSPENDED; -+ led_cdev->brightness_set(led_cdev, led_cdev->brightness); -+ write_unlock(&led_cdev->lock); -+} -+EXPORT_SYMBOL_GPL(led_classdev_resume); -+ -+/** -+ * led_classdev_register - register a new object of led_classdev class. -+ * @dev: The device to register. -+ * @led_cdev: the led_classdev structure for this device. -+ */ -+int led_classdev_register(struct device *parent, struct led_classdev *led_cdev) -+{ -+ led_cdev->class_dev = class_device_create(leds_class, NULL, 0, -+ parent, "%s", led_cdev->name); -+ if (unlikely(IS_ERR(led_cdev->class_dev))) -+ return PTR_ERR(led_cdev->class_dev); -+ -+ rwlock_init(&led_cdev->lock); -+ class_set_devdata(led_cdev->class_dev, led_cdev); -+ -+ /* register the attributes */ -+ class_device_create_file(led_cdev->class_dev, -+ &class_device_attr_brightness); -+ -+ /* add to the list of leds */ -+ write_lock(&leds_list_lock); -+ list_add_tail(&led_cdev->node, &leds_list); -+ write_unlock(&leds_list_lock); -+ -+#ifdef CONFIG_LEDS_TRIGGERS -+ rwlock_init(&led_cdev->trigger_lock); -+ -+ led_trigger_set_default(led_cdev); -+ -+ class_device_create_file(led_cdev->class_dev, -+ &class_device_attr_trigger); -+#endif -+ -+ printk(KERN_INFO "Registered led device: %s\n", -+ led_cdev->class_dev->class_id); -+ -+ return 0; -+} -+EXPORT_SYMBOL_GPL(led_classdev_register); -+ -+/** -+ * led_classdev_unregister - unregisters a object of led_properties class. -+ * @led_cdev: the led device to unreigister -+ * -+ * Unregisters a previously registered via led_classdev_register object. -+ */ -+void led_classdev_unregister(struct led_classdev *led_cdev) -+{ -+ class_device_remove_file(led_cdev->class_dev, -+ &class_device_attr_brightness); -+#ifdef CONFIG_LEDS_TRIGGERS -+ class_device_remove_file(led_cdev->class_dev, -+ &class_device_attr_trigger); -+ write_lock(&led_cdev->trigger_lock); -+ if (led_cdev->trigger) -+ led_trigger_set(led_cdev, NULL); -+ write_unlock(&led_cdev->trigger_lock); -+#endif -+ -+ class_device_unregister(led_cdev->class_dev); -+ -+ write_lock(&leds_list_lock); -+ list_del(&led_cdev->node); -+ write_unlock(&leds_list_lock); -+} -+EXPORT_SYMBOL_GPL(led_classdev_unregister); -+ -+static int __init leds_init(void) -+{ -+ leds_class = class_create(THIS_MODULE, "leds"); -+ if (IS_ERR(leds_class)) -+ return PTR_ERR(leds_class); -+ return 0; -+} -+ -+static void __exit leds_exit(void) -+{ -+ class_destroy(leds_class); -+} -+ -+subsys_initcall(leds_init); -+module_exit(leds_exit); -+ -+MODULE_AUTHOR("John Lenz, Richard Purdie"); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("LED Class Interface"); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/led-core.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,25 @@ -+/* -+ * LED Class Core -+ * -+ * Copyright 2005-2006 Openedhand Ltd. -+ * -+ * Author: Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/kernel.h> -+#include <linux/list.h> -+#include <linux/module.h> -+#include <linux/spinlock.h> -+#include <linux/leds.h> -+#include "leds.h" -+ -+rwlock_t leds_list_lock = RW_LOCK_UNLOCKED; -+LIST_HEAD(leds_list); -+ -+EXPORT_SYMBOL_GPL(leds_list); -+EXPORT_SYMBOL_GPL(leds_list_lock); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/leds.h 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,45 @@ -+/* -+ * LED Core -+ * -+ * Copyright 2005 Openedhand Ltd. -+ * -+ * Author: Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+#ifndef __LEDS_H_INCLUDED -+#define __LEDS_H_INCLUDED -+ -+#include <linux/leds.h> -+ -+/* led_cdev->lock must be held as write */ -+static inline void led_set_brightness(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ if (value > LED_FULL) -+ value = LED_FULL; -+ led_cdev->brightness = value; -+ if (!(led_cdev->flags & LED_SUSPENDED)) -+ led_cdev->brightness_set(led_cdev, value); -+} -+ -+extern rwlock_t leds_list_lock; -+extern struct list_head leds_list; -+ -+#ifdef CONFIG_LEDS_TRIGGERS -+void led_trigger_set_default(struct led_classdev *led_cdev); -+void led_trigger_set(struct led_classdev *led_cdev, -+ struct led_trigger *trigger); -+#else -+#define led_trigger_set_default(x) do {} while(0) -+#define led_trigger_set(x, y) do {} while(0) -+#endif -+ -+ssize_t led_trigger_store(struct class_device *dev, const char *buf, -+ size_t count); -+ssize_t led_trigger_show(struct class_device *dev, char *buf); -+ -+#endif /* __LEDS_H_INCLUDED */ ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/Makefile 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,15 @@ -+ -+# LED Core -+obj-$(CONFIG_NEW_LEDS) += led-core.o -+obj-$(CONFIG_LEDS_CLASS) += led-class.o -+obj-$(CONFIG_LEDS_TRIGGERS) += led-triggers.o -+ -+# LED Platform Drivers -+obj-$(CONFIG_LEDS_CORGI) += leds-corgi.o -+obj-$(CONFIG_LEDS_LOCOMO) += leds-locomo.o -+obj-$(CONFIG_LEDS_SPITZ) += leds-spitz.o -+obj-$(CONFIG_LEDS_IXP4XX) += leds-ixp4xx-gpio.o -+obj-$(CONFIG_LEDS_TOSA) += leds-tosa.o -+ -+# LED Triggers -+obj-$(CONFIG_LEDS_TRIGGER_TIMER) += ledtrig-timer.o ---- linux-ixp4xx.orig/drivers/Makefile 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/drivers/Makefile 2006-03-07 22:59:04.000000000 +0100 -@@ -68,6 +68,7 @@ obj-$(CONFIG_MCA) += mca/ - obj-$(CONFIG_EISA) += eisa/ - obj-$(CONFIG_CPU_FREQ) += cpufreq/ - obj-$(CONFIG_MMC) += mmc/ -+obj-$(CONFIG_NEW_LEDS) += leds/ - obj-$(CONFIG_INFINIBAND) += infiniband/ - obj-$(CONFIG_SGI_SN) += sn/ - obj-y += firmware/ ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/include/linux/leds.h 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,105 @@ -+/* -+ * Driver model for leds and led triggers -+ * -+ * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu> -+ * Copyright (C) 2005 Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+#ifndef __LINUX_LEDS_H_INCLUDED -+#define __LINUX_LEDS_H_INCLUDED -+ -+struct device; -+struct class_device; -+/* -+ * LED Core -+ */ -+ -+enum led_brightness { -+ LED_OFF = 0, -+ LED_HALF = 127, -+ LED_FULL = 255, -+}; -+ -+struct led_classdev { -+ const char *name; -+ int brightness; -+ int flags; -+#define LED_SUSPENDED (1 << 0) -+ -+ /* A function to set the brightness of the led */ -+ void (*brightness_set)(struct led_classdev *led_cdev, -+ enum led_brightness brightness); -+ -+ struct class_device *class_dev; -+ /* LED Device linked list */ -+ struct list_head node; -+ -+ /* Protects the LED properties data above */ -+ rwlock_t lock; -+ -+ /* Trigger data */ -+ char *default_trigger; -+#ifdef CONFIG_LEDS_TRIGGERS -+ rwlock_t trigger_lock; -+ /* Protects the trigger data below */ -+ -+ struct led_trigger *trigger; -+ struct list_head trig_list; -+ void *trigger_data; -+#endif -+}; -+ -+extern int led_classdev_register(struct device *parent, -+ struct led_classdev *led_cdev); -+extern void led_classdev_unregister(struct led_classdev *led_cdev); -+extern void led_classdev_suspend(struct led_classdev *led_cdev); -+extern void led_classdev_resume(struct led_classdev *led_cdev); -+ -+/* -+ * LED Triggers -+ */ -+#ifdef CONFIG_LEDS_TRIGGERS -+ -+#define TRIG_NAME_MAX 50 -+ -+struct led_trigger { -+ /* Trigger Properties */ -+ const char *name; -+ void (*activate)(struct led_classdev *led_cdev); -+ void (*deactivate)(struct led_classdev *led_cdev); -+ -+ /* LEDs under control by this trigger (for simple triggers) */ -+ rwlock_t leddev_list_lock; -+ struct list_head led_cdevs; -+ -+ /* Link to next registered trigger */ -+ struct list_head next_trig; -+}; -+ -+/* Registration functions for complex triggers */ -+int led_trigger_register(struct led_trigger *trigger); -+void led_trigger_unregister(struct led_trigger *trigger); -+ -+/* Registration functions for simple triggers */ -+#define DEFINE_LED_TRIGGER(x) static struct led_trigger *x; -+#define DEFINE_LED_TRIGGER_GLOBAL(x) struct led_trigger *x; -+void led_trigger_register_simple(const char *name, -+ struct led_trigger **trigger); -+void led_trigger_unregister_simple(struct led_trigger *trigger); -+void led_trigger_event(struct led_trigger *trigger, enum led_brightness event); -+ -+#else -+ -+/* Triggers aren't active - null macros */ -+#define DEFINE_LED_TRIGGER(x) -+#define DEFINE_LED_TRIGGER_GLOBAL(x) -+#define led_trigger_register_simple(x, y) do {} while(0) -+#define led_trigger_unregister_simple(x) do {} while(0) -+#define led_trigger_event(x, y) do {} while(0) -+ -+#endif -+#endif /* __LINUX_LEDS_H_INCLUDED */ ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/led-triggers.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,239 @@ -+/* -+ * LED Triggers Core -+ * -+ * Copyright 2005-2006 Openedhand Ltd. -+ * -+ * Author: Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/list.h> -+#include <linux/spinlock.h> -+#include <linux/device.h> -+#include <linux/sysdev.h> -+#include <linux/timer.h> -+#include <linux/leds.h> -+#include "leds.h" -+ -+/* -+ * Nests outside led_cdev->lock and led_cdev->trigger_lock -+ */ -+static rwlock_t triggers_list_lock = RW_LOCK_UNLOCKED; -+static LIST_HEAD(trigger_list); -+ -+ssize_t led_trigger_store(struct class_device *dev, const char *buf, -+ size_t count) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ char trigger_name[TRIG_NAME_MAX]; -+ struct led_trigger *trig; -+ size_t len; -+ -+ trigger_name[sizeof(trigger_name) - 1] = '\0'; -+ strncpy(trigger_name, buf, sizeof(trigger_name) - 1); -+ len = strlen(trigger_name); -+ -+ if (len && trigger_name[len - 1] == '\n') -+ trigger_name[len - 1] = '\0'; -+ -+ if (!strcmp(trigger_name, "none")) { -+ write_lock(&led_cdev->trigger_lock); -+ led_trigger_set(led_cdev, NULL); -+ write_unlock(&led_cdev->trigger_lock); -+ return count; -+ } -+ -+ read_lock(&triggers_list_lock); -+ list_for_each_entry(trig, &trigger_list, next_trig) { -+ if (!strcmp(trigger_name, trig->name)) { -+ write_lock(&led_cdev->trigger_lock); -+ led_trigger_set(led_cdev, trig); -+ write_unlock(&led_cdev->trigger_lock); -+ -+ read_unlock(&triggers_list_lock); -+ return count; -+ } -+ } -+ read_unlock(&triggers_list_lock); -+ -+ return -EINVAL; -+} -+ -+ -+ssize_t led_trigger_show(struct class_device *dev, char *buf) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ struct led_trigger *trig; -+ int len = 0; -+ -+ read_lock(&triggers_list_lock); -+ read_lock(&led_cdev->trigger_lock); -+ -+ if (!led_cdev->trigger) -+ len += sprintf(buf+len, "[none] "); -+ else -+ len += sprintf(buf+len, "none "); -+ -+ list_for_each_entry(trig, &trigger_list, next_trig) { -+ if (led_cdev->trigger && !strcmp(led_cdev->trigger->name, -+ trig->name)) -+ len += sprintf(buf+len, "[%s] ", trig->name); -+ else -+ len += sprintf(buf+len, "%s ", trig->name); -+ } -+ read_unlock(&led_cdev->trigger_lock); -+ read_unlock(&triggers_list_lock); -+ -+ len += sprintf(len+buf, "\n"); -+ return len; -+} -+ -+void led_trigger_event(struct led_trigger *trigger, -+ enum led_brightness brightness) -+{ -+ struct list_head *entry; -+ -+ if (!trigger) -+ return; -+ -+ read_lock(&trigger->leddev_list_lock); -+ list_for_each(entry, &trigger->led_cdevs) { -+ struct led_classdev *led_cdev; -+ -+ led_cdev = list_entry(entry, struct led_classdev, trig_list); -+ write_lock(&led_cdev->lock); -+ led_set_brightness(led_cdev, brightness); -+ write_unlock(&led_cdev->lock); -+ } -+ read_unlock(&trigger->leddev_list_lock); -+} -+ -+/* Caller must ensure led_cdev->trigger_lock held */ -+void led_trigger_set(struct led_classdev *led_cdev, struct led_trigger *trigger) -+{ -+ /* Remove any existing trigger */ -+ if (led_cdev->trigger) { -+ write_lock(&led_cdev->trigger->leddev_list_lock); -+ list_del(&led_cdev->trig_list); -+ write_unlock(&led_cdev->trigger->leddev_list_lock); -+ if (led_cdev->trigger->deactivate) -+ led_cdev->trigger->deactivate(led_cdev); -+ } -+ if (trigger) { -+ write_lock(&trigger->leddev_list_lock); -+ list_add_tail(&led_cdev->trig_list, &trigger->led_cdevs); -+ write_unlock(&trigger->leddev_list_lock); -+ if (trigger->activate) -+ trigger->activate(led_cdev); -+ } -+ led_cdev->trigger = trigger; -+} -+ -+void led_trigger_set_default(struct led_classdev *led_cdev) -+{ -+ struct led_trigger *trig; -+ -+ if (!led_cdev->default_trigger) -+ return; -+ -+ read_lock(&triggers_list_lock); -+ write_lock(&led_cdev->trigger_lock); -+ list_for_each_entry(trig, &trigger_list, next_trig) { -+ if (!strcmp(led_cdev->default_trigger, trig->name)) -+ led_trigger_set(led_cdev, trig); -+ } -+ write_unlock(&led_cdev->trigger_lock); -+ read_unlock(&triggers_list_lock); -+} -+ -+int led_trigger_register(struct led_trigger *trigger) -+{ -+ struct led_classdev *led_cdev; -+ -+ rwlock_init(&trigger->leddev_list_lock); -+ INIT_LIST_HEAD(&trigger->led_cdevs); -+ -+ /* Add to the list of led triggers */ -+ write_lock(&triggers_list_lock); -+ list_add_tail(&trigger->next_trig, &trigger_list); -+ write_unlock(&triggers_list_lock); -+ -+ /* Register with any LEDs that have this as a default trigger */ -+ read_lock(&leds_list_lock); -+ list_for_each_entry(led_cdev, &leds_list, node) { -+ write_lock(&led_cdev->trigger_lock); -+ if (!led_cdev->trigger && led_cdev->default_trigger && -+ !strcmp(led_cdev->default_trigger, trigger->name)) -+ led_trigger_set(led_cdev, trigger); -+ write_unlock(&led_cdev->trigger_lock); -+ } -+ read_unlock(&leds_list_lock); -+ -+ return 0; -+} -+ -+void led_trigger_register_simple(const char *name, struct led_trigger **tp) -+{ -+ struct led_trigger *trigger; -+ -+ trigger = kzalloc(sizeof(struct led_trigger), GFP_KERNEL); -+ -+ if (trigger) { -+ trigger->name = name; -+ led_trigger_register(trigger); -+ } -+ *tp = trigger; -+} -+ -+void led_trigger_unregister(struct led_trigger *trigger) -+{ -+ struct led_classdev *led_cdev; -+ -+ /* Remove from the list of led triggers */ -+ write_lock(&triggers_list_lock); -+ list_del(&trigger->next_trig); -+ write_unlock(&triggers_list_lock); -+ -+ /* Remove anyone actively using this trigger */ -+ read_lock(&leds_list_lock); -+ list_for_each_entry(led_cdev, &leds_list, node) { -+ write_lock(&led_cdev->trigger_lock); -+ if (led_cdev->trigger == trigger) -+ led_trigger_set(led_cdev, NULL); -+ write_unlock(&led_cdev->trigger_lock); -+ } -+ read_unlock(&leds_list_lock); -+} -+ -+void led_trigger_unregister_simple(struct led_trigger *trigger) -+{ -+ led_trigger_unregister(trigger); -+ kfree(trigger); -+} -+ -+/* Used by LED Class */ -+EXPORT_SYMBOL_GPL(led_trigger_set); -+EXPORT_SYMBOL_GPL(led_trigger_set_default); -+EXPORT_SYMBOL_GPL(led_trigger_show); -+EXPORT_SYMBOL_GPL(led_trigger_store); -+ -+/* LED Trigger Interface */ -+EXPORT_SYMBOL_GPL(led_trigger_register); -+EXPORT_SYMBOL_GPL(led_trigger_unregister); -+ -+/* Simple LED Tigger Interface */ -+EXPORT_SYMBOL_GPL(led_trigger_register_simple); -+EXPORT_SYMBOL_GPL(led_trigger_unregister_simple); -+EXPORT_SYMBOL_GPL(led_trigger_event); -+ -+MODULE_AUTHOR("Richard Purdie"); -+MODULE_LICENSE("GPL"); -+MODULE_DESCRIPTION("LED Triggers Core"); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/ledtrig-timer.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,174 @@ -+/* -+ * LED Kernel Timer Trigger -+ * -+ * Copyright 2005-2006 Openedhand Ltd. -+ * -+ * Author: Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/module.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/list.h> -+#include <linux/spinlock.h> -+#include <linux/device.h> -+#include <linux/sysdev.h> -+#include <linux/timer.h> -+#include <linux/leds.h> -+#include "leds.h" -+ -+struct timer_trig_data { -+ unsigned long delay_on; /* milliseconds on */ -+ unsigned long delay_off; /* milliseconds off */ -+ struct timer_list timer; -+}; -+ -+static void led_timer_function(unsigned long data) -+{ -+ struct led_classdev *led_cdev = (struct led_classdev *) data; -+ struct timer_trig_data *timer_data = led_cdev->trigger_data; -+ unsigned long brightness = LED_OFF; -+ unsigned long delay = timer_data->delay_off; -+ -+ if (!timer_data->delay_on || !timer_data->delay_off) { -+ write_lock(&led_cdev->lock); -+ led_set_brightness(led_cdev, LED_OFF); -+ write_unlock(&led_cdev->lock); -+ return; -+ } -+ -+ if (!led_cdev->brightness) { -+ brightness = LED_FULL; -+ delay = timer_data->delay_on; -+ } -+ -+ write_lock(&led_cdev->lock); -+ led_set_brightness(led_cdev, brightness); -+ write_unlock(&led_cdev->lock); -+ -+ mod_timer(&timer_data->timer, jiffies + msecs_to_jiffies(delay)); -+} -+ -+static ssize_t led_delay_on_show(struct class_device *dev, char *buf) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ struct timer_trig_data *timer_data = led_cdev->trigger_data; -+ -+ sprintf(buf, "%lu\n", timer_data->delay_on); -+ -+ return strlen(buf) + 1; -+} -+ -+static ssize_t led_delay_on_store(struct class_device *dev, const char *buf, -+ size_t size) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ struct timer_trig_data *timer_data = led_cdev->trigger_data; -+ int ret = -EINVAL; -+ char *after; -+ unsigned long state = simple_strtoul(buf, &after, 10); -+ -+ if (after - buf > 0) { -+ timer_data->delay_on = state; -+ mod_timer(&timer_data->timer, jiffies + 1); -+ ret = after - buf; -+ } -+ -+ return ret; -+} -+ -+static ssize_t led_delay_off_show(struct class_device *dev, char *buf) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ struct timer_trig_data *timer_data = led_cdev->trigger_data; -+ -+ sprintf(buf, "%lu\n", timer_data->delay_off); -+ -+ return strlen(buf) + 1; -+} -+ -+static ssize_t led_delay_off_store(struct class_device *dev, const char *buf, -+ size_t size) -+{ -+ struct led_classdev *led_cdev = class_get_devdata(dev); -+ struct timer_trig_data *timer_data = led_cdev->trigger_data; -+ int ret = -EINVAL; -+ char *after; -+ unsigned long state = simple_strtoul(buf, &after, 10); -+ -+ if (after - buf > 0) { -+ timer_data->delay_off = state; -+ mod_timer(&timer_data->timer, jiffies + 1); -+ ret = after - buf; -+ } -+ -+ return ret; -+} -+ -+static CLASS_DEVICE_ATTR(delay_on, 0644, led_delay_on_show, -+ led_delay_on_store); -+static CLASS_DEVICE_ATTR(delay_off, 0644, led_delay_off_show, -+ led_delay_off_store); -+ -+static void timer_trig_activate(struct led_classdev *led_cdev) -+{ -+ struct timer_trig_data *timer_data; -+ -+ timer_data = kzalloc(sizeof(struct timer_trig_data), GFP_KERNEL); -+ if (!timer_data) -+ return; -+ -+ led_cdev->trigger_data = timer_data; -+ -+ init_timer(&timer_data->timer); -+ timer_data->timer.function = led_timer_function; -+ timer_data->timer.data = (unsigned long) led_cdev; -+ -+ class_device_create_file(led_cdev->class_dev, -+ &class_device_attr_delay_on); -+ class_device_create_file(led_cdev->class_dev, -+ &class_device_attr_delay_off); -+} -+ -+static void timer_trig_deactivate(struct led_classdev *led_cdev) -+{ -+ struct timer_trig_data *timer_data = led_cdev->trigger_data; -+ -+ if (timer_data) { -+ class_device_remove_file(led_cdev->class_dev, -+ &class_device_attr_delay_on); -+ class_device_remove_file(led_cdev->class_dev, -+ &class_device_attr_delay_off); -+ del_timer_sync(&timer_data->timer); -+ kfree(timer_data); -+ } -+} -+ -+static struct led_trigger timer_led_trigger = { -+ .name = "timer", -+ .activate = timer_trig_activate, -+ .deactivate = timer_trig_deactivate, -+}; -+ -+static int __init timer_trig_init(void) -+{ -+ return led_trigger_register(&timer_led_trigger); -+} -+ -+static void __exit timer_trig_exit(void) -+{ -+ led_trigger_unregister(&timer_led_trigger); -+} -+ -+module_init(timer_trig_init); -+module_exit(timer_trig_exit); -+ -+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>"); -+MODULE_DESCRIPTION("Timer LED trigger"); -+MODULE_LICENSE("GPL"); ---- linux-ixp4xx.orig/arch/arm/mach-pxa/corgi.c 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-pxa/corgi.c 2006-03-07 22:59:04.000000000 +0100 -@@ -165,6 +165,14 @@ static struct platform_device corgikbd_d - - - /* -+ * Corgi LEDs -+ */ -+static struct platform_device corgiled_device = { -+ .name = "corgi-led", -+ .id = -1, -+}; -+ -+/* - * Corgi Touch Screen Device - */ - static struct resource corgits_resources[] = { -@@ -298,6 +306,7 @@ static struct platform_device *devices[] - &corgikbd_device, - &corgibl_device, - &corgits_device, -+ &corgiled_device, - }; - - static void __init corgi_init(void) ---- linux-ixp4xx.orig/arch/arm/mach-pxa/spitz.c 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-pxa/spitz.c 2006-03-07 22:59:04.000000000 +0100 -@@ -243,6 +243,14 @@ static struct platform_device spitzkbd_d - - - /* -+ * Spitz LEDs -+ */ -+static struct platform_device spitzled_device = { -+ .name = "spitz-led", -+ .id = -1, -+}; -+ -+/* - * Spitz Touch Screen Device - */ - static struct resource spitzts_resources[] = { -@@ -419,6 +427,7 @@ static struct platform_device *devices[] - &spitzkbd_device, - &spitzts_device, - &spitzbl_device, -+ &spitzled_device, - }; - - static void __init common_init(void) ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/leds-corgi.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,121 @@ -+/* -+ * LED Triggers Core -+ * -+ * Copyright 2005-2006 Openedhand Ltd. -+ * -+ * Author: Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/leds.h> -+#include <asm/mach-types.h> -+#include <asm/arch/corgi.h> -+#include <asm/arch/hardware.h> -+#include <asm/arch/pxa-regs.h> -+#include <asm/hardware/scoop.h> -+ -+static void corgiled_amber_set(struct led_classdev *led_cdev, enum led_brightness value) -+{ -+ if (value) -+ GPSR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); -+ else -+ GPCR0 = GPIO_bit(CORGI_GPIO_LED_ORANGE); -+} -+ -+static void corgiled_green_set(struct led_classdev *led_cdev, enum led_brightness value) -+{ -+ if (value) -+ set_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); -+ else -+ reset_scoop_gpio(&corgiscoop_device.dev, CORGI_SCP_LED_GREEN); -+} -+ -+static struct led_classdev corgi_amber_led = { -+ .name = "corgi:amber", -+ .default_trigger = "sharpsl-charge", -+ .brightness_set = corgiled_amber_set, -+}; -+ -+static struct led_classdev corgi_green_led = { -+ .name = "corgi:green", -+ .default_trigger = "nand-disk", -+ .brightness_set = corgiled_green_set, -+}; -+ -+#ifdef CONFIG_PM -+static int corgiled_suspend(struct platform_device *dev, pm_message_t state) -+{ -+#ifdef CONFIG_LEDS_TRIGGERS -+ if (corgi_amber_led.trigger && strcmp(corgi_amber_led.trigger->name, "sharpsl-charge")) -+#endif -+ led_classdev_suspend(&corgi_amber_led); -+ led_classdev_suspend(&corgi_green_led); -+ return 0; -+} -+ -+static int corgiled_resume(struct platform_device *dev) -+{ -+ led_classdev_resume(&corgi_amber_led); -+ led_classdev_resume(&corgi_green_led); -+ return 0; -+} -+#endif -+ -+static int corgiled_probe(struct platform_device *pdev) -+{ -+ int ret; -+ -+ ret = led_classdev_register(&pdev->dev, &corgi_amber_led); -+ if (ret < 0) -+ return ret; -+ -+ ret = led_classdev_register(&pdev->dev, &corgi_green_led); -+ if (ret < 0) -+ led_classdev_unregister(&corgi_amber_led); -+ -+ return ret; -+} -+ -+static int corgiled_remove(struct platform_device *pdev) -+{ -+ led_classdev_unregister(&corgi_amber_led); -+ led_classdev_unregister(&corgi_green_led); -+ return 0; -+} -+ -+static struct platform_driver corgiled_driver = { -+ .probe = corgiled_probe, -+ .remove = corgiled_remove, -+#ifdef CONFIG_PM -+ .suspend = corgiled_suspend, -+ .resume = corgiled_resume, -+#endif -+ .driver = { -+ .name = "corgi-led", -+ }, -+}; -+ -+static int __init corgiled_init(void) -+{ -+ return platform_driver_register(&corgiled_driver); -+} -+ -+static void __exit corgiled_exit(void) -+{ -+ platform_driver_unregister(&corgiled_driver); -+} -+ -+module_init(corgiled_init); -+module_exit(corgiled_exit); -+ -+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>"); -+MODULE_DESCRIPTION("Corgi LED driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/leds-spitz.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,125 @@ -+/* -+ * LED Triggers Core -+ * -+ * Copyright 2005-2006 Openedhand Ltd. -+ * -+ * Author: Richard Purdie <rpurdie@openedhand.com> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/leds.h> -+#include <asm/hardware/scoop.h> -+#include <asm/mach-types.h> -+#include <asm/arch/hardware.h> -+#include <asm/arch/pxa-regs.h> -+#include <asm/arch/spitz.h> -+ -+static void spitzled_amber_set(struct led_classdev *led_cdev, enum led_brightness value) -+{ -+ if (value) -+ set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); -+ else -+ reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_ORANGE); -+} -+ -+static void spitzled_green_set(struct led_classdev *led_cdev, enum led_brightness value) -+{ -+ if (value) -+ set_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); -+ else -+ reset_scoop_gpio(&spitzscoop_device.dev, SPITZ_SCP_LED_GREEN); -+} -+ -+static struct led_classdev spitz_amber_led = { -+ .name = "spitz:amber", -+ .default_trigger = "sharpsl-charge", -+ .brightness_set = spitzled_amber_set, -+}; -+ -+static struct led_classdev spitz_green_led = { -+ .name = "spitz:green", -+ .default_trigger = "ide-disk", -+ .brightness_set = spitzled_green_set, -+}; -+ -+#ifdef CONFIG_PM -+static int spitzled_suspend(struct platform_device *dev, pm_message_t state) -+{ -+#ifdef CONFIG_LEDS_TRIGGERS -+ if (spitz_amber_led.trigger && strcmp(spitz_amber_led.trigger->name, "sharpsl-charge")) -+#endif -+ led_classdev_suspend(&spitz_amber_led); -+ led_classdev_suspend(&spitz_green_led); -+ return 0; -+} -+ -+static int spitzled_resume(struct platform_device *dev) -+{ -+ led_classdev_resume(&spitz_amber_led); -+ led_classdev_resume(&spitz_green_led); -+ return 0; -+} -+#endif -+ -+static int spitzled_probe(struct platform_device *pdev) -+{ -+ int ret; -+ -+ if (machine_is_akita()) -+ spitz_green_led.default_trigger = "nand-disk"; -+ -+ ret = led_classdev_register(&pdev->dev, &spitz_amber_led); -+ if (ret < 0) -+ return ret; -+ -+ ret = led_classdev_register(&pdev->dev, &spitz_green_led); -+ if (ret < 0) -+ led_classdev_unregister(&spitz_amber_led); -+ -+ return ret; -+} -+ -+static int spitzled_remove(struct platform_device *pdev) -+{ -+ led_classdev_unregister(&spitz_amber_led); -+ led_classdev_unregister(&spitz_green_led); -+ -+ return 0; -+} -+ -+static struct platform_driver spitzled_driver = { -+ .probe = spitzled_probe, -+ .remove = spitzled_remove, -+#ifdef CONFIG_PM -+ .suspend = spitzled_suspend, -+ .resume = spitzled_resume, -+#endif -+ .driver = { -+ .name = "spitz-led", -+ }, -+}; -+ -+static int __init spitzled_init(void) -+{ -+ return platform_driver_register(&spitzled_driver); -+} -+ -+static void __exit spitzled_exit(void) -+{ -+ platform_driver_unregister(&spitzled_driver); -+} -+ -+module_init(spitzled_init); -+module_exit(spitzled_exit); -+ -+MODULE_AUTHOR("Richard Purdie <rpurdie@openedhand.com>"); -+MODULE_DESCRIPTION("Spitz LED driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/leds-locomo.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,95 @@ -+/* -+ * linux/drivers/leds/locomo.c -+ * -+ * Copyright (C) 2005 John Lenz <lenz@cs.wisc.edu> -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ */ -+ -+#include <linux/config.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/device.h> -+#include <linux/leds.h> -+ -+#include <asm/hardware.h> -+#include <asm/hardware/locomo.h> -+ -+static void locomoled_brightness_set(struct led_classdev *led_cdev, -+ enum led_brightness value, int offset) -+{ -+ struct locomo_dev *locomo_dev = LOCOMO_DEV(led_cdev->class_dev->dev); -+ unsigned long flags; -+ -+ local_irq_save(flags); -+ if (value) -+ locomo_writel(LOCOMO_LPT_TOFH, locomo_dev->mapbase + offset); -+ else -+ locomo_writel(LOCOMO_LPT_TOFL, locomo_dev->mapbase + offset); -+ local_irq_restore(flags); -+} -+ -+static void locomoled_brightness_set0(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ locomoled_brightness_set(led_cdev, value, LOCOMO_LPT0); -+} -+ -+static void locomoled_brightness_set1(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ locomoled_brightness_set(led_cdev, value, LOCOMO_LPT1); -+} -+ -+static struct led_classdev locomo_led0 = { -+ .name = "locomo:amber", -+ .brightness_set = locomoled_brightness_set0, -+}; -+ -+static struct led_classdev locomo_led1 = { -+ .name = "locomo:green", -+ .brightness_set = locomoled_brightness_set1, -+}; -+ -+static int locomoled_probe(struct locomo_dev *ldev) -+{ -+ int ret; -+ -+ ret = led_classdev_register(&ldev->dev, &locomo_led0); -+ if (ret < 0) -+ return ret; -+ -+ ret = led_classdev_register(&ldev->dev, &locomo_led1); -+ if (ret < 0) -+ led_classdev_unregister(&locomo_led0); -+ -+ return ret; -+} -+ -+static int locomoled_remove(struct locomo_dev *dev) -+{ -+ led_classdev_unregister(&locomo_led0); -+ led_classdev_unregister(&locomo_led1); -+ return 0; -+} -+ -+static struct locomo_driver locomoled_driver = { -+ .drv = { -+ .name = "locomoled" -+ }, -+ .devid = LOCOMO_DEVID_LED, -+ .probe = locomoled_probe, -+ .remove = locomoled_remove, -+}; -+ -+static int __init locomoled_init(void) -+{ -+ return locomo_driver_register(&locomoled_driver); -+} -+module_init(locomoled_init); -+ -+MODULE_AUTHOR("John Lenz <lenz@cs.wisc.edu>"); -+MODULE_DESCRIPTION("Locomo LED driver"); -+MODULE_LICENSE("GPL"); ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/leds-ixp4xx-gpio.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,215 @@ -+/* -+ * IXP4XX GPIO driver LED driver -+ * -+ * Author: John Bowler <jbowler@acm.org> -+ * -+ * Copyright (c) 2006 John Bowler -+ * -+ * Permission is hereby granted, free of charge, to any -+ * person obtaining a copy of this software and associated -+ * documentation files (the "Software"), to deal in the -+ * Software without restriction, including without -+ * limitation the rights to use, copy, modify, merge, -+ * publish, distribute, sublicense, and/or sell copies of -+ * the Software, and to permit persons to whom the -+ * Software is furnished to do so, subject to the -+ * following conditions: -+ * -+ * The above copyright notice and this permission notice -+ * shall be included in all copies or substantial portions -+ * of the Software. -+ * -+ * THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF -+ * ANY KIND, EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED -+ * TO THE WARRANTIES OF MERCHANTABILITY, FITNESS FOR A -+ * PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT -+ * SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR -+ * ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN -+ * ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -+ * OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR -+ * OTHER DEALINGS IN THE SOFTWARE. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/spinlock.h> -+#include <linux/leds.h> -+#include <asm/arch/hardware.h> -+ -+extern spinlock_t gpio_lock; -+ -+/* Up to 16 gpio lines are possible. */ -+#define GPIO_MAX 16 -+static struct ixp4xxgpioled_device { -+ struct led_classdev ancestor; -+ int flags; -+} ixp4xxgpioled_devices[GPIO_MAX]; -+ -+void ixp4xxgpioled_brightness_set(struct led_classdev *pled, -+ enum led_brightness value) -+{ -+ const struct ixp4xxgpioled_device *const ixp4xx_dev = -+ container_of(pled, struct ixp4xxgpioled_device, ancestor); -+ const u32 gpio_pin = ixp4xx_dev - ixp4xxgpioled_devices; -+ -+ if (gpio_pin < GPIO_MAX && ixp4xx_dev->ancestor.name != 0) { -+ /* Set or clear the 'gpio_pin' bit according to the style -+ * and the required setting (value > 0 == on) -+ */ -+ const int gpio_value = -+ (value > 0) == (ixp4xx_dev->flags != IXP4XX_GPIO_LOW) ? -+ IXP4XX_GPIO_HIGH : IXP4XX_GPIO_LOW; -+ -+ { -+ unsigned long flags; -+ spin_lock_irqsave(&gpio_lock, flags); -+ gpio_line_set(gpio_pin, gpio_value); -+ spin_unlock_irqrestore(&gpio_lock, flags); -+ } -+ } -+} -+ -+/* LEDs are described in resources, the following iterates over the valid -+ * LED resources. -+ */ -+#define for_all_leds(i, pdev) \ -+ for (i=0; i<pdev->num_resources; ++i) \ -+ if (pdev->resource[i].start < GPIO_MAX && \ -+ pdev->resource[i].name != 0) -+ -+/* The following applies 'operation' to each LED from the given platform, -+ * the function always returns 0 to allow tail call elimination. -+ */ -+static int apply_to_all_leds(struct platform_device *pdev, -+ void (*operation)(struct led_classdev *pled)) -+{ -+ int i; -+ -+ for_all_leds(i, pdev) -+ operation(&ixp4xxgpioled_devices[pdev->resource[i].start].ancestor); -+ return 0; -+} -+ -+#ifdef CONFIG_PM -+static int ixp4xxgpioled_suspend(struct platform_device *pdev, -+ pm_message_t state) -+{ -+ return apply_to_all_leds(pdev, led_classdev_suspend); -+} -+ -+static int ixp4xxgpioled_resume(struct platform_device *pdev) -+{ -+ return apply_to_all_leds(pdev, led_classdev_resume); -+} -+#endif -+ -+static void ixp4xxgpioled_remove_one_led(struct led_classdev *pled) -+{ -+ led_classdev_unregister(pled); -+ pled->name = 0; -+} -+ -+static int ixp4xxgpioled_remove(struct platform_device *pdev) -+{ -+ return apply_to_all_leds(pdev, ixp4xxgpioled_remove_one_led); -+} -+ -+static int ixp4xxgpioled_probe(struct platform_device *pdev) -+{ -+ /* The board level has to tell the driver where the -+ * LEDs are connected - there is no way to find out -+ * electrically. It must also say whether the GPIO -+ * lines are active high or active low. -+ * -+ * To do this read the num_resources (the number of -+ * LEDs) and the struct resource (the data for each -+ * LED). The name comes from the resource, and it -+ * isn't copied. -+ */ -+ int i; -+ -+ for_all_leds(i, pdev) { -+ const u8 gpio_pin = pdev->resource[i].start; -+ int rc; -+ -+ if (ixp4xxgpioled_devices[gpio_pin].ancestor.name == 0) { -+ unsigned long flags; -+ -+ spin_lock_irqsave(&gpio_lock, flags); -+ gpio_line_config(gpio_pin, IXP4XX_GPIO_OUT); -+ /* The config can, apparently, reset the state, -+ * I suspect the gpio line may be an input and -+ * the config may cause the line to be latched, -+ * so the setting depends on how the LED is -+ * connected to the line (which affects how it -+ * floats if not driven). -+ */ -+ gpio_line_set(gpio_pin, IXP4XX_GPIO_HIGH); -+ spin_unlock_irqrestore(&gpio_lock, flags); -+ -+ ixp4xxgpioled_devices[gpio_pin].flags = -+ pdev->resource[i].flags & IORESOURCE_BITS; -+ -+ ixp4xxgpioled_devices[gpio_pin].ancestor.name = -+ pdev->resource[i].name; -+ -+ /* This is how a board manufacturer makes the LED -+ * come on on reset - the GPIO line will be high, so -+ * make the LED light when the line is low... -+ */ -+ if (ixp4xxgpioled_devices[gpio_pin].flags != IXP4XX_GPIO_LOW) -+ ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 100; -+ else -+ ixp4xxgpioled_devices[gpio_pin].ancestor.brightness = 0; -+ -+ ixp4xxgpioled_devices[gpio_pin].ancestor.flags = 0; -+ -+ ixp4xxgpioled_devices[gpio_pin].ancestor.brightness_set = -+ ixp4xxgpioled_brightness_set; -+ -+ ixp4xxgpioled_devices[gpio_pin].ancestor.default_trigger = 0; -+ } -+ -+ rc = led_classdev_register(&pdev->dev, -+ &ixp4xxgpioled_devices[gpio_pin].ancestor); -+ if (rc < 0) { -+ ixp4xxgpioled_devices[gpio_pin].ancestor.name = 0; -+ ixp4xxgpioled_remove(pdev); -+ return rc; -+ } -+ } -+ -+ return 0; -+} -+ -+static struct platform_driver ixp4xxgpioled_driver = { -+ .probe = ixp4xxgpioled_probe, -+ .remove = ixp4xxgpioled_remove, -+#ifdef CONFIG_PM -+ .suspend = ixp4xxgpioled_suspend, -+ .resume = ixp4xxgpioled_resume, -+#endif -+ .driver = { -+ .name = "IXP4XX-GPIO-LED", -+ }, -+}; -+ -+static int __init ixp4xxgpioled_init(void) -+{ -+ return platform_driver_register(&ixp4xxgpioled_driver); -+} -+ -+static void __exit ixp4xxgpioled_exit(void) -+{ -+ platform_driver_unregister(&ixp4xxgpioled_driver); -+} -+ -+module_init(ixp4xxgpioled_init); -+module_exit(ixp4xxgpioled_exit); -+ -+MODULE_AUTHOR("John Bowler <jbowler@acm.org>"); -+MODULE_DESCRIPTION("IXP4XX GPIO LED driver"); -+MODULE_LICENSE("Dual MIT/GPL"); ---- linux-ixp4xx.orig/arch/arm/mach-pxa/tosa.c 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/arch/arm/mach-pxa/tosa.c 2006-03-07 22:59:04.000000000 +0100 -@@ -252,10 +252,19 @@ static struct platform_device tosakbd_de - .id = -1, - }; - -+/* -+ * Tosa LEDs -+ */ -+static struct platform_device tosaled_device = { -+ .name = "tosa-led", -+ .id = -1, -+}; -+ - static struct platform_device *devices[] __initdata = { - &tosascoop_device, - &tosascoop_jc_device, - &tosakbd_device, -+ &tosaled_device, - }; - - static void __init tosa_init(void) ---- /dev/null 1970-01-01 00:00:00.000000000 +0000 -+++ linux-ixp4xx/drivers/leds/leds-tosa.c 2006-03-07 22:59:04.000000000 +0100 -@@ -0,0 +1,131 @@ -+/* -+ * LED Triggers Core -+ * -+ * Copyright 2005 Dirk Opfer -+ * -+ * Author: Dirk Opfer <Dirk@Opfer-Online.de> -+ * based on spitz.c -+ * -+ * This program is free software; you can redistribute it and/or modify -+ * it under the terms of the GNU General Public License version 2 as -+ * published by the Free Software Foundation. -+ * -+ */ -+ -+#include <linux/config.h> -+#include <linux/kernel.h> -+#include <linux/init.h> -+#include <linux/platform_device.h> -+#include <linux/leds.h> -+#include <asm/hardware/scoop.h> -+#include <asm/mach-types.h> -+#include <asm/arch/hardware.h> -+#include <asm/arch/pxa-regs.h> -+#include <asm/arch/tosa.h> -+ -+static void tosaled_amber_set(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ if (value) -+ set_scoop_gpio(&tosascoop_jc_device.dev, -+ TOSA_SCOOP_JC_CHRG_ERR_LED); -+ else -+ reset_scoop_gpio(&tosascoop_jc_device.dev, -+ TOSA_SCOOP_JC_CHRG_ERR_LED); -+} -+ -+static void tosaled_green_set(struct led_classdev *led_cdev, -+ enum led_brightness value) -+{ -+ if (value) -+ set_scoop_gpio(&tosascoop_jc_device.dev, -+ TOSA_SCOOP_JC_NOTE_LED); -+ else -+ reset_scoop_gpio(&tosascoop_jc_device.dev, -+ TOSA_SCOOP_JC_NOTE_LED); -+} -+ -+static struct led_classdev tosa_amber_led = { -+ .name = "tosa:amber", -+ .default_trigger = "sharpsl-charge", -+ .brightness_set = tosaled_amber_set, -+}; -+ -+static struct led_classdev tosa_green_led = { -+ .name = "tosa:green", -+ .default_trigger = "nand-disk", -+ .brightness_set = tosaled_green_set, -+}; -+ -+#ifdef CONFIG_PM -+static int tosaled_suspend(struct platform_device *dev, pm_message_t state) -+{ -+#ifdef CONFIG_LEDS_TRIGGERS -+ if (tosa_amber_led.trigger && strcmp(tosa_amber_led.trigger->name, -+ "sharpsl-charge")) -+#endif -+ led_classdev_suspend(&tosa_amber_led); -+ led_classdev_suspend(&tosa_green_led); -+ return 0; -+} -+ -+static int tosaled_resume(struct platform_device *dev) -+{ -+ led_classdev_resume(&tosa_amber_led); -+ led_classdev_resume(&tosa_green_led); -+ return 0; -+} -+#else -+#define tosaled_suspend NULL -+#define tosaled_resume NULL -+#endif -+ -+static int tosaled_probe(struct platform_device *pdev) -+{ -+ int ret; -+ -+ ret = led_classdev_register(&pdev->dev, &tosa_amber_led); -+ if (ret < 0) -+ return ret; -+ -+ ret = led_classdev_register(&pdev->dev, &tosa_green_led); -+ if (ret < 0) -+ led_classdev_unregister(&tosa_amber_led); -+ -+ return ret; -+} -+ -+static int tosaled_remove(struct platform_device *pdev) -+{ -+ led_classdev_unregister(&tosa_amber_led); -+ led_classdev_unregister(&tosa_green_led); -+ -+ return 0; -+} -+ -+static struct platform_driver tosaled_driver = { -+ .probe = tosaled_probe, -+ .remove = tosaled_remove, -+ .suspend = tosaled_suspend, -+ .resume = tosaled_resume, -+ .driver = { -+ .name = "tosa-led", -+ }, -+}; -+ -+static int __init tosaled_init(void) -+{ -+ return platform_driver_register(&tosaled_driver); -+} -+ -+static void __exit tosaled_exit(void) -+{ -+ platform_driver_unregister(&tosaled_driver); -+} -+ -+module_init(tosaled_init); -+module_exit(tosaled_exit); -+ -+MODULE_AUTHOR("Dirk Opfer <Dirk@Opfer-Online.de>"); -+MODULE_DESCRIPTION("Tosa LED driver"); -+MODULE_LICENSE("GPL"); ---- linux-ixp4xx.orig/drivers/ide/ide-disk.c 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/drivers/ide/ide-disk.c 2006-03-07 22:59:04.000000000 +0100 -@@ -60,6 +60,7 @@ - #include <linux/genhd.h> - #include <linux/slab.h> - #include <linux/delay.h> -+#include <linux/leds.h> - - #define _IDE_DISK - -@@ -80,6 +81,8 @@ struct ide_disk_obj { - - static DECLARE_MUTEX(idedisk_ref_sem); - -+DEFINE_LED_TRIGGER(ide_led_trigger); -+ - #define to_ide_disk(obj) container_of(obj, struct ide_disk_obj, kref) - - #define ide_disk_g(disk) \ -@@ -298,6 +301,13 @@ static ide_startstop_t __ide_do_rw_disk( - } - } - -+static int ide_end_rw_disk(ide_drive_t *drive, int uptodate, int nr_sectors) -+{ -+ if (blk_fs_request(HWGROUP(drive)->rq)) -+ led_trigger_event(ide_led_trigger, LED_OFF); -+ return ide_end_request(drive, uptodate, nr_sectors); -+} -+ - /* - * 268435455 == 137439 MB or 28bit limit - * 320173056 == 163929 MB or 48bit addressing -@@ -312,10 +322,12 @@ static ide_startstop_t ide_do_rw_disk (i - - if (!blk_fs_request(rq)) { - blk_dump_rq_flags(rq, "ide_do_rw_disk - bad command"); -- ide_end_request(drive, 0, 0); -+ ide_end_rw_disk(drive, 0, 0); - return ide_stopped; - } - -+ led_trigger_event(ide_led_trigger, LED_FULL); -+ - pr_debug("%s: %sing: block=%llu, sectors=%lu, buffer=0x%08lx\n", - drive->name, rq_data_dir(rq) == READ ? "read" : "writ", - (unsigned long long)block, rq->nr_sectors, -@@ -1063,7 +1075,7 @@ static ide_driver_t idedisk_driver = { - .media = ide_disk, - .supports_dsc_overlap = 0, - .do_request = ide_do_rw_disk, -- .end_request = ide_end_request, -+ .end_request = ide_end_rw_disk, - .error = __ide_error, - .abort = __ide_abort, - .proc = idedisk_proc, -@@ -1236,12 +1248,16 @@ failed: - - static void __exit idedisk_exit (void) - { -+ led_trigger_unregister_simple(ide_led_trigger); - driver_unregister(&idedisk_driver.gen_driver); - } - - static int __init idedisk_init(void) - { -- return driver_register(&idedisk_driver.gen_driver); -+ int ret = driver_register(&idedisk_driver.gen_driver); -+ if (ret >= 0) -+ led_trigger_register_simple("ide-disk", &ide_led_trigger); -+ return ret; - } - - MODULE_ALIAS("ide:*m-disk*"); ---- linux-ixp4xx.orig/drivers/mtd/nand/nand_base.c 2006-03-07 22:57:47.000000000 +0100 -+++ linux-ixp4xx/drivers/mtd/nand/nand_base.c 2006-03-07 22:59:04.000000000 +0100 -@@ -80,6 +80,7 @@ - #include <linux/mtd/compatmac.h> - #include <linux/interrupt.h> - #include <linux/bitops.h> -+#include <linux/leds.h> - #include <asm/io.h> - - #ifdef CONFIG_MTD_PARTITIONS -@@ -515,6 +516,8 @@ static int nand_block_checkbad (struct m - return nand_isbad_bbt (mtd, ofs, allowbbt); - } - -+DEFINE_LED_TRIGGER(nand_led_trigger); -+ - /* - * Wait for the ready pin, after a command - * The timeout is catched later. -@@ -524,12 +527,14 @@ static void nand_wait_ready(struct mtd_i - struct nand_chip *this = mtd->priv; - unsigned long timeo = jiffies + 2; - -+ led_trigger_event(nand_led_trigger, LED_FULL); - /* wait until command is processed or timeout occures */ - do { - if (this->dev_ready(mtd)) -- return; -+ break; - touch_softlockup_watchdog(); - } while (time_before(jiffies, timeo)); -+ led_trigger_event(nand_led_trigger, LED_OFF); - } - - /** -@@ -817,6 +822,8 @@ static int nand_wait(struct mtd_info *mt - else - timeo += (HZ * 20) / 1000; - -+ led_trigger_event(nand_led_trigger, LED_FULL); -+ - /* Apply this short delay always to ensure that we do wait tWB in - * any case on any machine. */ - ndelay (100); -@@ -840,6 +847,8 @@ static int nand_wait(struct mtd_info *mt - } - cond_resched(); - } -+ led_trigger_event(nand_led_trigger, LED_OFF); -+ - status = (int) this->read_byte(mtd); - return status; - } -@@ -2724,6 +2733,21 @@ void nand_release (struct mtd_info *mtd) - EXPORT_SYMBOL_GPL (nand_scan); - EXPORT_SYMBOL_GPL (nand_release); - -+ -+static int __init nand_base_init(void) -+{ -+ led_trigger_register_simple("nand-disk", &nand_led_trigger); -+ return 0; -+} -+ -+static void __exit nand_base_exit(void) -+{ -+ led_trigger_unregister_simple(nand_led_trigger); -+} -+ -+module_init(nand_base_init); -+module_exit(nand_base_exit); -+ - MODULE_LICENSE ("GPL"); - MODULE_AUTHOR ("Steven J. Hill <sjhill@realitydiluted.com>, Thomas Gleixner <tglx@linutronix.de>"); - MODULE_DESCRIPTION ("Generic NAND flash driver code"); |