diff -up ./drivers/input/keyboard/locomokbd.c.org ./drivers/input/keyboard/locomokbd.c
--- ./drivers/input/keyboard/locomokbd.c.org	2008-05-21 00:04:41.000000000 +0200
+++ ./drivers/input/keyboard/locomokbd.c	2008-05-21 00:07:43.000000000 +0200
@@ -1,14 +1,12 @@
 /*
- *  Copyright (c) 2005 John Lenz
+ * LoCoMo keyboard driver for Linux-based ARM PDAs:
+ * 	- SHARP Zaurus Collie (SL-5500)
+ * 	- SHARP Zaurus Poodle (SL-5600)
  *
+ * Copyright (c) 2005 John Lenz
  * Based on from xtkbd.c
- */
-
-/*
- * LoCoMo keyboard driver for Linux/ARM
- */
-
-/*
+ *
+ *
  * 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
@@ -43,46 +41,53 @@ MODULE_LICENSE("GPL");
 
 #define LOCOMOKBD_NUMKEYS	128
 
-#define KEY_ACTIVITY		KEY_F16
-#define KEY_CONTACT		KEY_F18
-#define KEY_CENTER		KEY_F15
-
-static unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
-	0, KEY_ESC, KEY_ACTIVITY, 0, 0, 0, 0, 0, 0, 0,				/* 0 - 9 */
-	0, 0, 0, 0, 0, 0, 0, KEY_MENU, KEY_HOME, KEY_CONTACT,			/* 10 - 19 */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, 0,						/* 20 - 29 */
-	0, 0, 0, KEY_CENTER, 0, KEY_MAIL, 0, 0, 0, 0,				/* 30 - 39 */
-	0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_RIGHT,					/* 40 - 49 */
-	KEY_UP, KEY_LEFT, 0, 0, KEY_P, 0, KEY_O, KEY_I, KEY_Y, KEY_T,		/* 50 - 59 */
-	KEY_E, KEY_W, 0, 0, 0, 0, KEY_DOWN, KEY_ENTER, 0, 0,			/* 60 - 69 */
-	KEY_BACKSPACE, 0, KEY_L, KEY_U, KEY_H, KEY_R, KEY_D, KEY_Q, 0, 0,	/* 70 - 79 */
-	0, 0, 0, 0, 0, 0, KEY_ENTER, KEY_RIGHTSHIFT, KEY_K, KEY_J,		/* 80 - 89 */
-	KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0,				/* 90 - 99 */
-	0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A,		/* 100 - 109 */
-	KEY_LEFTSHIFT, KEY_TAB, KEY_LEFTCTRL, 0, 0, 0, 0, 0, 0, 0,		/* 110 - 119 */
-	KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0		/* 120 - 128 */
+
+#define LOCOMO_KEY_CALENDER	KEY_LEFTCTRL
+#define LOCOMO_KEY_ADDRESS	KEY_LEFTALT	/* Needed for SysRQ */
+#define LOCOMO_KEY_HOME		KEY_SYSRQ	/* Needed for SysRQ */
+#define LOCOMO_KEY_MENU		KEY_F12
+#define LOCOMO_KEY_MAIL		KEY_F10
+#define LOCOMO_KEY_OK		KEY_F11		/* Don't hardwire to KEY_RETURN */
+#define LOCOMO_KEY_CANCEL	KEY_POWER
+#define LOCOMO_KEY_CENTER	KEY_F5		/* Don't hardwire to KEY_RETURN */
+
+#define LOCOMO_KEY_FN		KEY_F9
+
+static const unsigned char locomokbd_keycode[LOCOMOKBD_NUMKEYS] = {
+	0, LOCOMO_KEY_CANCEL, LOCOMO_KEY_CALENDER, LOCOMO_KEY_HOME, 0, 0, 0, 0, 0, 0,	/* 0 - 9 */
+	0, 0, 0, 0, 0, 0, 0, LOCOMO_KEY_MENU, 0, LOCOMO_KEY_ADDRESS,			/* 10 - 19 */
+	0, 0, 0, 0, 0, LOCOMO_KEY_MAIL, 0, 0, 0, 0,					/* 20 - 29 */
+	0, 0, 0, LOCOMO_KEY_CENTER, 0, LOCOMO_KEY_MAIL, 0, 0, 0, 0,			/* 30 - 39 */
+	0, 0, 0, 0, 0, 0, 0, 0, 0, KEY_RIGHT,						/* 40 - 49 */
+	KEY_UP, KEY_LEFT, 0, 0, KEY_P, 0, KEY_O, KEY_I, KEY_Y, KEY_T,			/* 50 - 59 */
+	KEY_E, KEY_W, 0, 0, 0, 0, KEY_DOWN, LOCOMO_KEY_OK, 0, 0,			/* 60 - 69 */
+	KEY_BACKSPACE, 0, KEY_L, KEY_U, KEY_H, KEY_R, KEY_D, KEY_Q, 0, 0,		/* 70 - 79 */
+	0, 0, 0, 0, 0, 0, KEY_ENTER, KEY_RIGHTSHIFT, KEY_K, KEY_J,			/* 80 - 89 */
+	KEY_G, KEY_F, KEY_X, KEY_S, 0, 0, 0, 0, 0, 0,					/* 90 - 99 */
+	0, 0, KEY_DOT, 0, KEY_COMMA, KEY_N, KEY_B, KEY_C, KEY_Z, KEY_A,			/* 100 - 109 */
+	KEY_LEFTSHIFT, KEY_TAB, LOCOMO_KEY_FN, 0, 0, 0, 0, 0, 0, 0,			/* 110 - 119 */
+	KEY_M, KEY_SPACE, KEY_V, KEY_APOSTROPHE, KEY_SLASH, 0, 0, 0			/* 120 - 128 */
 };
 
 #define KB_ROWS			16
 #define KB_COLS			8
 #define KB_ROWMASK(r)		(1 << (r))
 #define SCANCODE(c,r)		( ((c)<<4) + (r) + 1 )
-#define	NR_SCANCODES		128
 
 #define KB_DELAY		8
 #define SCAN_INTERVAL		(HZ/10)
-#define LOCOMOKBD_PRESSED	1
 
 struct locomokbd {
 	unsigned char keycode[LOCOMOKBD_NUMKEYS];
 	struct input_dev *input;
 	char phys[32];
 
-	struct locomo_dev *ldev;
 	unsigned long base;
 	spinlock_t lock;
 
 	struct timer_list timer;
+	unsigned long suspend_jiffies;
+	unsigned int count_cancel;
 };
 
 /* helper functions for reading the keyboard matrix */
@@ -128,7 +133,7 @@ static inline void locomokbd_reset_col(u
 /* Scan the hardware keyboard and push any changes up through the input layer */
 static void locomokbd_scankeyboard(struct locomokbd *locomokbd)
 {
-	unsigned int row, col, rowd, scancode;
+	unsigned int row, col, rowd;
 	unsigned long flags;
 	unsigned int num_pressed;
 	unsigned long membase = locomokbd->base;
@@ -145,13 +150,33 @@ static void locomokbd_scankeyboard(struc
 
 		rowd = ~locomo_readl(membase + LOCOMO_KIB);
 		for (row = 0; row < KB_ROWS; row++) {
+			unsigned int scancode, pressed, key;
+
 			scancode = SCANCODE(col, row);
-			if (rowd & KB_ROWMASK(row)) {
-				num_pressed += 1;
-				input_report_key(locomokbd->input, locomokbd->keycode[scancode], 1);
-			} else {
-				input_report_key(locomokbd->input, locomokbd->keycode[scancode], 0);
-			}
+			pressed = rowd & KB_ROWMASK(row);
+			key = locomokbd->keycode[scancode];
+
+			input_report_key(locomokbd->input, key, pressed);
+			if (likely(!pressed))
+				continue;
+
+			num_pressed++;
+
+			/* The "Cancel/ESC" key is labeled "On/Off" on
+			 * Collie and Poodle and should suspend the device
+			 * if it was pressed for more than a second. */
+			if (unlikely(key == LOCOMO_KEY_CANCEL)) {
+				if (!time_after(jiffies,
+					locomokbd->suspend_jiffies + HZ))
+					continue;
+				if (locomokbd->count_cancel++
+					!= (HZ/SCAN_INTERVAL + 1))
+					continue;
+				input_event(locomokbd->input, EV_PWR,
+					KEY_SUSPEND, 1);
+				locomokbd->suspend_jiffies = jiffies;
+			} else
+				locomokbd->count_cancel = 0;
 		}
 		locomokbd_reset_col(membase, col);
 	}
@@ -162,6 +187,8 @@ static void locomokbd_scankeyboard(struc
 	/* if any keys are pressed, enable the timer */
 	if (num_pressed)
 		mod_timer(&locomokbd->timer, jiffies + SCAN_INTERVAL);
+	else
+		locomokbd->count_cancel = 0;
 
 	spin_unlock_irqrestore(&locomokbd->lock, flags);
 }
@@ -186,10 +213,11 @@ static irqreturn_t locomokbd_interrupt(i
 static void locomokbd_timer_callback(unsigned long data)
 {
 	struct locomokbd *locomokbd = (struct locomokbd *) data;
+
 	locomokbd_scankeyboard(locomokbd);
 }
 
-static int locomokbd_probe(struct locomo_dev *dev)
+static int __devinit locomokbd_probe(struct locomo_dev *dev)
 {
 	struct locomokbd *locomokbd;
 	struct input_dev *input_dev;
@@ -211,7 +239,6 @@ static int locomokbd_probe(struct locomo
 		goto err_free_mem;
 	}
 
-	locomokbd->ldev = dev;
 	locomo_set_drvdata(dev, locomokbd);
 
 	locomokbd->base = (unsigned long) dev->mapbase;
@@ -222,6 +249,8 @@ static int locomokbd_probe(struct locomo
 	locomokbd->timer.function = locomokbd_timer_callback;
 	locomokbd->timer.data = (unsigned long) locomokbd;
 
+	locomokbd->suspend_jiffies = jiffies;
+
 	locomokbd->input = input_dev;
 	strcpy(locomokbd->phys, "locomokbd/input0");
 
@@ -233,9 +262,10 @@ static int locomokbd_probe(struct locomo
 	input_dev->id.version = 0x0100;
 	input_dev->dev.parent = &dev->dev;
 
-	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP);
+	input_dev->evbit[0] = BIT_MASK(EV_KEY) | BIT_MASK(EV_REP) |
+				BIT_MASK(EV_PWR);
 	input_dev->keycode = locomokbd->keycode;
-	input_dev->keycodesize = sizeof(unsigned char);
+	input_dev->keycodesize = sizeof(locomokbd_keycode[0]);
 	input_dev->keycodemax = ARRAY_SIZE(locomokbd_keycode);
 
 	memcpy(locomokbd->keycode, locomokbd_keycode, sizeof(locomokbd->keycode));
@@ -268,7 +298,7 @@ static int locomokbd_probe(struct locomo
 	return err;
 }
 
-static int locomokbd_remove(struct locomo_dev *dev)
+static int __devexit locomokbd_remove(struct locomo_dev *dev)
 {
 	struct locomokbd *locomokbd = locomo_get_drvdata(dev);
 
@@ -292,7 +322,7 @@ static struct locomo_driver keyboard_dri
 	},
 	.devid	= LOCOMO_DEVID_KEYBOARD,
 	.probe	= locomokbd_probe,
-	.remove	= locomokbd_remove,
+	.remove	= __devexit_p(locomokbd_remove),
 };
 
 static int __init locomokbd_init(void)
