From 91a8ce7d80bd84f307659d2a9da2d320d91e2a7a Mon Sep 17 00:00:00 2001 From: Eric Biederman Date: Wed, 16 Jul 2003 07:04:58 +0000 Subject: [PATCH] - ldscripb.lb remove another $Id: line.. - romcc_io.h Add include guards. - hdama/Config nothing really but I have been moving the setting back and forth between 1 and 2 cpus - auto.c Changed the enabled debugging comments. This almost works with 2 cpus - coherent_ht.c First pass at getting this right. It can now find 2 cpus and place them in some semblance of a working state. - raminit.c Fix problems with 4GB of ram. Disable some of the debugging code. git-svn-id: svn://svn.coreboot.org/coreboot/trunk@965 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/arch/i386/include/arch/romcc_io.h | 4 + src/mainboard/arima/hdama/auto.c | 344 ++++++++-------- src/northbridge/amd/amdk8/coherent_ht.c | 513 +++++++++++++++++++++++- src/northbridge/amd/amdk8/raminit.c | 30 +- 4 files changed, 716 insertions(+), 175 deletions(-) diff --git a/src/arch/i386/include/arch/romcc_io.h b/src/arch/i386/include/arch/romcc_io.h index f460a36f4d..f8618b0e76 100644 --- a/src/arch/i386/include/arch/romcc_io.h +++ b/src/arch/i386/include/arch/romcc_io.h @@ -1,3 +1,6 @@ +#ifndef ARCH_ROMCC_IO_H +#define ARCH_ROMCC_IO_H 1 + static void outb(unsigned char value, unsigned short port) { __builtin_outb(value, port); @@ -182,3 +185,4 @@ static device_t pci_locate_device(unsigned pci_id, device_t dev) return PCI_DEV_INVALID; } +#endif /* ARCH_ROMCC_IO_H */ diff --git a/src/mainboard/arima/hdama/auto.c b/src/mainboard/arima/hdama/auto.c index c1651514b1..c24f442c22 100644 --- a/src/mainboard/arima/hdama/auto.c +++ b/src/mainboard/arima/hdama/auto.c @@ -9,165 +9,6 @@ #include "southbridge/amd/amd8111/amd8111_early_smbus.c" #include "northbridge/amd/amdk8/raminit.h" -#warning "FIXME move these delay functions somewhere more appropriate" -#warning "FIXME use the apic timer instead it needs no calibration on an Opteron it runs at 200Mhz" -static void print_clock_multiplier(void) -{ - msr_t msr; - print_debug("clock multipler: 0x"); - msr = rdmsr(0xc0010042); - print_debug_hex32(msr.lo & 0x3f); - print_debug(" = 0x"); - print_debug_hex32(((msr.lo & 0x3f) + 8) * 100); - print_debug("Mhz\r\n"); -} - -static unsigned usecs_to_ticks(unsigned usecs) -{ -#warning "FIXME make usecs_to_ticks work properly" -#if 1 - return usecs *2000; -#else - /* This can only be done if cpuid says fid changing is supported - * I need to look up the base frequency another way for other - * cpus. Is it worth dedicating a global register to this? - * Are the PET timers useable for this purpose? - */ - msr_t msr; - msr = rdmsr(0xc0010042); - return ((msr.lo & 0x3f) + 8) * 100 *usecs; -#endif -} - -static void init_apic_timer(void) -{ - volatile uint32_t *apic_reg = (volatile uint32_t *)0xfee00000; - uint32_t start, end; - /* Set the apic timer to no interrupts and periodic mode */ - apic_reg[0x320 >> 2] = (1 << 17)|(1<< 16)|(0 << 12)|(0 << 0); - /* Set the divider to 1, no divider */ - apic_reg[0x3e0 >> 2] = (1 << 3) | 3; - /* Set the initial counter to 0xffffffff */ - apic_reg[0x380 >> 2] = 0xffffffff; -} - -static void udelay(unsigned usecs) -{ -#if 1 - uint32_t start, ticks; - tsc_t tsc; - /* Calculate the number of ticks to run for */ - ticks = usecs_to_ticks(usecs); - /* Find the current time */ - tsc = rdtsc(); - start = tsc.lo; - do { - tsc = rdtsc(); - } while((tsc.lo - start) < ticks); -#else - volatile uint32_t *apic_reg = (volatile uint32_t *)0xfee00000; - uint32_t start, value, ticks; - /* Calculate the number of ticks to run for */ - ticks = usecs * 200; - start = apic_reg[0x390 >> 2]; - do { - value = apic_reg[0x390 >> 2]; - } while((start - value) < ticks); -#endif -} - -static void mdelay(unsigned msecs) -{ - int i; - for(i = 0; i < msecs; i++) { - udelay(1000); - } -} - -static void delay(unsigned secs) -{ - int i; - for(i = 0; i < secs; i++) { - mdelay(1000); - } -} - - -static void memreset_setup(const struct mem_controller *ctrl) -{ - /* Set the memreset low */ - outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 28); - /* Ensure the BIOS has control of the memory lines */ - outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 29); - print_debug("memreset lo\r\n"); -} - -static void memreset(const struct mem_controller *ctrl) -{ - udelay(800); - /* Set memreset_high */ - outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), SMBUS_IO_BASE + 0xc0 + 28); - print_debug("memreset hi\r\n"); - udelay(50); -} - - -#include "northbridge/amd/amdk8/raminit.c" -#include "northbridge/amd/amdk8/coherent_ht.c" -#include "sdram/generic_sdram.c" - -#define NODE_ID 0x60 -#define HT_INIT_CONTROL 0x6c - -#define HTIC_ColdR_Detect (1<<4) -#define HTIC_BIOSR_Detect (1<<5) -#define HTIC_INIT_Detect (1<<6) - -static int boot_cpu(void) -{ - volatile unsigned long *local_apic; - unsigned long apic_id; - int bsp; - msr_t msr; - msr = rdmsr(0x1b); - bsp = !!(msr.lo & (1 << 8)); - if (bsp) { - print_debug("Bootstrap cpu\r\n"); - } - - return bsp; -} - -static int cpu_init_detected(void) -{ - unsigned long dcl; - int cpu_init; - - unsigned long htic; - - htic = pci_read_config32(PCI_DEV(0, 0x18, 0), HT_INIT_CONTROL); -#if 0 - print_debug("htic: "); - print_debug_hex32(htic); - print_debug("\r\n"); - - if (!(htic & HTIC_ColdR_Detect)) { - print_debug("Cold Reset.\r\n"); - } - if ((htic & HTIC_ColdR_Detect) && !(htic & HTIC_BIOSR_Detect)) { - print_debug("BIOS generated Reset.\r\n"); - } - if (htic & HTIC_INIT_Detect) { - print_debug("Init event.\r\n"); - } -#endif - cpu_init = (htic & HTIC_INIT_Detect); - if (cpu_init) { - print_debug("CPU INIT Detected.\r\n"); - } - return cpu_init; -} - static void print_debug_pci_dev(unsigned dev) { @@ -197,7 +38,6 @@ static void print_pci_devices(void) } } - static void dump_pci_device(unsigned dev) { int i; @@ -297,6 +137,165 @@ static void dump_spd_registers(const struct mem_controller *ctrl) } } +#warning "FIXME move these delay functions somewhere more appropriate" +#warning "FIXME use the apic timer instead it needs no calibration on an Opteron it runs at 200Mhz" +static void print_clock_multiplier(void) +{ + msr_t msr; + print_debug("clock multipler: 0x"); + msr = rdmsr(0xc0010042); + print_debug_hex32(msr.lo & 0x3f); + print_debug(" = 0x"); + print_debug_hex32(((msr.lo & 0x3f) + 8) * 100); + print_debug("Mhz\r\n"); +} + +static unsigned usecs_to_ticks(unsigned usecs) +{ +#warning "FIXME make usecs_to_ticks work properly" +#if 1 + return usecs *2000; +#else + /* This can only be done if cpuid says fid changing is supported + * I need to look up the base frequency another way for other + * cpus. Is it worth dedicating a global register to this? + * Are the PET timers useable for this purpose? + */ + msr_t msr; + msr = rdmsr(0xc0010042); + return ((msr.lo & 0x3f) + 8) * 100 *usecs; +#endif +} + +static void init_apic_timer(void) +{ + volatile uint32_t *apic_reg = (volatile uint32_t *)0xfee00000; + uint32_t start, end; + /* Set the apic timer to no interrupts and periodic mode */ + apic_reg[0x320 >> 2] = (1 << 17)|(1<< 16)|(0 << 12)|(0 << 0); + /* Set the divider to 1, no divider */ + apic_reg[0x3e0 >> 2] = (1 << 3) | 3; + /* Set the initial counter to 0xffffffff */ + apic_reg[0x380 >> 2] = 0xffffffff; +} + +static void udelay(unsigned usecs) +{ +#if 1 + uint32_t start, ticks; + tsc_t tsc; + /* Calculate the number of ticks to run for */ + ticks = usecs_to_ticks(usecs); + /* Find the current time */ + tsc = rdtsc(); + start = tsc.lo; + do { + tsc = rdtsc(); + } while((tsc.lo - start) < ticks); +#else + volatile uint32_t *apic_reg = (volatile uint32_t *)0xfee00000; + uint32_t start, value, ticks; + /* Calculate the number of ticks to run for */ + ticks = usecs * 200; + start = apic_reg[0x390 >> 2]; + do { + value = apic_reg[0x390 >> 2]; + } while((start - value) < ticks); +#endif +} + +static void mdelay(unsigned msecs) +{ + int i; + for(i = 0; i < msecs; i++) { + udelay(1000); + } +} + +static void delay(unsigned secs) +{ + int i; + for(i = 0; i < secs; i++) { + mdelay(1000); + } +} + + +static void memreset_setup(const struct mem_controller *ctrl) +{ + /* Set the memreset low */ + outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 28); + /* Ensure the BIOS has control of the memory lines */ + outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 29); +} + +static void memreset(const struct mem_controller *ctrl) +{ + udelay(800); + /* Set memreset_high */ + outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), SMBUS_IO_BASE + 0xc0 + 28); + udelay(50); +} + + +#include "northbridge/amd/amdk8/raminit.c" +#include "northbridge/amd/amdk8/coherent_ht.c" +#include "sdram/generic_sdram.c" + +#define NODE_ID 0x60 +#define HT_INIT_CONTROL 0x6c + +#define HTIC_ColdR_Detect (1<<4) +#define HTIC_BIOSR_Detect (1<<5) +#define HTIC_INIT_Detect (1<<6) + +static int boot_cpu(void) +{ + volatile unsigned long *local_apic; + unsigned long apic_id; + int bsp; + msr_t msr; + msr = rdmsr(0x1b); + bsp = !!(msr.lo & (1 << 8)); + if (bsp) { + print_debug("Bootstrap cpu\r\n"); + } + + return bsp; +} + +static int cpu_init_detected(void) +{ + unsigned long dcl; + int cpu_init; + + unsigned long htic; + + htic = pci_read_config32(PCI_DEV(0, 0x18, 0), HT_INIT_CONTROL); +#if 0 + print_debug("htic: "); + print_debug_hex32(htic); + print_debug("\r\n"); + + if (!(htic & HTIC_ColdR_Detect)) { + print_debug("Cold Reset.\r\n"); + } + if ((htic & HTIC_ColdR_Detect) && !(htic & HTIC_BIOSR_Detect)) { + print_debug("BIOS generated Reset.\r\n"); + } + if (htic & HTIC_INIT_Detect) { + print_debug("Init event.\r\n"); + } +#endif + cpu_init = (htic & HTIC_INIT_Detect); + if (cpu_init) { + print_debug("CPU INIT Detected.\r\n"); + } + return cpu_init; +} + + + static void pnp_write_config(unsigned char port, unsigned char value, unsigned char reg) { outb(reg, port); @@ -397,18 +396,30 @@ static void main(void) uart_init(); console_init(); if (boot_cpu() && !cpu_init_detected()) { -#if 1 +#if 0 init_apic_timer(); #endif +#if 1 setup_default_resource_map(); +#endif + +#if 0 + dump_pci_device(PCI_DEV(0, 0x18, 0)); +#endif + setup_coherent_ht_domain(); +#if 1 + disable_probes(); +#endif enumerate_ht_chain(); print_pci_devices(); enable_smbus(); +#if 0 dump_spd_registers(&cpu0); +#endif sdram_initialize(&cpu0); -#if 0 +#if 1 dump_pci_devices(); #endif #if 0 @@ -416,22 +427,21 @@ static void main(void) #endif /* Check all of memory */ +#if 0 msr_t msr; msr = rdmsr(TOP_MEM); print_debug("TOP_MEM: "); print_debug_hex32(msr.hi); print_debug_hex32(msr.lo); print_debug("\r\n"); +#endif #if 0 ram_check(0x00000000, msr.lo); #else +#if 1 /* Check 16MB of memory */ - ram_check(0x00000000, 0x1600000); + ram_check(0x00000000, 0x01000000); #endif -#if 0 - print_debug("sleeping 15s\r\n"); - delay(15); - print_debug("sleeping 15s done\r\n"); #endif } } diff --git a/src/northbridge/amd/amdk8/coherent_ht.c b/src/northbridge/amd/amdk8/coherent_ht.c index fe2f3723ad..8bb7869286 100644 --- a/src/northbridge/amd/amdk8/coherent_ht.c +++ b/src/northbridge/amd/amdk8/coherent_ht.c @@ -1,3 +1,4 @@ +#if 0 static void setup_coherent_ht_domain(void) { static const unsigned int register_values[] = { @@ -127,7 +128,7 @@ static void setup_coherent_ht_domain(void) */ PCI_ADDR(0, 0x18, 0, 0x68), 0x00800000, 0x0f00840f, /* HT Initialization Control Register - * F0:0x6C + * F0:0x6C ok... * [ 0: 0] Routing Table Disable * 0 = Packets are routed according to routing tables * 1 = Packets are routed according to the default link field @@ -326,3 +327,513 @@ static void setup_coherent_ht_domain(void) } print_debug("done.\r\n"); } +#else +/* coherent hypertransport initialization for AMD64 + * written by Stefan Reinauer + * (c) 2003 by SuSE Linux AG + * + * This code is licensed under GPL. + */ + +/* + * This algorithm assumes a grid configuration as follows: + * + * nodes : 1 2 4 6 8 + * org. : 1x1 2x1 2x2 2x3 2x4 + * + */ + +#if 0 +#include "compat.h" +#endif + +#include +#include "arch/romcc_io.h" + + +/* when generating a temporary row configuration we + * don't want broadcast to be enabled for that node. + */ + +#define generate_temp_row(x...) ((generate_row(x)&(~0x0f0000))|0x010000) +#define clear_temp_row(x) fill_row(x,7,DEFAULT) +#define enable_bsp_routing() enable_routing(0) + +#define NODE_HT(x) PCI_DEV(0,24+x,0) +#define NODE_MP(x) PCI_DEV(0,24+x,1) +#define NODE_MC(x) PCI_DEV(0,24+x,3) + +#define DEFAULT 0x00010101 /* default row entry */ + +typedef uint8_t u8; +typedef uint32_t u32; +typedef int8_t bool; + +#define TRUE (-1) +#define FALSE (0) + +static void disable_probes(void) +{ + /* disable read/write/fill probes for uniprocessor setup + * they don't make sense if only one cpu is available + */ + + /* Hypetransport Transaction Control Register + * F0:0x68 + * [ 0: 0] Disable read byte probe + * 0 = Probes issues + * 1 = Probes not issued + * [ 1: 1] Disable Read Doubleword probe + * 0 = Probes issued + * 1 = Probes not issued + * [ 2: 2] Disable write byte probes + * 0 = Probes issued + * 1 = Probes not issued + * [ 3: 3] Disable Write Doubleword Probes + * 0 = Probes issued + * 1 = Probes not issued. + * [10:10] Disable Fill Probe + * 0 = Probes issued for cache fills + * 1 = Probes not issued for cache fills. + */ + + u32 val; + + print_debug("Disabling read/write/fill probes for UP... "); + + val=pci_read_config32(NODE_HT(0), 0x68); + val |= 0x0000040f; + pci_write_config32(NODE_HT(0), 0x68, val); + + print_debug("done.\r\n"); + +} + +static void enable_routing(u8 node) +{ + u32 val; + + /* HT Initialization Control Register + * F0:0x6C + * [ 0: 0] Routing Table Disable + * 0 = Packets are routed according to routing tables + * 1 = Packets are routed according to the default link field + * [ 1: 1] Request Disable (BSP should clear this) + * 0 = Request packets may be generated + * 1 = Request packets may not be generated. + * [ 3: 2] Default Link (Read-only) + * 00 = LDT0 + * 01 = LDT1 + * 10 = LDT2 + * 11 = CPU on same node + * [ 4: 4] Cold Reset + * - Scratch bit cleared by a cold reset + * [ 5: 5] BIOS Reset Detect + * - Scratch bit cleared by a cold reset + * [ 6: 6] INIT Detect + * - Scratch bit cleared by a warm or cold reset not by an INIT + * + */ + + /* Enable routing table for BSP */ + print_debug("Enabling routing table for node "); + print_debug_hex32(node); + + val=pci_read_config32(NODE_HT(node), 0x6c); + val |= (1 << 6) | (1 << 5) | (1 << 4); +#if 0 + val &= ~((1<<1)|(1<<0)); +#else + /* Don't enable requests here as the indicated processor starts booting */ + val &= ~(1<<0); +#endif + pci_write_config32(NODE_HT(node), 0x6c, val); + + print_debug(" done.\r\n"); +} + +#if MAX_CPUS > 1 + +static void rename_temp_node(u8 node) +{ + u32 val; + + print_debug("Renaming current temp node to "); + print_debug_hex32(node); + + val=pci_read_config32(NODE_HT(7), 0x60); + val &= (~7); /* clear low bits. */ + val |= node; /* new node */ + pci_write_config32(NODE_HT(7), 0x60, val); + + print_debug(" done.\r\n"); + + +} + +static bool check_connection(u8 src, u8 dest, u8 link) +{ + /* this function does 2 things: + * 1) detect whether the coherent HT link is connected + * 2) verify that the coherent hypertransport link + * is established and actually working by reading the + * remote node's vendor/device id + */ + +#define UP 0x00 +#define ACROSS 0x20 +#define DOWN 0x40 + + u32 val; + + /* 1) */ + val=pci_read_config32(NODE_HT(src), 0x98+link); + if ( (val&0x17) != 0x03) + return 0; + + /* 2) */ + val=pci_read_config32(NODE_HT(dest),0); + if(val != 0x11001022) + return 0; + + return 1; +} + +static unsigned int generate_row(u8 node, u8 row, u8 maxnodes) +{ + /* Routing Table Node i + * + * F0: 0x40, 0x44, 0x48, 0x4c, 0x50, 0x54, 0x58, 0x5c + * i: 0, 1, 2, 3, 4, 5, 6, 7 + * + * [ 0: 3] Request Route + * [0] Route to this node + * [1] Route to Link 0 + * [2] Route to Link 1 + * [3] Route to Link 2 + * [11: 8] Response Route + * [0] Route to this node + * [1] Route to Link 0 + * [2] Route to Link 1 + * [3] Route to Link 2 + * [19:16] Broadcast route + * [0] Route to this node + * [1] Route to Link 0 + * [2] Route to Link 1 + * [3] Route to Link 2 + */ + + u32 ret=DEFAULT; + + static const unsigned int rows_2p[2][2] = { + { 0x00030101, 0x00010404 }, + { 0x00010404, 0x00030101 } + }; + + static const unsigned int rows_4p[4][4] = { + { 0x00070101, 0x00010404, 0x00050202, 0x00010402 }, + { 0x00010808, 0x000b0101, 0x00010802, 0x00090202 }, + { 0x00090202, 0x00010802, 0x000b0101, 0x00010808 }, + { 0x00010402, 0x00050202, 0x00010404, 0x00070101 } + }; + + if (!(node>=maxnodes || row>=maxnodes)) { + if (maxnodes==2) + ret=rows_2p[node][row]; + if (maxnodes==4) + ret=rows_4p[node][row]; + } + +#if 0 + printk_spew("generating entry n=%d, r=%d, max=%d - row=%x\n", + node,row,maxnodes,ret); +#endif + + return ret; +} + +static void fill_row(u8 node, u8 row, u32 value) +{ +#if 0 + print_debug("fill_row: pci_write_config32("); + print_debug_hex32(NODE_HT(node)); + print_debug_char(','); + print_debug_hex32(0x40 + (row << 2)); + print_debug_char(','); + print_debug_hex32(value); + print_debug(")\r\n"); +#endif + pci_write_config32(NODE_HT(node), 0x40+(row<<2), value); +} + +static void setup_row(u8 source, u8 dest, u8 cpus) +{ +#if 0 + printk_spew("setting up link from node %d to %d (%d cpus)\r\n", + source, dest, cpus); +#endif + + fill_row(source,dest,generate_row(source,dest,cpus)); +} + +static void setup_temp_row(u8 source, u8 dest, u8 cpus) +{ +#if 0 + printk_spew("setting up temp. link from node %d to %d (%d cpus)\r\n", + source, dest, cpus); +#endif + + fill_row(source,7,generate_temp_row(source,dest,cpus)); +} + +static void setup_node(u8 node, u8 cpus) +{ + u8 row; + for(row=0; row 2 +static void setup_temp_node(u8 node, u8 cpus) +{ + u8 row; + for(row=0; row 1 +static u8 setup_smp(void) +{ + u8 cpus=2; + + print_debug("Enabling SMP settings\r\n"); + + setup_row(0,0,cpus); + /* Setup and check a temporary connection to node 1 */ + setup_temp_row(0,1,cpus); + + if (!check_connection(0, 7, ACROSS)) { // Link: ACROSS + print_debug("No connection to Node 1.\r\n"); + clear_temp_row(0); /* delete temp connection */ + setup_uniprocessor(); /* and get up working */ + return 1; + } + + /* We found 2 nodes so far */ + setup_node(0, cpus); /* Node 1 is there. Setup Node 0 correctly */ + setup_remote_node(1, cpus); /* Setup the routes on the remote node */ + enable_routing(1); /* Enable routing on Node 1 */ + rename_temp_node(1); /* Rename Node 7 to Node 1 */ + + clear_temp_row(0); /* delete temporary connection */ + +#if MAX_CPUS > 2 + cpus=4; + + /* Setup and check temporary connection from Node 0 to Node 2 */ + setup_temp_row(0,2,cpus); + + if (!check_connection(0, 7, UP)) { // Link: UP + print_debug("No connection to Node 2.\r\n"); + clear_temp_row(0); /* delete temp connection */ + // detect_mp_capability(2); /* and get 2p working */ + return 2; + } + + /* We found 3 nodes so far. Now setup a temporary + * connection from node 0 to node 3 via node 1 + */ + + setup_temp_row(0,1,cpus); /* temp. link between nodes 0 and 1 */ + setup_temp_row(1,3,cpus); /* temp. link between nodes 1 and 3 */ + + if (!check_connection(0, 7, UP)) { // Link: UP + print_debug("No connection to Node 3.\r\n"); + clear_temp_row(0); /* delete temp connection */ + clear_temp_row(1); /* delete temp connection */ + //detect_mp_capability(2); /* and get 2p working */ + return 2; + } + + /* We found 4 nodes so far. Now setup all nodes for 4p */ + + setup_node(0, cpus); /* The first 2 nodes are configured */ + setup_node(1, cpus); /* already. Just configure them for 4p */ + + setup_temp_row(0,2,cpus); + setup_temp_node(2,cpus); + enable_routing(7); + rename_temp_node(2); + + setup_temp_row(0,1,cpus); + setup_temp_row(1,3,cpus); + setup_temp_node(3,cpus); + enable_routing(3); + rename_temp_node(3); + + clear_temp_row(0); + clear_temp_row(1); + clear_temp_row(2); + clear_temp_row(3); + +#endif + print_debug_hex32(cpus); + print_debug(" nodes initialized.\r\n"); + return cpus; +} +#endif + +#if MAX_CPUS > 1 +static unsigned detect_mp_capabilities(unsigned cpus) +{ + unsigned node, row, mask; + bool mp_cap=TRUE; + +#if 1 + print_debug("detect_mp_capabilities: "); + print_debug_hex32(cpus); + print_debug("\r\n"); +#endif + if (cpus>2) + mask=0x04; /* BigMPCap */ + else + mask=0x02; /* MPCap */ + + for (node=0; node0; node--) + for (row=cpus; row>0; row--) + fill_row(NODE_HT(node-1), row-1, DEFAULT); + + return setup_uniprocessor(); +} + +#endif + +/* this is a shrunken cpuid. */ + +static unsigned int cpuid(unsigned int op) +{ + unsigned int ret; + + asm volatile ( "cpuid" : "=a" (ret) : "a" (op)); + + return ret; +} + +static void coherent_ht_finalize(unsigned cpus) +{ + int node; + bool rev_a0; + + /* set up cpu count and node count and enable Limit + * Config Space Range for all available CPUs. + * Also clear non coherent hypertransport bus range + * registers on Hammer A0 revision. + */ + +#if 1 + print_debug("coherent_ht_finalize\r\n"); +#endif + rev_a0=((cpuid(1)&0xffff)==0x0f10); + + for (node=0; nodef1, 0x44, limit | (0 << 7) | (link_id << 4) | (node_id << 0)); pci_write_config32(ctrl->f1, 0x40, (base_k << 2) | (0 << 8) | (1<<1) | (1<<0)); + +#if 1 + pci_write_config32(PCI_DEV(0, 0x19, 1), 0x44, limit | (0 << 7) | (link_id << 4) | (node_id << 0)); + pci_write_config32(PCI_DEV(0, 0x19, 1), 0x40, (base_k << 2) | (0 << 8) | (1<<1) | (1<<0)); +#endif } static void set_top_mem(unsigned tom_k) @@ -1141,10 +1146,21 @@ static void set_top_mem(unsigned tom_k) if (!tom_k) { die("No memory"); } + /* Now set top of memory */ msr_t msr; msr.lo = (tom_k & 0x003fffff) << 10; msr.hi = (tom_k & 0xffc00000) >> 22; + wrmsr(TOP_MEM2, msr); + + /* Leave a 64M hole between TOP_MEM and TOP_MEM2 + * so I can see my rom chip and other I/O devices. + */ + if (tom_k >= 0x003f0000) { + tom_k = 0x3f0000; + } + msr.lo = (tom_k & 0x003fffff) << 10; + msr.hi = (tom_k & 0xffc00000) >> 22; wrmsr(TOP_MEM, msr); #if 1 @@ -1219,7 +1235,7 @@ static void order_dimms(const struct mem_controller *ctrl) } tom_k = (tom & ~0xff000000) << 15; -#if 1 +#if 0 print_debug("tom: "); print_debug_hex32(tom); print_debug(" tom_k: "); @@ -1277,7 +1293,7 @@ static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl) dcl |= DCL_UnBufDimm; } pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl); -#if 1 +#if 0 if (is_registered(ctrl)) { print_debug("Registered\r\n"); } else { @@ -1450,7 +1466,7 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl) min_cycle_time = min_cycle_times[(value >> NBCAP_MEMCLK_SHIFT) & NBCAP_MEMCLK_MASK]; min_latency = 2; -#if 1 +#if 0 print_debug("min_cycle_time: "); print_debug_hex8(min_cycle_time); print_debug(" min_latency: "); @@ -1570,7 +1586,7 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl) dimm_err: disable_dimm(ctrl, i); } -#if 1 +#if 0 print_debug("min_cycle_time: "); print_debug_hex8(min_cycle_time); print_debug(" min_latency: "); @@ -1746,7 +1762,7 @@ static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_p #else clocks = (value + ((param->divisor & 0xff) << 1) - 1)/((param->divisor & 0xff) << 1); #endif -#if 1 +#if 0 print_debug("Trp: "); print_debug_hex8(clocks); print_debug(" spd value: "); @@ -2172,7 +2188,7 @@ static void sdram_enable(const struct mem_controller *ctrl) #warning "FIXME set the ECC type to perform" #warning "FIXME initialize the scrub registers" -#if 1 +#if 0 if (dcl & DCL_DimmEccEn) { print_debug("ECC enabled\r\n"); }