[coreboot] r3610 - in trunk/coreboot-v2/src: pc80 superio/ite/it8712f

svn at coreboot.org svn at coreboot.org
Fri Sep 26 21:15:38 CEST 2008


Author: mjones
Date: 2008-09-26 21:15:38 +0200 (Fri, 26 Sep 2008)
New Revision: 3610

Modified:
   trunk/coreboot-v2/src/pc80/keyboard.c
   trunk/coreboot-v2/src/superio/ite/it8712f/superio.c
Log:
This patch fixes the dbm690t keyboard not working issue. It should also
fix the a8n_e and any other it8712f SIO keyboard issues. The it8712f
requires an archaic PS/2 mode setting to the keyboard controller before
accessing the keyboard. Beyond that, I made the keyboard controller and
keyboard init more robust and added more informative debug output.

Signed-off-by: Marc Jones <marc.jones at amd.com>
Acked-by: Stefan Reinauer <stepan at coresystems.de>



Modified: trunk/coreboot-v2/src/pc80/keyboard.c
===================================================================
--- trunk/coreboot-v2/src/pc80/keyboard.c	2008-09-26 18:56:11 UTC (rev 3609)
+++ trunk/coreboot-v2/src/pc80/keyboard.c	2008-09-26 19:15:38 UTC (rev 3610)
@@ -1,3 +1,24 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 Advanced Micro Devices, Inc.
+ * Copyright (C) ???? Ollie Lo <ollielo at hotmail.com>
+ *
+ * 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; version 2 of the License.
+ *
+ * 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.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
+ */
+
+
 #include <console/console.h>
 #include <pc80/keyboard.h>
 #include <device/device.h>
@@ -3,75 +24,163 @@
 #include <arch/io.h>
 
-static int kbd_empty_input_buffer(void)
+static int kbc_input_buffer_empty(void)
 {
-	unsigned long timeout;
+	u32 timeout;
 	for(timeout = 1000000; timeout && (inb(0x64) & 0x02); timeout--) {
-		post_code(0);
+		inb(0x80);
 	}
+
+	if (!timeout) {
+		printk_err("Unexpected Keyboard controller input buffer full\n");
+	}
 	return !!timeout;
 }
 
-static int kbd_empty_output_buffer(void)
+
+static int kbc_output_buffer_full(void)
 {
-	unsigned long timeout;
+	u32 timeout;
 	for(timeout = 1000000; timeout && ((inb(0x64) & 0x01) == 0); timeout--) {
-		post_code(0);
+		inb(0x80);
 	}
+
+	if (!timeout) {
+		printk_err("Keyboard controller output buffer result timeout\n");
+	}
 	return !!timeout;
 }
 
-/* much better keyboard init courtesy ollie at sis.com.tw 
-   TODO: Typematic Setting, the keyboard is too slow for me */
+
+static int kbc_cleanup_buffers(void)
+{
+	u32 timeout;
+	for(timeout = 1000000; timeout && (inb(0x64) & 0x03); timeout--) {
+		inb(0x60);
+	}
+
+	if (!timeout) {
+		printk_err("Couldn't cleanup the keyboard controller buffers\n");
+		printk_err("0x64: 0x%x, 0x60: 0x%x\n", inb(0x64), inb(0x60));
+	}
+	return !!timeout;
+}
+
+
+static u8 send_keyboard(u8 command)
+{
+	u8 regval = 0;
+	u8 resend = 10;
+
+	do {
+		if (!kbc_input_buffer_empty()) return 0;
+		outb(command, 0x60);
+		if (!kbc_output_buffer_full()) return 0;
+		regval = inb(0x60);
+		--resend;
+	} while (regval == 0xFE && resend > 0);
+
+	return regval;
+}
+
+
 static void pc_keyboard_init(struct pc_keyboard *keyboard)
 {
-	unsigned char regval;
-
+	u8 regval;
+	u8 resend;
 	printk_debug("Keyboard init...\n");
-	/* send cmd = 0xAA, self test 8042 */
-	outb(0xaa, 0x64);
 
-	/* empty input buffer or any other command/data will be lost */
-	if (!kbd_empty_input_buffer()) {
-		printk_err("Keyboard input buffer would not empty\n");
-		return;
-	}
+	/* clean up any junk that might have been in the kbc */
+	if (!kbc_cleanup_buffers()) return;
 
-	/* empty output buffer or any other command/data will be lost */
-	if (!kbd_empty_output_buffer()) {
-		printk_err("Keyboard output buffer would not empty\n");
-		return;
-	}
+	/* reset/self test 8042 - send cmd 0xAA,  */
+	if (!kbc_input_buffer_empty()) return;
+	outb(0xAA, 0x64);
+	if (!kbc_output_buffer_full()) return;
 
-	/* read self-test result, 0x55 should be returned form 0x60 */
+	/* read self-test result, 0x55 is returned in the output buffer (0x60) */
 	if ((regval = inb(0x60) != 0x55)) {
-		printk_err("Keyboard selftest failed\n");
+		printk_err("Keyboard Controller selftest failed: 0x%x\n", regval);
 		return;
 	}
 
-	/* enable keyboard interface */
-	outb(0x60, 0x64);
-	kbd_empty_input_buffer();
+	/* Enable keyboard interface - No IRQ*/
+	resend = 10;
+	regval = 0;
+	do {
+		if (!kbc_input_buffer_empty()) return;
+		outb(0x60, 0x64);
+		if (!kbc_input_buffer_empty()) return;
+		outb(0x20, 0x60);	/* send cmd: enable keyboard and IRQ 1 */
+		u8 resend = 10;
+		if ((inb(0x64) & 0x01)) {
+			regval = inb(0x60);
+		}
+		--resend;
+	} while (regval == 0xFE && resend > 0);
 
-	/* send cmd: enable IRQ 1 */
-	outb(0x61, 0x60);
-	kbd_empty_input_buffer();
+	/* clean up any junk that might have been in the keyboard */
+	if (!kbc_cleanup_buffers()) return;
 
-	/* reset kerboard and self test  (keyboard side) */
-	outb(0xff, 0x60);
+	/* reset keyboard and self test (keyboard side) */
+	regval = send_keyboard(0xFF);
+	if (regval != 0xFA) {
+		printk_err("Keyboard selftest failed ACK: 0x%x\n", regval);
+		return;
+	}
+	if (!kbc_output_buffer_full()) return;
+	regval = inb(0x60);
+	if (regval != 0xAA) {
+		printk_err("Keyboard selftest failed: 0x%x\n", regval);
+		return;
+	}
 
-	/* empty inut bufferm or any other command/data will be lost */
-	kbd_empty_input_buffer();
+	/*
+	 * The following set scancode stuff is what normal BIOS do. It could be
+	 * argued that coreboot shouldn't set the scan code.....
+	 */
 
-	/* empty output buffer or any other command/data will be lost */
-	kbd_empty_output_buffer();
+	/* disable the keyboard */
+	regval = send_keyboard(0xF5);
+	if (regval != 0xFA) {
+		printk_err("Keyboard disable failed ACK: 0x%x\n", regval);
+		return;
+	}
 
-	if ((regval = inb(0x60) != 0xfa))
+	/* Set scancode command */
+	regval = send_keyboard(0xF0);
+	if (regval != 0xFA) {
+		printk_err("Keyboard set scancode cmd failed ACK: 0x%x\n", regval);
 		return;
+	}
+	/* Set scancode mode 2 */
+	regval = send_keyboard(0x02);
+	if (regval != 0xFA) {
+		printk_err("Keyboard set scancode mode failed ACK: 0x%x\n", regval);
+		return;
+	}
 
-	kbd_empty_output_buffer();
-	if ((regval = inb(0x60) != 0xaa))
+	/* enable the keyboard */
+	regval = send_keyboard(0xF4);
+	if (regval != 0xFA) {
+		printk_err("Keyboard enable failed ACK: 0x%x\n", regval);
 		return;
+	}
+
+	/* All is well - enable keyboard interface */
+	resend = 10;
+	regval = 0;
+	do {
+		if (!kbc_input_buffer_empty()) return;
+		outb(0x60, 0x64);
+		if (!kbc_input_buffer_empty()) return;
+		outb(0x61, 0x60);	/* send cmd: enable keyboard and IRQ 1 */
+		if ((inb(0x64) & 0x01)) {
+			regval = inb(0x60);
+		}
+		--resend;
+	} while (regval == 0xFE && resend > 0);
 }
 
+
 void init_pc_keyboard(unsigned port0, unsigned port1, struct pc_keyboard *kbd)
 {
@@ -80,3 +189,32 @@
 		pc_keyboard_init(kbd);
 	}
 }
+
+/*
+ * Support PS/2 mode -  oddball SIOs(KBC) need this setup
+ * Not well documented. Google - 0xcb keyboard controller
+ * This is called before pc_keyboard_init().
+ */
+void set_kbc_ps2_mode()
+{
+	/* clean up any junk that might have been in the kbc */
+	if (!kbc_cleanup_buffers()) return;
+
+	/* reset/self test 8042 before we can do anything */
+	if (!kbc_input_buffer_empty()) return;
+	outb(0xAA, 0x64);
+	if (!kbc_output_buffer_full()) return;
+
+	/* read self-test result, 0x55 is returned in the output buffer (0x60) */
+	if ((inb(0x60) != 0x55)) {
+		printk_err("Keyboard Controller selftest failed\n");
+		return;
+	}
+
+	/* Support PS/2 mode */
+	if (!kbc_input_buffer_empty()) return;
+	outb(0xcb, 0x64);
+	if (!kbc_input_buffer_empty()) return;
+	outb(0x01, 0x60);
+	kbc_cleanup_buffers();
+}

Modified: trunk/coreboot-v2/src/superio/ite/it8712f/superio.c
===================================================================
--- trunk/coreboot-v2/src/superio/ite/it8712f/superio.c	2008-09-26 18:56:11 UTC (rev 3609)
+++ trunk/coreboot-v2/src/superio/ite/it8712f/superio.c	2008-09-26 19:15:38 UTC (rev 3610)
@@ -76,6 +76,7 @@
 	case IT8712F_KBCK:
 		res0 = find_resource(dev, PNP_IDX_IO0);
 		res1 = find_resource(dev, PNP_IDX_IO1);
+		set_kbc_ps2_mode();
 		init_pc_keyboard(res0->base, res1->base, &conf->keyboard);
 		break;
 	case IT8712F_KBCM: /* TODO. */





More information about the coreboot mailing list