summaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
authorRonald G. Minnich <rminnich@gmail.com>2003-09-26 04:45:52 +0000
committerRonald G. Minnich <rminnich@gmail.com>2003-09-26 04:45:52 +0000
commitc817926a6bd4195cff6b6a0d8fa35b8637cee1b8 (patch)
tree0e359b22069293ab81af97c81c4e36ed083c2caa /src
parent10941401e8c040ade7456b0f49ab21c6306791fd (diff)
downloadcoreboot-c817926a6bd4195cff6b6a0d8fa35b8637cee1b8.tar.xz
via epia; also yh lu tyan.
git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1138 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1
Diffstat (limited to 'src')
-rw-r--r--src/mainboard/arima/hdama/Config.lb6
-rw-r--r--src/mainboard/via/epia/Config.lb250
-rw-r--r--src/mainboard/via/epia/auto.c89
-rw-r--r--src/mainboard/via/epia/chip.h5
-rw-r--r--src/mainboard/via/epia/cmos.layout74
-rw-r--r--src/mainboard/via/epia/debug.c128
-rw-r--r--src/mainboard/via/epia/failover.c38
-rw-r--r--src/mainboard/via/epia/irq_tables.c25
-rw-r--r--src/mainboard/via/epia/mainboard.c37
-rw-r--r--src/mainboard/via/epia/reset.c43
-rw-r--r--src/northbridge/via/vt8601/raminit.c2574
-rw-r--r--src/northbridge/via/vt8601/raminit.h4
-rw-r--r--src/southbridge/via/vt8231/vt8231_early_smbus.c114
13 files changed, 1103 insertions, 2284 deletions
diff --git a/src/mainboard/arima/hdama/Config.lb b/src/mainboard/arima/hdama/Config.lb
index 97882302ed..b056124b74 100644
--- a/src/mainboard/arima/hdama/Config.lb
+++ b/src/mainboard/arima/hdama/Config.lb
@@ -15,6 +15,9 @@ uses _ROMBASE
uses XIP_ROM_SIZE
uses XIP_ROM_BASE
+## ROM_SIZE is the size of boot ROM that this board will use.
+default ROM_SIZE 524288
+
###
### Build options
###
@@ -68,9 +71,6 @@ option MAINBOARD_VENDOR="ARIMA"
### LinuxBIOS layout values
###
-## ROM_SIZE is the size of boot ROM that this board will use.
-default ROM_SIZE = 524288
-
## ROM_IMAGE_SIZE is the amount of space to allow linuxBIOS to occupy.
option ROM_IMAGE_SIZE = 65536
diff --git a/src/mainboard/via/epia/Config.lb b/src/mainboard/via/epia/Config.lb
new file mode 100644
index 0000000000..6d30820105
--- /dev/null
+++ b/src/mainboard/via/epia/Config.lb
@@ -0,0 +1,250 @@
+uses HAVE_MP_TABLE
+uses HAVE_PIRQ_TABLE
+uses USE_FALLBACK_IMAGE
+uses MAINBOARD
+uses ARCH
+uses FALLBACK_SIZE
+uses ROM_SIZE
+uses ROM_SECTION_SIZE
+uses ROM_IMAGE_SIZE
+uses ROM_SECTION_SIZE
+uses ROM_SECTION_OFFSET
+uses CONFIG_ROM_STREAM_START
+uses PAYLOAD_SIZE
+uses _ROMBASE
+uses XIP_ROM_SIZE
+uses XIP_ROM_BASE
+
+## ROM_SIZE is the size of boot ROM that this board will use.
+default ROM_SIZE 524288
+
+###
+### Build options
+###
+
+##
+## Build code for the fallback boot
+##
+option HAVE_FALLBACK_BOOT=1
+
+##
+## Build code to reset the motherboard from linuxBIOS
+##
+option HAVE_HARD_RESET=1
+
+##
+## Build code to export a programmable irq routing table
+##
+option HAVE_PIRQ_TABLE=1
+option IRQ_SLOT_COUNT=7
+
+##
+## Build code to export an x86 MP table
+## Useful for specifying IRQ routing values
+##
+option HAVE_MP_TABLE=1
+
+##
+## Build code to export a CMOS option table
+##
+option HAVE_OPTION_TABLE=1
+
+##
+## Build code for SMP support
+## Only worry about 2 micro processors
+##
+option CONFIG_SMP=1
+option CONFIG_MAX_CPUS=2
+
+##
+## Build code to setup a generic IOAPIC
+##
+option CONFIG_IOAPIC=1
+
+##
+## Clean up the motherboard id strings
+##
+option MAINBOARD_PART_NUMBER="HDAMA"
+option MAINBOARD_VENDOR="ARIMA"
+
+###
+### LinuxBIOS layout values
+###
+
+## ROM_IMAGE_SIZE is the amount of space to allow linuxBIOS to occupy.
+option ROM_IMAGE_SIZE = 65536
+
+##
+## Use a small 8K stack
+##
+option STACK_SIZE=0x2000
+
+##
+## Use a small 16K heap
+##
+option HEAP_SIZE=0x4000
+
+##
+## Only use the option table in a normal image
+##
+option USE_OPTION_TABLE = !USE_FALLBACK_IMAGE
+
+##
+## Compute the location and size of where this firmware image
+## (linuxBIOS plus bootloader) will live in the boot rom chip.
+##
+if USE_FALLBACK_IMAGE
+ option ROM_SECTION_SIZE = FALLBACK_SIZE
+ option ROM_SECTION_OFFSET = ( ROM_SIZE - FALLBACK_SIZE )
+else
+ option ROM_SECTION_SIZE = ( ROM_SIZE - FALLBACK_SIZE )
+ option ROM_SECTION_OFFSET = 0
+end
+
+##
+## Compute the start location and size size of
+## The linuxBIOS bootloader.
+##
+option PAYLOAD_SIZE = ( ROM_SECTION_SIZE - ROM_IMAGE_SIZE )
+option CONFIG_ROM_STREAM_START = (0xffffffff - ROM_SIZE + ROM_SECTION_OFFSET + 1)
+option CONFIG_ROM_STREAM = 1
+
+##
+## Compute where this copy of linuxBIOS will start in the boot rom
+##
+option _ROMBASE = ( CONFIG_ROM_STREAM_START + PAYLOAD_SIZE )
+
+##
+## Compute a range of ROM that can cached to speed up linuxBIOS,
+## execution speed.
+##
+## XIP_ROM_SIZE must be a power of 2.
+## XIP_ROM_BASE must be a multiple of XIP_ROM_SIZE
+##
+option XIP_ROM_SIZE=65536
+option XIP_ROM_BASE = ( _ROMBASE + ROM_IMAGE_SIZE - XIP_ROM_SIZE )
+
+##
+## Set all of the defaults for an x86 architecture
+##
+
+arch i386 end
+
+##
+## Build the objects we have code for in this directory.
+##
+
+
+driver mainboard.o
+#object reset.o
+
+##
+## Romcc output
+##
+makerule ./failover.E
+ depends "$(MAINBOARD)/failover.c"
+ action "$(CPP) -I$(TOP)/src $(ROMCCPPFLAGS) $(CPPFLAGS) $(MAINBOARD)/failover.c > ./failover.E"
+end
+
+makerule ./failover.inc
+ depends "./failover.E ./romcc"
+ action "./romcc -O -o failover.inc --label-prefix=failover ./failover.E"
+end
+
+makerule ./auto.E
+ depends "$(MAINBOARD)/auto.c"
+ action "$(CPP) -I$(TOP)/src $(ROMCCPPFLAGS) $(CPPFLAGS) $(MAINBOARD)/auto.c > ./auto.E"
+end
+makerule ./auto.inc
+ depends "./auto.E ./romcc"
+ action "./romcc -O ./auto.E > auto.inc"
+end
+
+##
+## Build our 16 bit and 32 bit linuxBIOS entry code
+##
+mainboardinit cpu/i386/entry16.inc
+mainboardinit cpu/i386/entry32.inc
+ldscript /cpu/i386/entry16.lds
+ldscript /cpu/i386/entry32.lds
+
+##
+## Build our reset vector (This is where linuxBIOS is entered)
+##
+if USE_FALLBACK_IMAGE
+ mainboardinit cpu/i386/reset16.inc
+ ldscript /cpu/i386/reset16.lds
+else
+ mainboardinit cpu/i386/reset32.inc
+ ldscript /cpu/i386/reset32.lds
+end
+
+### Should this be in the northbridge code?
+mainboardinit arch/i386/lib/cpu_reset.inc
+
+##
+## Include an id string (For safe flashing)
+##
+mainboardinit arch/i386/lib/id.inc
+ldscript /arch/i386/lib/id.lds
+
+##
+## Setup our mtrrs
+##
+# mainboardinit cpu/p6/earlymtrr.inc
+
+###
+### This is the early phase of linuxBIOS startup
+### Things are delicate and we test to see if we should
+### failover to another image.
+###
+if USE_FALLBACK_IMAGE
+ ldscript /arch/i386/lib/failover.lds
+ mainboardinit ./failover.inc
+end
+
+###
+### O.k. We aren't just an intermediary anymore!
+###
+
+##
+## Setup RAM
+##
+mainboardinit ./auto.inc
+
+##
+## Include the secondary Configuration files
+##
+dir /pc80
+config chip.h
+
+northbridge via/vt8601 "vt8601"
+ pci 0:18.0
+ pci 0:18.0
+ pci 0:18.0
+ pci 0:18.1
+ pci 0:18.2
+ pci 0:18.3
+ southbridge via/vt8231 "vt8231"
+ register "enable_usb" = "0"
+ register "enable_native_ide" = "1"
+ register "enable_com_ports" = "1"
+ register "enable_keyboard" = "0"
+ register "enable_nvram" = "1"
+ pci 0:0.0
+ pci 0:0.1
+ pci 0:1.0
+ pci 0:1.1
+ end
+end
+
+cpu p5 "cpu0"
+
+end
+
+##
+## Include the old serial code for those few places that still need it.
+##
+mainboardinit pc80/serial.inc
+mainboardinit arch/i386/lib/console.inc
+
diff --git a/src/mainboard/via/epia/auto.c b/src/mainboard/via/epia/auto.c
new file mode 100644
index 0000000000..5b8aa0bbdd
--- /dev/null
+++ b/src/mainboard/via/epia/auto.c
@@ -0,0 +1,89 @@
+#define ASSEMBLY 1
+
+
+#include <stdint.h>
+#include <device/pci_def.h>
+#include <cpu/p6/apic.h>
+#include <arch/io.h>
+#include <device/pnp.h>
+#include <arch/romcc_io.h>
+#include "pc80/serial.c"
+#include "arch/i386/lib/console.c"
+#include "ram/ramtest.c"
+#include "northbridge/via/vt8601/raminit.h"
+void udelay(int usecs) {
+ int i;
+ for(i = 0; i < usecs; i++)
+ outb(0x80, 0x80);
+}
+
+#include "lib/delay.c"
+#include "cpu/p6/boot_cpu.c"
+#include "debug.c"
+
+#include "southbridge/via/vt8231/vt8231_early_smbus.c"
+#define SIO_BASE 0x2e
+#define MAXIMUM_CONSOLE_LOGLEVEL 9
+#define DEFAULT_CONSOLE_LOGLEVEL 9
+
+static void memreset_setup(void)
+{
+}
+
+/*
+static void memreset(int controllers, const struct mem_controller *ctrl)
+{
+}
+*/
+static inline int spd_read_byte(unsigned device, unsigned address)
+{
+ return smbus_read_byte(device, address);
+}
+
+
+
+#include "northbridge/via/vt8601/raminit.c"
+#include "sdram/generic_sdram.c"
+
+static void main(void)
+{
+ struct mem_controller cpu[1];
+ // init_timer();
+
+ uart_init();
+ console_init();
+
+ enable_smbus();
+ memreset_setup();
+ sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu);
+
+
+ /* Check all of memory */
+#if 0
+ msr_t msr;
+ msr = rdmsr(TOP_MEM);
+ print_debug("TOP_MEM: ");
+ print_debug_hex32(msr.hi);
+ print_debug_hex32(msr.lo);
+ print_debug("\r\n");
+#endif
+#if 0
+ ram_check(0x00000000, msr.lo);
+#endif
+#if 0
+ static const struct {
+ unsigned long lo, hi;
+ } check_addrs[] = {
+ /* Check 16MB of memory @ 0*/
+ { 0x00000000, 0x01000000 },
+#if TOTAL_CPUS > 1
+ /* Check 16MB of memory @ 2GB */
+ { 0x80000000, 0x81000000 },
+#endif
+ };
+ int i;
+ for(i = 0; i < sizeof(check_addrs)/sizeof(check_addrs[0]); i++) {
+ ram_check(check_addrs[i].lo, check_addrs[i].hi);
+ }
+#endif
+}
diff --git a/src/mainboard/via/epia/chip.h b/src/mainboard/via/epia/chip.h
new file mode 100644
index 0000000000..9836e2dfa9
--- /dev/null
+++ b/src/mainboard/via/epia/chip.h
@@ -0,0 +1,5 @@
+struct chip_control mainboard_arima_hdama_control;
+
+struct mainboard_arima_hdama_config {
+ int nothing;
+};
diff --git a/src/mainboard/via/epia/cmos.layout b/src/mainboard/via/epia/cmos.layout
new file mode 100644
index 0000000000..5ba4c032c1
--- /dev/null
+++ b/src/mainboard/via/epia/cmos.layout
@@ -0,0 +1,74 @@
+entries
+
+#start-bit length config config-ID name
+#0 8 r 0 seconds
+#8 8 r 0 alarm_seconds
+#16 8 r 0 minutes
+#24 8 r 0 alarm_minutes
+#32 8 r 0 hours
+#40 8 r 0 alarm_hours
+#48 8 r 0 day_of_week
+#56 8 r 0 day_of_month
+#64 8 r 0 month
+#72 8 r 0 year
+#80 4 r 0 rate_select
+#84 3 r 0 REF_Clock
+#87 1 r 0 UIP
+#88 1 r 0 auto_switch_DST
+#89 1 r 0 24_hour_mode
+#90 1 r 0 binary_values_enable
+#91 1 r 0 square-wave_out_enable
+#92 1 r 0 update_finished_enable
+#93 1 r 0 alarm_interrupt_enable
+#94 1 r 0 periodic_interrupt_enable
+#95 1 r 0 disable_clock_updates
+#96 288 r 0 temporary_filler
+0 384 r 0 reserved_memory
+384 1 e 4 boot_option
+385 1 e 4 last_boot
+386 1 e 1 ECC_memory
+388 4 r 0 reboot_bits
+392 3 e 5 baud_rate
+400 1 e 1 power_on_after_fail
+412 4 e 6 debug_level
+416 4 e 7 boot_first
+420 4 e 7 boot_second
+424 4 e 7 boot_third
+428 4 h 0 boot_index
+432 8 h 0 boot_countdown
+1008 16 h 0 check_sum
+
+enumerations
+
+#ID value text
+1 0 Disable
+1 1 Enable
+2 0 Enable
+2 1 Disable
+4 0 Fallback
+4 1 Normal
+5 0 115200
+5 1 57600
+5 2 38400
+5 3 19200
+5 4 9600
+5 5 4800
+5 6 2400
+5 7 1200
+6 6 Notice
+6 7 Info
+6 8 Debug
+6 9 Spew
+7 0 Network
+7 1 HDD
+7 2 Floppy
+7 8 Fallback_Network
+7 9 Fallback_HDD
+7 10 Fallback_Floppy
+#7 3 ROM
+
+checksums
+
+checksum 392 1007 1008
+
+
diff --git a/src/mainboard/via/epia/debug.c b/src/mainboard/via/epia/debug.c
new file mode 100644
index 0000000000..714fcc5783
--- /dev/null
+++ b/src/mainboard/via/epia/debug.c
@@ -0,0 +1,128 @@
+
+static void print_debug_pci_dev(unsigned dev)
+{
+ print_debug("PCI: ");
+ print_debug_hex8((dev >> 16) & 0xff);
+ print_debug_char(':');
+ print_debug_hex8((dev >> 11) & 0x1f);
+ print_debug_char('.');
+ print_debug_hex8((dev >> 8) & 7);
+}
+
+static void print_pci_devices(void)
+{
+ device_t dev;
+ for(dev = PCI_DEV(0, 0, 0);
+ dev <= PCI_DEV(0, 0x1f, 0x7);
+ dev += PCI_DEV(0,0,1)) {
+ uint32_t id;
+ id = pci_read_config32(dev, PCI_VENDOR_ID);
+ if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
+ (((id >> 16) & 0xffff) == 0xffff) ||
+ (((id >> 16) & 0xffff) == 0x0000)) {
+ continue;
+ }
+ print_debug_pci_dev(dev);
+ print_debug("\r\n");
+ }
+}
+
+static void dump_pci_device(unsigned dev)
+{
+ int i;
+ print_debug_pci_dev(dev);
+ print_debug("\r\n");
+
+ for(i = 0; i <= 255; i++) {
+ unsigned char val;
+ if ((i & 0x0f) == 0) {
+ print_debug_hex8(i);
+ print_debug_char(':');
+ }
+ val = pci_read_config8(dev, i);
+ print_debug_char(' ');
+ print_debug_hex8(val);
+ if ((i & 0x0f) == 0x0f) {
+ print_debug("\r\n");
+ }
+ }
+}
+
+static void dump_pci_devices(void)
+{
+ device_t dev;
+ for(dev = PCI_DEV(0, 0, 0);
+ dev <= PCI_DEV(0, 0x1f, 0x7);
+ dev += PCI_DEV(0,0,1)) {
+ uint32_t id;
+ id = pci_read_config32(dev, PCI_VENDOR_ID);
+ if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
+ (((id >> 16) & 0xffff) == 0xffff) ||
+ (((id >> 16) & 0xffff) == 0x0000)) {
+ continue;
+ }
+ dump_pci_device(dev);
+ }
+}
+#if 0
+static void dump_spd_registers(const struct mem_controller *ctrl)
+{
+ int i;
+ print_debug("\r\n");
+ for(i = 0; i < 4; i++) {
+ unsigned device;
+ device = ctrl->channel0[i];
+ if (device) {
+ int j;
+ print_debug("dimm: ");
+ print_debug_hex8(i);
+ print_debug(".0: ");
+ print_debug_hex8(device);
+ for(j = 0; j < 256; j++) {
+ int status;
+ unsigned char byte;
+ if ((j & 0xf) == 0) {
+ print_debug("\r\n");
+ print_debug_hex8(j);
+ print_debug(": ");
+ }
+ status = smbus_read_byte(device, j);
+ if (status < 0) {
+ print_debug("bad device\r\n");
+ break;
+ }
+ byte = status & 0xff;
+ print_debug_hex8(byte);
+ print_debug_char(' ');
+ }
+ print_debug("\r\n");
+ }
+ device = ctrl->channel1[i];
+ if (device) {
+ int j;
+ print_debug("dimm: ");
+ print_debug_hex8(i);
+ print_debug(".1: ");
+ print_debug_hex8(device);
+ for(j = 0; j < 256; j++) {
+ int status;
+ unsigned char byte;
+ if ((j & 0xf) == 0) {
+ print_debug("\r\n");
+ print_debug_hex8(j);
+ print_debug(": ");
+ }
+ status = smbus_read_byte(device, j);
+ if (status < 0) {
+ print_debug("bad device\r\n");
+ break;
+ }
+ byte = status & 0xff;
+ print_debug_hex8(byte);
+ print_debug_char(' ');
+ }
+ print_debug("\r\n");
+ }
+ }
+}
+#endif
diff --git a/src/mainboard/via/epia/failover.c b/src/mainboard/via/epia/failover.c
new file mode 100644
index 0000000000..8eeeaef7e1
--- /dev/null
+++ b/src/mainboard/via/epia/failover.c
@@ -0,0 +1,38 @@
+#define ASSEMBLY 1
+#include <stdint.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <arch/io.h>
+#include "arch/romcc_io.h"
+#include "pc80/mc146818rtc_early.c"
+#include "southbridge/amd/amd8111/amd8111_enable_rom.c"
+#include "northbridge/amd/amdk8/early_ht.c"
+#include "cpu/p6/boot_cpu.c"
+#include "northbridge/amd/amdk8/reset_test.c"
+
+static void main(void)
+{
+ /* Nothing special needs to be done to find bus 0 */
+ /* Allow the HT devices to be found */
+ enumerate_ht_chain(0);
+
+ /* Setup the 8111 */
+ amd8111_enable_rom();
+
+ /* Is this a cpu reset? */
+ if (cpu_init_detected()) {
+ if (last_boot_normal()) {
+ asm("jmp __normal_image");
+ } else {
+ asm("jmp __cpu_reset");
+ }
+ }
+ /* Is this a secondary cpu? */
+ else if (!boot_cpu() && last_boot_normal()) {
+ asm("jmp __normal_image");
+ }
+ /* This is the primary cpu how should I boot? */
+ else if (do_normal_boot()) {
+ asm("jmp __normal_image");
+ }
+}
diff --git a/src/mainboard/via/epia/irq_tables.c b/src/mainboard/via/epia/irq_tables.c
new file mode 100644
index 0000000000..b59ce9f1e9
--- /dev/null
+++ b/src/mainboard/via/epia/irq_tables.c
@@ -0,0 +1,25 @@
+/* This file was generated by getpir.c, do not modify!
+ (but if you do, please run checkpir on it to verify)
+ Contains the IRQ Routing Table dumped directly from your memory , wich BIOS sets up
+
+ Documentation at : http://www.microsoft.com/hwdev/busbios/PCIIRQ.HTM
+*/
+
+#include <arch/pirq_routing.h>
+
+
+const struct irq_routing_table intel_irq_routing_table = {
+ PIRQ_SIGNATURE, /* u32 signature */
+ PIRQ_VERSION, /* u16 version */
+ 32+16*18, /* there can be total 18 devices on the bus */
+ 1, /* Where the interrupt router lies (bus) */
+ 0x23, /* Where the interrupt router lies (dev) */
+ 0, /* IRQs devoted exclusively to PCI usage */
+ 0x0, /* Vendor */
+ 0x0, /* Device */
+ 0, /* Crap (miniport) */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
+ 0x35, /* u8 checksum , this hase to set to some value that would give 0 after the sum of all bytes for this structure (including checksum) */
+ {
+ }
+};
diff --git a/src/mainboard/via/epia/mainboard.c b/src/mainboard/via/epia/mainboard.c
new file mode 100644
index 0000000000..6790aaca1b
--- /dev/null
+++ b/src/mainboard/via/epia/mainboard.c
@@ -0,0 +1,37 @@
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+
+#include <arch/io.h>
+#include <device/chip.h>
+#include "../../../northbridge/amd/amdk8/northbridge.h"
+#include "chip.h"
+
+
+static struct device_operations mainboard_operations = {
+ .read_resources = root_dev_read_resources,
+ .set_resources = root_dev_set_resources,
+ .enable_resources = enable_childrens_resources,
+ .init = 0,
+ .scan_bus = vt8_scan_root_bus,
+ .enable = 0,
+};
+
+static void enumerate(struct chip *chip)
+{
+ struct chip *child;
+ dev_root.ops = &mainboard_operations;
+ chip->dev = &dev_root;
+ chip->bus = 0;
+ for(child = chip->children; child; child = child->next) {
+ child->bus = &dev_root.link[0];
+ }
+}
+struct chip_control mainboard_via_epia_control = {
+ .enumerate = enumerate,
+ .name = "Arima HDAMA mainboard ",
+};
+
diff --git a/src/mainboard/via/epia/reset.c b/src/mainboard/via/epia/reset.c
new file mode 100644
index 0000000000..5796e17dc8
--- /dev/null
+++ b/src/mainboard/via/epia/reset.c
@@ -0,0 +1,43 @@
+#if 0
+//#include "arch/romcc_io.h"
+#include <arch/io.h>
+
+typedef unsigned device_t;
+
+#define PCI_DEV(BUS, DEV, FN) ( \
+ (((BUS) & 0xFF) << 16) | \
+ (((DEV) & 0x1f) << 11) | \
+ (((FN) & 0x7) << 8))
+
+static void pci_write_config8(device_t dev, unsigned where, unsigned char value)
+{
+ unsigned addr;
+ addr = dev | where;
+ outl(0x80000000 | (addr & ~3), 0xCF8);
+ outb(value, 0xCFC + (addr & 3));
+}
+
+static void pci_write_config32(device_t dev, unsigned where, unsigned value)
+{
+ unsigned addr;
+ addr = dev | where;
+ outl(0x80000000 | (addr & ~3), 0xCF8);
+ outl(value, 0xCFC);
+}
+
+static unsigned pci_read_config32(device_t dev, unsigned where)
+{
+ unsigned addr;
+ addr = dev | where;
+ outl(0x80000000 | (addr & ~3), 0xCF8);
+ return inl(0xCFC);
+}
+
+#include "../../../northbridge/amd/amdk8/reset_test.c"
+
+void hard_reset(void)
+{
+ set_bios_reset();
+ pci_write_config8(PCI_DEV(1, 0x04, 0), 0x47, 1);
+}
+#endif
diff --git a/src/northbridge/via/vt8601/raminit.c b/src/northbridge/via/vt8601/raminit.c
index 802e4318b4..864fbbe282 100644
--- a/src/northbridge/via/vt8601/raminit.c
+++ b/src/northbridge/via/vt8601/raminit.c
@@ -1,2308 +1,320 @@
-#include <cpu/k8/mtrr.h>
+#include <cpu/p6/mtrr.h>
#include "raminit.h"
-
-#define ENABLE_IOMMU 1
-
-/* Function 2 */
-#define DRAM_CSBASE 0x40
-#define DRAM_CSMASK 0x60
-#define DRAM_BANK_ADDR_MAP 0x80
-#define DRAM_TIMING_LOW 0x88
-#define DTL_TCL_SHIFT 0
-#define DTL_TCL_MASK 0x7
-#define DTL_CL_2 1
-#define DTL_CL_3 2
-#define DTL_CL_2_5 5
-#define DTL_TRC_SHIFT 4
-#define DTL_TRC_MASK 0xf
-#define DTL_TRC_BASE 7
-#define DTL_TRC_MIN 7
-#define DTL_TRC_MAX 22
-#define DTL_TRFC_SHIFT 8
-#define DTL_TRFC_MASK 0xf
-#define DTL_TRFC_BASE 9
-#define DTL_TRFC_MIN 9
-#define DTL_TRFC_MAX 24
-#define DTL_TRCD_SHIFT 12
-#define DTL_TRCD_MASK 0x7
-#define DTL_TRCD_BASE 0
-#define DTL_TRCD_MIN 2
-#define DTL_TRCD_MAX 6
-#define DTL_TRRD_SHIFT 16
-#define DTL_TRRD_MASK 0x7
-#define DTL_TRRD_BASE 0
-#define DTL_TRRD_MIN 2
-#define DTL_TRRD_MAX 4
-#define DTL_TRAS_SHIFT 20
-#define DTL_TRAS_MASK 0xf
-#define DTL_TRAS_BASE 0
-#define DTL_TRAS_MIN 5
-#define DTL_TRAS_MAX 15
-#define DTL_TRP_SHIFT 24
-#define DTL_TRP_MASK 0x7
-#define DTL_TRP_BASE 0
-#define DTL_TRP_MIN 2
-#define DTL_TRP_MAX 6
-#define DTL_TWR_SHIFT 28
-#define DTL_TWR_MASK 0x1
-#define DTL_TWR_BASE 2
-#define DTL_TWR_MIN 2
-#define DTL_TWR_MAX 3
-#define DRAM_TIMING_HIGH 0x8c
-#define DTH_TWTR_SHIFT 0
-#define DTH_TWTR_MASK 0x1
-#define DTH_TWTR_BASE 1
-#define DTH_TWTR_MIN 1
-#define DTH_TWTR_MAX 2
-#define DTH_TRWT_SHIFT 4
-#define DTH_TRWT_MASK 0x7
-#define DTH_TRWT_BASE 1
-#define DTH_TRWT_MIN 1
-#define DTH_TRWT_MAX 6
-#define DTH_TREF_SHIFT 8
-#define DTH_TREF_MASK 0x1f
-#define DTH_TREF_100MHZ_4K 0x00
-#define DTH_TREF_133MHZ_4K 0x01
-#define DTH_TREF_166MHZ_4K 0x02
-#define DTH_TREF_200MHZ_4K 0x03
-#define DTH_TREF_100MHZ_8K 0x08
-#define DTH_TREF_133MHZ_8K 0x09
-#define DTH_TREF_166MHZ_8K 0x0A
-#define DTH_TREF_200MHZ_8K 0x0B
-#define DTH_TWCL_SHIFT 20
-#define DTH_TWCL_MASK 0x7
-#define DTH_TWCL_BASE 1
-#define DTH_TWCL_MIN 1
-#define DTH_TWCL_MAX 2
-#define DRAM_CONFIG_LOW 0x90
-#define DCL_DLL_Disable (1<<0)
-#define DCL_D_DRV (1<<1)
-#define DCL_QFC_EN (1<<2)
-#define DCL_DisDqsHys (1<<3)
-#define DCL_DramInit (1<<8)
-#define DCL_DramEnable (1<<10)
-#define DCL_MemClrStatus (1<<11)
-#define DCL_ESR (1<<12)
-#define DCL_SRS (1<<13)
-#define DCL_128BitEn (1<<16)
-#define DCL_DimmEccEn (1<<17)
-#define DCL_UnBufDimm (1<<18)
-#define DCL_32ByteEn (1<<19)
-#define DCL_x4DIMM_SHIFT 20
-#define DRAM_CONFIG_HIGH 0x94
-#define DCH_ASYNC_LAT_SHIFT 0
-#define DCH_ASYNC_LAT_MASK 0xf
-#define DCH_ASYNC_LAT_BASE 0
-#define DCH_ASYNC_LAT_MIN 0
-#define DCH_ASYNC_LAT_MAX 15
-#define DCH_RDPREAMBLE_SHIFT 8
-#define DCH_RDPREAMBLE_MASK 0xf
-#define DCH_RDPREAMBLE_BASE ((2<<1)+0) /* 2.0 ns */
-#define DCH_RDPREAMBLE_MIN ((2<<1)+0) /* 2.0 ns */
-#define DCH_RDPREAMBLE_MAX ((9<<1)+1) /* 9.5 ns */
-#define DCH_IDLE_LIMIT_SHIFT 16
-#define DCH_IDLE_LIMIT_MASK 0x7
-#define DCH_IDLE_LIMIT_0 0
-#define DCH_IDLE_LIMIT_4 1
-#define DCH_IDLE_LIMIT_8 2
-#define DCH_IDLE_LIMIT_16 3
-#define DCH_IDLE_LIMIT_32 4
-#define DCH_IDLE_LIMIT_64 5
-#define DCH_IDLE_LIMIT_128 6
-#define DCH_IDLE_LIMIT_256 7
-#define DCH_DYN_IDLE_CTR_EN (1 << 19)
-#define DCH_MEMCLK_SHIFT 20
-#define DCH_MEMCLK_MASK 0x7
-#define DCH_MEMCLK_100MHZ 0
-#define DCH_MEMCLK_133MHZ 2
-#define DCH_MEMCLK_166MHZ 5
-#define DCH_MEMCLK_200MHZ 7
-#define DCH_MEMCLK_VALID (1 << 25)
-#define DCH_MEMCLK_EN0 (1 << 26)
-#define DCH_MEMCLK_EN1 (1 << 27)
-#define DCH_MEMCLK_EN2 (1 << 28)
-#define DCH_MEMCLK_EN3 (1 << 29)
-
-/* Function 3 */
-#define SCRUB_CONTROL 0x58
-#define SCRUB_NONE 0
-#define SCRUB_40ns 1
-#define SCRUB_80ns 2
-#define SCRUB_160ns 3
-#define SCRUB_320ns 4
-#define SCRUB_640ns 5
-#define SCRUB_1_28us 6
-#define SCRUB_2_56us 7
-#define SCRUB_5_12us 8
-#define SCRUB_10_2us 9
-#define SCRUB_20_5us 10
-#define SCRUB_41_0us 11
-#define SCRUB_81_9us 12
-#define SCRUB_163_8us 13
-#define SCRUB_327_7us 14
-#define SCRUB_655_4us 15
-#define SCRUB_1_31ms 16
-#define SCRUB_2_62ms 17
-#define SCRUB_5_24ms 18
-#define SCRUB_10_49ms 19
-#define SCRUB_20_97ms 20
-#define SCRUB_42ms 21
-#define SCRUB_84ms 22
-#define SC_DRAM_SCRUB_RATE_SHFIT 0
-#define SC_DRAM_SCRUB_RATE_MASK 0x1f
-#define SC_L2_SCRUB_RATE_SHIFT 8
-#define SC_L2_SCRUB_RATE_MASK 0x1f
-#define SC_L1D_SCRUB_RATE_SHIFT 16
-#define SC_L1D_SCRUB_RATE_MASK 0x1f
-#define SCRUB_ADDR_LOW 0x5C
-#define SCRUB_ADDR_HIGH 0x60
-#define NORTHBRIDGE_CAP 0xE8
-#define NBCAP_128Bit 0x0001
-#define NBCAP_MP 0x0002
-#define NBCAP_BIG_MP 0x0004
-#define NBCAP_ECC 0x0004
-#define NBCAP_CHIPKILL_ECC 0x0010
-#define NBCAP_MEMCLK_SHIFT 5
-#define NBCAP_MEMCLK_MASK 3
-#define NBCAP_MEMCLK_100MHZ 3
-#define NBCAP_MEMCLK_133MHZ 2
-#define NBCAP_MEMCLK_166MHZ 1
-#define NBCAP_MEMCLK_200MHZ 0
-#define NBCAP_MEMCTRL 0x0100
-
-
-static void setup_resource_map(const unsigned int *register_values, int max)
-{
- int i;
- print_debug("setting up resource map....\r\n");
- for(i = 0; i < max; i += 3) {
- device_t dev;
- unsigned where;
- unsigned long reg;
-#if 0
- print_debug_hex32(register_values[i]);
- print_debug(" <-");
- print_debug_hex32(register_values[i+2]);
- print_debug("\r\n");
-#endif
- dev = register_values[i] & ~0xff;
- where = register_values[i] & 0xff;
- reg = pci_read_config32(dev, where);
- reg &= register_values[i+1];
- reg |= register_values[i+2];
- pci_write_config32(dev, where, reg);
#if 0
- reg = pci_read_config32(register_values[i]);
- reg &= register_values[i+1];
- reg |= register_values[i+2] & ~register_values[i+1];
- pci_write_config32(register_values[i], reg);
+/*
+This software and ancillary information (herein called SOFTWARE )
+called LinuxBIOS is made available under the terms described
+here. The SOFTWARE has been approved for release with associated
+LA-CC Number 00-34 . Unless otherwise indicated, this SOFTWARE has
+been authored by an employee or employees of the University of
+California, operator of the Los Alamos National Laboratory under
+Contract No. W-7405-ENG-36 with the U.S. Department of Energy. The
+U.S. Government has rights to use, reproduce, and distribute this
+SOFTWARE. The public may copy, distribute, prepare derivative works
+and publicly display this SOFTWARE without charge, provided that this
+Notice and any statement of authorship are reproduced on all copies.
+Neither the Government nor the University makes any warranty, express
+or implied, or assumes any liability or responsibility for the use of
+this SOFTWARE. If SOFTWARE is modified to produce derivative works,
+such modified SOFTWARE should be clearly marked, so as not to confuse
+it with the version available from LANL.
+ */
+/* Copyright 2000, Ron Minnich, Advanced Computing Lab, LANL
+ * rminnich@lanl.gov
+ */
+/*
+ * 11/26/02 - kevinh@ispiri.com - The existing comments implied that
+ * this didn't work yet. Therefore, I've updated it so that it works
+ * correctly - at least on my VIA epia motherboard. 64MB DIMM in slot 0.
+ */
+
+/* Added automatic detection of first equipped bank and its MA mapping type.
+ * (Rest of configuration is done in C)
+ * 5/19/03 by SONE Takeshi <ts1@tsn.or.jp>
+ */
+
+// Set to 1 if your DIMMs are PC133
+// Note that I'm assuming CPU's FSB frequency is 133MHz. If your CPU runs
+// at another bus speed, you might need to change some of register values.
+#ifndef DIMM_PC133
+#define DIMM_PC133 0
#endif
- }
- print_debug("done.\r\n");
-}
-
-static void setup_default_resource_map(void)
-{
- 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,
-
- /* Memory-Mapped I/O Limit i Registers
- * F1:0x84 i = 0
- * F1:0x8C i = 1
- * F1:0x94 i = 2
- * F1:0x9C i = 3
- * F1:0xA4 i = 4
- * F1:0xAC i = 5
- * F1:0xB4 i = 6
- * F1:0xBC 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
- * [ 3: 3] Reserved
- * [ 5: 4] Destination Link ID
- * 00 = Link 0
- * 01 = Link 1
- * 10 = Link 2
- * 11 = Reserved
- * [ 6: 6] Reserved
- * [ 7: 7] Non-Posted
- * 0 = CPU writes may be posted
- * 1 = CPU writes must be non-posted
- * [31: 8] Memory-Mapped I/O Limit Address i (39-16)
- * This field defines the upp adddress bits of a 40-bit address that
- * defines the end of a memory-mapped I/O region n
- */
- PCI_ADDR(0, 0x18, 1, 0x84), 0x00000048, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0x8C), 0x00000048, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0x94), 0x00000048, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0x9C), 0x00000048, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0xA4), 0x00000048, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0xAC), 0x00000048, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0xB4), 0x00000048, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0xBC), 0x00000048, 0x00ffff00,
-
- /* Memory-Mapped I/O Base i Registers
- * F1:0x80 i = 0
- * F1:0x88 i = 1
- * F1:0x90 i = 2
- * F1:0x98 i = 3
- * F1:0xA0 i = 4
- * F1:0xA8 i = 5
- * F1:0xB0 i = 6
- * F1:0xB8 i = 7
- * [ 0: 0] Read Enable
- * 0 = Reads disabled
- * 1 = Reads Enabled
- * [ 1: 1] Write Enable
- * 0 = Writes disabled
- * 1 = Writes Enabled
- * [ 2: 2] Cpu Disable
- * 0 = Cpu can use this I/O range
- * 1 = Cpu requests do not use this I/O range
- * [ 3: 3] Lock
- * 0 = base/limit registers i are read/write
- * 1 = base/limit registers i are read-only
- * [ 7: 4] Reserved
- * [31: 8] Memory-Mapped I/O Base Address i (39-16)
- * This field defines the upper address bits of a 40bit address
- * that defines the start of memory-mapped I/O region i
- */
- PCI_ADDR(0, 0x18, 1, 0x80), 0x000000f0, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0x88), 0x000000f0, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0x90), 0x000000f0, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0x98), 0x000000f0, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0xA0), 0x000000f0, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0xA8), 0x000000f0, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0xB0), 0x000000f0, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0xB8), 0x000000f0, 0x00fc0003,
-
- /* PCI I/O Limit i Registers
- * F1:0xC4 i = 0
- * F1:0xCC i = 1
- * F1:0xD4 i = 2
- * F1:0xDC i = 3
- * [ 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
- * [ 3: 3] Reserved
- * [ 5: 4] Destination Link ID
- * 00 = Link 0
- * 01 = Link 1
- * 10 = Link 2
- * 11 = reserved
- * [11: 6] Reserved
- * [24:12] PCI I/O Limit Address i
- * This field defines the end of PCI I/O region n
- * [31:25] Reserved
- */
- PCI_ADDR(0, 0x18, 1, 0xC4), 0xFE000FC8, 0x01fff000,
- PCI_ADDR(0, 0x18, 1, 0xCC), 0xFE000FC8, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0xD4), 0xFE000FC8, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0xDC), 0xFE000FC8, 0x00000000,
- /* PCI I/O Base i Registers
- * F1:0xC0 i = 0
- * F1:0xC8 i = 1
- * F1:0xD0 i = 2
- * F1:0xD8 i = 3
- * [ 0: 0] Read Enable
- * 0 = Reads Disabled
- * 1 = Reads Enabled
- * [ 1: 1] Write Enable
- * 0 = Writes Disabled
- * 1 = Writes Enabled
- * [ 3: 2] Reserved
- * [ 4: 4] VGA Enable
- * 0 = VGA matches Disabled
- * 1 = matches all address < 64K and where A[9:0] is in the
- * range 3B0-3BB or 3C0-3DF independen of the base & limit registers
- * [ 5: 5] ISA Enable
- * 0 = ISA matches Disabled
- * 1 = Blocks address < 64K and in the last 768 bytes of eack 1K block
- * from matching agains this base/limit pair
- * [11: 6] Reserved
- * [24:12] PCI I/O Base i
- * This field defines the start of PCI I/O region n
- * [31:25] Reserved
- */
- PCI_ADDR(0, 0x18, 1, 0xC0), 0xFE000FCC, 0x00000003,
- PCI_ADDR(0, 0x18, 1, 0xC8), 0xFE000FCC, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0xD0), 0xFE000FCC, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0xD8), 0xFE000FCC, 0x00000000,
-
- /* Config Base and Limit i Registers
- * F1:0xE0 i = 0
- * F1:0xE4 i = 1
- * F1:0xE8 i = 2
- * F1:0xEC i = 3
- * [ 0: 0] Read Enable
- * 0 = Reads Disabled
- * 1 = Reads Enabled
- * [ 1: 1] Write Enable
- * 0 = Writes Disabled
- * 1 = Writes Enabled
- * [ 2: 2] Device Number Compare Enable
- * 0 = The ranges are based on bus number
- * 1 = The ranges are ranges of devices on bus 0
- * [ 3: 3] Reserved
- * [ 6: 4] Destination Node
- * 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: 7] Reserved
- * [ 9: 8] Destination Link
- * 00 = Link 0
- * 01 = Link 1
- * 10 = Link 2
- * 11 - Reserved
- * [15:10] Reserved
- * [23:16] Bus Number Base i
- * This field defines the lowest bus number in configuration region i
- * [31:24] Bus Number Limit i
- * This field defines the highest bus number in configuration regin i
- */
- PCI_ADDR(0, 0x18, 1, 0xE0), 0x0000FC88, 0xff000003,
- PCI_ADDR(0, 0x18, 1, 0xE4), 0x0000FC88, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0xE8), 0x0000FC88, 0x00000000,
- PCI_ADDR(0, 0x18, 1, 0xEC), 0x0000FC88, 0x00000000,
- };
- int max;
- max = sizeof(register_values)/sizeof(register_values[0]);
- setup_resource_map(register_values, max);
-}
-
-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,
- /* 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,
-
-#if ENABLE_IOMMU != 0
- /* BY LYH add IOMMU 64M APERTURE */
- PCI_ADDR(0, 0x18, 3, 0x94), 0xffff8000, 0x00000f70,
- PCI_ADDR(0, 0x18, 3, 0x90), 0xffffff80, 0x00000002,
- PCI_ADDR(0, 0x18, 3, 0x98), 0x0000000f, 0x00068300,
+// Set to 1 if your DIMMs are CL=2
+#ifndef DIMM_CL2
+#define DIMM_CL2 0
#endif
- };
- int i;
- int max;
- 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;
- unsigned where;
- unsigned long reg;
-#if 0
- print_debug_hex32(register_values[i]);
- print_debug(" <-");
- print_debug_hex32(register_values[i+2]);
- print_debug("\r\n");
-#endif
- dev = (register_values[i] & ~0xff) - PCI_DEV(0, 0x18, 0) + ctrl->f0;
- where = register_values[i] & 0xff;
- reg = pci_read_config32(dev, where);
- reg &= register_values[i+1];
- reg |= register_values[i+2];
- pci_write_config32(dev, where, reg);
-#if 0
- reg = pci_read_config32(register_values[i]);
- reg &= register_values[i+1];
- reg |= register_values[i+2];
- pci_write_config32(register_values[i], reg);
-#endif
- }
- print_debug("done.\r\n");
-}
-
-static int is_dual_channel(const struct mem_controller *ctrl)
-{
- uint32_t 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 Testing dual channel capability is correct for now
- * but a beter test is probably required.
- */
-#warning "FIXME implement a better test for opterons"
- uint32_t 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.
- */
- uint32_t dcl;
- dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW);
- return !(dcl & DCL_UnBufDimm);
-}
-
-struct dimm_size {
- unsigned long side1;
- unsigned long side2;
-};
-
-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;
-
- /* 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 out;
- sz.side1 += value & 0xf;
-
- value = spd_read_byte(device, 4); /* columns */
- if (value < 0) goto out;
- sz.side1 += value & 0xf;
-
- 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 = spd_read_byte(device, 7); /* (high byte) */
- if (value < 0) goto out;
- value &= 0xff;
- value <<= 8;
-
- low = spd_read_byte(device, 6); /* (low byte) */
- if (low < 0) goto out;
- value = value | (low & 0xff);
- sz.side1 += log2(value);
-
- /* side 2 */
- 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 = 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 = 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 */
-
- out:
- return sz;
-}
-
-static void set_dimm_size(const struct mem_controller *ctrl, struct dimm_size sz, unsigned index)
-{
- uint32_t base0, base1, map;
- uint32_t dch;
-
-#if 0
- print_debug("set_dimm_size: (");
- print_debug_hex32(sz.side1);
- print_debug_char(',');
- print_debug_hex32(sz.side2);
- print_debug_char(',');
- print_debug_hex32(index);
- print_debug(")\r\n");
-#endif
- if (sz.side1 != sz.side2) {
- sz.side2 = 0;
- }
- map = pci_read_config32(ctrl->f2, DRAM_BANK_ADDR_MAP);
- map &= ~(0xf << (index + 4));
-
- /* 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)) {
- map |= (sz.side1 - (25 + 3)) << (index *4);
- 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);
- pci_write_config32(ctrl->f2, DRAM_BANK_ADDR_MAP, map);
-
- /* Enable the memory clocks for this DIMM */
- if (base0) {
- dch = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH);
- dch |= DCH_MEMCLK_EN0 << index;
- pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, dch);
- }
-}
-
-static void spd_set_ram_size(const struct mem_controller *ctrl)
-{
- int i;
-
- for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
- struct dimm_size sz;
- sz = spd_get_dimm_size(ctrl->channel0[i]);
- set_dimm_size(ctrl, sz, i);
- }
-}
-
-//BY LYH //Fill next base reg with right value
-static void fill_last(unsigned long node_id,unsigned long base)
-{
- unsigned i;
- unsigned base_reg;
- base &=0xffff0000;
- device_t device;
- for(device = PCI_DEV(0, 0x18, 1); device <= PCI_DEV(0, 0x1f, 1); device
-+= PCI_DEV(0, 1, 0)) {
- for(i=node_id+1;i<=7;i++) {
- base_reg=0x40+(i<<3);
- pci_write_config32(device,base_reg,base);
- }
- }
-}
-//BY LYH END
-
-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;
- 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;
- 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)
-{
- /* Error if I don't have memory */
- if (!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;
- msr.hi = (tom_k & 0xffc00000) >> 22;
- wrmsr(TOP_MEM2, msr);
-
- /* Leave a 64M hole between TOP_MEM and TOP_MEM2
- * so I can see my rom chip and other I/O devices.
- */
- if (tom_k >= 0x003f0000) {
- tom_k = 0x3f0000;
- }
- msr.lo = (tom_k & 0x003fffff) << 10;
- msr.hi = (tom_k & 0xffc00000) >> 22;
- wrmsr(TOP_MEM, msr);
-}
-
-static void order_dimms(const struct mem_controller *ctrl)
-{
- unsigned long tom, tom_k, base_k;
- unsigned node_id;
-
- /* Compute the memory base address address */
- base_k = 0;
- /* Remember which registers we have used in the high 8 bits of tom */
- tom = base_k >> 15;
- for(;;) {
- /* Find the largest remaining canidate */
- unsigned index, canidate;
- uint32_t csbase, csmask;
- unsigned size;
- csbase = 0;
- canidate = 0;
- for(index = 0; index < 8; index++) {
- uint32_t 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 */
-#warning "Don't forget to optimize the DIMM size"
-
- /* 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);
-
- }
- tom_k = (tom & ~0xff000000) << 15;
-
- /* Compute the memory base 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;
- }
- }
- tom_k += base_k;
-#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, base_k, tom_k);
-//BY LYH
- fill_last(ctrl->node_id, tom_k<<2);
-//BY LYH END
- set_top_mem(tom_k);
-}
-
-static void disable_dimm(const struct mem_controller *ctrl, unsigned index)
-{
- print_debug("disabling dimm");
- print_debug_hex8(index);
- print_debug("\r\n");
- pci_write_config32(ctrl->f2, DRAM_CSBASE + (((index << 1)+0)<<2), 0);
- pci_write_config32(ctrl->f2, DRAM_CSBASE + (((index << 1)+1)<<2), 0);
-}
-
-
-static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl)
-{
- int i;
- int registered;
- int unbuffered;
- uint32_t dcl;
- unbuffered = 0;
- registered = 0;
- for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
- int value;
- value = spd_read_byte(ctrl->channel0[i], 21);
- if (value < 0) {
- disable_dimm(ctrl, i);
- continue;
- }
- /* 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");
- }
- if (unbuffered && is_opteron(ctrl)) {
- die("Unbuffered Dimms not supported on Opteron");
- }
-
- dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW);
- dcl &= ~DCL_UnBufDimm;
- if (unbuffered) {
- dcl |= DCL_UnBufDimm;
- }
- pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl);
-#if 0
- if (is_registered(ctrl)) {
- print_debug("Registered\r\n");
- } else {
- print_debug("Unbuffered\r\n");
- }
-#endif
-}
-
-static void spd_enable_2channels(const struct mem_controller *ctrl)
-{
- int i;
- uint32_t nbcap;
- /* 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 */
- 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)) {
- return;
- }
- for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
- unsigned device0, device1;
- int value0, value1;
- int j;
- device0 = ctrl->channel0[i];
- device1 = ctrl->channel1[i];
- if (!device1)
- return;
- for(j = 0; j < sizeof(addresses)/sizeof(addresses[0]); j++) {
- unsigned addr;
- addr = addresses[j];
- value0 = spd_read_byte(device0, addr);
- if (value0 < 0) {
- break;
- }
- value1 = spd_read_byte(device1, addr);
- if (value1 < 0) {
- return;
- }
- if (value0 != value1) {
- return;
- }
- }
- }
- print_debug("Enabling dual channel memory\r\n");
- uint32_t 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);
-}
-
-struct mem_param {
- uint8_t cycle_time;
- uint8_t divisor; /* In 1/2 ns increments */
- uint8_t tRC;
- uint8_t tRFC;
- uint32_t dch_memclk;
- uint16_t dch_tref4k, dch_tref8k;
- uint8_t dtl_twr;
- 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,
- },
- {
- .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,
- },
- {
- .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,
- },
- {
- .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,
- },
- {
- .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");
- }
-#if 1
- print_debug(param->name);
+/* Stable ~1 usec delay by hitting unused ISA port. */
+#define UDELAY(x) movl $x,%ecx; 9: outb %al,$0x81; loop 9b
+
+#define DIMMS_READ(x) \
+ movl 0x00000000+x, %eax; \
+ movl 0x10000000+x, %eax; \
+ movl 0x20000000+x, %eax; \
+ movl 0x30000000+x, %eax; \
+ movl 0x40000000+x, %eax; \
+ movl 0x50000000+x, %eax
+
+#define DIMMS_WRITE(x) \
+ movl %eax, 0x00000000+x; \
+ movl %eax, 0x10000000+x; \
+ movl %eax, 0x20000000+x; \
+ movl %eax, 0x30000000+x; \
+ movl %eax, 0x40000000+x; \
+ movl %eax, 0x50000000+x
+
+raminit:
+ intel_chip_post_macro(0x35)
+
+ // memory clk enable. We are not using ECC
+ CS_WRITE($0x78, $0x01)
+ // dram control, see the book.
+#if DIMM_PC133
+ CS_WRITE($0x68, $0x52)
+#else
+ CS_WRITE($0x68, $0x42)
#endif
- return param;
-}
-
-static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
-{
- /* Compute the minimum cycle time for these dimms */
- const struct mem_param *param;
- unsigned min_cycle_time, min_latency;
- int i;
- uint32_t value;
-
- static const int 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];
- min_latency = 2;
-
-#if 0
- print_debug("min_cycle_time: ");
- print_debug_hex8(min_cycle_time);
- print_debug(" min_latency: ");
- print_debug_hex8(min_latency);
- print_debug("\r\n");
+ // dram control, see the book.
+ CS_WRITE($0x6B, $0x0c)
+ // Initial setting, 256MB in each bank, will be rewritten later.
+ CS_WRITE($0x5A, $0x20)
+ CS_WRITE($0x5B, $0x40)
+ CS_WRITE($0x5C, $0x60)
+ CS_WRITE($0x5D, $0x80)
+ CS_WRITE($0x5E, $0xA0)
+ CS_WRITE($0x5F, $0xC0)
+ // It seems we have to take care of these 2 registers as if
+ // they are bank 6 and 7.
+ CS_WRITE($0x56, $0xC0)
+ CS_WRITE($0x57, $0xC0)
+
+ // SDRAM in all banks
+ CS_WRITE($0x60, $0x3F)
+ // DRAM timing. I'm suspicious of this
+ // This is for all banks, 64 is 0,1. 65 is 2,3. 66 is 4,5.
+ // ras precharge 4T, RAS pulse 5T
+ // cas2 is 0xd6, cas3 is 0xe6
+ // we're also backing off write pulse width to 2T, so result is 0xee
+#if DIMM_CL2
+ CS_WRITE($0x64, $0xd4)
+ CS_WRITE($0x65, $0xd4)
+ CS_WRITE($0x66, $0xd4)
+#else // CL=3
+ CS_WRITE($0x64, $0xe4)
+ CS_WRITE($0x65, $0xe4)
+ CS_WRITE($0x66, $0xe4)
#endif
- /* Compute the least latency with the fastest clock supported
- * by both the memory controller and the dimms.
- */
- for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
- int new_cycle_time, new_latency;
- int index;
- int latencies;
- int latency;
-
- /* 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) {
- continue;
- }
-
- /* 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;
- }
-#if 0
- print_debug("i: ");
- print_debug_hex8(i);
- print_debug(" min_cycle_time: ");
- print_debug_hex8(min_cycle_time);
- print_debug(" min_latency: ");
- print_debug_hex8(min_latency);
- print_debug("\r\n");
+ // dram frequency select.
+ // enable 4K pages for 64M dram.
+#if DIMM_PC133
+ CS_WRITE($0x69, $0x3c)
+#else
+ CS_WRITE($0x69, $0xac)
#endif
- }
- /* Make a second pass through the dimms and disable
- * any that cannot support the selected memclk and cas latency.
- */
+ // refresh counter, disabled.
+ CS_WRITE($0x6A, $0x00)
+ // clkenable configuration. kevinh FIXME - add precharge
+ CS_WRITE($0x6C, $0x00)
+ // dram read latch delay of 1 ns, MD drive 8 mA,
+ // high drive strength on MA[2: 13], we#, cas#, ras#
+ // As per Cindy Lee, set to 0x37, not 0x57
+ CS_WRITE($0x6D, $0x7f)
+
+ /* Initialize all banks at once */
+
+/* begin to initialize*/
+ // I forget why we need this, but we do
+ mov $0xa55a5aa5, %eax
+ DIMMS_WRITE(0)
- for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
- int latencies;
- int latency;
- int index;
- int value;
- int dimm;
- latencies = spd_read_byte(ctrl->channel0[i], 18);
- if (latencies <= 0) {
- goto dimm_err;
- }
+/* set NOP*/
+ CS_WRITE($0x6C, $0x01)
- /* Compute the lowest cas latency supported */
- latency = log2(latencies) -2;
+/* wait 200us*/
+ // You need to do the memory reference. That causes the nop cycle.
+ DIMMS_READ(0)
+ UDELAY(400)
- /* 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]);
-
- /* 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:
- disable_dimm(ctrl, i);
- }
-#if 0
- print_debug("min_cycle_time: ");
- print_debug_hex8(min_cycle_time);
- print_debug(" min_latency: ");
- print_debug_hex8(min_latency);
- print_debug("\r\n");
-#endif
- /* Now that I know the minimum cycle time lookup the memory parameters */
- param = get_mem_param(min_cycle_time);
+/* set precharge */
+ CS_WRITE($0x6C, $0x02)
- /* 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);
- value |= param->dch_memclk;
- pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, value);
+/* dummy reads*/
+ DIMMS_READ(0)
+ UDELAY(200)
- 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);
+/* set CBR*/
+ CS_WRITE($0x6C, $0x04)
- return param;
-}
-
-
-static int update_dimm_Trc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
-{
- unsigned clocks, old_clocks;
- uint32_t 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 -1;
- }
-
- 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 0;
-}
-
-static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
-{
- unsigned clocks, old_clocks;
- uint32_t 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 -1;
- }
- 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 0;
-}
-
-
-static int update_dimm_Trcd(const struct mem_controller *ctrl, const struct mem_param *param, int i)
-{
- unsigned clocks, old_clocks;
- uint32_t dtl;
- int value;
- value = spd_read_byte(ctrl->channel0[i], 29);
- if (value < 0) return -1;
-#if 0
- clocks = (value + (param->divisor << 1) -1)/(param->divisor << 1);
-#else
- clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
+/* do 8 reads and wait >100us between each - from via*/
+ DIMMS_READ(0)
+ UDELAY(200)
+ DIMMS_READ(0)
+ UDELAY(200)
+ DIMMS_READ(0)
+ UDELAY(200)
+ DIMMS_READ(0)
+ UDELAY(200)
+ DIMMS_READ(0)
+ UDELAY(200)
+ DIMMS_READ(0)
+ UDELAY(200)
+ DIMMS_READ(0)
+ UDELAY(200)
+ DIMMS_READ(0)
+ UDELAY(200)
+
+/* set MRS*/
+ CS_WRITE($0x6c, $0x03)
+#if DIMM_CL2
+ DIMMS_READ(0x150)
+#else // CL=3
+ DIMMS_READ(0x1d0)
#endif
- if (clocks < DTL_TRCD_MIN) {
- clocks = DTL_TRCD_MIN;
- }
- if (clocks > DTL_TRCD_MAX) {
- return -1;
- }
- 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 0;
-}
-
-static int update_dimm_Trrd(const struct mem_controller *ctrl, const struct mem_param *param, int i)
-{
- unsigned clocks, old_clocks;
- uint32_t dtl;
- int value;
- 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) {
- clocks = DTL_TRRD_MIN;
- }
- if (clocks > DTL_TRRD_MAX) {
- return -1;
- }
- 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 0;
-}
-
-static int update_dimm_Tras(const struct mem_controller *ctrl, const struct mem_param *param, int i)
-{
- unsigned clocks, old_clocks;
- uint32_t 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 -1;
- }
- 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 0;
-}
-
-static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_param *param, int i)
-{
- unsigned clocks, old_clocks;
- uint32_t dtl;
- int value;
- value = spd_read_byte(ctrl->channel0[i], 27);
- if (value < 0) return -1;
-#if 0
- clocks = (value + (param->divisor << 1) - 1)/(param->divisor << 1);
+ UDELAY(200)
+
+/* set to normal mode */
+ CS_WRITE($0x6C, $0x08)
+ movl $0x55aa55aa, %eax
+ DIMMS_WRITE(0)
+ DIMMS_READ(0)
+ UDELAY(200)
+
+ // Set the refresh rate.
+#if DIMM_PC133
+ CS_WRITE($0x6A, $0x86)
#else
- clocks = (value + ((param->divisor & 0xff) << 1) - 1)/((param->divisor & 0xff) << 1);
+ CS_WRITE($0x6A, $0x65)
#endif
-#if 0
- print_debug("Trp: ");
- print_debug_hex8(clocks);
- print_debug(" spd value: ");
- print_debug_hex8(value);
- print_debug(" divisor: ");
- print_debug_hex8(param->divisor);
- print_debug("\r\n");
+ // enable multi-page open
+ CS_WRITE($0x6B, $0x0d)
+
+ /* Begin auto-detection
+ * Find the first bank with DIMM equipped. */
+
+ /* Maximum possible memory in bank 0, none in other banks.
+ * Starting from bank 0, we's fill 0 in these registers
+ * until memory is found. */
+ CS_WRITE($0x5A, $0xff)
+ CS_WRITE($0x5B, $0xff)
+ CS_WRITE($0x5C, $0xff)
+ CS_WRITE($0x5D, $0xff)
+ CS_WRITE($0x5E, $0xff)
+ CS_WRITE($0x5F, $0xff)
+ CS_WRITE($0x56, $0xff)
+ CS_WRITE($0x57, $0xff)
+
+ movl $0x5A, %ebx // first bank
+1:
+ /* Write different values to 0 and 8, then read from 0.
+ * If values of address 0 match, we have something there. */
+ movl $0x12345678, %eax
+ movl %eax, 0
+ movl $0x87654321, %edx
+ movl %edx, 8
+ movl 0, %edx
+ cmpl %eax, %edx
+ je 2f
+ /* No memory in this bank. Tell it to the bridge. */
+ movl %ebx, %eax
+ xorl %edx, %edx
+ PCI_WRITE_CONFIG_BYTE
+ incl %ebx
+ cmpl $0x60, %ebx
+ jne 1b
+ /* No memory at all! */
+ CONSOLE_EMERG_TX_STRING($msg_nomem)
+1:
+ hlt
+ jmp 1b
+2:
+
+ /* Detect MA mapping type of the first bank. */
+
+ jmp raminit_ma
+raminit_ma_reg_table:
+ /* Values for MA type register to try */
+ .word 0x0000, 0x8088, 0xe0ee
+ .word 0xffff // end mark
+
+raminit_ma:
+ xorl %esi, %esi // highest address
+ movl $raminit_ma_reg_table, %ebx
+1:
+ movw (%ebx), %cx
+ cmpw $0xffff, %cx
+ je raminit_ma_done
+ movl $0x58, %eax
+ PCI_WRITE_CONFIG_WORD
+
+ xorl %eax, %eax
+ movl %eax, (%eax)
+
+ // Write to addresses with only one address bit on,
+ // from 0x80000000 to 0x00000008 (lower 3 bits are ignored, assuming
+ // 64-bit bus).
+ // Then what is read at address 0 is the value written to the lowest
+ // address where it gets wrap-around. That address is either the size
+ // of the bank, or a missing bit due to incorrect MA mapping.
+ movl $0x80000000, %eax
+2:
+ movl %eax, (%eax)
+ shrl $1, %eax
+ cmpl $4, %eax
+ jne 2b
+
+ movl 0, %eax
+ cmpl %eax, %esi
+ jnc 3f
+
+ // This is the current best MA mapping.
+ // Save the address and its MA mapping value.
+ movl %eax, %esi
+ movl %ecx, %edi
+3:
+ incl %ebx
+ incl %ebx
+ jmp 1b
+
+
+raminit_ma_done:
+ // Set the best (hopefully correct) MA mapping type.
+ movl $0x58, %eax
+ movl %edi, %ecx
+ PCI_WRITE_CONFIG_WORD
+
+ CONSOLE_DEBUG_TX_STRING($msg_enabled)
+ CONSOLE_DEBUG_TX_HEX32(%esi)
+ CONSOLE_DEBUG_TX_STRING($msg_bytes)
+
+ /*
+ * We have the size of first bank in %esi, but throwing it away.
+ * Sizing will again be done in C, because we'll configure the rest
+ * of banks in there anyway.
+ */
+
+ //CALLSP(dumpnorth)
+
+ intel_chip_post_macro(0x36)
+
+
+ .section ".rom.data"
+msg_nomem:
+ .asciz "No memory\r\n"
+msg_enabled:
+ .asciz "Enabled first bank of RAM: 0x"
+msg_bytes:
+ .asciz " bytes\r\n"
+ .previous
#endif
- if (clocks < DTL_TRP_MIN) {
- clocks = DTL_TRP_MIN;
- }
- if (clocks > DTL_TRP_MAX) {
- return -1;
- }
- 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 0;
-}
-
-static void set_Twr(const struct mem_controller *ctrl, const struct mem_param *param)
-{
- uint32_t 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)
-{
- uint32_t 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 void sdram_set_registers(const struct mem_controller *ctrl) {
}
-static int update_dimm_Tref(const struct mem_controller *ctrl, const struct mem_param *param, int i)
-{
- uint32_t 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 0;
-}
-
-
-static int update_dimm_x4(const struct mem_controller *ctrl, const struct mem_param *param, int i)
-{
- uint32_t dcl;
- int value;
- int dimm;
- value = spd_read_byte(ctrl->channel0[i], 13);
- if (value < 0) {
- return -1;
- }
- dimm = i;
- dimm += DCL_x4DIMM_SHIFT;
- dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW);
- dcl &= ~(1 << dimm);
- if (value == 4) {
- dcl |= (1 << dimm);
- }
- pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl);
- return 0;
-}
-
-static int update_dimm_ecc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
-{
- uint32_t 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 0;
-}
-
-static int count_dimms(const struct mem_controller *ctrl)
-{
- int dimms;
- unsigned index;
- dimms = 0;
- for(index = 0; index < 8; index += 2) {
- uint32_t 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)
-{
- uint32_t dth;
- unsigned clocks;
- clocks = 1; /* AMD says hard code this */
- dth = pci_read_config32(ctrl->f2, DRAM_TIMING_HIGH);
- dth &= ~(DTH_TWTR_MASK << DTH_TWTR_SHIFT);
- dth |= ((clocks - 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)
-{
- uint32_t dth, dtl;
- unsigned divisor;
- unsigned latency;
- unsigned clocks;
-
- clocks = 0;
- dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW);
- latency = (dtl >> DTL_TCL_SHIFT) & DTL_TCL_MASK;
- divisor = param->divisor;
-
- if (is_opteron(ctrl)) {
- if (latency == DTL_CL_2) {
- if (divisor == ((6 << 0) + 0)) {
- /* 166Mhz */
- clocks = 3;
- }
- else if (divisor > ((6 << 0)+0)) {
- /* 100Mhz && 133Mhz */
- clocks = 2;
- }
- }
- else if (latency == DTL_CL_2_5) {
- clocks = 3;
- }
- else if (latency == DTL_CL_3) {
- if (divisor == ((6 << 0)+0)) {
- /* 166Mhz */
- clocks = 4;
- }
- else if (divisor > ((6 << 0)+0)) {
- /* 100Mhz && 133Mhz */
- clocks = 3;
- }
- }
- }
- else /* Athlon64 */ {
- if (is_registered(ctrl)) {
- if (latency == DTL_CL_2) {
- clocks = 2;
- }
- else if (latency == DTL_CL_2_5) {
- clocks = 3;
- }
- else if (latency == DTL_CL_3) {
- clocks = 3;
- }
- }
- else /* Unbuffered */{
- if (latency == DTL_CL_2) {
- clocks = 3;
- }
- else if (latency == DTL_CL_2_5) {
- clocks = 4;
- }
- else if (latency == DTL_CL_3) {
- clocks = 4;
- }
- }
- }
- if ((clocks < DTH_TRWT_MIN) || (clocks > DTH_TRWT_MAX)) {
- die("Unknown Trwt");
- }
-
- 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# */
- uint32_t 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)
-{
- uint32_t dch;
- unsigned divisor;
- unsigned rdpreamble;
- divisor = param->divisor;
- dch = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH);
- dch &= ~(DCH_RDPREAMBLE_MASK << DCH_RDPREAMBLE_SHIFT);
- rdpreamble = 0;
- if (is_registered(ctrl)) {
- if (divisor == ((10 << 1)+0)) {
- /* 100Mhz, 9ns */
- rdpreamble = ((9 << 1)+ 0);
- }
- else if (divisor == ((7 << 1)+1)) {
- /* 133Mhz, 8ns */
- rdpreamble = ((8 << 1)+0);
- }
- else if (divisor == ((6 << 1)+0)) {
- /* 166Mhz, 7.5ns */
- rdpreamble = ((7 << 1)+1);
- }
- }
- else {
- int slots;
- int i;
- slots = 0;
- for(i = 0; i < 4; i++) {
- if (ctrl->channel0[i]) {
- slots += 1;
- }
- }
- if (divisor == ((10 << 1)+0)) {
- /* 100Mhz */
- if (slots <= 2) {
- /* 9ns */
- rdpreamble = ((9 << 1)+0);
- } else {
- /* 14ns */
- rdpreamble = ((14 << 1)+0);
- }
- }
- else if (divisor == ((7 << 1)+1)) {
- /* 133Mhz */
- if (slots <= 2) {
- /* 7ns */
- rdpreamble = ((7 << 1)+0);
- } else {
- /* 11 ns */
- rdpreamble = ((11 << 1)+0);
- }
- }
- else if (divisor == ((6 << 1)+0)) {
- /* 166Mhz */
- if (slots <= 2) {
- /* 6ns */
- rdpreamble = ((7 << 1)+0);
- } else {
- /* 9ns */
- rdpreamble = ((9 << 1)+0);
- }
- }
- else if (divisor == ((5 << 1)+0)) {
- /* 200Mhz */
- if (slots <= 2) {
- /* 5ns */
- rdpreamble = ((5 << 1)+0);
- } else {
- /* 7ns */
- rdpreamble = ((7 << 1)+0);
- }
- }
- }
- 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)
-{
- uint32_t dch;
- int i;
- 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)
-{
- uint32_t 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 void spd_set_dram_timing(const struct mem_controller *ctrl, const struct mem_param *param)
-{
- int dimms;
- int i;
- init_Tref(ctrl, param);
- for(i = 0; (i < 4) && ctrl->channel0[i]; i++) {
- int rc;
- /* DRAM Timing Low Register */
- if (update_dimm_Trc (ctrl, param, i) < 0) goto dimm_err;
- if (update_dimm_Trfc(ctrl, param, i) < 0) goto dimm_err;
- if (update_dimm_Trcd(ctrl, param, i) < 0) goto dimm_err;
- if (update_dimm_Trrd(ctrl, param, i) < 0) goto dimm_err;
- if (update_dimm_Tras(ctrl, param, i) < 0) goto dimm_err;
- if (update_dimm_Trp (ctrl, param, i) < 0) goto dimm_err;
-
- /* DRAM Timing High Register */
- if (update_dimm_Tref(ctrl, param, i) < 0) goto dimm_err;
-
- /* DRAM Config Low */
- if (update_dimm_x4 (ctrl, param, i) < 0) goto dimm_err;
- if (update_dimm_ecc(ctrl, param, i) < 0) goto dimm_err;
- continue;
- dimm_err:
- disable_dimm(ctrl, i);
-
- }
- /* 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);
+static void sdram_set_spd_registers(const struct mem_controller *ctrl) {
}
-static void sdram_set_spd_registers(const struct mem_controller *ctrl)
-{
- const struct mem_param *param;
- spd_enable_2channels(ctrl);
- spd_set_ram_size(ctrl);
- spd_handle_unbuffered_dimms(ctrl);
- param = spd_set_memclk(ctrl);
- spd_set_dram_timing(ctrl, param);
- order_dimms(ctrl);
-}
-
-#define TIMEOUT_LOOPS 300000
-static void sdram_enable(int controllers, const struct mem_controller *ctrl)
-{
- int i;
-
- /* Before enabling memory start the memory clocks */
- 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(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
-#warning "FIXME set the ECC type to perform"
-#warning "FIXME initialize the scrub registers"
-#if 1
- if (dcl & DCL_DimmEccEn) {
- print_debug("ECC enabled\r\n");
- }
-#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);
-
- }
- for(i = 0; i < controllers; i++) {
- uint32_t dcl;
- print_debug("Initializing memory: ");
- int loops = 0;
- do {
- dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
- loops += 1;
- if ((loops & 1023) == 0) {
- print_debug(".");
- }
- } 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
- 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);
- }
-#endif
- }
+static void sdram_enable(int controllers, const struct mem_controller *ctrl) {
}
diff --git a/src/northbridge/via/vt8601/raminit.h b/src/northbridge/via/vt8601/raminit.h
index 4d3cdc16ce..a72535de1d 100644
--- a/src/northbridge/via/vt8601/raminit.h
+++ b/src/northbridge/via/vt8601/raminit.h
@@ -1,4 +1,8 @@
#ifndef RAMINIT_H
#define RAMINIT_H
+struct mem_controller {
+ int empty;
+};
+
#endif /* RAMINIT_H */
diff --git a/src/southbridge/via/vt8231/vt8231_early_smbus.c b/src/southbridge/via/vt8231/vt8231_early_smbus.c
new file mode 100644
index 0000000000..44672be310
--- /dev/null
+++ b/src/southbridge/via/vt8231/vt8231_early_smbus.c
@@ -0,0 +1,114 @@
+#define SMBUS_IO_BASE 0x5000
+
+#define SMBGSTATUS 0xe0
+#define SMBGCTL 0xe2
+#define SMBHSTADDR 0xe4
+#define SMBHSTDAT 0xe6
+#define SMBHSTCMD 0xe8
+#define SMBHSTFIFO 0xe9
+
+#define SMBUS_TIMEOUT (100*1000*10)
+
+static void enable_smbus(void)
+{
+ device_t dev;
+ /* Power management controller */
+ dev = pci_locate_device(PCI_ID(0x1106,0x8235), 0);
+
+ if (dev == PCI_DEV_INVALID) {
+ die("SMBUS controller not found\r\n");
+ }
+
+ // set IO base address to SMBUS_IO_BASE
+ pci_write_config32(dev, 0x90, SMBUS_IO_BASE|1);
+
+ // Enable SMBus
+ pci_write_config8(dev, 0xd2, 0x01);
+
+
+ print_debug("SMBus controller enabled\r\n");
+}
+
+
+static inline void smbus_delay(void)
+{
+ outb(0x80, 0x80);
+}
+
+static int smbus_wait_until_ready(void)
+{
+ unsigned long loops;
+ loops = SMBUS_TIMEOUT;
+ do {
+ unsigned short val;
+ smbus_delay();
+ val = inw(SMBUS_IO_BASE + SMBGSTATUS);
+ if ((val & 0x800) == 0) {
+ break;
+ }
+ } while(--loops);
+ return loops?0:-1;
+}
+
+static int smbus_wait_until_done(void)
+{
+ unsigned long loops;
+ loops = SMBUS_TIMEOUT;
+ do {
+ unsigned short val;
+ smbus_delay();
+
+ val = inw(SMBUS_IO_BASE + SMBGSTATUS);
+ if (((val & 0x8) == 0) | ((val & 0x437) != 0)) {
+ break;
+ }
+ } while(--loops);
+ return loops?0:-1;
+}
+
+static int smbus_read_byte(unsigned device, unsigned address)
+{
+ unsigned char global_control_register;
+ unsigned char global_status_register;
+ unsigned char byte;
+
+ if (smbus_wait_until_ready() < 0) {
+ return -1;
+ }
+
+ /* setup transaction */
+ /* disable interrupts */
+ outw(inw(SMBUS_IO_BASE + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), SMBUS_IO_BASE + SMBGCTL);
+ /* set the device I'm talking too */
+ outw(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBHSTADDR);
+ /* set the command/address... */
+ outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
+ /* set up for a byte data read */
+ outw((inw(SMBUS_IO_BASE + SMBGCTL) & ~7) | (0x2), SMBUS_IO_BASE + SMBGCTL);
+
+ /* clear any lingering errors, so the transaction will run */
+ /* Do I need to write the bits to a 1 to clear an error? */
+ outw(inw(SMBUS_IO_BASE + SMBGSTATUS), SMBUS_IO_BASE + SMBGSTATUS);
+
+ /* clear the data word...*/
+ outw(0, SMBUS_IO_BASE + SMBHSTDAT);
+
+ /* start the command */
+ outw((inw(SMBUS_IO_BASE + SMBGCTL) | (1 << 3)), SMBUS_IO_BASE + SMBGCTL);
+
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done() < 0) {
+ return -1;
+ }
+
+ global_status_register = inw(SMBUS_IO_BASE + SMBGSTATUS);
+
+ /* read results of transaction */
+ byte = inw(SMBUS_IO_BASE + SMBHSTDAT) & 0xff;
+
+ if (global_status_register != (1 << 4)) {
+ return -1;
+ }
+ return byte;
+}