Patchwork SECC Pentium 2/3 users are gonna love this

login
register
about
Submitter Jouni Mettälä
Date 2011-01-08 12:25:36
Message ID <AANLkTi=-7VzvWWuSQh5cbbkie2xAce0TtZqzQ3xYeXp4@mail.gmail.com>
Download mbox | patch
Permalink /patch/2493/
State Superseded
Headers show

Comments

Jouni Mettälä - 2011-01-08 12:25:36
Here is updated patch with l2_cache.c added.

Signed-off-by: Jouni Mettälä <jtmettala@gmail.com>
Roger - 2011-01-08 13:38:37
On Sat, Jan 08, 2011 at 12:25:36PM +0000, Jouni Mettälä wrote:
>   Here is updated patch with l2_cache.c added.
>   Signed-off-by: Jouni Mettälä <[1]jtmettala@gmail.com>

    CC         mainboard/tyan/s1846/crt0.s
    CC         mainboard/tyan/s1846/crt0.romstage.o
make: *** No rule to make target `/home/roger/src/coreboot-tyan/coreboot/build/config.h', needed by `build/lib/uart8250.romstage.o'.  Stop.
Myles Watson - 2011-01-08 14:39:54
On Sat, Jan 8, 2011 at 5:25 AM, Jouni Mettälä <jtmettala@gmail.com> wrote:
> Here is updated patch with l2_cache.c added.

I think it's missing l2_cache.h now.

Thanks,
Myles

Patch

Index: src/cpu/intel/model_67x/l2_cache.c
===================================================================
--- src/cpu/intel/model_67x/l2_cache.c	(revision 0)
+++ src/cpu/intel/model_67x/l2_cache.c	(revision 0)
@@ -0,0 +1,610 @@ 
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2000 Denis Dowling <dpd@alphalink.com.au>
+ * Copyright (C) 2010 Keith Hui <buurin@gmail.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; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * 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
+ */
+
+/*
+ * Intel Pentium L2 Cache initialization. 
+ * This code was developed by reversing engineering 
+ * the BIOS. Where the code accesses documented 
+ * registers I have added comments as best I can.
+ * Some undocumented registers on the PentiumII are
+ * used so some of the documentation is incomplete
+ *
+ * References:
+ * Intel Architecture Software Developer's Manual
+ * Volume 3: System Programming
+ */
+
+/* The L2 cache initalization sequence here only apply to SECC/SECC2 P6 family CPUs
+ * with Klamath (63x), Deschutes (65x) and Katmai (67x) cores.
+ * It is not required for Coppermine (68x) and Tualatin (6bx) cores.
+ * It is currently not known if Celerons with Mendocino core require the special initialization.
+ * Covington does not have L2 cache.
+ */
+
+/* This is a straight port from coreboot v1. */
+
+#include <console/console.h>
+#include <string.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/intel/l2_cache.h>
+#include <cpu/x86/cache.h>
+#include <cpu/x86/msr.h>
+
+/* Latency Tables */
+struct latency_entry {
+	unsigned char key;
+	unsigned char value;
+};
+
+static const struct latency_entry latency_650_t0[] = {
+	{0x10, 0x02}, {0x50, 0x02}, {0x20, 0x04}, {0x60, 0x06},
+	{0x00, 0x08}, {0x40, 0x0C}, {0x12, 0x06}, {0x52, 0x0A},
+	{0x22, 0x0E}, {0x62, 0x10}, {0x02, 0x10}, {0xFF, 0x00}
+};
+
+static const struct latency_entry latency_650_t1[] = {
+	{0x12, 0x14}, {0x52, 0x16}, {0x22, 0x16}, {0x62, 0x16},
+	{0xFF, 0x00}
+};
+
+static const struct latency_entry latency_670_t0[] = {
+	{0x60, 0x06}, {0x00, 0x08}, {0x12, 0x06}, {0x52, 0x0A},
+	{0x22, 0x0E}, {0x62, 0x10}, {0x02, 0x10}, {0x42, 0x02},
+	{0x11, 0x0E}, {0x51, 0x0C}, {0x21, 0x02}, {0x61, 0x10},
+	{0x01, 0x10}, {0x41, 0x02}, {0xFF, 0x00}
+};
+
+static const struct latency_entry latency_670_t1[] = {
+	{0x22, 0x18}, {0x62, 0x18}, {0x02, 0x1A}, {0x11, 0x18},
+	{0xFF, 0x00}
+};
+
+static const struct latency_entry latency_670_t2[] = {
+	{0x22, 0x12}, {0x62, 0x14}, {0x02, 0x16}, {0x42, 0x1E},
+	{0x11, 0x12}, {0x51, 0x16}, {0x21, 0x1E}, {0x61, 0x14},
+	{0x01, 0x16}, {0x41, 0x1E}, {0xFF, 0x00}
+};
+
+/* Latency tables for 650 model/type */
+static const struct latency_entry *latency_650[] = {
+	latency_650_t0, latency_650_t1, latency_650_t1
+};
+
+/* Latency tables for 670 model/type */
+static const struct latency_entry *latency_670[] = {
+	latency_670_t0, latency_670_t1, latency_670_t2
+};
+
+int calculate_l2_latency(void)
+{
+	unsigned int eax, edx;
+	int l;
+	const struct latency_entry *latency_table, *le;
+	msr_t msr;
+
+	/* Read an undocumented MSR */
+	msr = rdmsr(IA32_PLATFORM_ID);
+
+	printk(BIOS_DEBUG,"rdmsr(IA32_PLATFORM_ID) = %x, %x\n", msr.lo,msr.hi);
+
+	/* Mask out [23:20] in EDX. Are Intel trying to hide this?? */
+	edx = msr.hi & 0x1e00000;
+
+	if (edx != 0) {
+		/* Get latency value directly from edx */
+		l = edx >> 20;
+	} else {
+		/* Look up the latency from tables */
+		int t, a;
+
+		/* Read L2 register 0 */
+		a = read_l2(0);
+		if (a < 0)
+			return -1;
+
+		/* Mask out [7:4] */
+		a &= 0xf0;
+
+		if ((a & 0x20) == 0)
+			t = 0;
+		else if (a == 0x20)
+			t = 1;
+		else if (a == 0x30)
+			t = 2;
+		else
+			return -1;
+
+		/* Get CPUID family/model */
+		eax = cpuid_eax(1) & 0xfff0;
+
+		printk(BIOS_DEBUG,"L2 latency type = %x\n", t);
+
+		/* Read EBL_CR_POWERON */
+		msr = rdmsr(EBL_CR_POWERON);
+		if (eax == 0x650) {
+			/* Read EBL_CR_POWERON */
+			eax = msr.lo;
+
+			/* Mask [25:22] [19] Clock frequency Ratio & reserved */
+			eax &= 0x3c80000;
+
+			/* Shift to [7:4] [1] */
+			eax >>= 18;
+
+			latency_table = latency_650[t];
+		} else if (eax == 0x670) {
+			/* Read EBL_CR_POWERON */
+			eax = msr.lo;
+
+			/* Mask [25:22] [19:18] Clock frequency Ratio & reserved */
+			eax &= 0x3cc0000;
+
+			/* Shift to [7:4] [1:0] */
+			eax >>= 18;
+
+			latency_table = latency_670[t];
+		} else
+			return -1;
+
+		printk(BIOS_DEBUG, "Searching for key %x\n", eax);
+
+		/* Search table for matching entry */
+		for (le = latency_table; le->key != eax; le++) {
+			/* Fail if we get to the end of the table */
+			if (le->key == 0xff) {
+				printk(BIOS_ERR, "Could not find key %x in latency table\n", eax);
+				return -1;
+			}
+		}
+
+		l = le->value;
+	}
+
+	printk(BIOS_DEBUG,"L2 Cache latency is %d\n", l / 2);
+
+	/* Read BBL_CR_CTL3 */
+	msr = rdmsr(BBL_CR_CTL3);
+
+	/* Mask out the latency */
+	eax = msr.lo & 0xffffffe1;
+
+	/* Or in the new value */
+	eax |= l;
+
+	/* Write BBL_CR_CTL3 */
+	msr.lo = eax;
+	wrmsr(BBL_CR_CTL3, msr);
+
+	return 0;
+}
+
+
+/* Setup address_high:address_low, data_high:data_low into the L2
+ * control registers and then issue command with correct cache way
+ */
+int signal_l2(unsigned int address_high, unsigned int address_low,
+	      unsigned int data_high, unsigned int data_low,
+	      int way, int command)
+{
+	unsigned int i;
+	msr_t msr;
+
+	/* Write L2 Address to BBL_CR_ADDR */
+	msr.lo = address_low;
+	msr.hi = address_high;
+	wrmsr(BBL_CR_ADDR, msr);
+
+	/* Write data to BBL_CR_D[0-3] */
+	msr.lo = data_low;
+	msr.hi = data_high;
+	for (i = BBL_CR_D0; i <= BBL_CR_D3; i++) {
+		wrmsr(i, msr);
+	}
+
+	/* Put the command into BBL_CR_CTL */
+	msr = rdmsr(BBL_CR_CTL);
+	i = msr.lo & 0xfffffce0;
+	i |= command;
+	i |= way << 8;
+	msr.lo = i;
+	wrmsr(BBL_CR_CTL, msr);
+
+	/* Write to BBL_CR_TRIG to trigger L2 controller */
+	msr.lo = 0;
+	msr.hi = 0;
+	wrmsr(BBL_CR_TRIG, msr);
+
+	/* Poll the controller to see when done */
+	for (i = 0; i < 0x100; i++) {
+		/* Read BBL_CR_BUSY */
+		msr = rdmsr(BBL_CR_BUSY);
+		/* If not busy then return */
+		if ((msr.lo & 1) == 0)
+			return 0;
+	}
+
+	/* Return timeout code */
+	return -1;
+}
+
+/* Read the L2 Cache controller register at given address */
+unsigned int read_l2(unsigned int address)
+{
+	msr_t msr;
+
+	/* Send a L2 Control Register Read to L2 controller */
+	if (signal_l2(0, address << 5, 0, 0, 0, 2) != 0)
+		return -1;
+
+	/* If OK then get the result from BBL_CR_ADDR */
+	msr = rdmsr(BBL_CR_ADDR);
+	return (msr.lo >> 0x15);
+
+}
+
+/* data1 = eax, data2 = ebx */
+/* TODO: Merge me into write_l2() */
+int write_l2_2(unsigned int address, unsigned int data1, unsigned int data2)
+{
+	data1 &= 0xff;
+	data1 = data1 << 0x15;
+
+	data2 = data2 << 0x0b;
+	data2 &= 0x1800;
+	data1 |= data2;
+
+	data2 = data2 << 6;
+	data2 &= 0x20000;
+	data1 |= data2;
+
+	address = address << 5;
+	address |= data1;
+
+	/* L2 Control Register Write */
+	return signal_l2(0, address, 0, 0, 0, 3);
+}
+
+/* Write data into the L2 controller register at address */
+int write_l2(unsigned int address, int data)
+{
+	int v1, v2, i;
+
+	v1 = read_l2(0);
+	if (v1 < 0)
+		return -1;
+
+	v2 = read_l2(2);
+	if (v2 < 0)
+		return -1;
+
+	if ((v1 & 0x20) == 0) {
+		v2 &= 0x3;
+		v2++;
+	} else
+		v2 &= 0x7;
+
+	for (i = 0; i < v2; i++)
+		if (write_l2_2(address, data, i) != 0)
+			return -1;
+
+	return 0;
+}
+
+/* Write data_high:data_low into the cache at address1. Test address2
+ * to see if the same data is returned. Return 0 if the data matches.
+ * return lower 16 bits if mismatched data if mismatch. Return -1
+ * on error
+ */
+int test_l2_address_alias(unsigned int address1,
+				 unsigned int address2,
+				 unsigned int data_high,
+				 unsigned int data_low)
+{
+	int d;
+	msr_t msr;
+
+	/* Tag Write with Data Write for L2 */
+	if (signal_l2(0, address1, data_high, data_low, 0, 0x1c) != 0)
+		return -1;
+
+	/* Tag Read with Data Read for L2 */
+	if (signal_l2(0, address2, 0, 0, 0, 0xe) != 0)
+		return -1;
+
+	/* Read data from BBL_CR_D[0-3] */
+	for (d = BBL_CR_D0; d <= BBL_CR_D3; d++) {
+		msr = rdmsr(d);
+		if (msr.lo != data_low || msr.hi != data_high)
+			return (msr.lo & 0xffff);
+	}
+
+	return 0;
+}
+
+/* Pass some infomation into the L2 controller register 4*/
+int set_l2_register4(int l)
+{
+	int a;
+
+	/* Mask out all but lower 2 bits in l */
+	l &= 3;
+
+	/* Read L2 register 4 */
+	a = read_l2(4);
+	if (a < 0)
+		return -1;
+
+	/* Mask off the lower 2 bits */
+	a &= 0xfffc;
+
+	/* Or in the new latency */
+	a |= l;
+
+	/* Write L2 register 4 */
+	if (write_l2(4, a) != 0)
+		return -1;
+
+	return 0;
+}
+
+int calculate_l2_cache_size(void)
+{
+	unsigned int eax;
+	int v;
+	msr_t msr;
+	unsigned int cache_setting;
+	unsigned int address, size;
+
+	v = read_l2(0);
+	if (v < 0)
+		return -1;
+	if ((v & 0x20) == 0) {
+
+		/* Read BBL_CR_CTL3 */
+		msr = rdmsr(BBL_CR_CTL3);		
+
+		/* Check sizes from 256KB up to 4MB */
+		for (cache_setting = 0x2000;
+		     cache_setting <= 0x20000; cache_setting <<= 1) {
+			unsigned int new_eax;
+
+			/* Mask out the cache size */
+			eax = msr.lo & 0xfffc1fff;
+
+			/* Or in the current setting */
+			eax |= cache_setting;
+
+			new_eax = eax;
+
+			/* Write new value into BBL_CR_CTL3 and read it back */
+			
+			msr.lo = new_eax;
+			wrmsr(BBL_CR_CTL3, msr);
+			msr = rdmsr(BBL_CR_CTL3);
+
+			/* If the value didn't change then break */
+			if (msr.lo != new_eax)
+				break;
+		}
+
+		/* Reset to the last value that worked */
+		cache_setting >>= 1;
+
+		/* Mask to just the cache setting bits */
+		cache_setting &= 0x3e000;
+
+		/* Mask out cache size from eax */
+		msr.lo &= 0xfffc1fff;
+
+		/* Or in the correct setting */
+		msr.lo |= cache_setting;
+
+		/* Write new value into BBL_CR_CTL3 */
+		wrmsr(BBL_CR_CTL3, msr);
+
+		printk(BIOS_DEBUG,"Maximum cache mask is %x\n", cache_setting);
+
+		/* Write aaaaaaaa:aaaaaaaa to address 0 in the l2 cache */
+		v = test_l2_address_alias(0, 0, 0xaaaaaaaa, 0xaaaaaaaa);
+		if (v != 0)
+			return -1;
+
+		size = 1;
+		address = 0x8000;
+
+		while (1) {
+			v =
+			    test_l2_address_alias(address, 0, 0x55555555,
+						  0x55555555);
+			if (v < 0)
+				return -1;
+			else if (v == 0)
+				break;
+
+			size <<= 1;
+			address <<= 1;
+
+			if (address > 0x200000)
+				return -1;
+		}
+
+		/* Mask size */
+		size &= 0x3e;
+
+		/* Shift to [17:13] */
+		size <<= 12;
+
+		/* Read BBL_CR_CTL3 */
+		msr = rdmsr(BBL_CR_CTL3);
+
+		/* Mask out the cache_setting */
+		msr.lo &= 0xfffc1fff;
+
+		/* Or in the calculated value */
+		msr.lo |= size;
+
+		/* Write cache size into BBL_CR_CTL3 */
+		wrmsr(BBL_CR_CTL3, msr);
+
+		printk(BIOS_DEBUG,"L2 Cache Mask is %x\n", size);
+
+		/* Shift to [6:2] */
+		size >>= 11;
+
+		v = read_l2(2);
+
+		printk(BIOS_DEBUG,"read_l2(2) = %x\n", v);
+
+		if (v < 0)
+			return -1;
+
+		v &= 0x3;
+
+		/* Shift size right by v */
+		size >>= v;
+
+		/* Or in this size */
+		v |= size;
+
+		printk(BIOS_DEBUG,"write_l2(2) = %x\n", v);
+
+		if (write_l2(2, v) != 0)
+			return -1;
+	} else {
+		int a, b, c;
+
+		a = read_l2(2);
+
+		printk(BIOS_DEBUG,"read_l2(2) = %x\n", a);
+
+		if (a < 0)
+			return -1;
+
+		b = a & 0x7;
+		c = a >> 6;
+
+		a = 1 << c * b;
+
+		a &= 0xf;
+
+		printk(BIOS_DEBUG,"Calculated a = %x\n", a);
+
+		if (a == 0)
+			return -1;
+
+		/* Shift to 17:14 */
+		a <<= 14;
+
+		/* Read BBL_CR_CTL3 */
+		msr = rdmsr(BBL_CR_CTL3);
+
+		/* Mask out the cache */
+		msr.lo &= 0xfffc1fff;
+
+		/* Or in the calculated value */
+		msr.lo |= a;
+
+		/* Write cache size into BBL_CR_CTL3 */
+		wrmsr(BBL_CR_CTL3, msr);
+	}
+
+	return 0;
+}
+
+int calculate_l2_physical_address_range(void)
+{
+	int r0, r3;
+	msr_t msr;
+
+	r3 = read_l2(3);
+	if (r3 < 0)
+		return -1;
+
+	r0 = read_l2(0);
+	if (r0 < 0)
+		return -1;
+
+	if (r0 & 0x20)
+		r3 = 0x7;
+	else
+		r3 &= 0x7;
+
+	printk(BIOS_DEBUG,"L2 Physical Address Range is %dM\n", (1 << r3) * 512);
+
+	/* Shift into [22:20] */
+	r3 = r3 << 20;
+
+	/* Read BBL_CR_CTL3 */
+	msr = rdmsr(BBL_CR_CTL3);
+
+	/* Mask out [22:20] */
+	msr.lo &= 0xff8fffff;
+
+	/* Or in the new value */
+	msr.lo |= r3;
+
+	/* Write BBL_CR_CTL3 */
+	wrmsr(BBL_CR_CTL3, msr);
+
+	return 0;
+}
+
+int calculate_l2_ecc(void)
+{
+	unsigned int eax;
+	const unsigned int data1 = 0xaa55aa55;
+	const unsigned int data2 = 0xaaaaaaaa;
+	msr_t msr;
+
+	/* Set User Supplied ECC in BBL_CR_CTL */
+	msr = rdmsr(BBL_CR_CTL);
+	msr.lo |= 0x40000;
+	wrmsr(BBL_CR_CTL, msr);
+
+	/* Write a value into the L2 Data ECC register BBL_CR_DECC */
+	msr.lo = data1;
+	msr.hi = 0;
+	wrmsr(BBL_CR_DECC, msr);
+
+	if (test_l2_address_alias(0, 0, data2, data2) < 0)
+		return -1;
+
+	/* Read back ECC from BBL_CR_DECC */
+	msr = rdmsr(BBL_CR_DECC);
+	eax = msr.lo;
+
+	if (eax == data1) {
+		printk(BIOS_DEBUG,"L2 ECC Checking is enabled\n");
+
+		/* Set ECC Check Enable in BBL_CR_CTL3 */
+		msr = rdmsr(BBL_CR_CTL3);
+		msr.lo |= 0x20;
+		wrmsr(BBL_CR_CTL3, msr);
+	}
+
+	/* Clear User Supplied ECC in BBL_CR_CTL */
+	msr = rdmsr(BBL_CR_CTL);
+	msr.lo &= 0xfffbffff;
+	wrmsr(BBL_CR_CTL, msr);
+
+	return 0;
+}
Index: src/cpu/intel/model_67x/Makefile.inc
===================================================================
--- src/cpu/intel/model_67x/Makefile.inc	(revision 6247)
+++ src/cpu/intel/model_67x/Makefile.inc	(working copy)
@@ -18,5 +18,6 @@ 
 ## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
 ##
 
+driver-y += l2_cache.c
 driver-y += model_67x_init.c
-
+obj-y += l2_cache.o
Index: src/cpu/intel/model_67x/model_67x_init.c
===================================================================
--- src/cpu/intel/model_67x/model_67x_init.c	(revision 6247)
+++ src/cpu/intel/model_67x/model_67x_init.c	(working copy)
@@ -24,6 +24,7 @@ 
 #include <cpu/x86/mtrr.h>
 #include <cpu/x86/lapic.h>
 #include <cpu/intel/microcode.h>
+#include <cpu/intel/l2_cache.h>
 #include <cpu/x86/cache.h>
 #include <cpu/x86/msr.h>
 
@@ -41,14 +42,296 @@ 
 	0x0, 0x0, 0x0, 0x0,
 };
 
+/*--- Begin L2 init code from coreboot v1 ---
+ * The rest of this code is in l2_cache.c
+ */
+
+
+/* int calculate_l2_latency(void);
+int signal_l2(unsigned int address_high, unsigned int address_low,
+	unsigned int data_high, unsigned int data_low,
+	int way, int command);
+unsigned int read_l2(unsigned int address);
+int write_l2(unsigned int address, int data);
+int write_l2_2(unsigned int address, unsigned int data1, unsigned int data2);
+int test_l2_address_alias(unsigned int address1, unsigned int address2,
+                                unsigned int data_high, unsigned int data_low);
+int set_l2_register4(int l);
+int calculate_l2_cache_size(void);
+int calculate_l2_physical_address_range(void);
+int calculate_l2_ecc(void); */
+
+
+static int p6_configure_l2_cache(void)
+{
+        struct cpuid_result cpuid_res;
+        msr_t msr, bblctl3;
+        unsigned int eax;
+         int signature, tmp;
+        int cache_size;
+        int result;
+
+ printk(BIOS_INFO, "Configuring L2 cache... ");
+
+        cpuid_res = cpuid(0);
+
+        if (cpuid_res.ebx != 0x756e6547 || cpuid_res.edx != 0x49656e69 || cpuid_res.ecx != 0x6c65746e) {
+                printk(BIOS_INFO, "Not 'GenuineIntel' Processor");
+                return 0;
+        }
+
+        /* Mask out the stepping */
+        signature = cpuid_eax(1) & 0xfff0;
+	if (signature & 0x1000) {
+                printk(BIOS_DEBUG,"Overdrive chip no L2 cache configuration\n");
+                return 0;
+        }
+
+        if (signature < 0x630 || signature >= 0x680) {
+                printk(BIOS_DEBUG,"L2 cache on CPUID %x does not require configuration\n", signature);
+                return 0;
+        }
+
+        /* Read BBL_CR_CTL3 */
+        bblctl3 = rdmsr(BBL_CR_CTL3);
+        eax = bblctl3.lo;
+        /* If bit 23 (L2 Hardware disable) is set then done */
+        /* These would be Covington core Celerons with no L2 cache */
+        if (eax & 0x800000) {
+                printk(BIOS_INFO,"L2 Hardware disabled");
+                return 0;
+        }
+
+        int calc_eax;
+        int v;
+
+        /* Read EBL_CR_POWERON */
+        msr = rdmsr(EBL_CR_POWERON);
+        eax = msr.lo;
+        /* Mask out [22-24] Clock frequency ratio */
+        eax &= 0x3c00000;
+        if (eax == 0xc00000 || eax == 0x3000000) {
+                printk(BIOS_ERR, "Incorrect clock frequency ratio %x\n", eax);
+                goto bad;
+        }
+
+        disable_cache();
+
+        /* Mask out from BBL_CR_CTL3:
+         * [0] L2 Configured
+         * [5] ECC Check Enable
+         * [6] Address Parity Check Enable
+         * [7] CRTN Parity Check Enable
+         * [8] L2 Enabled
+         * [12:11] Number of L2 banks
+         * [17:13] Cache size per bank
+         * [18] Cache state error checking enable
+         * [22:20] L2 Physical Address Range Support
+         */
+        bblctl3.lo &= 0xff88061e;
+        bblctl3.lo |= 0x40000;
+
+        /* Set:
+         * [17:13] = 00000 = 128Kbyte Cache size per bank
+         * [18] Cache state error checking enable
+         */
+
+/* Write BBL_CR_CTL3 */
+        wrmsr(BBL_CR_CTL3, bblctl3);
+        eax = bblctl3.lo;
+
+        /* Set the l2 latency in BBL_CR_CTL3 */
+        if (calculate_l2_latency() != 0)
+                goto bad;
+
+        /* Read the new latency values back */
+        bblctl3 = rdmsr(BBL_CR_CTL3);
+        calc_eax = bblctl3.lo;
+
+        /* Write back the original default value */
+        bblctl3.lo = eax;
+        wrmsr(BBL_CR_CTL3, bblctl3);
+
+        /* Mask [27:26] out of BBL_CR_CTL3 - Reserved?? */
+        v = calc_eax & 0xc000000;
+
+        /* Shift to [1:0] */
+        v >>= 26;
+
+        printk(BIOS_DEBUG,"Sending %x to set_l2_register4\n", v);
+        if (set_l2_register4(v) != 0)
+                goto bad;
+
+/* Restore the correct latency value into BBL_CR_CTL3 */
+        bblctl3.lo = calc_eax;
+        wrmsr(BBL_CR_CTL3, bblctl3);
+
+        /* Read L2 register 0 */
+        tmp = read_l2(0);
+        if (tmp < 0) {
+                printk(BIOS_ERR, "Failed to read_l2(0)\n");
+                goto bad;
+        }
+
+        /* test if L2(0) has bit 0x20 set */
+         if ((tmp & 0x20) != 0) {
+                /* Read BBL_CR_CTL3 */
+                 bblctl3 = rdmsr(BBL_CR_CTL3);
+                /* Set bits [6-7] CRTN + Address Parity enable */
+                bblctl3.lo |= 0xc0;
+                /* Write BBL_CR_CTL3 */
+                 wrmsr(BBL_CR_CTL3, bblctl3);
+        }
+
+        if (calculate_l2_ecc() != 0) {
+                printk(BIOS_ERR, "Failed to calculate L2 ECC");
+                goto bad;
+        }
+
+        if (calculate_l2_physical_address_range() != 0) {
+                printk(BIOS_ERR, "Failed to calculate L2 physical address range");
+                goto bad;
+        }
+
+        if (calculate_l2_cache_size() != 0) {
+                printk(BIOS_ERR, "Failed to calculate L2 cache size");
+                goto bad;
+        } 
+
+/* Turn on cache. Only L1 is active at this time. */
+        enable_cache();
+
+        /* Get the calculated cache size from BBL_CR_CTL3 [17:13] */
+        bblctl3 = rdmsr(BBL_CR_CTL3);
+        cache_size = (bblctl3.lo & 0x3e000);
+        if (cache_size == 0)
+                cache_size = 0x1000;
+        cache_size = cache_size << 3;
+
+        /* Cache is 4 way for each address */
+        printk(BIOS_DEBUG, "L2 Cache size is %dK\n", cache_size * 4 / 1024);
+
+        /* Write to all cache lines to initialize */
+        while (cache_size > 0) {
+                int way;
+
+                /* Each Cache line in 32 bytes */
+                cache_size -= 0x20;
+
+                /* Update each way */
+                for (way = 0; way < 4; way++) {
+                        /* Send Tag Write w/Data Write (TWW) to L2 controller 
+                         * MESI = Invalid
+                         */
+                        if (signal_l2(0, cache_size, 0, 0, way, 0x1c) != 0) {
+                                printk(BIOS_ERR,
+                                       "Failed on signal_l2(%x, %x)\n",
+                                       cache_size, way);
+                                goto bad;
+                        }
+                }
+        }
+        printk(BIOS_DEBUG, "L2 Cache lines initialized\n");
+
+/* Disable cache */
+        disable_cache();
+
+        /* Set L2 cache configured in BBL_CR_CTL3 */
+        bblctl3 = rdmsr(BBL_CR_CTL3);
+        bblctl3.lo |= 0x1;
+        wrmsr(BBL_CR_CTL3, bblctl3);
+
+        /* Invalidate cache and discard unsaved writes */
+        asm volatile ("invd");
+
+        /* Write 0 to L2 control register 5 */
+        if (write_l2(5, 0) != 0) {
+                printk(BIOS_ERR,"write_l2(5, 0) failed\n");
+                goto done;
+        }
+
+        bblctl3 = rdmsr(BBL_CR_CTL3);
+        if (signature == 0x650 || signature == 0x670) {
+                /* Change the L2 latency to 0101 then back to 
+                 * original value. I don't know why this is needed - dpd
+                 */
+                int old_eax;
+                old_eax = bblctl3.lo;
+                bblctl3.lo &= 0xffffffe1;
+                bblctl3.lo |= 0x0000000a;
+                wrmsr(BBL_CR_CTL3, bblctl3);
+                bblctl3.lo = old_eax;
+                wrmsr(BBL_CR_CTL3, bblctl3);
+        }
+
+        /* Set L2 enabled in BBL_CR_CTL3 */
+        bblctl3.lo |= 0x00000100;
+        wrmsr(BBL_CR_CTL3, bblctl3);
+
+
+ /* Turn on cache. Both L1 and L2 are now active. Wahoo! */
+done:
+        result = 0;
+ out:
+
+
+        printk(BIOS_INFO, "done.\n");
+        return result;
+bad: 
+        result = -1;
+        goto out;
+}
+
+/*--- End L2 init code from coreboot v1 ---*/
+
+static void fill_processor_name(char *processor_name)
+{
+       struct cpuid_result regs;
+       char temp_processor_name[49];
+       char *processor_name_start;
+       unsigned int *name_as_ints = (unsigned int *)temp_processor_name;
+       int i;
+
+       for (i=0; i<3; i++) {
+               regs = cpuid(0x80000002 + i);
+               name_as_ints[i*4 + 0] = regs.eax;
+               name_as_ints[i*4 + 1] = regs.ebx;
+               name_as_ints[i*4 + 2] = regs.ecx;
+               name_as_ints[i*4 + 3] = regs.edx;
+       }
+
+       temp_processor_name[48] = 0;
+
+       /* Skip leading spaces */
+       processor_name_start = temp_processor_name;
+       while (*processor_name_start == ' ')
+               processor_name_start++;
+
+       memset(processor_name, 0, 49);
+       strcpy(processor_name, processor_name_start);
+}
+
+
 static void model_67x_init(device_t cpu)
 {
+	char processor_name[49];
+        int l2res;
+
+
 	/* Update the microcode */
 	intel_update_microcode(microcode_updates);
 
+	/* Initialize L2 cache */
+	l2res = p6_configure_l2_cache();
+
 	/* Turn on caching if we haven't already */
 	x86_enable_cache();
 
+	/* Print processor name */
+        fill_processor_name(processor_name);
+        printk(BIOS_INFO, "CPU: %s.\n", processor_name);
+
+
 	/* Setup MTRRs */
 	x86_setup_mtrrs(36);
 	x86_mtrr_check();
Index: src/cpu/intel/slot_1/Kconfig
===================================================================
--- src/cpu/intel/slot_1/Kconfig	(revision 6247)
+++ src/cpu/intel/slot_1/Kconfig	(working copy)
@@ -26,3 +26,5 @@ 
 	default 0x01000
 	depends on CPU_INTEL_SLOT_1
 
+select CPU_INTEL_MODEL_67X
+select MMX
Index: src/mainboard/a-trend/atc-6220/Kconfig
===================================================================
--- src/mainboard/a-trend/atc-6220/Kconfig	(revision 6247)
+++ src/mainboard/a-trend/atc-6220/Kconfig	(working copy)
@@ -39,6 +39,6 @@ 
 
 config IRQ_SLOT_COUNT
 	int
-	default 7
+	default 9
 
 endif # BOARD_A_TREND_ATC_6220
Index: src/mainboard/a-trend/atc-6220/devicetree.cb
===================================================================
--- src/mainboard/a-trend/atc-6220/devicetree.cb	(revision 6247)
+++ src/mainboard/a-trend/atc-6220/devicetree.cb	(working copy)
@@ -10,12 +10,12 @@ 
     chip southbridge/intel/i82371eb	# Southbridge
       device pci 7.0 on			# ISA bridge
         chip superio/winbond/w83977tf	# Super I/O (FIXME: It's W83977EF!)
-          device pnp 3f0.0 on		# Floppy
+          device pnp 3f0.0 off		# Floppy
             io 0x60 = 0x3f0
             irq 0x70 = 6
             drq 0x74 = 2
           end
-          device pnp 3f0.1 on		# Parallel port
+          device pnp 3f0.1 off		# Parallel port
             io 0x60 = 0x378
             irq 0x70 = 7
           end
@@ -50,9 +50,9 @@ 
       register "ide1_enable" = "1"
       register "ide_legacy_enable" = "1"
       # Enable UDMA/33 for higher speed if your IDE device(s) support it.
-      register "ide0_drive0_udma33_enable" = "0"
+      register "ide0_drive0_udma33_enable" = "1"
       register "ide0_drive1_udma33_enable" = "0"
-      register "ide1_drive0_udma33_enable" = "0"
+      register "ide1_drive0_udma33_enable" = "1"
       register "ide1_drive1_udma33_enable" = "0"
     end
   end
Index: src/mainboard/a-trend/atc-6220/irq_tables.c
===================================================================
--- src/mainboard/a-trend/atc-6220/irq_tables.c	(revision 6247)
+++ src/mainboard/a-trend/atc-6220/irq_tables.c	(working copy)
@@ -1,7 +1,7 @@ 
 /*
  * This file is part of the coreboot project.
  *
- * Copyright (C) 2007 Uwe Hermann <uwe@hermann-uwe.de>
+ * Copyright (C) 200x TODO <TODO@TODO>
  *
  * 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
@@ -18,29 +18,37 @@ 
  * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA  02110-1301 USA
  */
 
+#ifdef GETPIR
+#include "pirq_routing.h"
+#else
 #include <arch/pirq_routing.h>
+#endif
 
 const struct irq_routing_table intel_irq_routing_table = {
-	PIRQ_SIGNATURE,
-	PIRQ_VERSION,
-	32 + 16 * CONFIG_IRQ_SLOT_COUNT,/* Max. number of devices on the bus */
+	PIRQ_SIGNATURE,		/* u32 signature */
+	PIRQ_VERSION,		/* u16 version */
+	32 + 16 * 8,		/* Max. number of devices on the bus */
 	0x00,			/* Interrupt router bus */
-	(0x07 << 3) | 0x0,	/* Interrupt router device */
-	0x600,			/* IRQs devoted exclusively to PCI usage */
+	(0x07 << 3) | 0x0,	/* Interrupt router dev */
+	0xc20,			/* IRQs devoted exclusively to PCI usage */
 	0x8086,			/* Vendor */
 	0x7000,			/* Device */
-	0,			/* Miniport data */
+	0,			/* Miniport */
 	{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
-	0x4e,			/* Checksum */
+	0x18,			/* Checksum (has to be set to some value that
+				 * would give 0 after the sum of all bytes
+				 * for this structure (including checksum).
+                                 */
 	{
-		/* bus,     dev|fn,   {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap},  slot, rfu */
-		{0x00,(0x0a<<3)|0x0, {{0x60, 0xdeb8}, {0x61, 0xdeb8}, {0x62, 0xdeb8}, {0x63, 0x0deb8}}, 0x1, 0x0},
-		{0x00,(0x0b<<3)|0x0, {{0x61, 0xdeb8}, {0x62, 0xdeb8}, {0x63, 0xdeb8}, {0x60, 0x0deb8}}, 0x2, 0x0},
-		{0x00,(0x0c<<3)|0x0, {{0x62, 0xdeb8}, {0x63, 0xdeb8}, {0x60, 0xdeb8}, {0x61, 0x0deb8}}, 0x3, 0x0},
-		{0x00,(0x0d<<3)|0x0, {{0x63, 0xdeb8}, {0x60, 0xdeb8}, {0x61, 0xdeb8}, {0x62, 0x0deb8}}, 0x4, 0x0},
-		{0x00,(0x07<<3)|0x1, {{0x00, 0xdeb8}, {0x00, 0xdeb8}, {0x00, 0xdeb8}, {0x00, 0x0deb8}}, 0x0, 0x0},
-		{0x00,(0x01<<3)|0x0, {{0x60, 0xdeb8}, {0x61, 0xdeb8}, {0x62, 0xdeb8}, {0x63, 0x0deb8}}, 0x0, 0x0},
-		{0x00,(0x07<<3)|0x2, {{0x00, 0xdeb8}, {0x00, 0xdeb8}, {0x00, 0xdeb8}, {0x63, 0x0deb8}}, 0x0, 0x0},
+		/* bus,        dev | fn,   {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */
+		{0x00, (0x13 << 3) | 0x0, {{0x61, 0xdeb8}, {0x60, 0xdeb8}, {0x63, 0xdeb8}, {0x62, 0xdeb8}}, 0x1, 0x0},
+		{0x00, (0x0e << 3) | 0x0, {{0x60, 0xdeb8}, {0x61, 0xdeb8}, {0x62, 0xdeb8}, {0x63, 0xdeb8}}, 0x2, 0x0},
+		{0x00, (0x10 << 3) | 0x0, {{0x61, 0xdeb8}, {0x62, 0xdeb8}, {0x63, 0xdeb8}, {0x60, 0xdeb8}}, 0x3, 0x0},
+		{0x00, (0x12 << 3) | 0x0, {{0x62, 0xdeb8}, {0x63, 0xdeb8}, {0x60, 0xdeb8}, {0x61, 0xdeb8}}, 0x4, 0x0},
+		{0x00, (0x14 << 3) | 0x0, {{0x61, 0xdeb8}, {0x60, 0xdeb8}, {0x63, 0xdeb8}, {0x62, 0xdeb8}}, 0x5, 0x0},
+		{0x00, (0x0c << 3) | 0x0, {{0x62, 0xdeb8}, {0x63, 0xdeb8}, {0x60, 0xdeb8}, {0x61, 0xdeb8}}, 0x6, 0x0},
+		{0x00, (0x07 << 3) | 0x1, {{0x60, 0xdeb8}, {0x61, 0xdeb8}, {0x62, 0xdeb8}, {0x63, 0xdeb8}}, 0x0, 0x0},
+		{0x00, (0x01 << 3) | 0x0, {{0x60, 0xdeb8}, {0x61, 0xdeb8}, {0x62, 0xdeb8}, {0x63, 0xdeb8}}, 0x0, 0x0},
 	}
 };