[Strange. I _did_ check these in before. Seems SF restored an old
version of the repository???]

* Patch by Reinhard Meyer, 09 Jan 2004:
  - add RTC support for MPC5200 based boards (requires RTC_XTAL)

* Add support for IDE LED on BMS2003 board
  (exclusive with status LED!)

* Add support for PS/2 keyboard (used with PS/2 multiplexor on
  BMS2003 board)

* Patches by Reinhard Meyer, 4 Jan 2004 + 7 Jan 2004:
  Add common files for "emk" boards
diff --git a/drivers/pc_keyb.c b/drivers/pc_keyb.c
new file mode 100644
index 0000000..07c7914
--- /dev/null
+++ b/drivers/pc_keyb.c
@@ -0,0 +1,256 @@
+/***********************************************************************
+ *
+ * (C) Copyright 2004
+ * DENX Software Engineering
+ * Wolfgang Denk, wd@denx.de
+ * All rights reserved.
+ *
+ * PS/2 keyboard driver
+ *
+ * Originally from linux source (drivers/char/pc_keyb.c)
+ *
+ ***********************************************************************/
+
+#include <common.h>
+
+#ifdef CONFIG_PS2KBD
+
+#include <keyboard.h>
+#include <pc_keyb.h>
+
+#undef KBG_DEBUG
+
+#ifdef KBG_DEBUG
+#define	PRINTF(fmt,args...)	printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+
+/*
+ * This reads the keyboard status port, and does the
+ * appropriate action.
+ *
+ */
+static unsigned char handle_kbd_event(void)
+{
+	unsigned char status = kbd_read_status();
+	unsigned int work = 10000;
+
+	while ((--work > 0) && (status & KBD_STAT_OBF)) {
+		unsigned char scancode;
+
+		scancode = kbd_read_input();
+
+		/* Error bytes must be ignored to make the
+		   Synaptics touchpads compaq use work */
+		/* Ignore error bytes */
+		if (!(status & (KBD_STAT_GTO | KBD_STAT_PERR))) {
+			if (status & KBD_STAT_MOUSE_OBF)
+				; /* not supported: handle_mouse_event(scancode); */
+			else
+				handle_scancode(scancode);
+		}
+		status = kbd_read_status();
+	}
+	if (!work)
+		PRINTF("pc_keyb: controller jammed (0x%02X).\n", status);
+	return status;
+}
+
+
+static int kbd_read_data(void)
+{
+	int val;
+	unsigned char status;
+
+	val=-1;
+	status = kbd_read_status();
+	if (status & KBD_STAT_OBF) {
+		val = kbd_read_input();
+		if (status & (KBD_STAT_GTO | KBD_STAT_PERR))
+			val = -2;
+	}
+	return val;
+}
+
+static int kbd_wait_for_input(void)
+{
+	unsigned long timeout;
+	int val;
+
+	timeout = KBD_TIMEOUT;
+	val=kbd_read_data();
+	while(val < 0) {
+		if(timeout--==0)
+			return -1;
+		udelay(1000);
+		val=kbd_read_data();
+	}
+	return val;
+}
+
+
+static int kb_wait(void)
+{
+	unsigned long timeout = KBC_TIMEOUT * 10;
+
+	do {
+		unsigned char status = handle_kbd_event();
+		if (!(status & KBD_STAT_IBF))
+			return 0; /* ok */
+		udelay(1000);
+		timeout--;
+	} while (timeout);
+	return 1;
+}
+
+static void kbd_write_command_w(int data)
+{
+	if(kb_wait())
+		PRINTF("timeout in kbd_write_command_w\n");
+	kbd_write_command(data);
+}
+
+static void kbd_write_output_w(int data)
+{
+	if(kb_wait())
+		PRINTF("timeout in kbd_write_output_w\n");
+	kbd_write_output(data);
+}
+
+static void kbd_send_data(unsigned char data)
+{
+	kbd_write_output_w(data);
+	kbd_wait_for_input();
+}
+
+
+static char * kbd_initialize(void)
+{
+	int status;
+
+	/*
+	 * Test the keyboard interface.
+	 * This seems to be the only way to get it going.
+	 * If the test is successful a x55 is placed in the input buffer.
+	 */
+	kbd_write_command_w(KBD_CCMD_SELF_TEST);
+	if (kbd_wait_for_input() != 0x55)
+		return "Kbd:   failed self test";
+	/*
+	 * Perform a keyboard interface test.  This causes the controller
+	 * to test the keyboard clock and data lines.  The results of the
+	 * test are placed in the input buffer.
+	 */
+	kbd_write_command_w(KBD_CCMD_KBD_TEST);
+	if (kbd_wait_for_input() != 0x00)
+		return "Kbd:   interface failed self test";
+	/*
+	 * Enable the keyboard by allowing the keyboard clock to run.
+	 */
+	kbd_write_command_w(KBD_CCMD_KBD_ENABLE);
+
+	/*
+	 * Reset keyboard. If the read times out
+	 * then the assumption is that no keyboard is
+	 * plugged into the machine.
+	 * This defaults the keyboard to scan-code set 2.
+	 *
+	 * Set up to try again if the keyboard asks for RESEND.
+	 */
+	do {
+		kbd_write_output_w(KBD_CMD_RESET);
+		status = kbd_wait_for_input();
+		if (status == KBD_REPLY_ACK)
+			break;
+		if (status != KBD_REPLY_RESEND) {
+			PRINTF("status: %X\n",status);
+			return "Kbd:   reset failed, no ACK";
+		}
+	} while (1);
+	if (kbd_wait_for_input() != KBD_REPLY_POR)
+		return "Kbd:   reset failed, no POR";
+
+	/*
+	 * Set keyboard controller mode. During this, the keyboard should be
+	 * in the disabled state.
+	 *
+	 * Set up to try again if the keyboard asks for RESEND.
+	 */
+	do {
+		kbd_write_output_w(KBD_CMD_DISABLE);
+		status = kbd_wait_for_input();
+		if (status == KBD_REPLY_ACK)
+			break;
+		if (status != KBD_REPLY_RESEND)
+			return "Kbd:   disable keyboard: no ACK";
+	} while (1);
+
+	kbd_write_command_w(KBD_CCMD_WRITE_MODE);
+	kbd_write_output_w(KBD_MODE_KBD_INT
+			      | KBD_MODE_SYS
+			      | KBD_MODE_DISABLE_MOUSE
+			      | KBD_MODE_KCC);
+
+	/* ibm powerpc portables need this to use scan-code set 1 -- Cort */
+	kbd_write_command_w(KBD_CCMD_READ_MODE);
+	if (!(kbd_wait_for_input() & KBD_MODE_KCC)) {
+		/*
+		 * If the controller does not support conversion,
+		 * Set the keyboard to scan-code set 1.
+		 */
+		kbd_write_output_w(0xF0);
+		kbd_wait_for_input();
+		kbd_write_output_w(0x01);
+		kbd_wait_for_input();
+	}
+	kbd_write_output_w(KBD_CMD_ENABLE);
+	if (kbd_wait_for_input() != KBD_REPLY_ACK)
+		return "Kbd:   enable keyboard: no ACK";
+
+	/*
+	 * Finally, set the typematic rate to maximum.
+	 */
+	kbd_write_output_w(KBD_CMD_SET_RATE);
+	if (kbd_wait_for_input() != KBD_REPLY_ACK)
+		return "Kbd:   Set rate: no ACK";
+	kbd_write_output_w(0x00);
+	if (kbd_wait_for_input() != KBD_REPLY_ACK)
+		return "Kbd:   Set rate: no ACK";
+	return NULL;
+}
+
+static void kbd_interrupt(void *dev_id)
+{
+	handle_kbd_event();
+}
+
+/******************************************************************
+ * Init
+ ******************************************************************/
+
+int kbd_init_hw(void)
+{
+	char* result;
+
+	kbd_request_region();
+
+	result=kbd_initialize();
+	if (result==NULL) {
+		PRINTF("AT Keyboard initialized\n");
+		kbd_request_irq(kbd_interrupt);
+		return (1);
+	} else {
+		printf("%s\n",result);
+		return (-1);
+	}
+}
+
+void pckbd_leds(unsigned char leds)
+{
+	kbd_send_data(KBD_CMD_SET_LEDS);
+	kbd_send_data(leds);
+}
+
+#endif /* CONFIG_PS2KBD */