- ldscripb.lb remove another $Id: line..
authorEric Biederman <ebiederm@xmission.com>
Wed, 16 Jul 2003 07:04:58 +0000 (07:04 +0000)
committerEric Biederman <ebiederm@xmission.com>
Wed, 16 Jul 2003 07:04:58 +0000 (07:04 +0000)
- 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
src/mainboard/arima/hdama/auto.c
src/northbridge/amd/amdk8/coherent_ht.c
src/northbridge/amd/amdk8/raminit.c

index f460a36f4d1335b99ad4f41e77a364182e0a0830..f8618b0e76e6a295e40c862a3c0306df7870f416 100644 (file)
@@ -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 */
index c1651514b170a515c1e65ff74739ae38352fe676..c24f442c22dbaab6069638197eaf50338bcba77f 100644 (file)
@@ -9,6 +9,134 @@
 #include "southbridge/amd/amd8111/amd8111_early_smbus.c"
 #include "northbridge/amd/amdk8/raminit.h"
 
+
+static void print_debug_pci_dev(unsigned dev)
+{
+       print_debug("PCI: ");
+       print_debug_hex8((dev >> 16) & 0xff);
+       print_debug_char(':');
+       print_debug_hex8((dev >> 11) & 0x1f);
+       print_debug_char('.');
+       print_debug_hex8((dev >> 8) & 7);
+}
+
+static void print_pci_devices(void)
+{
+       device_t dev;
+       for(dev = PCI_DEV(0, 0, 0); 
+               dev <= PCI_DEV(0, 0x1f, 0x7); 
+               dev += PCI_DEV(0,0,1)) {
+               uint32_t id;
+               id = pci_read_config32(dev, PCI_VENDOR_ID);
+               if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
+                       (((id >> 16) & 0xffff) == 0xffff) ||
+                       (((id >> 16) & 0xffff) == 0x0000)) {
+                       continue;
+               }
+               print_debug_pci_dev(dev);
+               print_debug("\r\n");
+       }
+}
+
+static void dump_pci_device(unsigned dev)
+{
+       int i;
+       print_debug_pci_dev(dev);
+       print_debug("\r\n");
+       
+       for(i = 0; i <= 255; i++) {
+               unsigned char val;
+               if ((i & 0x0f) == 0) {
+                       print_debug_hex8(i);
+                       print_debug_char(':');
+               }
+               val = pci_read_config8(dev, i);
+               print_debug_char(' ');
+               print_debug_hex8(val);
+               if ((i & 0x0f) == 0x0f) {
+                       print_debug("\r\n");
+               }
+       }
+}
+
+static void dump_pci_devices(void)
+{
+       device_t dev;
+       for(dev = PCI_DEV(0, 0, 0); 
+               dev <= PCI_DEV(0, 0x1f, 0x7); 
+               dev += PCI_DEV(0,0,1)) {
+               uint32_t id;
+               id = pci_read_config32(dev, PCI_VENDOR_ID);
+               if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
+                       (((id >> 16) & 0xffff) == 0xffff) ||
+                       (((id >> 16) & 0xffff) == 0x0000)) {
+                       continue;
+               }
+               dump_pci_device(dev);
+       }
+}
+
+static void dump_spd_registers(const struct mem_controller *ctrl)
+{
+       int i;
+       print_debug("\r\n");
+       for(i = 0; i < 4; i++) {
+               unsigned device;
+               device = ctrl->channel0[i];
+               if (device) {
+                       int j;
+                       print_debug("dimm: "); 
+                       print_debug_hex8(i); 
+                       print_debug(".0: ");
+                       print_debug_hex8(device);
+                       for(j = 0; j < 256; j++) {
+                               int status;
+                               unsigned char byte;
+                               if ((j & 0xf) == 0) {
+                                       print_debug("\r\n");
+                                       print_debug_hex8(j);
+                                       print_debug(": ");
+                               }
+                               status = smbus_read_byte(device, j);
+                               if (status < 0) {
+                                       print_debug("bad device\r\n");
+                                       break;
+                               }
+                               byte = status & 0xff;
+                               print_debug_hex8(byte);
+                               print_debug_char(' ');
+                       }
+                       print_debug("\r\n");
+               }
+               device = ctrl->channel1[i];
+               if (device) {
+                       int j;
+                       print_debug("dimm: "); 
+                       print_debug_hex8(i); 
+                       print_debug(".1: ");
+                       print_debug_hex8(device);
+                       for(j = 0; j < 256; j++) {
+                               int status;
+                               unsigned char byte;
+                               if ((j & 0xf) == 0) {
+                                       print_debug("\r\n");
+                                       print_debug_hex8(j);
+                                       print_debug(": ");
+                               }
+                               status = smbus_read_byte(device, j);
+                               if (status < 0) {
+                                       print_debug("bad device\r\n");
+                                       break;
+                               }
+                               byte = status & 0xff;
+                               print_debug_hex8(byte);
+                               print_debug_char(' ');
+                       }
+                       print_debug("\r\n");
+               }
+       }
+}
+
 #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)
@@ -99,7 +227,6 @@ static void memreset_setup(const struct mem_controller *ctrl)
        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)
@@ -107,7 +234,6 @@ 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);
 }
 
@@ -169,133 +295,6 @@ static int cpu_init_detected(void)
 }
 
 
-static void print_debug_pci_dev(unsigned dev)
-{
-       print_debug("PCI: ");
-       print_debug_hex8((dev >> 16) & 0xff);
-       print_debug_char(':');
-       print_debug_hex8((dev >> 11) & 0x1f);
-       print_debug_char('.');
-       print_debug_hex8((dev >> 8) & 7);
-}
-
-static void print_pci_devices(void)
-{
-       device_t dev;
-       for(dev = PCI_DEV(0, 0, 0); 
-               dev <= PCI_DEV(0, 0x1f, 0x7); 
-               dev += PCI_DEV(0,0,1)) {
-               uint32_t id;
-               id = pci_read_config32(dev, PCI_VENDOR_ID);
-               if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
-                       (((id >> 16) & 0xffff) == 0xffff) ||
-                       (((id >> 16) & 0xffff) == 0x0000)) {
-                       continue;
-               }
-               print_debug_pci_dev(dev);
-               print_debug("\r\n");
-       }
-}
-
-
-static void dump_pci_device(unsigned dev)
-{
-       int i;
-       print_debug_pci_dev(dev);
-       print_debug("\r\n");
-       
-       for(i = 0; i <= 255; i++) {
-               unsigned char val;
-               if ((i & 0x0f) == 0) {
-                       print_debug_hex8(i);
-                       print_debug_char(':');
-               }
-               val = pci_read_config8(dev, i);
-               print_debug_char(' ');
-               print_debug_hex8(val);
-               if ((i & 0x0f) == 0x0f) {
-                       print_debug("\r\n");
-               }
-       }
-}
-
-static void dump_pci_devices(void)
-{
-       device_t dev;
-       for(dev = PCI_DEV(0, 0, 0); 
-               dev <= PCI_DEV(0, 0x1f, 0x7); 
-               dev += PCI_DEV(0,0,1)) {
-               uint32_t id;
-               id = pci_read_config32(dev, PCI_VENDOR_ID);
-               if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
-                       (((id >> 16) & 0xffff) == 0xffff) ||
-                       (((id >> 16) & 0xffff) == 0x0000)) {
-                       continue;
-               }
-               dump_pci_device(dev);
-       }
-}
-
-static void dump_spd_registers(const struct mem_controller *ctrl)
-{
-       int i;
-       print_debug("\r\n");
-       for(i = 0; i < 4; i++) {
-               unsigned device;
-               device = ctrl->channel0[i];
-               if (device) {
-                       int j;
-                       print_debug("dimm: "); 
-                       print_debug_hex8(i); 
-                       print_debug(".0: ");
-                       print_debug_hex8(device);
-                       for(j = 0; j < 256; j++) {
-                               int status;
-                               unsigned char byte;
-                               if ((j & 0xf) == 0) {
-                                       print_debug("\r\n");
-                                       print_debug_hex8(j);
-                                       print_debug(": ");
-                               }
-                               status = smbus_read_byte(device, j);
-                               if (status < 0) {
-                                       print_debug("bad device\r\n");
-                                       break;
-                               }
-                               byte = status & 0xff;
-                               print_debug_hex8(byte);
-                               print_debug_char(' ');
-                       }
-                       print_debug("\r\n");
-               }
-               device = ctrl->channel1[i];
-               if (device) {
-                       int j;
-                       print_debug("dimm: "); 
-                       print_debug_hex8(i); 
-                       print_debug(".1: ");
-                       print_debug_hex8(device);
-                       for(j = 0; j < 256; j++) {
-                               int status;
-                               unsigned char byte;
-                               if ((j & 0xf) == 0) {
-                                       print_debug("\r\n");
-                                       print_debug_hex8(j);
-                                       print_debug(": ");
-                               }
-                               status = smbus_read_byte(device, j);
-                               if (status < 0) {
-                                       print_debug("bad device\r\n");
-                                       break;
-                               }
-                               byte = status & 0xff;
-                               print_debug_hex8(byte);
-                               print_debug_char(' ');
-                       }
-                       print_debug("\r\n");
-               }
-       }
-}
 
 static void pnp_write_config(unsigned char port, unsigned char value, unsigned char reg)
 {
@@ -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
        }
 }
index fe2f3723adf93f9b206f1e1a63a4a6bc2f419be0..8bb7869286a20b0ec016b814a085e172620ff936 100644 (file)
@@ -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 <stepan@openbios.info>
+ * (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 <device/pci_def.h>
+#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<cpus; row++)
+               setup_row(node, row, cpus);
+}
+
+static void setup_remote_row(u8 source, u8 dest, u8 cpus)
+{
+       fill_row(7, dest, generate_row(source, dest, cpus));
+}
+
+static void setup_remote_node(u8 node, u8 cpus)
+{
+       static const uint8_t pci_reg[] = { 
+               0x44, 0x4c, 0x54, 0x5c, 0x64, 0x6c, 0x74, 0x7c, 
+               0x40, 0x48, 0x50, 0x58, 0x60, 0x68, 0x70, 0x78,
+               0x84, 0x8c, 0x94, 0x9c, 0xa4, 0xac, 0xb4, 0xbc,
+               0x80, 0x88, 0x90, 0x98, 0xa0, 0xa8, 0xb0, 0xb8,
+               0xc4, 0xcc, 0xd4, 0xdc,
+               0xc0, 0xc8, 0xd0, 0xd8,
+               0xe0, 0xe4, 0xe8, 0xec,
+       };
+       uint8_t row;
+       int i;
+#if 1
+       print_debug("setup_remote_node\r\n");
+#endif
+       for(row=0; row<cpus; row++)
+               setup_remote_row(node, row, cpus);
+
+       /* copy the default resource map from node 0 */
+       for(i = 0; i < sizeof(pci_reg)/sizeof(pci_reg[0]); i++) {
+               uint32_t value;
+               uint8_t reg;
+               reg = pci_reg[i];
+               print_debug("copying reg: ");
+               print_debug_hex8(reg);
+               print_debug("\r\n");
+               value = pci_read_config32(NODE_MP(0), reg);
+               pci_write_config32(NODE_MP(7), reg, value);
+
+       }
+#if 1
+       print_debug("setup_remote_done\r\n");
+#endif
+}
+
+#endif
+
+#if MAX_CPUS > 2
+static void setup_temp_node(u8 node, u8 cpus)
+{
+       u8 row;
+       for(row=0; row<cpus; row++)
+               fill_row(7,row,generate_row(node,row,cpus));
+}
+#endif
+
+static u8 setup_uniprocessor(void)
+{
+       print_debug("Enabling UP settings\r\n");
+       disable_probes();
+       return 1;
+}
+
+#if MAX_CPUS > 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; node<cpus; node++) {
+               if (!(pci_read_config32(NODE_MC(node), 0xe8) & mask))
+                       mp_cap=FALSE;
+       }
+
+       if (mp_cap)
+               return cpus;
+
+       /* one of our cpus is not mp capable */
+
+       print_debug("One of the CPUs is not MP capable. Going back to UP\r\n");
+
+       for (node=cpus; node>0; 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; node<cpus; node++) {
+               u32 val;
+               val=pci_read_config32(NODE_HT(node), 0x60);
+               val &= 0x000F0070;
+               val |= ((cpus-1)<<16)|((cpus-1)<<4);
+               pci_write_config32(NODE_HT(node),0x60,val);
+
+               val=pci_read_config32(NODE_HT(node), 0x68);
+               val |= 0x00008000;
+               pci_write_config32(NODE_HT(node),0x68,val);
+
+               if (rev_a0) {
+                       pci_write_config32(NODE_HT(node),0x94,0);
+                       pci_write_config32(NODE_HT(node),0xb4,0);
+                       pci_write_config32(NODE_HT(node),0xd4,0);
+               }
+       }
+
+#if 1
+       print_debug("done\n");
+#endif
+}
+
+static void setup_coherent_ht_domain(void)
+{
+       unsigned cpus;
+
+       enable_bsp_routing();
+
+#if MAX_CPUS == 1
+       cpus=setup_uniprocessor();
+#else
+       cpus=setup_smp();
+       cpus=detect_mp_capabilities(cpus);
+#endif
+       coherent_ht_finalize(cpus);
+}
+
+#endif
index abfa058821403cbd38dfde543bb76472bec0dd2b..1c1e475f2c10ff44c13c81f0b1171c5a58c83154 100644 (file)
@@ -1051,7 +1051,7 @@ static void set_dimm_size(const struct mem_controller *ctrl, struct dimm_size sz
        uint32_t base0, base1, map;
        uint32_t dch;
 
-#if 1
+#if 0
        print_debug("set_dimm_size: (");
        print_debug_hex32(sz.side1);
        print_debug_char(',');
@@ -1133,6 +1133,11 @@ static void route_dram_accesses(const struct mem_controller *ctrl,
        limit -= 0x00010000;
        pci_write_config32(ctrl->f1, 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");
        }