
#
# Patch managed by http://www.holgerschurig.de/patcher.html
#

--- /dev/null
+++ linux/arch/arm/mach-sa1100/collie_batswitch.c
@@ -0,0 +1,149 @@
+/*
+ * drivers/misc/collie_batswitch.c
+ *
+ * Handling for the Collie battery switch
+ *
+ * 1) immediately suspend if switch isnt flipped during initial boot
+ * 2) abort resume and resuspend if bat switch isnt flipped when unit
+ *    awakens.
+ * 3) register an interrupt handler so that flipping the switch results
+ *    in the user expected "soft reset"
+ *
+ * Copyright (C) 2003 Chris Larson <kergoth@handhelds.org>
+ *
+ * Updated Mar 27, 2004 by John Lenz <lenz@cs.wisc.edu> to work
+ * with 2.6
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/kernel.h>
+#include <linux/init.h>
+#include <linux/pm.h>
+#include <linux/delay.h>
+#include <linux/reboot.h>
+#include <linux/sched.h>
+#include <linux/interrupt.h>
+
+#include <asm/irq.h>
+#include <asm/hardware.h>
+#include <asm/arch/collie.h>
+
+static inline int batswitch_status(void)
+{
+	return GPLR & COLLIE_GPIO_MAIN_BAT_LOW;
+}
+
+#ifdef CONFIG_PM
+/* item #2 from comments */
+static int batswitch_pm_callback(struct pm_dev* pm_dev, pm_request_t req, void *data)
+{
+	switch (req) {
+	case PM_SUSPEND:
+		disable_irq(COLLIE_IRQ_GPIO_MAIN_BAT_LOW);
+		break;
+	case PM_RESUME:
+		if (batswitch_status() == 0) {
+			printk("return to suspend\n");
+			return 1;
+		}
+		enable_irq(COLLIE_IRQ_GPIO_MAIN_BAT_LOW);
+		break;
+	}
+	return 0;
+}
+#endif
+
+/* item #3 from comments */
+extern asmlinkage long sys_reboot(int magic1, int magic2, unsigned int cmd, void * arg);
+
+static void batswitch_routine(unsigned long arg)
+{
+	mdelay(10);
+	if (batswitch_status()) {
+		printk("cancel emergency off\n");
+		return;
+	}
+
+	pm_send_all(PM_SUSPEND, (void *)3);
+	pm_suspend(PM_SUSPEND_MEM);
+	sys_reboot(LINUX_REBOOT_MAGIC1, LINUX_REBOOT_MAGIC2, LINUX_REBOOT_CMD_RESTART, NULL);
+}
+
+DECLARE_TASKLET(batswitch_tasklet, batswitch_routine, 0);
+
+static irqreturn_t batswitch_interrupt(int irq, void *dev_id, struct pt_regs *regs)
+{
+	if (batswitch_status() == 0)
+		tasklet_schedule(&batswitch_tasklet);
+
+	return IRQ_HANDLED;
+}
+
+extern int sa11x0_pm_enter(u32 state);
+
+#if 0
+int batswitch_suspend(void)
+{
+	int retval;
+
+	retval = pm_send_all(PM_SUSPEND, (void *)3);
+
+	if (retval == 0) {
+		int resumeval = 1;
+		while ((retval == 0) && (resumeval != 0)) {
+			retval = sa11x0_pm_enter(PM_SUSPEND_MEM);
+			resumeval = pm_send_all(PM_RESUME, (void *)0);
+		}
+	}
+
+	return retval;
+}
+#endif
+
+static int __init batswitch_checkswitch(void)
+{
+	/* suspend if we were reset */
+	/*if (RCSR == 0x01)
+		pm_suspend(PM_SUSPEND_MEM);*/
+
+	/* item #1 from comments */
+	if (batswitch_status() == 0) {
+		/*pm_suspend(PM_SUSPEND_MEM);*/
+		sa11x0_pm_enter(PM_SUSPEND_MEM);
+	}
+
+	return 0;
+}
+
+static int __init batswitch_registerirq(void)
+{
+
+#ifdef CONFIG_PM
+	pm_register(PM_SYS_DEV, 0, batswitch_pm_callback);
+#endif
+
+	/* set COLLIE_IRQ_GPIO_MAIN_BAT_LOW to be an edge triggered interrupt */
+
+	if (request_irq(COLLIE_IRQ_GPIO_MAIN_BAT_LOW, 
+			batswitch_interrupt, 
+			SA_INTERRUPT, 
+			"batswitch", 
+			&batswitch_tasklet)) {
+		printk(KERN_INFO "Battery switch install error: Could not register irq handler.\n");
+	}
+
+	return 0;
+}
+
+//arch_initcall(batswitch_checkswitch);
+device_initcall(batswitch_registerirq);
--- linux/arch/arm/mach-sa1100/Makefile~collie_batswitch
+++ linux/arch/arm/mach-sa1100/Makefile
@@ -24,6 +24,7 @@
 led-$(CONFIG_SA1100_CERF)		+= leds-cerf.o
 
 obj-$(CONFIG_SA1100_COLLIE)		+= collie.o
+obj-$(CONFIG_SA1100_COLLIE)		+= collie_batswitch.o
 
 obj-$(CONFIG_SA1100_H3600)		+= h3600.o
 

