From patchwork Sat Jan 8 12:25:36 2011 Content-Type: text/plain; charset="utf-8" MIME-Version: 1.0 Content-Transfer-Encoding: 8bit Subject: SECC Pentium 2/3 users are gonna love this Date: Sat, 08 Jan 2011 12:25:36 -0000 From: =?utf-8?b?Sm91bmkgTWV0dMOkbMOkIDxqdG1ldHRhbGFAZ21haWwuY29tPg==?= X-Patchwork-Id: 2493 Message-Id: To: coreboot@coreboot.org Here is updated patch with l2_cache.c added. Signed-off-by: Jouni Mettälä 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 + * Copyright (C) 2010 Keith Hui + * + * 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 +#include +#include +#include +#include +#include +#include + +/* 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 #include #include +#include #include #include @@ -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 + * Copyright (C) 200x 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 +#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}, } };