Author: rminnich Date: 2008-08-03 21:36:53 +0200 (Sun, 03 Aug 2008) New Revision: 715
Modified: coreboot-v3/northbridge/amd/k8/raminit.c Log: This mostly compiles.
Also, per Uwe, remove the \r\n for \n
Signed-off-by: Ronald G. Minnich rminnich@gmail.com
Acked-by: Carl-Daniel Hailfinger c-d.hailfinger.devel.2006@gmx.net
Modified: coreboot-v3/northbridge/amd/k8/raminit.c =================================================================== --- coreboot-v3/northbridge/amd/k8/raminit.c 2008-08-02 20:56:11 UTC (rev 714) +++ coreboot-v3/northbridge/amd/k8/raminit.c 2008-08-03 19:36:53 UTC (rev 715) @@ -52,7 +52,7 @@ struct device *dev; unsigned where; unsigned long reg; - printk(BIOS_DEBUG, "%08x <- %08x\r\n", register_values[i], register_values[i+2]); + printk(BIOS_DEBUG, "%08x <- %08x\n", register_values[i], register_values[i+2]); dev = register_values[i] & ~0xfff; where = register_values[i] & 0xfff; reg = pci_read_config32(dev, where); @@ -61,7 +61,7 @@ pci_write_config32(dev, where, reg); } */ - printk(BIOS_DEBUG, "done.\r\n"); + printk(BIOS_DEBUG, "done.\n"); }
static int controller_present(const struct mem_controller *ctrl) @@ -543,7 +543,7 @@ int max;
if (!controller_present(ctrl)) { - printk(BIOS_DEBUG, "No memory controller present\r\n"); + printk(BIOS_DEBUG, "No memory controller present\n"); return; } printk(BIOS_SPEW, "setting up CPU 0x%x northbridge registers ", ctrl->node_id); @@ -552,7 +552,7 @@ struct device *dev; unsigned where; unsigned long reg; - printk(BIOS_DEBUG, "%08x <- %08x\r\n", register_values[i], register_values[i+2]); + printk(BIOS_DEBUG, "%08x <- %08x\n", register_values[i], register_values[i+2]); dev = (register_values[i] & ~0xfff) - PCI_BDF(0, 0x18, 0) + ctrl->f0; where = register_values[i] & 0xfff; reg = pci_read_config32(dev, where); @@ -560,7 +560,7 @@ reg |= register_values[i+2]; pci_write_config32(dev, where, reg); } - printk(BIOS_SPEW, "done.\r\n"); + printk(BIOS_SPEW, "done.\n"); }
@@ -695,7 +695,7 @@ goto out;
val_err: - die("Bad SPD value\r\n"); + die("Bad SPD value\n"); /* If an hw_error occurs report that I have no memory */ hw_err: sz.side1 = 0; @@ -857,7 +857,7 @@
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)) { + for(device = PCI_BDF(0, 0x18, 1); device <= PCI_BDF(0, 0x1f, 1); device += PCI_BDF(0, 1, 0)) { pci_write_config32(device, limit_reg, limit); pci_write_config32(device, base_reg, base); } @@ -871,12 +871,10 @@ }
/* Report the amount of memory. */ - print_spew("RAM: 0x"); - print_spew_hex32(tom_k); - print_spew(" KB\r\n"); + printk(BIOS_SPEW, "RAM: 0x%x KB\n", tom_k);
/* Now set top of memory */ - msr_t msr; + struct msr msr; if(tom_k > (4*1024*1024)) { msr.lo = (tom_k & 0x003fffff) << 10; msr.hi = (tom_k & 0xffc00000) >> 22; @@ -988,7 +986,7 @@ if(is_dual_channel(ctrl)) { /* Also we run out of address mask bits if we try and interleave 8 4GB dimms */ if ((bits == 3) && (common_size == (1 << (32 - 3)))) { -// printk(BIOS_DEBUG, "8 4GB chip selects cannot be interleaved\r\n"); +// printk(BIOS_DEBUG, "8 4GB chip selects cannot be interleaved\n"); return 0; } csbase_inc <<=1; @@ -998,7 +996,7 @@ csbase_inc = 1 << csbase_low_d0_shift[common_cs_mode]; if(is_dual_channel(ctrl)) { if( (bits==3) && (common_cs_mode > 8)) { -// printk(BIOS_DEBUG, "8 cs_mode>8 chip selects cannot be interleaved\r\n"); +// printk(BIOS_DEBUG, "8 cs_mode>8 chip selects cannot be interleaved\n"); return 0; } csbase_inc <<=1; @@ -1124,7 +1122,7 @@ if (read_option(CMOS_VSTART_interleave_chip_selects, CMOS_VLEN_interleave_chip_selects, 1) != 0) { tom_k = interleave_chip_selects(ctrl); } else { - printk(BIOS_DEBUG, "Interleaving disabled\r\n"); + printk(BIOS_DEBUG, "Interleaving disabled\n"); tom_k = 0; } if (!tom_k) { @@ -1195,9 +1193,9 @@ } pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl); if (is_registered(ctrl)) { - printk(BIOS_DEBUG, "Registered\r\n"); + printk(BIOS_DEBUG, "Registered\n"); } else { - printk(BIOS_DEBUG, "Unbuffered\r\n"); + printk(BIOS_DEBUG, "Unbuffered\n"); } return dimm_mask; } @@ -1291,7 +1289,7 @@ } } } - printk(BIOS_SPEW, "Enabling dual channel memory\r\n"); + printk(BIOS_SPEW, "Enabling dual channel memory\n"); u32 dcl; dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); dcl &= ~DCL_32ByteEn; @@ -1321,7 +1319,7 @@ { static const struct mem_param speed[] = { { - .name = "100Mhz\r\n", + .name = "100Mhz\n", .cycle_time = 0xa0, .divisor = (10 <<1), .tRC = 0x46, @@ -1335,7 +1333,7 @@ .rdpreamble = { ((9 << 1) + 0), ((9 << 1) + 0), ((9 << 1) + 0), ((9 << 1) + 0) } }, { - .name = "133Mhz\r\n", + .name = "133Mhz\n", .cycle_time = 0x75, .divisor = (7<<1)+1, .tRC = 0x41, @@ -1349,7 +1347,7 @@ .rdpreamble = { ((8 << 1) + 0), ((7 << 1) + 0), ((7 << 1) + 1), ((7 << 1) + 0) } }, { - .name = "166Mhz\r\n", + .name = "166Mhz\n", .cycle_time = 0x60, .divisor = (6<<1), .tRC = 0x3C, @@ -1363,7 +1361,7 @@ .rdpreamble = { ((7 << 1) + 1), ((6 << 1) + 0), ((6 << 1) + 1), ((6 << 1) + 0) } }, { - .name = "200Mhz\r\n", + .name = "200Mhz\n", .cycle_time = 0x50, .divisor = (5<<1), .tRC = 0x37, @@ -1389,7 +1387,7 @@ if (!param->cycle_time) { die("min_cycle_time to low"); } - print_spew(param->name); + printk(BIOS_SPEW, param->name); #ifdef DRAM_MIN_CYCLE_TIME printk(BIOS_DEBUG, param->name); #endif @@ -1914,7 +1912,7 @@
clocks = param->dtl_trwt[lat][mtype]; if ((clocks < DTH_TRWT_MIN) || (clocks > DTH_TRWT_MAX)) { - die("Unknown Trwt\r\n"); + die("Unknown Trwt\n"); } dth = pci_read_config32(ctrl->f2, DRAM_TIMING_HIGH); @@ -2082,14 +2080,14 @@ const struct mem_param *param; long dimm_mask; if (!controller_present(ctrl)) { - printk(BIOS_DEBUG, "No memory controller present\r\n"); + printk(BIOS_DEBUG, "No memory controller present\n"); return; } hw_enable_ecc(ctrl); activate_spd_rom(ctrl); dimm_mask = spd_detect_dimms(ctrl); if (!(dimm_mask & ((1 << DIMM_SOCKETS) - 1))) { - printk(BIOS_DEBUG, "No memory for this cpu\r\n"); + printk(BIOS_DEBUG, "No memory for this cpu\n"); return; } dimm_mask = spd_enable_2channels(ctrl, dimm_mask); @@ -2113,7 +2111,7 @@ return; hw_spd_err: /* Unrecoverable error reading SPD data */ - print_err("SPD error - reset\r\n"); + print_err("SPD error - reset\n"); hard_reset(); return; } @@ -2235,7 +2233,7 @@
/* Error if I don't have memory */ if (memory_end_k(ctrl, controllers) == 0) { - die("No memory\r\n"); + die("No memory\n"); }
/* Before enabling memory start the memory clocks */ @@ -2276,7 +2274,7 @@ dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW); if (dcl & DCL_DimmEccEn) { u32 mnc; - print_spew("ECC enabled\r\n"); + printk(BIOS_SPEW, "ECC enabled\n"); mnc = pci_read_config32(ctrl[i].f3, MCA_NB_CONFIG); mnc |= MNC_ECC_EN; if (dcl & DCL_128BitEn) { @@ -2315,7 +2313,7 @@ } } while(((dcl & DCL_DramInit) != 0) && (loops < TIMEOUT_LOOPS)); if (loops >= TIMEOUT_LOOPS) { - printk(BIOS_DEBUG, " failed\r\n"); + printk(BIOS_DEBUG, " failed\n"); continue; }
@@ -2328,7 +2326,7 @@ } while(((dcl & DCL_MemClrStatus) == 0) || ((dcl & DCL_DramEnable) == 0) ); }
- printk(BIOS_DEBUG, " done\r\n"); + printk(BIOS_DEBUG, " done\n"); }
#if HW_MEM_HOLE_SIZEK != 0 @@ -2361,10 +2359,10 @@ for(i=0;i<controllers; i++) { ctrl = &ctrl_a[i]; ctrl->node_id = i; - ctrl->f0 = PCI_DEV(0, 0x18+i, 0); - ctrl->f1 = PCI_DEV(0, 0x18+i, 1); - ctrl->f2 = PCI_DEV(0, 0x18+i, 2); - ctrl->f3 = PCI_DEV(0, 0x18+i, 3); + ctrl->f0 = PCI_BDF(0, 0x18+i, 0); + ctrl->f1 = PCI_BDF(0, 0x18+i, 1); + ctrl->f2 = PCI_BDF(0, 0x18+i, 2); + ctrl->f3 = PCI_BDF(0, 0x18+i, 3);
if(spd_addr == (void *)0) continue;
@@ -2374,2383 +2372,3 @@ } } } -#endif - -/* - * This file is part of the coreboot project. - * - * Copyright (C) 2002 Linux Networx - * (Written by Eric Biederman ebiederman@lnxi.com for Linux Networx) - * Copyright (C) 2004 YingHai Lu - * Copyright (C) 2007 Ronald G. Minnich rminnich@gmail.com - * - * This program is free software; you can redistribute it and/or modify - * it under the terms of the GNU General Public License as published by - * the Free Software Foundation; version 2 of the License. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA, 02110-1301 USA - */ -/* This should be done by Eric - 2004.11 yhlu add 4 rank DIMM support - 2004.12 yhlu add D0 support - 2005.02 yhlu add E0 memory hole support -*/ -/* not yet -#if K8_REV_F_SUPPORT == 1 - #include "raminit_f.c" -#else - */ - -#include <mem.h> -#include <cache.h> -#include <mtrr.h> -#include "raminit.h" -#include "k8.h" -#include "sysconf.h" - -#ifndef QRANK_DIMM_SUPPORT -#define QRANK_DIMM_SUPPORT 0 -#endif - -static void hard_reset(void); - -static void setup_resource_map(const unsigned int *register_values, int max) -{ - int i; - printk(BIOS_DEBUG, "setting up resource map...."); - for(i = 0; i < max; i += 3) { - struct device *dev; - unsigned where; - unsigned long reg; - printk(BIOS_DEBUG, "%08x <- %08x\r\n", register_values[i], register_values[i+2]); - dev = register_values[i] & ~0xfff; - where = register_values[i] & 0xfff; - reg = pci_read_config32(dev, where); - reg &= register_values[i+1]; - reg |= register_values[i+2]; - pci_write_config32(dev, where, reg); - } - printk(BIOS_DEBUG, "done.\r\n"); -} - -static int controller_present(const struct mem_controller *ctrl) -{ - return pci_read_config32(ctrl->f0, 0) == 0x11001022; -} - -static void sdram_set_registers(const struct mem_controller *ctrl) -{ - static const unsigned int register_values[] = { - - /* Careful set limit registers before base registers which contain the enables */ - /* DRAM Limit i Registers - * F1:0x44 i = 0 - * F1:0x4C i = 1 - * F1:0x54 i = 2 - * F1:0x5C i = 3 - * F1:0x64 i = 4 - * F1:0x6C i = 5 - * F1:0x74 i = 6 - * F1:0x7C i = 7 - * [ 2: 0] Destination Node ID - * 000 = Node 0 - * 001 = Node 1 - * 010 = Node 2 - * 011 = Node 3 - * 100 = Node 4 - * 101 = Node 5 - * 110 = Node 6 - * 111 = Node 7 - * [ 7: 3] Reserved - * [10: 8] Interleave select - * specifies the values of A[14:12] to use with interleave enable. - * [15:11] Reserved - * [31:16] DRAM Limit Address i Bits 39-24 - * This field defines the upper address bits of a 40 bit address - * that define the end of the DRAM region. - */ - PCI_ADDR(0, 0x18, 1, 0x44), 0x0000f8f8, 0x00000000, - PCI_ADDR(0, 0x18, 1, 0x4C), 0x0000f8f8, 0x00000001, - PCI_ADDR(0, 0x18, 1, 0x54), 0x0000f8f8, 0x00000002, - PCI_ADDR(0, 0x18, 1, 0x5C), 0x0000f8f8, 0x00000003, - PCI_ADDR(0, 0x18, 1, 0x64), 0x0000f8f8, 0x00000004, - PCI_ADDR(0, 0x18, 1, 0x6C), 0x0000f8f8, 0x00000005, - PCI_ADDR(0, 0x18, 1, 0x74), 0x0000f8f8, 0x00000006, - PCI_ADDR(0, 0x18, 1, 0x7C), 0x0000f8f8, 0x00000007, - /* DRAM Base i Registers - * F1:0x40 i = 0 - * F1:0x48 i = 1 - * F1:0x50 i = 2 - * F1:0x58 i = 3 - * F1:0x60 i = 4 - * F1:0x68 i = 5 - * F1:0x70 i = 6 - * F1:0x78 i = 7 - * [ 0: 0] Read Enable - * 0 = Reads Disabled - * 1 = Reads Enabled - * [ 1: 1] Write Enable - * 0 = Writes Disabled - * 1 = Writes Enabled - * [ 7: 2] Reserved - * [10: 8] Interleave Enable - * 000 = No interleave - * 001 = Interleave on A[12] (2 nodes) - * 010 = reserved - * 011 = Interleave on A[12] and A[14] (4 nodes) - * 100 = reserved - * 101 = reserved - * 110 = reserved - * 111 = Interleve on A[12] and A[13] and A[14] (8 nodes) - * [15:11] Reserved - * [13:16] DRAM Base Address i Bits 39-24 - * This field defines the upper address bits of a 40-bit address - * that define the start of the DRAM region. - */ - PCI_ADDR(0, 0x18, 1, 0x40), 0x0000f8fc, 0x00000000, - PCI_ADDR(0, 0x18, 1, 0x48), 0x0000f8fc, 0x00000000, - PCI_ADDR(0, 0x18, 1, 0x50), 0x0000f8fc, 0x00000000, - PCI_ADDR(0, 0x18, 1, 0x58), 0x0000f8fc, 0x00000000, - PCI_ADDR(0, 0x18, 1, 0x60), 0x0000f8fc, 0x00000000, - PCI_ADDR(0, 0x18, 1, 0x68), 0x0000f8fc, 0x00000000, - PCI_ADDR(0, 0x18, 1, 0x70), 0x0000f8fc, 0x00000000, - PCI_ADDR(0, 0x18, 1, 0x78), 0x0000f8fc, 0x00000000, - - /* DRAM CS Base Address i Registers - * F2:0x40 i = 0 - * F2:0x44 i = 1 - * F2:0x48 i = 2 - * F2:0x4C i = 3 - * F2:0x50 i = 4 - * F2:0x54 i = 5 - * F2:0x58 i = 6 - * F2:0x5C i = 7 - * [ 0: 0] Chip-Select Bank Enable - * 0 = Bank Disabled - * 1 = Bank Enabled - * [ 8: 1] Reserved - * [15: 9] Base Address (19-13) - * An optimization used when all DIMM are the same size... - * [20:16] Reserved - * [31:21] Base Address (35-25) - * This field defines the top 11 addresses bit of a 40-bit - * address that define the memory address space. These - * bits decode 32-MByte blocks of memory. - */ - PCI_ADDR(0, 0x18, 2, 0x40), 0x001f01fe, 0x00000000, - PCI_ADDR(0, 0x18, 2, 0x44), 0x001f01fe, 0x00000000, - PCI_ADDR(0, 0x18, 2, 0x48), 0x001f01fe, 0x00000000, - PCI_ADDR(0, 0x18, 2, 0x4C), 0x001f01fe, 0x00000000, - PCI_ADDR(0, 0x18, 2, 0x50), 0x001f01fe, 0x00000000, - PCI_ADDR(0, 0x18, 2, 0x54), 0x001f01fe, 0x00000000, - PCI_ADDR(0, 0x18, 2, 0x58), 0x001f01fe, 0x00000000, - PCI_ADDR(0, 0x18, 2, 0x5C), 0x001f01fe, 0x00000000, - /* DRAM CS Mask Address i Registers - * F2:0x60 i = 0 - * F2:0x64 i = 1 - * F2:0x68 i = 2 - * F2:0x6C i = 3 - * F2:0x70 i = 4 - * F2:0x74 i = 5 - * F2:0x78 i = 6 - * F2:0x7C i = 7 - * Select bits to exclude from comparison with the DRAM Base address register. - * [ 8: 0] Reserved - * [15: 9] Address Mask (19-13) - * Address to be excluded from the optimized case - * [20:16] Reserved - * [29:21] Address Mask (33-25) - * The bits with an address mask of 1 are excluded from address comparison - * [31:30] Reserved - * - */ - PCI_ADDR(0, 0x18, 2, 0x60), 0xC01f01ff, 0x00000000, - PCI_ADDR(0, 0x18, 2, 0x64), 0xC01f01ff, 0x00000000, - PCI_ADDR(0, 0x18, 2, 0x68), 0xC01f01ff, 0x00000000, - PCI_ADDR(0, 0x18, 2, 0x6C), 0xC01f01ff, 0x00000000, - PCI_ADDR(0, 0x18, 2, 0x70), 0xC01f01ff, 0x00000000, - PCI_ADDR(0, 0x18, 2, 0x74), 0xC01f01ff, 0x00000000, - PCI_ADDR(0, 0x18, 2, 0x78), 0xC01f01ff, 0x00000000, - PCI_ADDR(0, 0x18, 2, 0x7C), 0xC01f01ff, 0x00000000, - /* DRAM Bank Address Mapping Register - * F2:0x80 - * Specify the memory module size - * [ 2: 0] CS1/0 - * [ 6: 4] CS3/2 - * [10: 8] CS5/4 - * [14:12] CS7/6 - * 000 = 32Mbyte (Rows = 12 & Col = 8) - * 001 = 64Mbyte (Rows = 12 & Col = 9) - * 010 = 128Mbyte (Rows = 13 & Col = 9)|(Rows = 12 & Col = 10) - * 011 = 256Mbyte (Rows = 13 & Col = 10)|(Rows = 12 & Col = 11) - * 100 = 512Mbyte (Rows = 13 & Col = 11)|(Rows = 14 & Col = 10) - * 101 = 1Gbyte (Rows = 14 & Col = 11)|(Rows = 13 & Col = 12) - * 110 = 2Gbyte (Rows = 14 & Col = 12) - * 111 = reserved - * [ 3: 3] Reserved - * [ 7: 7] Reserved - * [11:11] Reserved - * [31:15] - */ - PCI_ADDR(0, 0x18, 2, 0x80), 0xffff8888, 0x00000000, - /* DRAM Timing Low Register - * F2:0x88 - * [ 2: 0] Tcl (Cas# Latency, Cas# to read-data-valid) - * 000 = reserved - * 001 = CL 2 - * 010 = CL 3 - * 011 = reserved - * 100 = reserved - * 101 = CL 2.5 - * 110 = reserved - * 111 = reserved - * [ 3: 3] Reserved - * [ 7: 4] Trc (Row Cycle Time, Ras#-active to Ras#-active/bank auto refresh) - * 0000 = 7 bus clocks - * 0001 = 8 bus clocks - * ... - * 1110 = 21 bus clocks - * 1111 = 22 bus clocks - * [11: 8] Trfc (Row refresh Cycle time, Auto-refresh-active to RAS#-active or RAS#auto-refresh) - * 0000 = 9 bus clocks - * 0010 = 10 bus clocks - * .... - * 1110 = 23 bus clocks - * 1111 = 24 bus clocks - * [14:12] Trcd (Ras#-active to Case#-read/write Delay) - * 000 = reserved - * 001 = reserved - * 010 = 2 bus clocks - * 011 = 3 bus clocks - * 100 = 4 bus clocks - * 101 = 5 bus clocks - * 110 = 6 bus clocks - * 111 = reserved - * [15:15] Reserved - * [18:16] Trrd (Ras# to Ras# Delay) - * 000 = reserved - * 001 = reserved - * 010 = 2 bus clocks - * 011 = 3 bus clocks - * 100 = 4 bus clocks - * 101 = reserved - * 110 = reserved - * 111 = reserved - * [19:19] Reserved - * [23:20] Tras (Minmum Ras# Active Time) - * 0000 to 0100 = reserved - * 0101 = 5 bus clocks - * ... - * 1111 = 15 bus clocks - * [26:24] Trp (Row Precharge Time) - * 000 = reserved - * 001 = reserved - * 010 = 2 bus clocks - * 011 = 3 bus clocks - * 100 = 4 bus clocks - * 101 = 5 bus clocks - * 110 = 6 bus clocks - * 111 = reserved - * [27:27] Reserved - * [28:28] Twr (Write Recovery Time) - * 0 = 2 bus clocks - * 1 = 3 bus clocks - * [31:29] Reserved - */ - PCI_ADDR(0, 0x18, 2, 0x88), 0xe8088008, 0x02522001 /* 0x03623125 */ , - /* DRAM Timing High Register - * F2:0x8C - * [ 0: 0] Twtr (Write to Read Delay) - * 0 = 1 bus Clocks - * 1 = 2 bus Clocks - * [ 3: 1] Reserved - * [ 6: 4] Trwt (Read to Write Delay) - * 000 = 1 bus clocks - * 001 = 2 bus clocks - * 010 = 3 bus clocks - * 011 = 4 bus clocks - * 100 = 5 bus clocks - * 101 = 6 bus clocks - * 110 = reserved - * 111 = reserved - * [ 7: 7] Reserved - * [12: 8] Tref (Refresh Rate) - * 00000 = 100Mhz 4K rows - * 00001 = 133Mhz 4K rows - * 00010 = 166Mhz 4K rows - * 00011 = 200Mhz 4K rows - * 01000 = 100Mhz 8K/16K rows - * 01001 = 133Mhz 8K/16K rows - * 01010 = 166Mhz 8K/16K rows - * 01011 = 200Mhz 8K/16K rows - * [19:13] Reserved - * [22:20] Twcl (Write CAS Latency) - * 000 = 1 Mem clock after CAS# (Unbuffered Dimms) - * 001 = 2 Mem clocks after CAS# (Registered Dimms) - * [31:23] Reserved - */ - PCI_ADDR(0, 0x18, 2, 0x8c), 0xff8fe08e, (0 << 20)|(0 << 8)|(0 << 4)|(0 << 0), - /* DRAM Config Low Register - * F2:0x90 - * [ 0: 0] DLL Disable - * 0 = Enabled - * 1 = Disabled - * [ 1: 1] D_DRV - * 0 = Normal Drive - * 1 = Weak Drive - * [ 2: 2] QFC_EN - * 0 = Disabled - * 1 = Enabled - * [ 3: 3] Disable DQS Hystersis (FIXME handle this one carefully) - * 0 = Enable DQS input filter - * 1 = Disable DQS input filtering - * [ 7: 4] Reserved - * [ 8: 8] DRAM_Init - * 0 = Initialization done or not yet started. - * 1 = Initiate DRAM intialization sequence - * [ 9: 9] SO-Dimm Enable - * 0 = Do nothing - * 1 = SO-Dimms present - * [10:10] DramEnable - * 0 = DRAM not enabled - * 1 = DRAM initialized and enabled - * [11:11] Memory Clear Status - * 0 = Memory Clear function has not completed - * 1 = Memory Clear function has completed - * [12:12] Exit Self-Refresh - * 0 = Exit from self-refresh done or not yet started - * 1 = DRAM exiting from self refresh - * [13:13] Self-Refresh Status - * 0 = Normal Operation - * 1 = Self-refresh mode active - * [15:14] Read/Write Queue Bypass Count - * 00 = 2 - * 01 = 4 - * 10 = 8 - * 11 = 16 - * [16:16] 128-bit/64-Bit - * 0 = 64bit Interface to DRAM - * 1 = 128bit Interface to DRAM - * [17:17] DIMM ECC Enable - * 0 = Some DIMMs do not have ECC - * 1 = ALL DIMMS have ECC bits - * [18:18] UnBuffered DIMMs - * 0 = Buffered DIMMS - * 1 = Unbuffered DIMMS - * [19:19] Enable 32-Byte Granularity - * 0 = Optimize for 64byte bursts - * 1 = Optimize for 32byte bursts - * [20:20] DIMM 0 is x4 - * [21:21] DIMM 1 is x4 - * [22:22] DIMM 2 is x4 - * [23:23] DIMM 3 is x4 - * 0 = DIMM is not x4 - * 1 = x4 DIMM present - * [24:24] Disable DRAM Receivers - * 0 = Receivers enabled - * 1 = Receivers disabled - * [27:25] Bypass Max - * 000 = Arbiters chois is always respected - * 001 = Oldest entry in DCQ can be bypassed 1 time - * 010 = Oldest entry in DCQ can be bypassed 2 times - * 011 = Oldest entry in DCQ can be bypassed 3 times - * 100 = Oldest entry in DCQ can be bypassed 4 times - * 101 = Oldest entry in DCQ can be bypassed 5 times - * 110 = Oldest entry in DCQ can be bypassed 6 times - * 111 = Oldest entry in DCQ can be bypassed 7 times - * [31:28] Reserved - */ - PCI_ADDR(0, 0x18, 2, 0x90), 0xf0000000, - (4 << 25)|(0 << 24)| - (0 << 23)|(0 << 22)|(0 << 21)|(0 << 20)| - (1 << 19)|(0 << 18)|(1 << 17)|(0 << 16)| - (2 << 14)|(0 << 13)|(0 << 12)| - (0 << 11)|(0 << 10)|(0 << 9)|(0 << 8)| - (0 << 3) |(0 << 1) |(0 << 0), - /* DRAM Config High Register - * F2:0x94 - * [ 0: 3] Maximum Asynchronous Latency - * 0000 = 0 ns - * ... - * 1111 = 15 ns - * [ 7: 4] Reserved - * [11: 8] Read Preamble - * 0000 = 2.0 ns - * 0001 = 2.5 ns - * 0010 = 3.0 ns - * 0011 = 3.5 ns - * 0100 = 4.0 ns - * 0101 = 4.5 ns - * 0110 = 5.0 ns - * 0111 = 5.5 ns - * 1000 = 6.0 ns - * 1001 = 6.5 ns - * 1010 = 7.0 ns - * 1011 = 7.5 ns - * 1100 = 8.0 ns - * 1101 = 8.5 ns - * 1110 = 9.0 ns - * 1111 = 9.5 ns - * [15:12] Reserved - * [18:16] Idle Cycle Limit - * 000 = 0 cycles - * 001 = 4 cycles - * 010 = 8 cycles - * 011 = 16 cycles - * 100 = 32 cycles - * 101 = 64 cycles - * 110 = 128 cycles - * 111 = 256 cycles - * [19:19] Dynamic Idle Cycle Center Enable - * 0 = Use Idle Cycle Limit - * 1 = Generate a dynamic Idle cycle limit - * [22:20] DRAM MEMCLK Frequency - * 000 = 100Mhz - * 001 = reserved - * 010 = 133Mhz - * 011 = reserved - * 100 = reserved - * 101 = 166Mhz - * 110 = reserved - * 111 = reserved - * [24:23] Reserved - * [25:25] Memory Clock Ratio Valid (FIXME carefully enable memclk) - * 0 = Disable MemClks - * 1 = Enable MemClks - * [26:26] Memory Clock 0 Enable - * 0 = Disabled - * 1 = Enabled - * [27:27] Memory Clock 1 Enable - * 0 = Disabled - * 1 = Enabled - * [28:28] Memory Clock 2 Enable - * 0 = Disabled - * 1 = Enabled - * [29:29] Memory Clock 3 Enable - * 0 = Disabled - * 1 = Enabled - * [31:30] Reserved - */ - PCI_ADDR(0, 0x18, 2, 0x94), 0xc180f0f0, - (0 << 29)|(0 << 28)|(0 << 27)|(0 << 26)|(0 << 25)| - (0 << 20)|(0 << 19)|(DCH_IDLE_LIMIT_16 << 16)|(0 << 8)|(0 << 0), - /* DRAM Delay Line Register - * F2:0x98 - * Adjust the skew of the input DQS strobe relative to DATA - * [15: 0] Reserved - * [23:16] Delay Line Adjust - * Adjusts the DLL derived PDL delay by one or more delay stages - * in either the faster or slower direction. - * [24:24} Adjust Slower - * 0 = Do Nothing - * 1 = Adj is used to increase the PDL delay - * [25:25] Adjust Faster - * 0 = Do Nothing - * 1 = Adj is used to decrease the PDL delay - * [31:26] Reserved - */ - PCI_ADDR(0, 0x18, 2, 0x98), 0xfc00ffff, 0x00000000, - /* MCA NB Status Low reg */ - PCI_ADDR(0, 0x18, 3, 0x48), 0x00f00000, 0x00000000, - /* MCA NB Status high reg */ - PCI_ADDR(0, 0x18, 3, 0x4c), 0x01801e8c, 0x00000000, - /* MCA NB address Low reg */ - PCI_ADDR(0, 0x18, 3, 0x50), 0x00000007, 0x00000000, - /* MCA NB address high reg */ - PCI_ADDR(0, 0x18, 3, 0x54), 0xffffff00, 0x00000000, - /* DRAM Scrub Control Register - * F3:0x58 - * [ 4: 0] DRAM Scrube Rate - * [ 7: 5] reserved - * [12: 8] L2 Scrub Rate - * [15:13] reserved - * [20:16] Dcache Scrub - * [31:21] reserved - * Scrub Rates - * 00000 = Do not scrub - * 00001 = 40.00 ns - * 00010 = 80.00 ns - * 00011 = 160.00 ns - * 00100 = 320.00 ns - * 00101 = 640.00 ns - * 00110 = 1.28 us - * 00111 = 2.56 us - * 01000 = 5.12 us - * 01001 = 10.20 us - * 01011 = 41.00 us - * 01100 = 81.90 us - * 01101 = 163.80 us - * 01110 = 327.70 us - * 01111 = 655.40 us - * 10000 = 1.31 ms - * 10001 = 2.62 ms - * 10010 = 5.24 ms - * 10011 = 10.49 ms - * 10100 = 20.97 ms - * 10101 = 42.00 ms - * 10110 = 84.00 ms - * All Others = Reserved - */ - PCI_ADDR(0, 0x18, 3, 0x58), 0xffe0e0e0, 0x00000000, - /* DRAM Scrub Address Low Register - * F3:0x5C - * [ 0: 0] DRAM Scrubber Redirect Enable - * 0 = Do nothing - * 1 = Scrubber Corrects errors found in normal operation - * [ 5: 1] Reserved - * [31: 6] DRAM Scrub Address 31-6 - */ - PCI_ADDR(0, 0x18, 3, 0x5C), 0x0000003e, 0x00000000, - /* DRAM Scrub Address High Register - * F3:0x60 - * [ 7: 0] DRAM Scrubb Address 39-32 - * [31: 8] Reserved - */ - PCI_ADDR(0, 0x18, 3, 0x60), 0xffffff00, 0x00000000, - }; - int i; - int max; - - if (!controller_present(ctrl)) { - printk(BIOS_DEBUG, "No memory controller present\r\n"); - return; - } - printk(BIOS_SPEW, "setting up CPU 0x%x northbridge registers ", ctrl->node_id); - max = sizeof(register_values)/sizeof(register_values[0]); -/* - for(i = 0; i < max; i += 3) { - struct device *dev; - unsigned where; - unsigned long reg; - printk(BIOS_DEBUG, "%08x <- %08x\r\n", register_values[i], register_values[i+2]); - dev = (register_values[i] & ~0xfff) - PCI_DEV(0, 0x18, 0) + ctrl->f0; - where = register_values[i] & 0xfff; - reg = pci_read_config32(dev, where); - reg &= register_values[i+1]; - reg |= register_values[i+2]; - pci_write_config32(dev, where, reg); - } -*/ - printk(BIOS_SPEW, "done.\r\n"); -} - - -static void hw_enable_ecc(const struct mem_controller *ctrl) -{ - u32 dcl, nbcap; - nbcap = pci_read_config32(ctrl->f3, NORTHBRIDGE_CAP); - dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); - dcl &= ~DCL_DimmEccEn; - if (nbcap & NBCAP_ECC) { - dcl |= DCL_DimmEccEn; - } - if (read_option(CMOS_VSTART_ECC_memory, CMOS_VLEN_ECC_memory, 1) == 0) { - dcl &= ~DCL_DimmEccEn; - } - pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl); - -} - -static int is_dual_channel(const struct mem_controller *ctrl) -{ - u32 dcl; - dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); - return dcl & DCL_128BitEn; -} - -static int is_opteron(const struct mem_controller *ctrl) -{ - /* Test to see if I am an Opteron. - * FIXME Socket 939 based Athlon64 have dual channel capability, - * too, so we need a better test for Opterons - */ -#warning "FIXME: Implement a better test for Opterons" - u32 nbcap; - nbcap = pci_read_config32(ctrl->f3, NORTHBRIDGE_CAP); - return !!(nbcap & NBCAP_128Bit); -} - -static int is_registered(const struct mem_controller *ctrl) -{ - /* Test to see if we are dealing with registered SDRAM. - * If we are not registered we are unbuffered. - * This function must be called after spd_handle_unbuffered_dimms. - */ - u32 dcl; - dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); - return !(dcl & DCL_UnBufDimm); -} - -struct dimm_size { - unsigned long side1; - unsigned long side2; - unsigned long rows; - unsigned long col; -#if QRANK_DIMM_SUPPORT == 1 - unsigned long rank; -#endif -}; - -static struct dimm_size spd_get_dimm_size(unsigned device) -{ - /* Calculate the log base 2 size of a DIMM in bits */ - struct dimm_size sz; - int value, low; - sz.side1 = 0; - sz.side2 = 0; - sz.rows = 0; - sz.col = 0; -#if QRANK_DIMM_SUPPORT == 1 - sz.rank = 0; -#endif - - /* Note it might be easier to use byte 31 here, it has the DIMM size as - * a multiple of 4MB. The way we do it now we can size both - * sides of an assymetric dimm. - */ - value = spd_read_byte(device, 3); /* rows */ - if (value < 0) goto hw_err; - if ((value & 0xf) == 0) goto val_err; - sz.side1 += value & 0xf; - sz.rows = value & 0xf; - - value = spd_read_byte(device, 4); /* columns */ - if (value < 0) goto hw_err; - if ((value & 0xf) == 0) goto val_err; - sz.side1 += value & 0xf; - sz.col = value & 0xf; - - value = spd_read_byte(device, 17); /* banks */ - if (value < 0) goto hw_err; - if ((value & 0xff) == 0) goto val_err; - sz.side1 += log2(value & 0xff); - - /* Get the module data width and convert it to a power of two */ - value = spd_read_byte(device, 7); /* (high byte) */ - if (value < 0) goto hw_err; - value &= 0xff; - value <<= 8; - - low = spd_read_byte(device, 6); /* (low byte) */ - if (low < 0) goto hw_err; - value = value | (low & 0xff); - if ((value != 72) && (value != 64)) goto val_err; - sz.side1 += log2(value); - - /* side 2 */ - value = spd_read_byte(device, 5); /* number of physical banks */ - if (value < 0) goto hw_err; - if (value == 1) goto out; - if ((value != 2) && (value != 4 )) { - goto val_err; - } -#if QRANK_DIMM_SUPPORT == 1 - sz.rank = value; -#endif - - /* Start with the symmetrical case */ - sz.side2 = sz.side1; - - value = spd_read_byte(device, 3); /* rows */ - if (value < 0) goto hw_err; - 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 = spd_read_byte(device, 4); /* columns */ - if (value < 0) goto hw_err; - if ((value & 0xff) == 0) goto val_err; - sz.side2 -= (value & 0x0f); /* Subtract out columns on side 1 */ - sz.side2 += ((value >> 4) & 0x0f); /* Add in columsn on side 2 */ - - goto out; - - val_err: - die("Bad SPD value\r\n"); - /* If an hw_error occurs report that I have no memory */ -hw_err: - sz.side1 = 0; - sz.side2 = 0; - sz.rows = 0; - sz.col = 0; -#if QRANK_DIMM_SUPPORT == 1 - sz.rank = 0; -#endif - out: - return sz; -} - - -static void set_dimm_size(const struct mem_controller *ctrl, struct dimm_size sz, unsigned index) -{ - u32 base0, base1; - u32 dch; - - if (sz.side1 != sz.side2) { - sz.side2 = 0; - } - - /* For each base register. - * Place the dimm size in 32 MB quantities in the bits 31 - 21. - * The initialize dimm size is in bits. - * Set the base enable bit0. - */ - - base0 = base1 = 0; - - /* Make certain side1 of the dimm is at least 32MB */ - if (sz.side1 >= (25 +3)) { - base0 = (1 << ((sz.side1 - (25 + 3)) + 21)) | 1; - } - - /* Make certain side2 of the dimm is at least 32MB */ - if (sz.side2 >= (25 + 3)) { - base1 = (1 << ((sz.side2 - (25 + 3)) + 21)) | 1; - } - - /* Double the size if we are using dual channel memory */ - if (is_dual_channel(ctrl)) { - base0 = (base0 << 1) | (base0 & 1); - base1 = (base1 << 1) | (base1 & 1); - } - - /* Clear the reserved bits */ - base0 &= ~0x001ffffe; - base1 &= ~0x001ffffe; - - /* Set the appropriate DIMM base address register */ - pci_write_config32(ctrl->f2, DRAM_CSBASE + (((index << 1)+0)<<2), base0); - pci_write_config32(ctrl->f2, DRAM_CSBASE + (((index << 1)+1)<<2), base1); -#if QRANK_DIMM_SUPPORT == 1 - if(sz.rank == 4) { - pci_write_config32(ctrl->f2, DRAM_CSBASE + (((index << 1)+4)<<2), base0); - pci_write_config32(ctrl->f2, DRAM_CSBASE + (((index << 1)+5)<<2), base1); - } -#endif - - /* Enable the memory clocks for this DIMM */ - if (base0) { - dch = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH); - dch |= DCH_MEMCLK_EN0 << index; -#if QRANK_DIMM_SUPPORT == 1 - if(sz.rank == 4) { - dch |= DCH_MEMCLK_EN0 << (index + 2); - } -#endif - pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, dch); - } -} - -static void set_dimm_map(const struct mem_controller *ctrl, struct dimm_size sz, unsigned index) -{ - static const unsigned cs_map_aa[] = { - /* (row=12, col=8)(14, 12) ---> (0, 0) (2, 4) */ - 0, 1, 3, 6, 0, - 0, 2, 4, 7, 9, - 0, 0, 5, 8,10, - }; - - u32 map; - u32 dch; - - map = pci_read_config32(ctrl->f2, DRAM_BANK_ADDR_MAP); - map &= ~(0xf << (index * 4)); -#if QRANK_DIMM_SUPPORT == 1 - if(sz.rank == 4) { - map &= ~(0xf << ( (index + 2) * 4)); - } -#endif - - - /* Make certain side1 of the dimm is at least 32MB */ - if (sz.side1 >= (25 +3)) { - if(is_cpu_pre_d0()) { - map |= (sz.side1 - (25 + 3)) << (index *4); -#if QRANK_DIMM_SUPPORT == 1 - if(sz.rank == 4) { - map |= (sz.side1 - (25 + 3)) << ( (index + 2) * 4); - } -#endif - } - else { - map |= cs_map_aa[(sz.rows - 12) * 5 + (sz.col - 8) ] << (index*4); -#if QRANK_DIMM_SUPPORT == 1 - if(sz.rank == 4) { - map |= cs_map_aa[(sz.rows - 12) * 5 + (sz.col - 8) ] << ( (index + 2) * 4); - } -#endif - } - } - - pci_write_config32(ctrl->f2, DRAM_BANK_ADDR_MAP, map); - -} - -static long spd_set_ram_size(const struct mem_controller *ctrl, long dimm_mask) -{ - int i; - - for(i = 0; i < DIMM_SOCKETS; i++) { - struct dimm_size sz; - if (!(dimm_mask & (1 << i))) { - continue; - } - sz = spd_get_dimm_size(ctrl->channel0[i]); - if (sz.side1 == 0) { - return -1; /* Report SPD error */ - } - set_dimm_size(ctrl, sz, i); - set_dimm_map (ctrl, sz, i); - } - return dimm_mask; -} - -static void route_dram_accesses(const struct mem_controller *ctrl, - unsigned long base_k, unsigned long limit_k) -{ - /* Route the addresses to the controller node */ - unsigned node_id; - unsigned limit; - unsigned base; - unsigned index; - unsigned limit_reg, base_reg; - struct device *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; - base |= (0 << 8) | (1<<1) | (1<<0); - - 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, unsigned hole_startk) -{ - /* Error if I don't have memory */ - if (!tom_k) { - die("No memory?"); - } - - /* Report the amount of memory. */ - print_spew("RAM: 0x"); - print_spew_hex32(tom_k); - print_spew(" KB\r\n"); - - /* Now set top of memory */ - msr_t msr; - if(tom_k > (4*1024*1024)) { - 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) { -#if HW_MEM_HOLE_SIZEK != 0 - if(hole_startk != 0) { - tom_k = hole_startk; - } else -#endif - tom_k = 0x3f0000; - } - msr.lo = (tom_k & 0x003fffff) << 10; - msr.hi = (tom_k & 0xffc00000) >> 22; - wrmsr(TOP_MEM, msr); -} - -static unsigned long interleave_chip_selects(const struct mem_controller *ctrl) -{ - /* 35 - 25 */ - static const u8 csbase_low_shift[] = { - /* 32MB */ (13 - 4), - /* 64MB */ (14 - 4), - /* 128MB */ (14 - 4), - /* 256MB */ (15 - 4), - /* 512MB */ (15 - 4), - /* 1GB */ (16 - 4), - /* 2GB */ (16 - 4), - }; - - static const u8 csbase_low_d0_shift[] = { - /* 32MB */ (13 - 4), - /* 64MB */ (14 - 4), - /* 128MB */ (14 - 4), - /* 128MB */ (15 - 4), - /* 256MB */ (15 - 4), - /* 512MB */ (15 - 4), - /* 256MB */ (16 - 4), - /* 512MB */ (16 - 4), - /* 1GB */ (16 - 4), - /* 1GB */ (17 - 4), - /* 2GB */ (17 - 4), - }; - - /* cs_base_high is not changed */ - - u32 csbase_inc; - int chip_selects, index; - int bits; - unsigned common_size; - unsigned common_cs_mode; - u32 csbase, csmask; - - /* See if all of the memory chip selects are the same size - * and if so count them. - */ - chip_selects = 0; - common_size = 0; - common_cs_mode = 0; - for(index = 0; index < 8; index++) { - unsigned size; - unsigned cs_mode; - u32 value; - - value = pci_read_config32(ctrl->f2, DRAM_CSBASE + (index << 2)); - - /* Is it enabled? */ - if (!(value & 1)) { - continue; - } - chip_selects++; - size = value >> 21; - if (common_size == 0) { - common_size = size; - } - /* The size differed fail */ - if (common_size != size) { - return 0; - } - - value = pci_read_config32(ctrl->f2, DRAM_BANK_ADDR_MAP); - cs_mode =( value >> ((index>>1)*4)) & 0xf; - if(cs_mode == 0 ) continue; - if(common_cs_mode == 0) { - common_cs_mode = cs_mode; - } - /* The size differed fail */ - if(common_cs_mode != cs_mode) { - return 0; - } - } - - /* Chip selects can only be interleaved when there is - * more than one and their is a power of two of them. - */ - bits = log2(chip_selects); - if (((1 << bits) != chip_selects) || (bits < 1) || (bits > 3)) { - return 0; - } - - /* Find the bits of csbase that we need to interleave on */ - if(is_cpu_pre_d0()){ - csbase_inc = 1 << csbase_low_shift[common_cs_mode]; - if(is_dual_channel(ctrl)) { - /* Also we run out of address mask bits if we try and interleave 8 4GB dimms */ - if ((bits == 3) && (common_size == (1 << (32 - 3)))) { -// printk(BIOS_DEBUG, "8 4GB chip selects cannot be interleaved\r\n"); - return 0; - } - csbase_inc <<=1; - } - } - else { - csbase_inc = 1 << csbase_low_d0_shift[common_cs_mode]; - if(is_dual_channel(ctrl)) { - if( (bits==3) && (common_cs_mode > 8)) { -// printk(BIOS_DEBUG, "8 cs_mode>8 chip selects cannot be interleaved\r\n"); - return 0; - } - csbase_inc <<=1; - } - } - - /* Compute the initial values for csbase and csbask. - * In csbase just set the enable bit and the base to zero. - * In csmask set the mask bits for the size and page level interleave. - */ - csbase = 0 | 1; - csmask = (((common_size << bits) - 1) << 21); - csmask |= 0xfe00 & ~((csbase_inc << bits) - csbase_inc); - for(index = 0; index < 8; index++) { - u32 value; - - value = pci_read_config32(ctrl->f2, DRAM_CSBASE + (index << 2)); - /* Is it enabled? */ - if (!(value & 1)) { - continue; - } - pci_write_config32(ctrl->f2, DRAM_CSBASE + (index << 2), csbase); - pci_write_config32(ctrl->f2, DRAM_CSMASK + (index << 2), csmask); - csbase += csbase_inc; - } - - printk(BIOS_SPEW, "Interleaved\n"); - - /* Return the memory size in K */ - return common_size << (15 + bits); -} - -static unsigned long order_chip_selects(const struct mem_controller *ctrl) -{ - unsigned long tom; - - /* Remember which registers we have used in the high 8 bits of tom */ - tom = 0; - for(;;) { - /* Find the largest remaining canidate */ - unsigned index, canidate; - u32 csbase, csmask; - unsigned size; - csbase = 0; - canidate = 0; - for(index = 0; index < 8; index++) { - u32 value; - value = pci_read_config32(ctrl->f2, DRAM_CSBASE + (index << 2)); - - /* Is it enabled? */ - if (!(value & 1)) { - continue; - } - - /* Is it greater? */ - if (value <= csbase) { - continue; - } - - /* Has it already been selected */ - if (tom & (1 << (index + 24))) { - continue; - } - /* I have a new canidate */ - csbase = value; - canidate = index; - } - /* See if I have found a new canidate */ - if (csbase == 0) { - break; - } - - /* Remember the dimm size */ - size = csbase >> 21; - - /* Remember I have used this register */ - tom |= (1 << (canidate + 24)); - - /* Recompute the cs base register value */ - csbase = (tom << 21) | 1; - - /* Increment the top of memory */ - tom += size; - - /* Compute the memory mask */ - csmask = ((size -1) << 21); - csmask |= 0xfe00; /* For now don't optimize */ - - /* Write the new base register */ - pci_write_config32(ctrl->f2, DRAM_CSBASE + (canidate << 2), csbase); - /* Write the new mask register */ - pci_write_config32(ctrl->f2, DRAM_CSMASK + (canidate << 2), csmask); - - } - /* Return the memory size in K */ - return (tom & ~0xff000000) << 15; -} - -unsigned long memory_end_k(const struct mem_controller *ctrl, int max_node_id) -{ - unsigned node_id; - unsigned end_k; - /* Find the last memory address used */ - end_k = 0; - for(node_id = 0; node_id < max_node_id; node_id++) { - u32 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); - end_k = ((limit + 0x00010000) & 0xffff0000) >> 2; - } - } - return end_k; -} - -static void order_dimms(const struct mem_controller *ctrl) -{ - unsigned long tom_k, base_k; - - if (read_option(CMOS_VSTART_interleave_chip_selects, CMOS_VLEN_interleave_chip_selects, 1) != 0) { - tom_k = interleave_chip_selects(ctrl); - } else { - printk(BIOS_DEBUG, "Interleaving disabled\r\n"); - tom_k = 0; - } - if (!tom_k) { - tom_k = order_chip_selects(ctrl); - } - /* Compute the memory base address */ - base_k = memory_end_k(ctrl, ctrl->node_id); - tom_k += base_k; - route_dram_accesses(ctrl, base_k, tom_k); - set_top_mem(tom_k, 0); -} - -static long disable_dimm(const struct mem_controller *ctrl, unsigned index, long dimm_mask) -{ - printk(BIOS_DEBUG, "disabling dimm 0x%x\n", index); - pci_write_config32(ctrl->f2, DRAM_CSBASE + (((index << 1)+0)<<2), 0); - pci_write_config32(ctrl->f2, DRAM_CSBASE + (((index << 1)+1)<<2), 0); - dimm_mask &= ~(1 << index); - return dimm_mask; -} - -static long spd_handle_unbuffered_dimms(const struct mem_controller *ctrl, long dimm_mask) -{ - int i; - int registered; - int unbuffered; - int has_dualch = is_opteron(ctrl); - u32 dcl; - unbuffered = 0; - registered = 0; - for(i = 0; (i < DIMM_SOCKETS); i++) { - int value; - if (!(dimm_mask & (1 << i))) { - continue; - } - value = spd_read_byte(ctrl->channel0[i], 21); - if (value < 0) { - return -1; - } - /* Registered dimm ? */ - if (value & (1 << 1)) { - registered = 1; - } - /* Otherwise it must be an unbuffered dimm */ - else { - unbuffered = 1; - } - } - if (unbuffered && registered) { - die("Mixed buffered and registered dimms not supported"); - } - - dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); - dcl &= ~DCL_UnBufDimm; - if (unbuffered) { - if ((has_dualch) && (!is_cpu_pre_d0())) { - dcl |= DCL_UnBufDimm; /* set DCL_DualDIMMen too? */ - - /* set DCL_En2T if you have non-equal DDR mem types! */ - - if ((cpuid_eax(1) & 0x30) == 0x30) { - /* CS[7:4] is copy of CS[3:0], should be set for 939 socket */ - dcl |= DCL_UpperCSMap; - } - } else { - dcl |= DCL_UnBufDimm; - } - } - pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl); - if (is_registered(ctrl)) { - printk(BIOS_DEBUG, "Registered\r\n"); - } else { - printk(BIOS_DEBUG, "Unbuffered\r\n"); - } - return dimm_mask; -} - -static unsigned int spd_detect_dimms(const struct mem_controller *ctrl) -{ - unsigned dimm_mask; - int i; - dimm_mask = 0; - for(i = 0; i < DIMM_SOCKETS; i++) { - int byte; - unsigned device; - device = ctrl->channel0[i]; - if (device) { - byte = spd_read_byte(ctrl->channel0[i], 2); /* Type */ - if (byte == 7) { - dimm_mask |= (1 << i); - } - } - device = ctrl->channel1[i]; - if (device) { - byte = spd_read_byte(ctrl->channel1[i], 2); - if (byte == 7) { - dimm_mask |= (1 << (i + DIMM_SOCKETS)); - } - } - } - return dimm_mask; -} - -static long spd_enable_2channels(const struct mem_controller *ctrl, long dimm_mask) -{ - int i; - u32 nbcap; - /* SPD addresses to verify are identical */ - static const u8 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 */ - 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) */ - }; - /* If the dimms are not in pairs do not do dual channels */ - if ((dimm_mask & ((1 << DIMM_SOCKETS) - 1)) != - ((dimm_mask >> DIMM_SOCKETS) & ((1 << DIMM_SOCKETS) - 1))) { - goto single_channel; - } - /* If the cpu is not capable of doing dual channels don't do dual channels */ - nbcap = pci_read_config32(ctrl->f3, NORTHBRIDGE_CAP); - if (!(nbcap & NBCAP_128Bit)) { - goto single_channel; - } - for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) { - unsigned device0, device1; - int value0, value1; - int j; - /* If I don't have a dimm skip this one */ - if (!(dimm_mask & (1 << i))) { - continue; - } - device0 = ctrl->channel0[i]; - device1 = ctrl->channel1[i]; - for(j = 0; j < sizeof(addresses)/sizeof(addresses[0]); j++) { - unsigned addr; - addr = addresses[j]; - value0 = spd_read_byte(device0, addr); - if (value0 < 0) { - return -1; - } - value1 = spd_read_byte(device1, addr); - if (value1 < 0) { - return -1; - } - if (value0 != value1) { - goto single_channel; - } - } - } - printk(BIOS_SPEW, "Enabling dual channel memory\r\n"); - u32 dcl; - dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); - dcl &= ~DCL_32ByteEn; - dcl |= DCL_128BitEn; - pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl); - return dimm_mask; - single_channel: - dimm_mask &= ~((1 << (DIMM_SOCKETS *2)) - (1 << DIMM_SOCKETS)); - return dimm_mask; -} - -struct mem_param { - u8 cycle_time; - u8 divisor; /* In 1/2 ns increments */ - u8 tRC; - u8 tRFC; - u32 dch_memclk; - u16 dch_tref4k, dch_tref8k; - u8 dtl_twr; - u8 dtl_twtr; - u8 dtl_trwt[3][3]; /* first index is CAS_LAT 2/2.5/3 and 128/registered64/64 */ - u8 rdpreamble[4]; /* 0 is for registered, 1 for 1-2 DIMMS, 2 and 3 for 3 or 4 unreg dimm slots */ - char name[9]; -}; - -static const struct mem_param *get_mem_param(unsigned min_cycle_time) -{ - static const struct mem_param speed[] = { - { - .name = "100Mhz\r\n", - .cycle_time = 0xa0, - .divisor = (10 <<1), - .tRC = 0x46, - .tRFC = 0x50, - .dch_memclk = DCH_MEMCLK_100MHZ << DCH_MEMCLK_SHIFT, - .dch_tref4k = DTH_TREF_100MHZ_4K, - .dch_tref8k = DTH_TREF_100MHZ_8K, - .dtl_twr = 2, - .dtl_twtr = 1, - .dtl_trwt = { { 2, 2, 3 }, { 3, 3, 4 }, { 3, 3, 4 }}, - .rdpreamble = { ((9 << 1) + 0), ((9 << 1) + 0), ((9 << 1) + 0), ((9 << 1) + 0) } - }, - { - .name = "133Mhz\r\n", - .cycle_time = 0x75, - .divisor = (7<<1)+1, - .tRC = 0x41, - .tRFC = 0x4B, - .dch_memclk = DCH_MEMCLK_133MHZ << DCH_MEMCLK_SHIFT, - .dch_tref4k = DTH_TREF_133MHZ_4K, - .dch_tref8k = DTH_TREF_133MHZ_8K, - .dtl_twr = 2, - .dtl_twtr = 1, - .dtl_trwt = { { 2, 2, 3 }, { 3, 3, 4 }, { 3, 3, 4 }}, - .rdpreamble = { ((8 << 1) + 0), ((7 << 1) + 0), ((7 << 1) + 1), ((7 << 1) + 0) } - }, - { - .name = "166Mhz\r\n", - .cycle_time = 0x60, - .divisor = (6<<1), - .tRC = 0x3C, - .tRFC = 0x48, - .dch_memclk = DCH_MEMCLK_166MHZ << DCH_MEMCLK_SHIFT, - .dch_tref4k = DTH_TREF_166MHZ_4K, - .dch_tref8k = DTH_TREF_166MHZ_8K, - .dtl_twr = 3, - .dtl_twtr = 1, - .dtl_trwt = { { 3, 2, 3 }, { 3, 3, 4 }, { 4, 3, 4 }}, - .rdpreamble = { ((7 << 1) + 1), ((6 << 1) + 0), ((6 << 1) + 1), ((6 << 1) + 0) } - }, - { - .name = "200Mhz\r\n", - .cycle_time = 0x50, - .divisor = (5<<1), - .tRC = 0x37, - .tRFC = 0x46, - .dch_memclk = DCH_MEMCLK_200MHZ << DCH_MEMCLK_SHIFT, - .dch_tref4k = DTH_TREF_200MHZ_4K, - .dch_tref8k = DTH_TREF_200MHZ_8K, - .dtl_twr = 3, - .dtl_twtr = 2, - .dtl_trwt = { { 0, 2, 3 }, { 3, 3, 4 }, { 3, 3, 4 }}, - .rdpreamble = { ((7 << 1) + 0), ((5 << 1) + 0), ((5 << 1) + 1), ((5 << 1) + 1) } - }, - { - .cycle_time = 0x00, - }, - }; - const struct mem_param *param; - for(param = &speed[0]; param->cycle_time ; param++) { - if (min_cycle_time > (param+1)->cycle_time) { - break; - } - } - if (!param->cycle_time) { - die("min_cycle_time to low"); - } - print_spew(param->name); -#ifdef DRAM_MIN_CYCLE_TIME - printk(BIOS_DEBUG, param->name); -#endif - return param; -} - -struct spd_set_memclk_result { - const struct mem_param *param; - long dimm_mask; -}; -static struct spd_set_memclk_result spd_set_memclk(const struct mem_controller *ctrl, long dimm_mask) -{ - /* Compute the minimum cycle time for these dimms */ - struct spd_set_memclk_result result; - unsigned min_cycle_time, min_latency, bios_cycle_time; - int i; - u32 value; - - static const u8 latency_indicies[] = { 26, 23, 9 }; - static const unsigned char min_cycle_times[] = { - [NBCAP_MEMCLK_200MHZ] = 0x50, /* 5ns */ - [NBCAP_MEMCLK_166MHZ] = 0x60, /* 6ns */ - [NBCAP_MEMCLK_133MHZ] = 0x75, /* 7.5ns */ - [NBCAP_MEMCLK_100MHZ] = 0xa0, /* 10ns */ - }; - - value = pci_read_config32(ctrl->f3, NORTHBRIDGE_CAP); - - min_cycle_time = min_cycle_times[(value >> NBCAP_MEMCLK_SHIFT) & NBCAP_MEMCLK_MASK]; - bios_cycle_time = min_cycle_times[ - read_option(CMOS_VSTART_max_mem_clock, CMOS_VLEN_max_mem_clock, 0)]; - if (bios_cycle_time > min_cycle_time) { - min_cycle_time = bios_cycle_time; - } - min_latency = 2; - - /* Compute the least latency with the fastest clock supported - * by both the memory controller and the dimms. - */ - for(i = 0; i < DIMM_SOCKETS; i++) { - int new_cycle_time, new_latency; - int index; - int latencies; - int latency; - - if (!(dimm_mask & (1 << i))) { - continue; - } - - /* First find the supported CAS latencies - * Byte 18 for DDR SDRAM is interpreted: - * bit 0 == CAS Latency = 1.0 - * bit 1 == CAS Latency = 1.5 - * bit 2 == CAS Latency = 2.0 - * bit 3 == CAS Latency = 2.5 - * bit 4 == CAS Latency = 3.0 - * bit 5 == CAS Latency = 3.5 - * bit 6 == TBD - * bit 7 == TBD - */ - new_cycle_time = 0xa0; - new_latency = 5; - - latencies = spd_read_byte(ctrl->channel0[i], 18); - if (latencies <= 0) continue; - - /* Compute the lowest cas latency supported */ - latency = log2(latencies) -2; - - /* Loop through and find a fast clock with a low latency */ - for(index = 0; index < 3; index++, latency++) { - int value; - if ((latency < 2) || (latency > 4) || - (!(latencies & (1 << latency)))) { - continue; - } - value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]); - if (value < 0) { - goto hw_error; - } - - /* Only increase the latency if we decreas the clock */ - if ((value >= min_cycle_time) && (value < new_cycle_time)) { - new_cycle_time = value; - new_latency = latency; - } - } - if (new_latency > 4){ - continue; - } - /* Does min_latency need to be increased? */ - if (new_cycle_time > min_cycle_time) { - min_cycle_time = new_cycle_time; - } - /* Does min_cycle_time need to be increased? */ - if (new_latency > min_latency) { - min_latency = new_latency; - } - } - /* Make a second pass through the dimms and disable - * any that cannot support the selected memclk and cas latency. - */ - - for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) { - int latencies; - int latency; - int index; - int value; - if (!(dimm_mask & (1 << i))) { - continue; - } - latencies = spd_read_byte(ctrl->channel0[i], 18); - if (latencies < 0) goto hw_error; - if (latencies == 0) { - goto dimm_err; - } - - /* Compute the lowest cas latency supported */ - latency = log2(latencies) -2; - - /* Walk through searching for the selected latency */ - for(index = 0; index < 3; index++, latency++) { - if (!(latencies & (1 << latency))) { - continue; - } - if (latency == min_latency) - break; - } - /* If I can't find the latency or my index is bad error */ - if ((latency != min_latency) || (index >= 3)) { - goto dimm_err; - } - - /* Read the min_cycle_time for this latency */ - value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]); - if (value < 0) goto hw_error; - - /* All is good if the selected clock speed - * is what I need or slower. - */ - if (value <= min_cycle_time) { - continue; - } - /* Otherwise I have an error, disable the dimm */ - dimm_err: - dimm_mask = disable_dimm(ctrl, i, dimm_mask); - } -#if 0 -//down speed for full load 4 rank support -#if QRANK_DIMM_SUPPORT - if(dimm_mask == (3|(3<<DIMM_SOCKETS)) ) { - int ranks = 4; - for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) { - int val; - if (!(dimm_mask & (1 << i))) { - continue; - } - val = spd_read_byte(ctrl->channel0[i], 5); - if(val!=ranks) { - ranks = val; - break; - } - } - if(ranks==4) { - if(min_cycle_time <= 0x50 ) { - min_cycle_time = 0x60; - } - } - - } -#endif -#endif - /* Now that I know the minimum cycle time lookup the memory parameters */ - result.param = get_mem_param(min_cycle_time); - - /* Update DRAM Config High with our selected memory speed */ - value = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH); - value &= ~(DCH_MEMCLK_MASK << DCH_MEMCLK_SHIFT); -#if 0 - /* Improves DQS centering by correcting for case when core speed multiplier and MEMCLK speed - * result in odd clock divisor, by selecting the next lowest memory speed, required only at DDR400 - * and higher speeds with certain DIMM loadings ---- cheating???*/ - if(!is_cpu_pre_e0()) { - if(min_cycle_time==0x50) { - value |= 1<<31; - } - } -#endif - - value |= result.param->dch_memclk; - pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, value); - - static const unsigned latencies[] = { DTL_CL_2, DTL_CL_2_5, DTL_CL_3 }; - /* Update DRAM Timing Low with our selected cas latency */ - value = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW); - value &= ~(DTL_TCL_MASK << DTL_TCL_SHIFT); - value |= latencies[min_latency - 2] << DTL_TCL_SHIFT; - pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, value); - - result.dimm_mask = dimm_mask; - return result; - hw_error: - result.param = (const struct mem_param *)0; - result.dimm_mask = -1; - return result; -} - - -static int update_dimm_Trc(const struct mem_controller *ctrl, const struct mem_param *param, int i) -{ - unsigned clocks, old_clocks; - u32 dtl; - int value; - value = spd_read_byte(ctrl->channel0[i], 41); - if (value < 0) return -1; - if ((value == 0) || (value == 0xff)) { - value = param->tRC; - } - clocks = ((value << 1) + param->divisor - 1)/param->divisor; - if (clocks < DTL_TRC_MIN) { - clocks = DTL_TRC_MIN; - } - if (clocks > DTL_TRC_MAX) { - return 0; - } - - dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW); - old_clocks = ((dtl >> DTL_TRC_SHIFT) & DTL_TRC_MASK) + DTL_TRC_BASE; - if (old_clocks > clocks) { - clocks = old_clocks; - } - dtl &= ~(DTL_TRC_MASK << DTL_TRC_SHIFT); - dtl |= ((clocks - DTL_TRC_BASE) << DTL_TRC_SHIFT); - pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, dtl); - return 1; -} - -static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_param *param, int i) -{ - unsigned clocks, old_clocks; - u32 dtl; - int value; - value = spd_read_byte(ctrl->channel0[i], 42); - if (value < 0) return -1; - if ((value == 0) || (value == 0xff)) { - value = param->tRFC; - } - clocks = ((value << 1) + param->divisor - 1)/param->divisor; - if (clocks < DTL_TRFC_MIN) { - clocks = DTL_TRFC_MIN; - } - if (clocks > DTL_TRFC_MAX) { - return 0; - } - dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW); - old_clocks = ((dtl >> DTL_TRFC_SHIFT) & DTL_TRFC_MASK) + DTL_TRFC_BASE; - if (old_clocks > clocks) { - clocks = old_clocks; - } - dtl &= ~(DTL_TRFC_MASK << DTL_TRFC_SHIFT); - dtl |= ((clocks - DTL_TRFC_BASE) << DTL_TRFC_SHIFT); - pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, dtl); - return 1; -} - - -static int update_dimm_Trcd(const struct mem_controller *ctrl, const struct mem_param *param, int i) -{ - unsigned clocks, old_clocks; - u32 dtl; - int value; - value = spd_read_byte(ctrl->channel0[i], 29); - if (value < 0) return -1; - clocks = (value + (param->divisor << 1) -1)/(param->divisor << 1); - if (clocks < DTL_TRCD_MIN) { - clocks = DTL_TRCD_MIN; - } - if (clocks > DTL_TRCD_MAX) { - return 0; - } - dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW); - old_clocks = ((dtl >> DTL_TRCD_SHIFT) & DTL_TRCD_MASK) + DTL_TRCD_BASE; - if (old_clocks > clocks) { - clocks = old_clocks; - } - dtl &= ~(DTL_TRCD_MASK << DTL_TRCD_SHIFT); - dtl |= ((clocks - DTL_TRCD_BASE) << DTL_TRCD_SHIFT); - pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, dtl); - return 1; -} - -static int update_dimm_Trrd(const struct mem_controller *ctrl, const struct mem_param *param, int i) -{ - unsigned clocks, old_clocks; - u32 dtl; - int value; - value = spd_read_byte(ctrl->channel0[i], 28); - if (value < 0) return -1; - clocks = (value + (param->divisor << 1) -1)/(param->divisor << 1); - if (clocks < DTL_TRRD_MIN) { - clocks = DTL_TRRD_MIN; - } - if (clocks > DTL_TRRD_MAX) { - return 0; - } - dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW); - old_clocks = ((dtl >> DTL_TRRD_SHIFT) & DTL_TRRD_MASK) + DTL_TRRD_BASE; - if (old_clocks > clocks) { - clocks = old_clocks; - } - dtl &= ~(DTL_TRRD_MASK << DTL_TRRD_SHIFT); - dtl |= ((clocks - DTL_TRRD_BASE) << DTL_TRRD_SHIFT); - pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, dtl); - return 1; -} - -static int update_dimm_Tras(const struct mem_controller *ctrl, const struct mem_param *param, int i) -{ - unsigned clocks, old_clocks; - u32 dtl; - int value; - 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) { - clocks = DTL_TRAS_MIN; - } - if (clocks > DTL_TRAS_MAX) { - return 0; - } - dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW); - old_clocks = ((dtl >> DTL_TRAS_SHIFT) & DTL_TRAS_MASK) + DTL_TRAS_BASE; - if (old_clocks > clocks) { - clocks = old_clocks; - } - dtl &= ~(DTL_TRAS_MASK << DTL_TRAS_SHIFT); - dtl |= ((clocks - DTL_TRAS_BASE) << DTL_TRAS_SHIFT); - pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, dtl); - return 1; -} - -static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_param *param, int i) -{ - unsigned clocks, old_clocks; - u32 dtl; - int value; - value = spd_read_byte(ctrl->channel0[i], 27); - if (value < 0) return -1; - clocks = (value + (param->divisor << 1) - 1)/(param->divisor << 1); - if (clocks < DTL_TRP_MIN) { - clocks = DTL_TRP_MIN; - } - if (clocks > DTL_TRP_MAX) { - return 0; - } - dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW); - old_clocks = ((dtl >> DTL_TRP_SHIFT) & DTL_TRP_MASK) + DTL_TRP_BASE; - if (old_clocks > clocks) { - clocks = old_clocks; - } - dtl &= ~(DTL_TRP_MASK << DTL_TRP_SHIFT); - dtl |= ((clocks - DTL_TRP_BASE) << DTL_TRP_SHIFT); - pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, dtl); - return 1; -} - -static void set_Twr(const struct mem_controller *ctrl, const struct mem_param *param) -{ - u32 dtl; - dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW); - dtl &= ~(DTL_TWR_MASK << DTL_TWR_SHIFT); - dtl |= (param->dtl_twr - DTL_TWR_BASE) << DTL_TWR_SHIFT; - pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, dtl); -} - - -static void init_Tref(const struct mem_controller *ctrl, const struct mem_param *param) -{ - u32 dth; - dth = pci_read_config32(ctrl->f2, DRAM_TIMING_HIGH); - dth &= ~(DTH_TREF_MASK << DTH_TREF_SHIFT); - dth |= (param->dch_tref4k << DTH_TREF_SHIFT); - pci_write_config32(ctrl->f2, DRAM_TIMING_HIGH, dth); -} - -static int update_dimm_Tref(const struct mem_controller *ctrl, const struct mem_param *param, int i) -{ - u32 dth; - int value; - unsigned tref, old_tref; - value = spd_read_byte(ctrl->channel0[i], 3); - if (value < 0) return -1; - value &= 0xf; - - tref = param->dch_tref8k; - if (value == 12) { - tref = param->dch_tref4k; - } - - dth = pci_read_config32(ctrl->f2, DRAM_TIMING_HIGH); - old_tref = (dth >> DTH_TREF_SHIFT) & DTH_TREF_MASK; - if ((value == 12) && (old_tref == param->dch_tref4k)) { - tref = param->dch_tref4k; - } else { - tref = param->dch_tref8k; - } - dth &= ~(DTH_TREF_MASK << DTH_TREF_SHIFT); - dth |= (tref << DTH_TREF_SHIFT); - pci_write_config32(ctrl->f2, DRAM_TIMING_HIGH, dth); - return 1; -} - - -static int update_dimm_x4(const struct mem_controller *ctrl, const struct mem_param *param, int i) -{ - u32 dcl; - int value; -#if QRANK_DIMM_SUPPORT == 1 - int rank; -#endif - int dimm; - value = spd_read_byte(ctrl->channel0[i], 13); - if (value < 0) { - return -1; - } - -#if QRANK_DIMM_SUPPORT == 1 - rank = spd_read_byte(ctrl->channel0[i], 5); /* number of physical banks */ - if (rank < 0) { - return -1; - } -#endif - - dimm = 1<<(DCL_x4DIMM_SHIFT+i); -#if QRANK_DIMM_SUPPORT == 1 - if(rank==4) { - dimm |= 1<<(DCL_x4DIMM_SHIFT+i+2); - } -#endif - dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); - dcl &= ~dimm; - if (value == 4) { - dcl |= dimm; - } - pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl); - return 1; -} - -static int update_dimm_ecc(const struct mem_controller *ctrl, const struct mem_param *param, int i) -{ - u32 dcl; - int value; - value = spd_read_byte(ctrl->channel0[i], 11); - if (value < 0) { - return -1; - } - if (value != 2) { - dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); - dcl &= ~DCL_DimmEccEn; - pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl); - } - return 1; -} - -static int count_dimms(const struct mem_controller *ctrl) -{ - int dimms; - unsigned index; - dimms = 0; - for(index = 0; index < 8; index += 2) { - u32 csbase; - csbase = pci_read_config32(ctrl->f2, (DRAM_CSBASE + (index << 2))); - if (csbase & 1) { - dimms += 1; - } - } - return dimms; -} - -static void set_Twtr(const struct mem_controller *ctrl, const struct mem_param *param) -{ - u32 dth; - - dth = pci_read_config32(ctrl->f2, DRAM_TIMING_HIGH); - dth &= ~(DTH_TWTR_MASK << DTH_TWTR_SHIFT); - dth |= ((param->dtl_twtr - DTH_TWTR_BASE) << DTH_TWTR_SHIFT); - pci_write_config32(ctrl->f2, DRAM_TIMING_HIGH, dth); -} - -static void set_Trwt(const struct mem_controller *ctrl, const struct mem_param *param) -{ - u32 dth, dtl; - unsigned latency; - unsigned clocks; - int lat, mtype; - - clocks = 0; - dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW); - latency = (dtl >> DTL_TCL_SHIFT) & DTL_TCL_MASK; - - if (is_opteron(ctrl)) { - mtype = 0; /* dual channel */ - } else if (is_registered(ctrl)) { - mtype = 1; /* registered 64bit interface */ - } else { - mtype = 2; /* unbuffered 64bit interface */ - } - - switch (latency) { - case DTL_CL_2: - lat = 0; - break; - case DTL_CL_2_5: - lat = 1; - break; - case DTL_CL_3: - lat = 2; - break; - default: - die("Unknown LAT for Trwt"); - } - - clocks = param->dtl_trwt[lat][mtype]; - if ((clocks < DTH_TRWT_MIN) || (clocks > DTH_TRWT_MAX)) { - die("Unknown Trwt\r\n"); - } - - dth = pci_read_config32(ctrl->f2, DRAM_TIMING_HIGH); - dth &= ~(DTH_TRWT_MASK << DTH_TRWT_SHIFT); - dth |= ((clocks - DTH_TRWT_BASE) << DTH_TRWT_SHIFT); - pci_write_config32(ctrl->f2, DRAM_TIMING_HIGH, dth); - return; -} - -static void set_Twcl(const struct mem_controller *ctrl, const struct mem_param *param) -{ - /* Memory Clocks after CAS# */ - u32 dth; - unsigned clocks; - if (is_registered(ctrl)) { - clocks = 2; - } else { - clocks = 1; - } - dth = pci_read_config32(ctrl->f2, DRAM_TIMING_HIGH); - dth &= ~(DTH_TWCL_MASK << DTH_TWCL_SHIFT); - dth |= ((clocks - DTH_TWCL_BASE) << DTH_TWCL_SHIFT); - pci_write_config32(ctrl->f2, DRAM_TIMING_HIGH, dth); -} - - -static void set_read_preamble(const struct mem_controller *ctrl, const struct mem_param *param) -{ - u32 dch; - unsigned rdpreamble; - int slots, i; - - slots = 0; - - for(i = 0; i < 4; i++) { - if (ctrl->channel0[i]) { - slots += 1; - } - } - - /* map to index to param.rdpreamble array */ - if (is_registered(ctrl)) { - i = 0; - } else if (slots < 3) { - i = 1; - } else if (slots == 3) { - i = 2; - } else if (slots == 4) { - i = 3; - } else { - die("Unknown rdpreamble for this nr of slots"); - } - - dch = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH); - dch &= ~(DCH_RDPREAMBLE_MASK << DCH_RDPREAMBLE_SHIFT); - rdpreamble = param->rdpreamble[i]; - - if ((rdpreamble < DCH_RDPREAMBLE_MIN) || (rdpreamble > DCH_RDPREAMBLE_MAX)) { - die("Unknown rdpreamble"); - } - - dch |= (rdpreamble - DCH_RDPREAMBLE_BASE) << DCH_RDPREAMBLE_SHIFT; - pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, dch); -} - -static void set_max_async_latency(const struct mem_controller *ctrl, const struct mem_param *param) -{ - u32 dch; - unsigned async_lat; - int dimms; - - dimms = count_dimms(ctrl); - - dch = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH); - dch &= ~(DCH_ASYNC_LAT_MASK << DCH_ASYNC_LAT_SHIFT); - async_lat = 0; - if (is_registered(ctrl)) { - if (dimms == 4) { - /* 9ns */ - async_lat = 9; - } - else { - /* 8ns */ - async_lat = 8; - } - } - else { - if (dimms > 3) { - die("Too many unbuffered dimms"); - } - else if (dimms == 3) { - /* 7ns */ - async_lat = 7; - } - else { - /* 6ns */ - async_lat = 6; - } - } - dch |= ((async_lat - DCH_ASYNC_LAT_BASE) << DCH_ASYNC_LAT_SHIFT); - pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, dch); -} - -static void set_idle_cycle_limit(const struct mem_controller *ctrl, const struct mem_param *param) -{ - u32 dch; - /* AMD says to Hardcode this */ - dch = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH); - dch &= ~(DCH_IDLE_LIMIT_MASK << DCH_IDLE_LIMIT_SHIFT); - dch |= DCH_IDLE_LIMIT_16 << DCH_IDLE_LIMIT_SHIFT; - dch |= DCH_DYN_IDLE_CTR_EN; - pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, dch); -} - -static long spd_set_dram_timing(const struct mem_controller *ctrl, const struct mem_param *param, long dimm_mask) -{ - int i; - - init_Tref(ctrl, param); - for(i = 0; i < DIMM_SOCKETS; i++) { - int rc; - if (!(dimm_mask & (1 << i))) { - continue; - } - /* DRAM Timing Low Register */ - if ((rc = update_dimm_Trc (ctrl, param, i)) <= 0) goto dimm_err; - if ((rc = update_dimm_Trfc(ctrl, param, i)) <= 0) goto dimm_err; - if ((rc = update_dimm_Trcd(ctrl, param, i)) <= 0) goto dimm_err; - if ((rc = update_dimm_Trrd(ctrl, param, i)) <= 0) goto dimm_err; - if ((rc = update_dimm_Tras(ctrl, param, i)) <= 0) goto dimm_err; - if ((rc = update_dimm_Trp (ctrl, param, i)) <= 0) goto dimm_err; - - /* DRAM Timing High Register */ - if ((rc = update_dimm_Tref(ctrl, param, i)) <= 0) goto dimm_err; - - - /* DRAM Config Low */ - if ((rc = update_dimm_x4 (ctrl, param, i)) <= 0) goto dimm_err; - if ((rc = update_dimm_ecc(ctrl, param, i)) <= 0) goto dimm_err; - continue; - dimm_err: - if (rc < 0) { - return -1; - } - dimm_mask = disable_dimm(ctrl, i, dimm_mask); - } - /* DRAM Timing Low Register */ - set_Twr(ctrl, param); - - /* DRAM Timing High Register */ - set_Twtr(ctrl, param); - set_Trwt(ctrl, param); - set_Twcl(ctrl, param); - - /* DRAM Config High */ - set_read_preamble(ctrl, param); - set_max_async_latency(ctrl, param); - set_idle_cycle_limit(ctrl, param); - return dimm_mask; -} - -static void sdram_set_spd_registers(const struct mem_controller *ctrl, struct sys_info *sysinfo) -{ - struct spd_set_memclk_result result; - const struct mem_param *param; - long dimm_mask; - if (!controller_present(ctrl)) { - printk(BIOS_DEBUG, "No memory controller present\r\n"); - return; - } - hw_enable_ecc(ctrl); - activate_spd_rom(ctrl); - dimm_mask = spd_detect_dimms(ctrl); - if (!(dimm_mask & ((1 << DIMM_SOCKETS) - 1))) { - printk(BIOS_DEBUG, "No memory for this cpu\r\n"); - return; - } - dimm_mask = spd_enable_2channels(ctrl, dimm_mask); - if (dimm_mask < 0) - goto hw_spd_err; - dimm_mask = spd_set_ram_size(ctrl , dimm_mask); - if (dimm_mask < 0) - goto hw_spd_err; - dimm_mask = spd_handle_unbuffered_dimms(ctrl, dimm_mask); - if (dimm_mask < 0) - goto hw_spd_err; - result = spd_set_memclk(ctrl, dimm_mask); - param = result.param; - dimm_mask = result.dimm_mask; - if (dimm_mask < 0) - goto hw_spd_err; - dimm_mask = spd_set_dram_timing(ctrl, param , dimm_mask); - if (dimm_mask < 0) - goto hw_spd_err; - order_dimms(ctrl); - return; - hw_spd_err: - /* Unrecoverable error reading SPD data */ - print_err("SPD error - reset\r\n"); - hard_reset(); - return; -} - -#if HW_MEM_HOLE_SIZEK != 0 -static u32 hoist_memory(int controllers, const struct mem_controller *ctrl,unsigned hole_startk, int i) -{ - int ii; - u32 carry_over; - struct device *dev; - u32 base, limit; - u32 basek; - u32 hoist; - int j; - - carry_over = (4*1024*1024) - hole_startk; - - for(ii=controllers - 1;ii>i;ii--) { - base = pci_read_config32(ctrl[0].f1, 0x40 + (ii << 3)); - if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) { - continue; - } - limit = pci_read_config32(ctrl[0].f1, 0x44 + (ii << 3)); - for(j = 0; j < controllers; j++) { - pci_write_config32(ctrl[j].f1, 0x44 + (ii << 3), limit + (carry_over << 2)); - pci_write_config32(ctrl[j].f1, 0x40 + (ii << 3), base + (carry_over << 2)); - } - } - limit = pci_read_config32(ctrl[0].f1, 0x44 + (i << 3)); - for(j = 0; j < controllers; j++) { - pci_write_config32(ctrl[j].f1, 0x44 + (i << 3), limit + (carry_over << 2)); - } - dev = ctrl[i].f1; - base = pci_read_config32(dev, 0x40 + (i << 3)); - basek = (base & 0xffff0000) >> 2; - if(basek == hole_startk) { - //don't need set memhole here, because hole off set will be 0, overflow - //so need to change base reg instead, new basek will be 4*1024*1024 - base &= 0x0000ffff; - base |= (4*1024*1024)<<2; - for(j = 0; j < controllers; j++) { - pci_write_config32(ctrl[j].f1, 0x40 + (i<<3), base); - } - } - else { - hoist = /* hole start address */ - ((hole_startk << 10) & 0xff000000) + - /* hole address to memory controller address */ - (((basek + carry_over) >> 6) & 0x0000ff00) + - /* enable */ - 1; - pci_write_config32(dev, 0xf0, hoist); - } - - return carry_over; -} - -static void set_hw_mem_hole(int controllers, const struct mem_controller *ctrl) -{ - - u32 hole_startk; - int i; - - hole_startk = 4*1024*1024 - HW_MEM_HOLE_SIZEK; - -#if HW_MEM_HOLE_SIZE_AUTO_INC == 1 - /* We need to double check if hole_startk is valid. - * If it is equal to the dram base address in K (base_k), - * we need to decrease it. - */ - u32 basek_pri; - for(i=0; i<controllers; i++) { - u32 base; - unsigned base_k; - base = pci_read_config32(ctrl[0].f1, 0x40 + (i << 3)); - if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) { - continue; - } - base_k = (base & 0xffff0000) >> 2; - if(base_k == hole_startk) { - /* decrease memory hole startk to make sure it is - * in the middle of the previous node - */ - hole_startk -= (base_k - basek_pri)>>1; - break; /* only one hole */ - } - basek_pri = base_k; - } - -#endif - /* Find node number that needs the memory hole configured */ - for(i=0; i<controllers; i++) { - u32 base, limit; - unsigned base_k, limit_k; - base = pci_read_config32(ctrl[0].f1, 0x40 + (i << 3)); - if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) { - continue; - } - limit = pci_read_config32(ctrl[0].f1, 0x44 + (i << 3)); - base_k = (base & 0xffff0000) >> 2; - limit_k = ((limit + 0x00010000) & 0xffff0000) >> 2; - if ((base_k <= hole_startk) && (limit_k > hole_startk)) { - unsigned end_k; - hoist_memory(controllers, ctrl, hole_startk, i); - end_k = memory_end_k(ctrl, controllers); - set_top_mem(end_k, hole_startk); - break; /* only one hole */ - } - } - -} - -#endif - -#define TIMEOUT_LOOPS 300000 -static void sdram_enable(int controllers, const struct mem_controller *ctrl, struct sys_info *sysinfo) -{ - int i; - - /* Error if I don't have memory */ - if (memory_end_k(ctrl, controllers) == 0) { - die("No memory\r\n"); - } - - /* Before enabling memory start the memory clocks */ - for(i = 0; i < controllers; i++) { - u32 dch; - if (!controller_present(ctrl + i)) - continue; - dch = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_HIGH); - if (dch & (DCH_MEMCLK_EN0|DCH_MEMCLK_EN1|DCH_MEMCLK_EN2|DCH_MEMCLK_EN3)) { - dch |= DCH_MEMCLK_VALID; - pci_write_config32(ctrl[i].f2, DRAM_CONFIG_HIGH, dch); - } - else { - /* Disable dram receivers */ - u32 dcl; - dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW); - dcl |= DCL_DisInRcvrs; - pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl); - } - } - - /* And if necessary toggle the the reset on the dimms by hand */ - memreset(controllers, ctrl); - - /* We need to wait a mimmium of 20 MEMCLKS to enable the InitDram */ - - for(i = 0; i < controllers; i++) { - u32 dcl, dch; - if (!controller_present(ctrl + i)) - continue; - /* Skip everything if I don't have any memory on this controller */ - dch = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_HIGH); - if (!(dch & DCH_MEMCLK_VALID)) { - continue; - } - - /* Toggle DisDqsHys to get it working */ - dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW); - if (dcl & DCL_DimmEccEn) { - u32 mnc; - print_spew("ECC enabled\r\n"); - mnc = pci_read_config32(ctrl[i].f3, MCA_NB_CONFIG); - mnc |= MNC_ECC_EN; - if (dcl & DCL_128BitEn) { - mnc |= MNC_CHIPKILL_EN; - } - pci_write_config32(ctrl[i].f3, MCA_NB_CONFIG, mnc); - } - 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); - - } - for(i = 0; i < controllers; i++) { - u32 dcl, dch; - if (!controller_present(ctrl + i)) - continue; - /* Skip everything if I don't have any memory on this controller */ - dch = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_HIGH); - if (!(dch & DCH_MEMCLK_VALID)) { - continue; - } - - printk(BIOS_DEBUG, "Initializing memory: "); - - int loops = 0; - do { - dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW); - loops += 1; - if ((loops & 1023) == 0) { - printk(BIOS_DEBUG, "."); - } - } while(((dcl & DCL_DramInit) != 0) && (loops < TIMEOUT_LOOPS)); - if (loops >= TIMEOUT_LOOPS) { - printk(BIOS_DEBUG, " failed\r\n"); - continue; - } - - if (!is_cpu_pre_c0()) { - /* Wait until it is safe to touch memory */ - dcl &= ~(DCL_MemClrStatus | DCL_DramEnable); - pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl); - do { - dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW); - } while(((dcl & DCL_MemClrStatus) == 0) || ((dcl & DCL_DramEnable) == 0) ); - } - - printk(BIOS_DEBUG, " done\r\n"); - } - -#if HW_MEM_HOLE_SIZEK != 0 - // init hw mem hole here - /* DramHoleValid bit only can be set after MemClrStatus is set by Hardware */ - if(!is_cpu_pre_e0()) - set_hw_mem_hole(controllers, ctrl); -#endif - - //FIXME add enable node interleaving here -- yhlu - /*needed? - 1. check how many nodes we have , if not all has ram installed get out - 2. check cs_base lo is 0, node 0 f2 0x40,,,,, if any one is not using lo is CS_BASE, get out - 3. check if other node is the same as node 0 about f2 0x40,,,,, otherwise get out - 4. if all ready enable node_interleaving in f1 0x40..... of every node - 5. for node interleaving we need to set mem hole to every node ( need recalcute hole offset in f0 for every node) - */ - -} - -static void set_sysinfo_in_ram(unsigned val) -{ -} - -static void fill_mem_ctrl(int controllers, struct mem_controller *ctrl_a, const u16 *spd_addr) -{ - int i; - int j; - struct mem_controller *ctrl; - for(i=0;i<controllers; i++) { - ctrl = &ctrl_a[i]; - ctrl->node_id = i; - ctrl->f0 = PCI_DEV(0, 0x18+i, 0); - ctrl->f1 = PCI_DEV(0, 0x18+i, 1); - ctrl->f2 = PCI_DEV(0, 0x18+i, 2); - ctrl->f3 = PCI_DEV(0, 0x18+i, 3); - - if(spd_addr == (void *)0) continue; - - for(j=0;j<DIMM_SOCKETS;j++) { - ctrl->channel0[j] = spd_addr[(i*2+0)*DIMM_SOCKETS + j]; - ctrl->channel1[j] = spd_addr[(i*2+1)*DIMM_SOCKETS + j]; - } - } -} -#endif -