Patchwork some more i945 patches

login
register
about
Submitter Stefan Reinauer
Date 2009-07-21 16:45:19
Message ID <4A65F09F.4000308@coresystems.de>
Download mbox | patch
Permalink /patch/58/
State Accepted
Headers show

Comments

Stefan Reinauer - 2009-07-21 16:45:19
I'm pushing out a number of i945 patches in order to get more public
input and testing on the i945 chipset port and in order to keep some
structural changes (XSDT support et al) from bit-rotting.

See patches

Stefan
Peter Stuge - 2009-07-21 18:11:05
Stefan Reinauer wrote:
> See patches

All are:

Acked-by: Peter Stuge <peter@stuge.se>


> +++ src/pc80/i8259.c	(working copy)
..
> +void i8259_configure_irq_trigger(int int_num, int is_level_triggered)
..
> +	/* Write new values */
> +	printk_spew("%s: try to set interrupts 0x%x\n", __func__, int_bits);
> +	outb((u8)(int_bits & 0xff), ELCR1);
> +	outb((u8)(int_bits >> 8), ELCR2);
> +
> +#ifdef PARANOID_IRQ_TRIGGERS
> +	/* Try reading back the new values. This seems like an error but is not ... */
> +	if (inb(ELCR1) != (int_bits & 0xff)) {
> +		printk_err("%s: lower order bits are wrong: want 0x%x, got 0x%x\n",
> +				__func__, (int_bits & 0xff), inb(ELCR1));
> +	}
> +
> +	if (inb(ELCR2) != (int_bits >> 8)) {
> +		printk_err("%s: lower order bits are wrong: want 0x%x, got 0x%x\n",
> +				__func__, (int_bits>>8), inb(ELCR2));
> +	}
> +#endif

Copypaste right? Both of these are not the lower bits.


> +++ src/boot/elfboot.c	(working copy)
..
> - * - After loading an ELF image copy coreboot to the upper half of the
> + * - After loading an ELF image copy coreboot to the top of the
>   *   buffer.

Could fold buffer up onto the previous line.


> - * - After loading an ELF image copy coreboot to the upper half of the
> + * - After loading an ELF image copy coreboot to the top of the
>   *   buffer.

..and again. Is this the same code? Could it be reused?


> +++ src/cpu/x86/lapic/apic_timer.c	(.../trunk/coreboot-v2)	
..
> +/* NOTE: We use the APIC TIMER register is to hold flags for AP init during
> + * pre-memory init (ROMCC). Don't use init_timer() and  udelay is redirected
> + * to udelay_tsc().
> + */

What? "We use the .. is to hold flags for " ? This text is confusing.


> +++ src/arch/i386/boot/acpi.c	(working copy)
..
> +	memcpy(&ssdt->asl_compiler_id, "CORE", 4);
..
> +	memcpy(header->asl_compiler_id, ASLC, 4);

Is this difference on purpose? Is one static and the other not?
Please explain?


> +#define RSDP_NAME	"RSDP"
> +#define RSDT_NAME	"RSDT"
> +#define HPET_NAME	"HPET"
> +#define MADT_NAME	"APIC"
> +#define MCFG_NAME	"MCFG"
> +#define SRAT_NAME	"SRAT"
> +#define SLIT_NAME	"SLIT"
> +#define SSDT_NAME	"SSDT"
> +#define FACS_NAME	"FACS"
> +#define FADT_NAME	"FACP"
> +#define XSDT_NAME	"XSDT"

Does it really make sense to use defines for these names?


> +// Misnomer, the NAME above is the 4 byte signature, this (TABLE) is the
> +// OEM_TABLE_ID.
> +//
> +#define ACPI_TABLE_CREATOR	"COREBOOT"
> +#define RSDT_TABLE	ACPI_TABLE_CREATOR
> +#define HPET_TABLE	ACPI_TABLE_CREATOR
> +#define MCFG_TABLE	ACPI_TABLE_CREATOR
> +#define MADT_TABLE	ACPI_TABLE_CREATOR
> +#define SRAT_TABLE	ACPI_TABLE_CREATOR
> +#define SLIT_TABLE	ACPI_TABLE_CREATOR
> +#define XSDT_TABLE	ACPI_TABLE_CREATOR

Seems even more wrong. Why use these defines?


> +++ src/northbridge/intel/i945/early_init.c	(working copy)
..
> +			reg32 = DMIBAR32(0x224);
> +			reg32 &= ~(7 << 0);
> +			reg32 |= (3 << 0);
> +			DMIBAR32(0x224) = reg32;

How do you feel about making this a single function call?


> -#if SETUP_PCIE_X16_LINK
> +

Is this a part of the Config.lb system? Should it be removed from
there? Why was it there before and removed now? Is x16 never optional
on 945?


> +++ src/northbridge/intel/i945/raminit.c	(working copy)
..
> +#if C2_SELF_REFRESH_DISABLE

Where is this set?


> +	 * However, the Kontron 986LCD-M does not like unused clock
> +	 * signals to be disabled.

(Do you know why? Just curious.)


> +++ src/pc80/keyboard.c	(.../trunk/coreboot-v2)	
> @@ -75,7 +81,11 @@
>  	do {
>  		if (!kbc_input_buffer_empty()) return 0;

No error here?


>  		outb(command, 0x60);
> -		if (!kbc_output_buffer_full()) return 0;
> +		if (!kbc_output_buffer_full()) {
> +			printk_err("Could not send keyboard command %02x\n",
> +					command);
> +			return 0;
> +		}
>  		regval = inb(0x60);
>  		--resend;
>  	} while (regval == 0xFE && resend > 0);


//Peter
Carl-Daniel Hailfinger - 2009-07-21 20:03:27
I read through all patches, but for some, the reformatting makes it
really hard to see what changed. For others, I don't know the code well
enough to review except for coding style.

The following patches are
Acked-by: Carl-Daniel Hailfinger <c-d.hailfinger.devel.2006@gmx.net>

14_config
13_flags
12_keyboard
11_simple_printk
08_usbdebug
07_timer
04_intel_945
03_intel_core

Regards,
Carl-Daniel
Stefan Reinauer - 2009-07-21 21:16:00
Peter Stuge wrote:
> Stefan Reinauer wrote:
>   
>> See patches
>>     
>
> All are:
>
> Acked-by: Peter Stuge <peter@stuge.se>
>
>   
Thank you!

>> +++ src/pc80/i8259.c	(working copy)
>>     
> ..
>   
>> +void i8259_configure_irq_trigger(int int_num, int is_level_triggered)
>>     
> ..
>   
>> +	/* Write new values */
>> +	printk_spew("%s: try to set interrupts 0x%x\n", __func__, int_bits);
>> +	outb((u8)(int_bits & 0xff), ELCR1);
>> +	outb((u8)(int_bits >> 8), ELCR2);
>> +
>> +#ifdef PARANOID_IRQ_TRIGGERS
>> +	/* Try reading back the new values. This seems like an error but is not ... */
>> +	if (inb(ELCR1) != (int_bits & 0xff)) {
>> +		printk_err("%s: lower order bits are wrong: want 0x%x, got 0x%x\n",
>> +				__func__, (int_bits & 0xff), inb(ELCR1));
>> +	}
>> +
>> +	if (inb(ELCR2) != (int_bits >> 8)) {
>> +		printk_err("%s: lower order bits are wrong: want 0x%x, got 0x%x\n",
>> +				__func__, (int_bits>>8), inb(ELCR2));
>> +	}
>> +#endif
>>     
>
> Copypaste right? Both of these are not the lower bits.
>   
D'uh, yes, must be "higher" in the second case . I never got these
messages, so I neglected them.


>> +++ src/boot/elfboot.c	(working copy)
>>     
> ..
>   
>> - * - After loading an ELF image copy coreboot to the upper half of the
>> + * - After loading an ELF image copy coreboot to the top of the
>>   *   buffer.
>>     
>
> Could fold buffer up onto the previous line.
>   
Agreed.


>> - * - After loading an ELF image copy coreboot to the upper half of the
>> + * - After loading an ELF image copy coreboot to the top of the
>>   *   buffer.
>>     
>
> ..and again. Is this the same code? Could it be reused?
>
>   
Agreed. Not sure if it's easy to reuse it..  I think Ron has still hopes
that we drop elfboot completely... Maybe it is indeed time for that.

>> +++ src/cpu/x86/lapic/apic_timer.c	(.../trunk/coreboot-v2)	
>>     
> ..
>   
>> +/* NOTE: We use the APIC TIMER register is to hold flags for AP init during
>> + * pre-memory init (ROMCC). Don't use init_timer() and  udelay is redirected
>> + * to udelay_tsc().
>> + */
>>     
>
> What? "We use the .. is to hold flags for " ? This text is confusing.
>
>   
This code was taken from AMD, but the lapic timer code never worked in
ROMCC. (Nor does AMD pre-memory init) So I completely wiped the
paragraph for now.

>> +++ src/arch/i386/boot/acpi.c	(working copy)
>>     
> ..
>   
>> +	memcpy(&ssdt->asl_compiler_id, "CORE", 4);
>>     
> ..
>   
>> +	memcpy(header->asl_compiler_id, ASLC, 4);
>>     
>
> Is this difference on purpose? Is one static and the other not?
> Please explain?
>   
No, it should be the same.

>
>   
>> +#define RSDP_NAME	"RSDP"
>> +#define RSDT_NAME	"RSDT"
>> +#define HPET_NAME	"HPET"
>> +#define MADT_NAME	"APIC"
>> +#define MCFG_NAME	"MCFG"
>> +#define SRAT_NAME	"SRAT"
>> +#define SLIT_NAME	"SLIT"
>> +#define SSDT_NAME	"SSDT"
>> +#define FACS_NAME	"FACS"
>> +#define FADT_NAME	"FACP"
>> +#define XSDT_NAME	"XSDT"
>>     
>
> Does it really make sense to use defines for these names?
>
>   
No. But I didn't dare dropping them, in this run, either. Same goes for
the next set (OEM_TABLE_ID)

>> +// Misnomer, the NAME above is the 4 byte signature, this (TABLE) is the
>> +// OEM_TABLE_ID.
>> +//
>> +#define ACPI_TABLE_CREATOR	"COREBOOT"
>> +#define RSDT_TABLE	ACPI_TABLE_CREATOR
>> +#define HPET_TABLE	ACPI_TABLE_CREATOR
>> +#define MCFG_TABLE	ACPI_TABLE_CREATOR
>> +#define MADT_TABLE	ACPI_TABLE_CREATOR
>> +#define SRAT_TABLE	ACPI_TABLE_CREATOR
>> +#define SLIT_TABLE	ACPI_TABLE_CREATOR
>> +#define XSDT_TABLE	ACPI_TABLE_CREATOR
>>     
>
> Seems even more wrong. Why use these defines?
>   
They were in use before, and when I started on the code, I wanted to
somewhat clean it up, but not touch too many files. The best way would
be to use ACPI_TABLE_CREATOR directly wherever those tables are created.

We can give this a try, but I'm going to push these changes in first, or
it'll become too confusing.

>> +++ src/northbridge/intel/i945/early_init.c	(working copy)
>>     
> ..
>   
>> +			reg32 = DMIBAR32(0x224);
>> +			reg32 &= ~(7 << 0);
>> +			reg32 |= (3 << 0);
>> +			DMIBAR32(0x224) = reg32;
>>     
>
> How do you feel about making this a single function call?
>   
For this part, or generally for this kind of construct?


>> -#if SETUP_PCIE_X16_LINK
>> +
>>     
>
> Is this a part of the Config.lb system? Should it be removed from
> there? Why was it there before and removed now? Is x16 never optional
> on 945?
>   
The chipset can do it, so the code should look if something is there. 
There's a way to enable the links x16, then x1, then disable it, if none
of the link widths bring up a connection.

So, basically, always having this code there is safe. The downside is,
the code does not work yet, it doesn't detect the one graphics card I
have here.


>> +++ src/northbridge/intel/i945/raminit.c	(working copy)
>>     
> ..
>   
>> +#if C2_SELF_REFRESH_DISABLE
>>     
>
> Where is this set?
>
>   
Not at all yet. I think we're going to need this for S2R, but I'm not
sure how to fit the decision in.


>> +	 * However, the Kontron 986LCD-M does not like unused clock
>> +	 * signals to be disabled.
>>     
>
> (Do you know why? Just curious.)
>   

I guess it might be a bug in the mainboard. The Kontron is the only
board I saw that behaves like that. Maybe they had some very smart
reasons to do this. I don't know them, though.

>> +++ src/pc80/keyboard.c	(.../trunk/coreboot-v2)	
>> @@ -75,7 +81,11 @@
>>  	do {
>>  		if (!kbc_input_buffer_empty()) return 0;
>>     
>
> No error here?
>
>   
Good question..

>   
>>  		outb(command, 0x60);
>> -		if (!kbc_output_buffer_full()) return 0;
>> +		if (!kbc_output_buffer_full()) {
>> +			printk_err("Could not send keyboard command %02x\n",
>> +					command);
>> +			return 0;
>> +		}
>>  		regval = inb(0x60);
>>  		--resend;
>>  	} while (regval == 0xFE && resend > 0);
>>     
>
>
> //Peter
>

Patch

Rewrite keyboard driver to actually wait time in ms as specified in the specs,
rather than doing inexact and slow idle loops.
Also improve error reporting in case of problems

Signed-off-by: Stefan Reinauer <stepan@coresystems.de>

--- src/pc80/keyboard.c	(.../branches/upstream/coreboot-v2)	
+++ src/pc80/keyboard.c	(.../trunk/coreboot-v2)	
@@ -1,8 +1,9 @@ 
 /*
  * This file is part of the coreboot project.
  *
+ * Copyright (C) 2009 coresystems GmbH
  * Copyright (C) 2008 Advanced Micro Devices, Inc.
- * Copyright (C) ???? Ollie Lo <ollielo@hotmail.com>
+ * Copyright (C) 2003 Ollie Lo <ollielo@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
@@ -23,16 +24,20 @@ 
 #include <pc80/keyboard.h>
 #include <device/device.h>
 #include <arch/io.h>
+#include <delay.h>
 
+/* Wait 200ms for keyboard controller answers */
+#define KBC_TIMEOUT_IN_MS 200
+
 static int kbc_input_buffer_empty(void)
 {
 	u32 timeout;
-	for(timeout = 1000000; timeout && (inb(0x64) & 0x02); timeout--) {
-		inb(0x80);
+	for(timeout = KBC_TIMEOUT_IN_MS; timeout && (inb(0x64) & 0x02); timeout--) {
+		mdelay(1);
 	}
 
 	if (!timeout) {
-		printk_err("Unexpected Keyboard controller input buffer full\n");
+		printk_warning("Unexpected Keyboard controller input buffer full\n");
 	}
 	return !!timeout;
 }
@@ -41,12 +46,12 @@ 
 static int kbc_output_buffer_full(void)
 {
 	u32 timeout;
-	for(timeout = 1000000; timeout && ((inb(0x64) & 0x01) == 0); timeout--) {
-		inb(0x80);
+	for(timeout = KBC_TIMEOUT_IN_MS; timeout && ((inb(0x64) & 0x01) == 0); timeout--) {
+		mdelay(1);
 	}
 
 	if (!timeout) {
-		printk_err("Keyboard controller output buffer result timeout\n");
+		printk_warning("Keyboard controller output buffer result timeout\n");
 	}
 	return !!timeout;
 }
@@ -55,7 +60,8 @@ 
 static int kbc_cleanup_buffers(void)
 {
 	u32 timeout;
-	for(timeout = 1000000; timeout && (inb(0x64) & 0x03); timeout--) {
+	for(timeout = KBC_TIMEOUT_IN_MS; timeout && (inb(0x64) & 0x03); timeout--) {
+		mdelay(1);
 		inb(0x60);
 	}
 
@@ -75,7 +81,11 @@ 
 	do {
 		if (!kbc_input_buffer_empty()) return 0;
 		outb(command, 0x60);
-		if (!kbc_output_buffer_full()) return 0;
+		if (!kbc_output_buffer_full()) {
+			printk_err("Could not send keyboard command %02x\n",
+					command);
+			return 0;
+		}
 		regval = inb(0x60);
 		--resend;
 	} while (regval == 0xFE && resend > 0);
@@ -93,18 +103,21 @@ 
 	/* clean up any junk that might have been in the kbc */
 	if (!kbc_cleanup_buffers()) return;
 
-	/* reset/self test 8042 - send cmd 0xAA,  */
+	/* reset/self test 8042 - send cmd 0xAA */
 	if (!kbc_input_buffer_empty()) return;
 	outb(0xAA, 0x64);
-	if (!kbc_output_buffer_full()) return;
+	if (!kbc_output_buffer_full()) {
+		printk_err("Could not reset keyboard controller.\n");
+		return;
+	}
 
 	/* read self-test result, 0x55 is returned in the output buffer (0x60) */
 	if ((regval = inb(0x60) != 0x55)) {
-		printk_err("Keyboard Controller selftest failed: 0x%x\n", regval);
+		printk_err("Keyboard Controller self-test failed: 0x%x\n", regval);
 		return;
 	}
 
-	/* Enable keyboard interface - No IRQ*/
+	/* Enable keyboard interface - No IRQ */
 	resend = 10;
 	regval = 0;
 	do {
@@ -112,8 +125,11 @@ 
 		outb(0x60, 0x64);
 		if (!kbc_input_buffer_empty()) return;
 		outb(0x20, 0x60);	/* send cmd: enable keyboard */
-		if ((inb(0x64) & 0x01)) {
+		if (kbc_output_buffer_full()) {
 			regval = inb(0x60);
+		} else {
+			printk_info("Timeout while enabling keyboard. (No keyboard present?)\n");
+			regval = inb(0x60); /* Better than 0 ? */
 		}
 		--resend;
 	} while (regval == 0xFE && resend > 0);
@@ -127,7 +143,11 @@ 
 		printk_err("Keyboard selftest failed ACK: 0x%x\n", regval);
 		return;
 	}
-	if (!kbc_output_buffer_full()) return;
+	if (!kbc_output_buffer_full()) {
+		printk_err("Timeout waiting for keyboard after reset.\n");
+		return;
+	}
+		
 	regval = inb(0x60);
 	if (regval != 0xAA) {
 		printk_err("Keyboard selftest failed: 0x%x\n", regval);
@@ -174,7 +194,7 @@ 
 		outb(0x60, 0x64);
 		if (!kbc_input_buffer_empty()) return;
 		outb(0x61, 0x60);	/* send cmd: enable keyboard and IRQ 1 */
-		if ((inb(0x64) & 0x01)) {
+		if (kbc_output_buffer_full()) {
 			regval = inb(0x60);
 		}
 		--resend;