---
 arch/arm/mach-ixp4xx/Makefile    |    2 
 arch/arm/mach-ixp4xx/fsg-power.c |  168 +++++++++++++++++++++++++++++++++++++++
 2 files changed, 169 insertions(+), 1 deletion(-)

Index: linux-2.6.21.6-armeb/arch/arm/mach-ixp4xx/fsg-power.c
===================================================================
--- /dev/null
+++ linux-2.6.21.6-armeb/arch/arm/mach-ixp4xx/fsg-power.c
@@ -0,0 +1,168 @@
+/*
+ * arch/arm/mach-ixp4xx/fsg-power.c
+ *
+ * FSG buttons driver
+ *
+ * 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/module.h>
+#include <linux/reboot.h>
+#include <linux/irq.h>
+#include <linux/interrupt.h>
+#include <asm/mach-types.h>
+#include <linux/kernel.h>
+
+struct event_t {
+	struct work_struct wq;
+	char *button_name;
+	int action;
+};
+
+static void hotplug_button(struct event_t *event)
+{
+	static char buf[128];
+	char *argv[3], *envp[6], *action;
+	int i;
+
+        i = 0;
+        argv[i++] = "/sbin/hotplug";
+        argv[i++] = "button";
+        argv[i] = 0;
+
+	i = 0;
+	/* minimal command environment */
+	envp [i++] = "HOME=/";
+	envp [i++] = "PATH=/sbin:/bin:/usr/sbin:/usr/bin";
+	envp [i++] = "SUBSYSTEM=button";
+
+	snprintf(buf, 128, "BUTTON=%s", event->button_name);
+	envp [i++] = buf;
+
+	action = event->action ? "released" : "pressed";
+	snprintf(buf, 128, "ACTION=%s", action);
+	envp [i++] = buf;
+
+	envp [i] = 0;
+
+	// create hotplug event
+	call_usermodehelper (argv[0], argv, envp, 0);
+
+	//destroy event structure
+	kfree(event);
+}
+
+static irqreturn_t fsg_sync_button_handler(int irq, void *dev_id)
+{
+	int holdkey;
+	struct event_t *event;
+
+	//check button status
+	gpio_line_get(FSG_SB_GPIO, &holdkey);
+
+	//create event
+	if ((event = (struct event_t *)kzalloc (sizeof(struct event_t), GFP_ATOMIC))) {
+		event->action = holdkey;
+		event->button_name = "sync";
+
+		INIT_WORK(&event->wq, (void *)(void *)hotplug_button);
+		schedule_work(&event->wq);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t fsg_reset_button_handler(int irq, void *dev_id)
+{
+	int holdkey;
+	struct event_t *event;
+
+	//check button status
+	gpio_line_get(FSG_RB_GPIO, &holdkey);
+
+	//create event
+	if ((event = (struct event_t *)kzalloc (sizeof(struct event_t), GFP_ATOMIC))) {
+		event->action = holdkey;
+		event->button_name = "reset";
+
+		INIT_WORK(&event->wq, (void *)(void *)hotplug_button);
+		schedule_work(&event->wq);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static irqreturn_t fsg_unplug_button_handler(int irq, void *dev_id)
+{
+	int holdkey;
+	struct event_t *event;
+
+	//check button status
+	gpio_line_get(FSG_UB_GPIO, &holdkey);
+
+	//create event
+	if ((event = (struct event_t *)kzalloc (sizeof(struct event_t), GFP_ATOMIC))) {
+		event->action = holdkey;
+		event->button_name = "unplug";
+
+		INIT_WORK(&event->wq, (void *)(void *)hotplug_button);
+		schedule_work(&event->wq);
+	}
+
+	return IRQ_HANDLED;
+}
+
+static int __init fsg_buttons_init(void)
+{
+	if (!(machine_is_fsg()))
+		return 0;
+
+	/* Configure interrupt input for SYNC button */
+	set_irq_type(FSG_SB_IRQ, IRQT_BOTHEDGE);
+	if (request_irq(FSG_SB_IRQ, &fsg_sync_button_handler, IRQF_DISABLED, "SYNC", NULL) < 0) {
+		printk(KERN_DEBUG "SYNC button IRQ %d not available\n", FSG_SB_IRQ);
+		return -EIO;
+	}
+	else
+		printk("SYNC button registered on IRQ%d\n", FSG_SB_IRQ);
+
+	/* Configure interrupt input for RESET button */
+	set_irq_type(FSG_RB_IRQ, IRQT_BOTHEDGE);
+	if (request_irq(FSG_RB_IRQ, &fsg_reset_button_handler, IRQF_DISABLED, "RESET", NULL) < 0) {
+		printk(KERN_DEBUG "RESET button IRQ %d not available\n", FSG_RB_IRQ);
+		return -EIO;
+	}
+	else
+		printk("RESET button registered on IRQ%d\n", FSG_RB_IRQ);
+
+	/* Configure interrupt input for UNPLUG button */
+	set_irq_type(FSG_UB_IRQ, IRQT_BOTHEDGE);
+	if (request_irq(FSG_UB_IRQ, &fsg_unplug_button_handler, IRQF_DISABLED, "RESET", NULL) < 0) {
+		printk(KERN_DEBUG "UNPLUG button IRQ %d not available\n", FSG_UB_IRQ);
+		return -EIO;
+	}
+	else
+		printk("UNPLUG button registered on IRQ%d\n", FSG_UB_IRQ);
+
+	return 0;
+}
+
+static void __exit fsg_buttons_exit(void)
+{
+	if (!(machine_is_fsg()))
+		return;
+
+	free_irq(FSG_SB_IRQ, NULL);
+	free_irq(FSG_RB_IRQ, NULL);
+	free_irq(FSG_UB_IRQ, NULL);
+}
+
+module_init(fsg_buttons_init);
+module_exit(fsg_buttons_exit);
+
+MODULE_AUTHOR("Zintis Petersons <Zintis.Petersons@e-mail.lv>");
+MODULE_DESCRIPTION("FSG buttons driver");
+MODULE_LICENSE("GPL");
Index: linux-2.6.21.6-armeb/arch/arm/mach-ixp4xx/Makefile
===================================================================
--- linux-2.6.21.6-armeb.orig/arch/arm/mach-ixp4xx/Makefile
+++ linux-2.6.21.6-armeb/arch/arm/mach-ixp4xx/Makefile
@@ -30,7 +30,7 @@
 obj-$(CONFIG_MACH_NSLU2)	+= nslu2-setup.o nslu2-power.o
 obj-$(CONFIG_MACH_NAS100D)	+= nas100d-setup.o nas100d-power.o
 obj-$(CONFIG_MACH_DSMG600)      += dsmg600-setup.o dsmg600-power.o
-obj-$(CONFIG_MACH_FSG)          += fsg-setup.o
+obj-$(CONFIG_MACH_FSG)          += fsg-setup.o fsg-power.o
 obj-$(CONFIG_MACH_GATEWAY7001)	+= gateway7001-setup.o
 obj-$(CONFIG_MACH_WG302V2)	+= wg302v2-setup.o
 obj-$(CONFIG_MACH_PRONGHORNMETRO)	+= pronghornmetro-setup.o
