diff options
| author | wdenk <wdenk> | 2004-01-16 00:30:56 +0000 | 
|---|---|---|
| committer | wdenk <wdenk> | 2004-01-16 00:30:56 +0000 | 
| commit | 1c43771ba888bb9260692636d645fb2d73390a4b (patch) | |
| tree | 5fbd3865ac2a0d926396927ba2a192c5f1609339 /drivers/pc_keyb.c | |
| parent | c83bf6a2d00ef846c1fb2b0c60540f03ef203125 (diff) | |
| download | olio-uboot-2014.01-1c43771ba888bb9260692636d645fb2d73390a4b.tar.xz olio-uboot-2014.01-1c43771ba888bb9260692636d645fb2d73390a4b.zip | |
[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
Diffstat (limited to 'drivers/pc_keyb.c')
| -rw-r--r-- | drivers/pc_keyb.c | 256 | 
1 files changed, 256 insertions, 0 deletions
| diff --git a/drivers/pc_keyb.c b/drivers/pc_keyb.c new file mode 100644 index 000000000..07c7914fa --- /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 */ |