From 2c018fba95a5f40c4eaaa20421e8c893dffdb62e Mon Sep 17 00:00:00 2001 From: Eric Biederman Date: Mon, 21 Jul 2003 20:13:45 +0000 Subject: - 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 --- src/northbridge/amd/amdk8/coherent_ht.c | 4 +- src/northbridge/amd/amdk8/northbridge.c | 93 ++++++++-- src/northbridge/amd/amdk8/raminit.c | 294 ++++++++++++++++++-------------- src/northbridge/amd/amdk8/raminit.h | 1 + src/northbridge/amd/amdk8/reset_test.c | 8 +- 5 files changed, 257 insertions(+), 143 deletions(-) (limited to 'src/northbridge') 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 #include #include +#include +#include +#include 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); } -- cgit v1.2.3