summaryrefslogtreecommitdiff
path: root/src/northbridge
diff options
context:
space:
mode:
authorEric Biederman <ebiederm@xmission.com>2003-07-21 20:13:45 +0000
committerEric Biederman <ebiederm@xmission.com>2003-07-21 20:13:45 +0000
commit2c018fba95a5f40c4eaaa20421e8c893dffdb62e (patch)
tree3b6ecc6eb72d145dd70bb549fe0130370d7e40fb /src/northbridge
parent6d4512cdf976fc071720dbec686cf8a1a40f1db0 (diff)
downloadcoreboot-2c018fba95a5f40c4eaaa20421e8c893dffdb62e.tar.xz
- First pass at s2880 support.
- SMP cleanups (remove SMP only use CONFIG_SMP) - Minor tweaks to romcc to keep it from taking forever compiling - failover fixes - Get a good implementation of k8_cpufixup and sizeram for the opteron git-svn-id: svn://svn.coreboot.org/coreboot/trunk@998 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src/northbridge')
-rw-r--r--src/northbridge/amd/amdk8/coherent_ht.c4
-rw-r--r--src/northbridge/amd/amdk8/northbridge.c93
-rw-r--r--src/northbridge/amd/amdk8/raminit.c294
-rw-r--r--src/northbridge/amd/amdk8/raminit.h1
-rw-r--r--src/northbridge/amd/amdk8/reset_test.c8
5 files changed, 257 insertions, 143 deletions
diff --git a/src/northbridge/amd/amdk8/coherent_ht.c b/src/northbridge/amd/amdk8/coherent_ht.c
index 471af5a415..6828294ead 100644
--- a/src/northbridge/amd/amdk8/coherent_ht.c
+++ b/src/northbridge/amd/amdk8/coherent_ht.c
@@ -104,12 +104,12 @@ static void enable_routing(u8 node)
*
*/
- /* Enable routing table for BSP */
+ /* Enable routing table */
print_debug("Enabling routing table for node ");
print_debug_hex32(node);
val=pci_read_config32(NODE_HT(node), 0x6c);
- val &= ~((1<<1)|(1<<0));
+ val &= ~((1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0));
pci_write_config32(NODE_HT(node), 0x6c, val);
print_debug(" done.\r\n");
diff --git a/src/northbridge/amd/amdk8/northbridge.c b/src/northbridge/amd/amdk8/northbridge.c
index 8c2dbf1d16..4d1e6987af 100644
--- a/src/northbridge/amd/amdk8/northbridge.c
+++ b/src/northbridge/amd/amdk8/northbridge.c
@@ -2,22 +2,91 @@
#include <stdint.h>
#include <mem.h>
#include <part/sizeram.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <console/console.h>
struct mem_range *sizeram(void)
{
- static struct mem_range mem[3];
- uint32_t size;
- /* Convert size in bytes to size in K */
-#warning "FINISH sizeram"
- /* FIXME hardcoded for now */
- size = 512*1024;
+ unsigned long mmio_basek;
+ static struct mem_range mem[10];
+ device_t dev;
+ int i, idx;
- mem[0].basek = 0;
- mem[0].sizek = 640;
- mem[1].basek = 960;
- mem[1].sizek = size - mem[1].basek;
- mem[2].basek = 0;
- mem[2].sizek = 0;
+#warning "FIXME handle interleaved nodes"
+ dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
+ if (!dev) {
+ return 0;
+ }
+ mmio_basek = (dev_root.resource[1].base >> 10);
+ /* Round mmio_basek to something the processor can support */
+ mmio_basek &= ~((1 << 6) -1);
+
+#if 1
+#warning "FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M MMIO hole"
+ /* Round the mmio hold to 256M */
+ mmio_basek &= ~((256*1024) - 1);
+#endif
+
+ /* Temporary hack to get mmio handling working */
+ for(i = 0; i < 8; i++) {
+#warning "FIXME handle multiple Hypertransport chains in device.c"
+ device_t node;
+ node = dev_find_slot(0, PCI_DEVFN(0x18 + i, 1));
+ pci_write_config32(node, 0xB8, ((mmio_basek >> 6) << 8) | (1<<1) | (1 << 0));
+ pci_write_config32(node, 0xBC, 0x00ffff00);
+ }
+ for(idx = i = 0; i < 8; i++) {
+ uint32_t base, limit;
+ unsigned basek, limitk, sizek;
+ base = pci_read_config32(dev, 0x40 + (i<<3));
+ limit = pci_read_config32(dev, 0x44 + (i<<3));
+ if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) {
+ continue;
+ }
+ basek = (base & 0xffff0000) >> 2;
+ limitk = ((limit + 0x00010000) & 0xffff0000) >> 2;
+ sizek = limitk - basek;
+ if ((idx > 0) &&
+ ((mem[idx -1].basek + mem[idx - 1].sizek) == basek)) {
+ mem[idx -1].sizek += sizek;
+ }
+ else {
+ mem[idx].basek = basek;
+ mem[idx].sizek = sizek;
+ idx++;
+ }
+ /* See if I need to split the region to accomodate pci memory space */
+ if ((mem[idx - 1].basek <= mmio_basek) &&
+ ((mem[idx - 1].basek + mem[idx - 1].sizek) > mmio_basek)) {
+ if (mem[idx - 1].basek < mmio_basek) {
+ unsigned pre_sizek;
+ pre_sizek = mmio_basek - mem[idx - 1].basek;
+ mem[idx].basek = mmio_basek;
+ mem[idx].sizek = mem[idx - 1].sizek - pre_sizek;
+ mem[idx - 1].sizek = pre_sizek;
+ idx++;
+ }
+ if ((mem[idx - 1].basek + mem[idx - 1].sizek) <= 4*1024*1024) {
+ idx -= 1;
+ }
+ else {
+ mem[idx - 1].basek = 4*1024*1024;
+ mem[idx - 1].sizek -= (4*1024*1024 - mmio_basek);
+ }
+ }
+ }
+#if 0
+ for(i = 0; i < idx; i++) {
+ printk_debug("mem[%d].basek = %08x mem[%d].sizek = %08x\n",
+ i, mem[i].basek, i, mem[i].sizek);
+ }
+#endif
+ while(idx < sizeof(mem)/sizeof(mem[0])) {
+ mem[idx].basek = 0;
+ mem[idx].sizek = 0;
+ idx++;
+ }
return mem;
}
diff --git a/src/northbridge/amd/amdk8/raminit.c b/src/northbridge/amd/amdk8/raminit.c
index 41a93b51e9..1b258c62ce 100644
--- a/src/northbridge/amd/amdk8/raminit.c
+++ b/src/northbridge/amd/amdk8/raminit.c
@@ -922,10 +922,9 @@ static void sdram_set_registers(const struct mem_controller *ctrl)
};
int i;
int max;
-#if 1
- memreset_setup(ctrl);
-#endif
- print_debug("setting up CPU0 northbridge registers\r\n");
+ print_debug("setting up CPU");
+ print_debug_hex8(ctrl->node_id);
+ print_debug(" northbridge registers\r\n");
max = sizeof(register_values)/sizeof(register_values[0]);
for(i = 0; i < max; i += 3) {
device_t dev;
@@ -1001,43 +1000,43 @@ static struct dimm_size spd_get_dimm_size(unsigned device)
* a multiple of 4MB. The way we do it now we can size both
* sides of an assymetric dimm.
*/
- value = smbus_read_byte(device, 3); /* rows */
+ value = spd_read_byte(device, 3); /* rows */
if (value < 0) goto out;
sz.side1 += value & 0xf;
- value = smbus_read_byte(device, 4); /* columns */
+ value = spd_read_byte(device, 4); /* columns */
if (value < 0) goto out;
sz.side1 += value & 0xf;
- value = smbus_read_byte(device, 17); /* banks */
+ value = spd_read_byte(device, 17); /* banks */
if (value < 0) goto out;
sz.side1 += log2(value & 0xff);
/* Get the module data width and convert it to a power of two */
- value = smbus_read_byte(device, 7); /* (high byte) */
+ value = spd_read_byte(device, 7); /* (high byte) */
if (value < 0) goto out;
value &= 0xff;
value <<= 8;
- low = smbus_read_byte(device, 6); /* (low byte) */
+ low = spd_read_byte(device, 6); /* (low byte) */
if (low < 0) goto out;
value = value | (low & 0xff);
sz.side1 += log2(value);
/* side 2 */
- value = smbus_read_byte(device, 5); /* number of physical banks */
+ value = spd_read_byte(device, 5); /* number of physical banks */
if (value <= 1) goto out;
/* Start with the symmetrical case */
sz.side2 = sz.side1;
- value = smbus_read_byte(device, 3); /* rows */
+ value = spd_read_byte(device, 3); /* rows */
if (value < 0) goto out;
if ((value & 0xf0) == 0) goto out; /* If symmetrical we are done */
sz.side2 -= (value & 0x0f); /* Subtract out rows on side 1 */
sz.side2 += ((value >> 4) & 0x0f); /* Add in rows on side 2 */
- value = smbus_read_byte(device, 4); /* columns */
+ value = spd_read_byte(device, 4); /* columns */
if (value < 0) goto out;
sz.side2 -= (value & 0x0f); /* Subtract out columns on side 1 */
sz.side2 += ((value >> 4) & 0x0f); /* Add in columsn on side 2 */
@@ -1121,24 +1120,29 @@ static void spd_set_ram_size(const struct mem_controller *ctrl)
static void route_dram_accesses(const struct mem_controller *ctrl,
unsigned long base_k, unsigned long limit_k)
{
-#warning "FIXME this is hardcoded for one cpu"
+ /* Route the addresses to the controller node */
unsigned node_id;
unsigned limit;
unsigned base;
- node_id = 0;
- /* Route the addresses to node 0 */
+ unsigned index;
+ unsigned limit_reg, base_reg;
+ device_t device;
+ node_id = ctrl->node_id;
+ index = (node_id << 3);
limit = (limit_k << 2);
limit &= 0xffff0000;
limit -= 0x00010000;
+ limit |= ( 0 << 8) | (node_id << 0);
base = (base_k << 2);
base &= 0xffff0000;
- pci_write_config32(ctrl->f1, 0x44, limit | (0 << 8) | (node_id << 0));
- pci_write_config32(ctrl->f1, 0x40, base | (0 << 8) | (1<<1) | (1<<0));
+ base |= (0 << 8) | (1<<1) | (1<<0);
-#if 1
- pci_write_config32(PCI_DEV(0, 0x19, 1), 0x44, limit | (0 << 8) | (1 << 4) | (node_id << 0));
- pci_write_config32(PCI_DEV(0, 0x19, 1), 0x40, base | (0 << 8) | (1<<1) | (1<<0));
-#endif
+ limit_reg = 0x44 + index;
+ base_reg = 0x40 + index;
+ for(device = PCI_DEV(0, 0x18, 1); device <= PCI_DEV(0, 0x1f, 1); device += PCI_DEV(0, 1, 0)) {
+ pci_write_config32(device, limit_reg, limit);
+ pci_write_config32(device, base_reg, base);
+ }
}
static void set_top_mem(unsigned tom_k)
@@ -1148,6 +1152,13 @@ static void set_top_mem(unsigned tom_k)
die("No memory");
}
+#if 1
+ /* Report the amount of memory. */
+ print_debug("RAM: 0x");
+ print_debug_hex32(tom_k);
+ print_debug(" KB\r\n");
+#endif
+
/* Now set top of memory */
msr_t msr;
msr.lo = (tom_k & 0x003fffff) << 10;
@@ -1163,21 +1174,28 @@ static void set_top_mem(unsigned tom_k)
msr.lo = (tom_k & 0x003fffff) << 10;
msr.hi = (tom_k & 0xffc00000) >> 22;
wrmsr(TOP_MEM, msr);
-
-#if 1
- /* And report the amount of memory. */
- print_debug("RAM: 0x");
- print_debug_hex32(tom_k);
- print_debug(" KB\r\n");
-#endif
}
static void order_dimms(const struct mem_controller *ctrl)
{
- unsigned long tom, tom_k;
+ unsigned long tom, tom_k, base_k;
+ unsigned node_id;
+ /* Compute the memory base address address */
+ base_k = 0;
+ for(node_id = 0; node_id < ctrl->node_id; node_id++) {
+ uint32_t limit, base;
+ unsigned index;
+ index = node_id << 3;
+ base = pci_read_config32(ctrl->f1, 0x40 + index);
+ /* Only look at the limit if the base is enabled */
+ if ((base & 3) == 3) {
+ limit = pci_read_config32(ctrl->f1, 0x44 + index);
+ base_k = ((limit + 0x00010000) & 0xffff0000) >> 2;
+ }
+ }
/* Remember which registers we have used in the high 8 bits of tom */
- tom = 0;
+ tom = base_k >> 15;
for(;;) {
/* Find the largest remaining canidate */
unsigned index, canidate;
@@ -1212,12 +1230,24 @@ static void order_dimms(const struct mem_controller *ctrl)
break;
}
- /* Remember I have used this register */
- tom |= (1 << (canidate + 24));
-
/* Remember the dimm size */
size = csbase >> 21;
+ /* If this is the first chip select, round base_k to
+ * be a multiple of it's size. Then set tom to equal
+ * base_k.
+ * I assume that size is a power of two.
+ */
+ if ((tom & 0xff000000) == 0) {
+ unsigned size_k;
+ size_k = size << 15;
+ base_k = (base_k + size_k -1) & ~(size_k -1);
+ tom = base_k >> 15;
+ }
+
+ /* Remember I have used this register */
+ tom |= (1 << (canidate + 24));
+
/* Recompute the cs base register value */
csbase = (tom << 21) | 1;
@@ -1239,11 +1269,13 @@ static void order_dimms(const struct mem_controller *ctrl)
#if 0
print_debug("tom: ");
print_debug_hex32(tom);
+ print_debug(" base_k: ");
+ print_debug_hex32(base_k);
print_debug(" tom_k: ");
print_debug_hex32(tom_k);
print_debug("\r\n");
#endif
- route_dram_accesses(ctrl, 0, tom_k);
+ route_dram_accesses(ctrl, base_k, tom_k);
set_top_mem(tom_k);
}
@@ -1267,7 +1299,7 @@ static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl)
registered = 0;
for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
int value;
- value = smbus_read_byte(ctrl->channel0[i], 21);
+ value = spd_read_byte(ctrl->channel0[i], 21);
if (value < 0) {
disable_dimm(ctrl, i);
continue;
@@ -1307,31 +1339,30 @@ static void spd_enable_2channels(const struct mem_controller *ctrl)
{
int i;
uint32_t nbcap;
- /* SMBUS addresses to verify are identical */
+ /* SPD addresses to verify are identical */
#warning "FINISHME review and see if these are the bytes I need"
/* FINISHME review and see if these are the bytes I need */
static const unsigned addresses[] = {
2, /* Type should be DDR SDRAM */
- 3, /* Row addresses */
- 4, /* Column addresses */
- 5, /* Physical Banks */
- 6, /* Module Data Width low */
- 7, /* Module Data Width high */
- 9, /* Cycle time at highest CAS Latency CL=X */
- 11, /* SDRAM Type */
- 12, /* Refresh Interval */
- 13, /* SDRAM Width */
- 15, /* Back-to-Back Random Column Access */
- 16, /* Burst Lengths */
- 17, /* Logical Banks */
- 18, /* Supported CAS Latencies */
- 23, /* Cycle time at CAS Latnecy (CLX - 0.5) */
- 26, /* Cycle time at CAS Latnecy (CLX - 1.0) */
- 27, /* tRP Row precharge time */
- 29, /* tRCD RAS to CAS */
- 30, /* tRAS Activate to Precharge */
- 31, /* Module Bank Density */
- 33, /* Address and Command Hold Time After Clock */
+ 3, /* *Row addresses */
+ 4, /* *Column addresses */
+ 5, /* *Physical Banks */
+ 6, /* *Module Data Width low */
+ 7, /* *Module Data Width high */
+ 9, /* *Cycle time at highest CAS Latency CL=X */
+ 11, /* *SDRAM Type */
+ 13, /* *SDRAM Width */
+ 17, /* *Logical Banks */
+ 18, /* *Supported CAS Latencies */
+ 21, /* *SDRAM Module Attributes */
+ 23, /* *Cycle time at CAS Latnecy (CLX - 0.5) */
+ 26, /* *Cycle time at CAS Latnecy (CLX - 1.0) */
+ 27, /* *tRP Row precharge time */
+ 28, /* *Minimum Row Active to Row Active Delay (tRRD) */
+ 29, /* *tRCD RAS to CAS */
+ 30, /* *tRAS Activate to Precharge */
+ 41, /* *Minimum Active to Active/Auto Refresh Time(Trc) */
+ 42, /* *Minimum Auto Refresh Command Time(Trfc) */
};
nbcap = pci_read_config32(ctrl->f3, NORTHBRIDGE_CAP);
if (!(nbcap & NBCAP_128Bit)) {
@@ -1348,11 +1379,11 @@ static void spd_enable_2channels(const struct mem_controller *ctrl)
for(j = 0; j < sizeof(addresses)/sizeof(addresses[0]); j++) {
unsigned addr;
addr = addresses[j];
- value0 = smbus_read_byte(device0, addr);
+ value0 = spd_read_byte(device0, addr);
if (value0 < 0) {
break;
}
- value1 = smbus_read_byte(device1, addr);
+ value1 = spd_read_byte(device1, addr);
if (value1 < 0) {
return;
}
@@ -1498,7 +1529,7 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
new_cycle_time = 0xa0;
new_latency = 5;
- latencies = smbus_read_byte(ctrl->channel0[i], 18);
+ latencies = spd_read_byte(ctrl->channel0[i], 18);
if (latencies <= 0) continue;
/* Compute the lowest cas latency supported */
@@ -1511,7 +1542,7 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
(!(latencies & (1 << latency)))) {
continue;
}
- value = smbus_read_byte(ctrl->channel0[i], latency_indicies[index]);
+ value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
if (value < 0) {
continue;
}
@@ -1553,7 +1584,7 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
int index;
int value;
int dimm;
- latencies = smbus_read_byte(ctrl->channel0[i], 18);
+ latencies = spd_read_byte(ctrl->channel0[i], 18);
if (latencies <= 0) {
goto dimm_err;
}
@@ -1575,7 +1606,7 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
}
/* Read the min_cycle_time for this latency */
- value = smbus_read_byte(ctrl->channel0[i], latency_indicies[index]);
+ value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
/* All is good if the selected clock speed
* is what I need or slower.
@@ -1619,7 +1650,7 @@ static int update_dimm_Trc(const struct mem_controller *ctrl, const struct mem_p
unsigned clocks, old_clocks;
uint32_t dtl;
int value;
- value = smbus_read_byte(ctrl->channel0[i], 41);
+ value = spd_read_byte(ctrl->channel0[i], 41);
if (value < 0) return -1;
if ((value == 0) || (value == 0xff)) {
value = param->tRC;
@@ -1648,7 +1679,7 @@ static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_
unsigned clocks, old_clocks;
uint32_t dtl;
int value;
- value = smbus_read_byte(ctrl->channel0[i], 42);
+ value = spd_read_byte(ctrl->channel0[i], 42);
if (value < 0) return -1;
if ((value == 0) || (value == 0xff)) {
value = param->tRFC;
@@ -1677,7 +1708,7 @@ static int update_dimm_Trcd(const struct mem_controller *ctrl, const struct mem_
unsigned clocks, old_clocks;
uint32_t dtl;
int value;
- value = smbus_read_byte(ctrl->channel0[i], 29);
+ value = spd_read_byte(ctrl->channel0[i], 29);
if (value < 0) return -1;
#if 0
clocks = (value + (param->divisor << 1) -1)/(param->divisor << 1);
@@ -1706,7 +1737,7 @@ static int update_dimm_Trrd(const struct mem_controller *ctrl, const struct mem_
unsigned clocks, old_clocks;
uint32_t dtl;
int value;
- value = smbus_read_byte(ctrl->channel0[i], 28);
+ value = spd_read_byte(ctrl->channel0[i], 28);
if (value < 0) return -1;
clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
if (clocks < DTL_TRRD_MIN) {
@@ -1731,7 +1762,7 @@ static int update_dimm_Tras(const struct mem_controller *ctrl, const struct mem_
unsigned clocks, old_clocks;
uint32_t dtl;
int value;
- value = smbus_read_byte(ctrl->channel0[i], 30);
+ value = spd_read_byte(ctrl->channel0[i], 30);
if (value < 0) return -1;
clocks = ((value << 1) + param->divisor - 1)/param->divisor;
if (clocks < DTL_TRAS_MIN) {
@@ -1756,7 +1787,7 @@ static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_p
unsigned clocks, old_clocks;
uint32_t dtl;
int value;
- value = smbus_read_byte(ctrl->channel0[i], 27);
+ value = spd_read_byte(ctrl->channel0[i], 27);
if (value < 0) return -1;
#if 0
clocks = (value + (param->divisor << 1) - 1)/(param->divisor << 1);
@@ -1813,7 +1844,7 @@ static int update_dimm_Tref(const struct mem_controller *ctrl, const struct mem_
uint32_t dth;
int value;
unsigned tref, old_tref;
- value = smbus_read_byte(ctrl->channel0[i], 3);
+ value = spd_read_byte(ctrl->channel0[i], 3);
if (value < 0) return -1;
value &= 0xf;
@@ -1841,7 +1872,7 @@ static int update_dimm_x4(const struct mem_controller *ctrl, const struct mem_pa
uint32_t dcl;
int value;
int dimm;
- value = smbus_read_byte(ctrl->channel0[i], 13);
+ value = spd_read_byte(ctrl->channel0[i], 13);
if (value < 0) {
return -1;
}
@@ -1860,7 +1891,7 @@ static int update_dimm_ecc(const struct mem_controller *ctrl, const struct mem_p
{
uint32_t dcl;
int value;
- value = smbus_read_byte(ctrl->channel0[i], 11);
+ value = spd_read_byte(ctrl->channel0[i], 11);
if (value < 0) {
return -1;
}
@@ -2169,78 +2200,89 @@ static void sdram_set_spd_registers(const struct mem_controller *ctrl)
}
#define TIMEOUT_LOOPS 300000
-static void sdram_enable(const struct mem_controller *ctrl)
+static void sdram_enable(int controllers, const struct mem_controller *ctrl)
{
- uint32_t dcl, dch;
+ int i;
/* Before enabling memory start the memory clocks */
- dch = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH);
- dch |= DCH_MEMCLK_VALID;
- pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, dch);
+ for(i = 0; i < controllers; i++) {
+ uint32_t dch;
+ dch = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_HIGH);
+ dch |= DCH_MEMCLK_VALID;
+ pci_write_config32(ctrl[i].f2, DRAM_CONFIG_HIGH, dch);
+ }
/* And if necessary toggle the the reset on the dimms by hand */
- memreset(ctrl);
-
- /* Toggle DisDqsHys to get it working */
- dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW);
- print_debug("dcl: ");
- print_debug_hex32(dcl);
- print_debug("\r\n");
+ memreset(controllers, ctrl);
+ for(i = 0; i < controllers; i++) {
+ uint32_t dcl;
+ /* Toggle DisDqsHys to get it working */
+ dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
+#if 0
+ print_debug("dcl: ");
+ print_debug_hex32(dcl);
+ print_debug("\r\n");
+#endif
+#if 1
+ dcl &= ~DCL_DimmEccEn;
+#endif
#warning "FIXME set the ECC type to perform"
#warning "FIXME initialize the scrub registers"
#if 0
- if (dcl & DCL_DimmEccEn) {
- print_debug("ECC enabled\r\n");
- }
-#endif
- dcl |= DCL_DisDqsHys;
- pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl);
- dcl &= ~DCL_DisDqsHys;
- dcl &= ~DCL_DLL_Disable;
- dcl &= ~DCL_D_DRV;
- dcl &= ~DCL_QFC_EN;
- dcl |= DCL_DramInit;
- pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl);
-
- print_debug("Initializing memory: ");
- int loops = 0;
- do {
- dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW);
- loops += 1;
- if ((loops & 1023) == 0) {
- print_debug(".");
+ if (dcl & DCL_DimmEccEn) {
+ print_debug("ECC enabled\r\n");
}
- } while(((dcl & DCL_DramInit) != 0) && (loops < TIMEOUT_LOOPS));
- if (loops >= TIMEOUT_LOOPS) {
- print_debug(" failed\r\n");
- } else {
- print_debug(" done\r\n");
- }
-
-#if 0
+#endif
+ dcl |= DCL_DisDqsHys;
+ pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
+ dcl &= ~DCL_DisDqsHys;
+ dcl &= ~DCL_DLL_Disable;
+ dcl &= ~DCL_D_DRV;
+ dcl &= ~DCL_QFC_EN;
+ dcl |= DCL_DramInit;
+ pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
- if (dcl & DCL_DimmEccEn) {
- print_debug("Clearing memory: ");
- loops = 0;
- dcl &= ~DCL_MemClrStatus;
- pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl);
-
+ }
+ for(i = 0; i < controllers; i++) {
+ uint32_t dcl;
+ print_debug("Initializing memory: ");
+ int loops = 0;
do {
- dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW);
+ dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
loops += 1;
if ((loops & 1023) == 0) {
- print_debug(" ");
- print_debug_hex32(loops);
+ print_debug(".");
}
- } while(((dcl & DCL_MemClrStatus) == 0) && (loops < TIMEOUT_LOOPS));
+ } while(((dcl & DCL_DramInit) != 0) && (loops < TIMEOUT_LOOPS));
if (loops >= TIMEOUT_LOOPS) {
- print_debug("failed\r\n");
+ print_debug(" failed\r\n");
} else {
- print_debug("done\r\n");
+ print_debug(" done\r\n");
+ }
+#if 0
+ if (dcl & DCL_DimmEccEn) {
+ print_debug("Clearing memory: ");
+ loops = 0;
+ dcl &= ~DCL_MemClrStatus;
+ pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
+
+ do {
+ dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
+ loops += 1;
+ if ((loops & 1023) == 0) {
+ print_debug(" ");
+ print_debug_hex32(loops);
+ }
+ } while(((dcl & DCL_MemClrStatus) == 0) && (loops < TIMEOUT_LOOPS));
+ if (loops >= TIMEOUT_LOOPS) {
+ print_debug("failed\r\n");
+ } else {
+ print_debug("done\r\n");
+ }
+ pci_write_config32(ctrl[i].f3, SCRUB_ADDR_LOW, 0);
+ pci_write_config32(ctrl[i].f3, SCRUB_ADDR_HIGH, 0);
}
- pci_write_config32(ctrl->f3, SCRUB_ADDR_LOW, 0);
- pci_write_config32(ctrl->f3, SCRUB_ADDR_HIGH, 0);
- }
#endif
+ }
}
diff --git a/src/northbridge/amd/amdk8/raminit.h b/src/northbridge/amd/amdk8/raminit.h
index 6778243706..44c9b7575c 100644
--- a/src/northbridge/amd/amdk8/raminit.h
+++ b/src/northbridge/amd/amdk8/raminit.h
@@ -2,6 +2,7 @@
#define RAMINIT_H
struct mem_controller {
+ unsigned node_id;
device_t f0, f1, f2, f3;
uint8_t channel0[4];
uint8_t channel1[4];
diff --git a/src/northbridge/amd/amdk8/reset_test.c b/src/northbridge/amd/amdk8/reset_test.c
index 949bd7cc15..ab48f9830e 100644
--- a/src/northbridge/amd/amdk8/reset_test.c
+++ b/src/northbridge/amd/amdk8/reset_test.c
@@ -34,10 +34,12 @@ static int cpu_init_detected(void)
return cpu_init;
}
-static void distinguish_cpu_resets(void)
+static void distinguish_cpu_resets(unsigned node_id)
{
uint32_t htic;
- htic = pci_read_config32(PCI_DEV(0, 0x18, 0), HT_INIT_CONTROL);
+ device_t device;
+ device = PCI_DEV(0, 0x18 + node_id, 0);
+ htic = pci_read_config32(device, HT_INIT_CONTROL);
htic |= HTIC_ColdR_Detect | HTIC_BIOSR_Detect | HTIC_INIT_Detect;
- pci_write_config32(PCI_DEV(0, 0x18, 0), HT_INIT_CONTROL, htic);
+ pci_write_config32(device, HT_INIT_CONTROL, htic);
}