[coreboot] Patch set updated for coreboot: f9cf7e3 Add code to set the clock speed for Winbond W83627THF/THG.
Idwer Vollering (vidwer@gmail.com)
gerrit at coreboot.org
Sat Nov 5 18:09:17 CET 2011
Idwer Vollering (vidwer at gmail.com) just uploaded a new patch set to gerrit, which you can find at http://review.coreboot.org/411
-gerrit
commit f9cf7e33e64fe399a77aff25b105132cf90990ab
Author: Idwer Vollering <vidwer at gmail.com>
Date: Sat Nov 5 18:08:08 2011 +0100
Add code to set the clock speed for Winbond W83627THF/THG.
Change-Id: If92d96d117683cc59081061d5ac93aa23cb87327
Signed-off-by: Idwer Vollering <vidwer at gmail.com>
---
src/cpu/intel/model_f2x/Kconfig | 3 +
src/cpu/intel/model_f2x/Makefile.inc | 1 +
src/cpu/intel/model_f2x/cache_as_ram.inc | 376 ++++++++++
src/cpu/intel/socket_mPGA478/Kconfig | 1 +
src/cpu/intel/socket_mPGA478/Makefile.inc | 2 +-
src/include/device/pci_ids.h | 6 +-
src/mainboard/asrock/Kconfig | 5 +-
src/mainboard/asrock/p4i65gv/Kconfig | 53 ++
src/mainboard/asrock/p4i65gv/Makefile.inc | 1 +
src/mainboard/asrock/p4i65gv/chip.h | 22 +
src/mainboard/asrock/p4i65gv/devicetree.cb | 49 ++
src/mainboard/asrock/p4i65gv/irq_tables.c | 63 ++
src/mainboard/asrock/p4i65gv/mainboard.c | 26 +
src/mainboard/asrock/p4i65gv/romstage.c | 84 +++
src/mainboard/asrock/p4i65gv/rtl8139.c | 46 ++
src/mainboard/asrock/p4i65gv/watchdog.c | 36 +
src/mainboard/asus/Kconfig | 4 +-
src/mainboard/asus/p4p800-vm/Kconfig | 53 ++
src/mainboard/asus/p4p800-vm/Makefile.inc | 1 +
src/mainboard/asus/p4p800-vm/chip.h | 22 +
src/mainboard/asus/p4p800-vm/devicetree.cb | 49 ++
src/mainboard/asus/p4p800-vm/e100.c | 46 ++
src/mainboard/asus/p4p800-vm/irq_tables.c | 63 ++
src/mainboard/asus/p4p800-vm/mainboard.c | 26 +
src/mainboard/asus/p4p800-vm/romstage.c | 84 +++
src/mainboard/asus/p4p800-vm/watchdog.c | 36 +
src/northbridge/intel/Kconfig | 1 +
src/northbridge/intel/Makefile.inc | 1 +
src/northbridge/intel/i865/Kconfig | 25 +
src/northbridge/intel/i865/Makefile.inc | 2 +
src/northbridge/intel/i865/TODO | 16 +
src/northbridge/intel/i865/chip.h | 25 +
src/northbridge/intel/i865/debug.c | 139 ++++
src/northbridge/intel/i865/i865.h | 89 +++
src/northbridge/intel/i865/northbridge.c | 171 +++++
src/northbridge/intel/i865/raminit.c | 1031 ++++++++++++++++++++++++++
src/northbridge/intel/i865/raminit.h | 181 +++++
src/northbridge/intel/i865/reset_test.c | 38 +
src/southbridge/intel/i82801ex/early_smbus.c | 4 +-
src/southbridge/intel/i82801ex/smbus.h | 3 +
src/superio/winbond/w83627thg/early_serial.c | 11 +
41 files changed, 2888 insertions(+), 7 deletions(-)
diff --git a/src/cpu/intel/model_f2x/Kconfig b/src/cpu/intel/model_f2x/Kconfig
index 50cac79..ca57343 100644
--- a/src/cpu/intel/model_f2x/Kconfig
+++ b/src/cpu/intel/model_f2x/Kconfig
@@ -1,3 +1,6 @@
config CPU_INTEL_MODEL_F2X
bool
select SMP
+ select MMX
+ select SSE
+ select CACHE_AS_RAM
diff --git a/src/cpu/intel/model_f2x/Makefile.inc b/src/cpu/intel/model_f2x/Makefile.inc
index c393343..d4ddb7b 100644
--- a/src/cpu/intel/model_f2x/Makefile.inc
+++ b/src/cpu/intel/model_f2x/Makefile.inc
@@ -1 +1,2 @@
+cpu_incs += $(src)/cpu/intel/model_f2x/cache_as_ram.inc
driver-y += model_f2x_init.c
diff --git a/src/cpu/intel/model_f2x/cache_as_ram.inc b/src/cpu/intel/model_f2x/cache_as_ram.inc
new file mode 100644
index 0000000..7742a68
--- /dev/null
+++ b/src/cpu/intel/model_f2x/cache_as_ram.inc
@@ -0,0 +1,376 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2000, 2007 Ronald G. Minnich <rminnich at gmail.com>
+ * Copyright (C) 2005 Eswar Nallusamy, LANL
+ * Copyright (C) 2005 Tyan (written by Yinghai Lu for Tyan)
+ * Copyright (C) 2007-2010 coresystems GmbH
+ * Copyright (C) 2007 Carl-Daniel Hailfinger
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; version 2 of the License.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <cpu/x86/stack.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/lapic_def.h>
+#include <cpu/x86/post_code.h>
+
+#define CacheSize CONFIG_DCACHE_RAM_SIZE
+#define CacheBase (0xd0000 - CacheSize)
+
+ /* Save the BIST result. */
+ movl %eax, %ebp
+
+CacheAsRam:
+ /* Check whether the processor has HT capability. */
+ movl $01, %eax
+ cpuid
+ btl $28, %edx
+ jnc NotHtProcessor
+ bswapl %ebx
+ cmpb $01, %bh
+ jbe NotHtProcessor
+
+ /*
+ * It is a HT processor. Send SIPI to the other logical processor
+ * within this processor so that the CAR related common system
+ * registers are programmed accordingly.
+ */
+
+ /*
+ * Use some register that is common to both logical processors
+ * as semaphore. Refer Appendix B, Vol.3.
+ */
+ xorl %eax, %eax
+ xorl %edx, %edx
+ movl $MTRRfix64K_00000_MSR, %ecx
+ wrmsr
+
+ /*
+ * Figure out the logical AP's APIC ID; the following logic will
+ * work only for processors with 2 threads.
+ * Refer to Vol 3. Table 7-1 for details about this logic.
+ */
+ movl $0xFEE00020, %esi
+ movl (%esi), %ebx
+ andl $0xFF000000, %ebx
+ bswapl %ebx
+ btl $0, %ebx
+ jnc LogicalAP0
+ andb $0xFE, %bl
+ jmp Send_SIPI
+LogicalAP0:
+ orb $0x01, %bl
+Send_SIPI:
+ bswapl %ebx /* EBX - logical AP's APIC ID. */
+
+ /*
+ * Fill up the IPI command registers in the Local APIC mapped to
+ * default address and issue SIPI to the other logical processor
+ * within this processor die.
+ */
+Retry_SIPI:
+ movl %ebx, %eax
+ movl $0xFEE00310, %esi
+ movl %eax, (%esi)
+
+ /* SIPI vector - F900:0000 */
+ movl $0x000006F9, %eax
+ movl $0xFEE00300, %esi
+ movl %eax, (%esi)
+
+ movl $0x30, %ecx
+SIPI_Delay:
+ pause
+ decl %ecx
+ jnz SIPI_Delay
+
+ movl (%esi), %eax
+ andl $0x00001000, %eax
+ jnz Retry_SIPI
+
+ /* Wait for the Logical AP to complete initialization. */
+LogicalAP_SIPINotdone:
+ movl $MTRRfix64K_00000_MSR, %ecx
+ rdmsr
+ orl %eax, %eax
+ jz LogicalAP_SIPINotdone
+
+NotHtProcessor:
+ /* Set the default memory type and enable fixed and variable MTRRs. */
+ movl $MTRRdefType_MSR, %ecx
+ xorl %edx, %edx
+ movl $(MTRRdefTypeEn | MTRRdefTypeFixEn), %eax
+ wrmsr
+
+ /* Clear all MTRRs. */
+ xorl %edx, %edx
+ movl $all_mtrr_msrs, %esi
+
+clear_fixed_var_mtrr:
+ lodsl (%esi), %eax
+ testl %eax, %eax
+ jz clear_fixed_var_mtrr_out
+
+ movl %eax, %ecx
+ xorl %eax, %eax
+ wrmsr
+
+ jmp clear_fixed_var_mtrr
+
+all_mtrr_msrs:
+ /* fixed MTRR MSRs */
+ .long MTRRfix64K_00000_MSR
+ .long MTRRfix16K_80000_MSR
+ .long MTRRfix16K_A0000_MSR
+ .long MTRRfix4K_C0000_MSR
+ .long MTRRfix4K_C8000_MSR
+ .long MTRRfix4K_D0000_MSR
+ .long MTRRfix4K_D8000_MSR
+ .long MTRRfix4K_E0000_MSR
+ .long MTRRfix4K_E8000_MSR
+ .long MTRRfix4K_F0000_MSR
+ .long MTRRfix4K_F8000_MSR
+
+ /* var MTRR MSRs */
+ .long MTRRphysBase_MSR(0)
+ .long MTRRphysMask_MSR(0)
+ .long MTRRphysBase_MSR(1)
+ .long MTRRphysMask_MSR(1)
+ .long MTRRphysBase_MSR(2)
+ .long MTRRphysMask_MSR(2)
+ .long MTRRphysBase_MSR(3)
+ .long MTRRphysMask_MSR(3)
+ .long MTRRphysBase_MSR(4)
+ .long MTRRphysMask_MSR(4)
+ .long MTRRphysBase_MSR(5)
+ .long MTRRphysMask_MSR(5)
+ .long MTRRphysBase_MSR(6)
+ .long MTRRphysMask_MSR(6)
+ .long MTRRphysBase_MSR(7)
+ .long MTRRphysMask_MSR(7)
+
+ .long 0x000 /* NULL, end of table */
+
+clear_fixed_var_mtrr_out:
+
+/*
+ * 0x06 is the WB IO type for a given 4k segment.
+ * segs is the number of 4k segments in the area of the particular
+ * register we want to use for CAR.
+ * reg is the register where the IO type should be stored.
+ */
+.macro extractmask segs, reg
+.if \segs <= 0
+ /*
+ * The xorl here is superfluous because at the point of first execution
+ * of this macro, %eax and %edx are cleared. Later invocations of this
+ * macro will have a monotonically increasing segs parameter.
+ */
+ xorl \reg, \reg
+.elseif \segs == 1
+ movl $0x06000000, \reg /* WB IO type */
+.elseif \segs == 2
+ movl $0x06060000, \reg /* WB IO type */
+.elseif \segs == 3
+ movl $0x06060600, \reg /* WB IO type */
+.elseif \segs >= 4
+ movl $0x06060606, \reg /* WB IO type */
+.endif
+.endm
+
+/*
+ * carsize is the cache size in bytes we want to use for CAR.
+ * windowoffset is the 32k-aligned window into CAR size.
+ */
+.macro simplemask carsize, windowoffset
+ .set gas_bug_workaround,(((\carsize - \windowoffset) / 0x1000) - 4)
+ extractmask gas_bug_workaround, %eax
+ .set gas_bug_workaround,(((\carsize - \windowoffset) / 0x1000))
+ extractmask gas_bug_workaround, %edx
+ /*
+ * Without the gas bug workaround, the entire macro would consist
+ * only of the two lines below:
+ * extractmask (((\carsize - \windowoffset) / 0x1000) - 4), %eax
+ * extractmask (((\carsize - \windowoffset) / 0x1000)), %edx
+ */
+.endm
+
+#if CacheSize > 0x10000
+#error Invalid CAR size, must be at most 64k.
+#endif
+#if CacheSize < 0x1000
+#error Invalid CAR size, must be at least 4k. This is a processor limitation.
+#endif
+#if (CacheSize & (0x1000 - 1))
+#error Invalid CAR size, is not a multiple of 4k. This is a processor limitation.
+#endif
+
+#if CacheSize > 0x8000
+ /* Enable caching for 32K-64K using fixed MTRR. */
+ movl $MTRRfix4K_C0000_MSR, %ecx
+ simplemask CacheSize, 0x8000
+ wrmsr
+#endif
+
+ /* Enable caching for 0-32K using fixed MTRR. */
+ movl $MTRRfix4K_C8000_MSR, %ecx
+ simplemask CacheSize, 0
+ wrmsr
+
+#if CONFIG_XIP_ROM_SIZE
+
+ /*
+ * Enable write base caching so we can do execute in place (XIP)
+ * on the flash ROM.
+ */
+ movl $MTRRphysBase_MSR(1), %ecx
+ xorl %edx, %edx
+ /*
+ * IMPORTANT: The following calculation _must_ be done at runtime. See
+ * http://www.coreboot.org/pipermail/coreboot/2010-October/060855.html
+ */
+ movl $copy_and_run, %eax
+ andl $(~(CONFIG_XIP_ROM_SIZE - 1)), %eax
+ orl $MTRR_TYPE_WRBACK, %eax
+ wrmsr
+
+ movl $MTRRphysMask_MSR(1), %ecx
+ movl $0x0000000f, %edx
+ movl $(~(CONFIG_XIP_ROM_SIZE - 1) | MTRRphysMaskValid), %eax
+ wrmsr
+#endif /* CONFIG_XIP_ROM_SIZE */
+
+ /* Enable cache. */
+ movl %cr0, %eax
+ andl $(~((1 << 30) | (1 << 29))), %eax
+ movl %eax, %cr0
+
+ /* Read the range with lodsl. */
+ movl $CacheBase, %esi
+ cld
+ movl $(CacheSize >> 2), %ecx
+ rep lodsl
+
+ /* Clear the range. */
+ movl $CacheBase, %edi
+ movl $(CacheSize >> 2), %ecx
+ xorl %eax, %eax
+ rep stosl
+
+#if 0
+ /* Check the cache as ram. */
+ movl $CacheBase, %esi
+ movl $(CacheSize >> 2), %ecx
+.xin1:
+ movl %esi, %eax
+ movl %eax, (%esi)
+ decl %ecx
+ je .xout1
+ add $4, %esi
+ jmp .xin1
+.xout1:
+
+ movl $CacheBase, %esi
+ // movl $(CacheSize >> 2), %ecx
+ movl $4, %ecx
+.xin1x:
+ movl %esi, %eax
+
+ movl $0x4000, %edx
+ movb %ah, %al
+.testx1:
+ outb %al, $0x80
+ decl %edx
+ jnz .testx1
+
+ movl (%esi), %eax
+ cmpb 0xff, %al
+ je .xin2 /* Don't show. */
+
+ movl $0x4000, %edx
+.testx2:
+ outb %al, $0x80
+ decl %edx
+ jnz .testx2
+
+.xin2:
+ decl %ecx
+ je .xout1x
+ add $4, %esi
+ jmp .xin1x
+.xout1x:
+#endif
+
+ movl $(CacheBase + CacheSize - 4), %eax
+ movl %eax, %esp
+lout:
+ /* Restore the BIST result. */
+ movl %ebp, %eax
+
+ /* We need to set EBP? No need. */
+ movl %esp, %ebp
+ pushl %eax /* BIST */
+ call main
+
+ /* We don't need CAR from now on. */
+
+ /* Disable cache. */
+ movl %cr0, %eax
+ orl $(1 << 30), %eax
+ movl %eax, %cr0
+
+ /* Clear sth. */
+ movl $MTRRfix4K_C8000_MSR, %ecx
+ xorl %edx, %edx
+ xorl %eax, %eax
+ wrmsr
+
+#if CONFIG_DCACHE_RAM_SIZE > 0x8000
+ movl $MTRRfix4K_C0000_MSR, %ecx
+ wrmsr
+#endif
+
+ /*
+ * Set the default memory type and disable fixed
+ * and enable variable MTRRs.
+ */
+ movl $MTRRdefType_MSR, %ecx
+ xorl %edx, %edx
+ movl $MTRRdefTypeEn, %eax /* Enable variable and disable fixed MTRRs. */
+ wrmsr
+
+ /* Enable cache. */
+ movl %cr0, %eax
+ andl $(~((1 << 30) | (1 << 29))), %eax
+ movl %eax, %cr0
+
+ /* Clear boot_complete flag. */
+ xorl %ebp, %ebp
+__main:
+ post_code(POST_PREPARE_RAMSTAGE)
+ cld /* Clear direction flag. */
+
+ movl %ebp, %esi
+
+ movl $ROMSTAGE_STACK, %esp
+ movl %esp, %ebp
+ pushl %esi
+ call copy_and_run
+
+.Lhlt:
+ post_code(POST_DEAD_CODE)
+ hlt
+ jmp .Lhlt
+
diff --git a/src/cpu/intel/socket_mPGA478/Kconfig b/src/cpu/intel/socket_mPGA478/Kconfig
index 8c447c9..c17780f 100644
--- a/src/cpu/intel/socket_mPGA478/Kconfig
+++ b/src/cpu/intel/socket_mPGA478/Kconfig
@@ -2,3 +2,4 @@ config CPU_INTEL_SOCKET_MPGA478
bool
select CPU_INTEL_MODEL_69X
select CPU_INTEL_MODEL_6DX
+ select CPU_INTEL_MODEL_F2X
diff --git a/src/cpu/intel/socket_mPGA478/Makefile.inc b/src/cpu/intel/socket_mPGA478/Makefile.inc
index ba2f13c..c3742f3 100644
--- a/src/cpu/intel/socket_mPGA478/Makefile.inc
+++ b/src/cpu/intel/socket_mPGA478/Makefile.inc
@@ -1,6 +1,7 @@
ramstage-y += socket_mPGA478.c
subdirs-y += ../model_69x
subdirs-y += ../model_6dx
+subdirs-y += ../model_f2x
subdirs-y += ../../x86/tsc
subdirs-y += ../../x86/mtrr
subdirs-y += ../../x86/lapic
@@ -8,4 +9,3 @@ subdirs-y += ../../x86/cache
subdirs-y += ../../x86/smm
subdirs-y += ../microcode
subdirs-y += ../hyperthreading
-
diff --git a/src/include/device/pci_ids.h b/src/include/device/pci_ids.h
index d16f85e..37b5848 100644
--- a/src/include/device/pci_ids.h
+++ b/src/include/device/pci_ids.h
@@ -2142,7 +2142,8 @@
#define PCI_DEVICE_ID_INTEL_82801DBM_EHCI 0x24cd
/* Intel 82801EB (ICH5) */
-#define PCI_DEVICE_ID_INTEL_82801EB_LAN 0x1051
+#define PCI_DEVICE_ID_INTEL_82801EB_LAN1 0x1050
+#define PCI_DEVICE_ID_INTEL_82801EB_LAN2 0x1051
#define PCI_DEVICE_ID_INTEL_82801EB_PCI 0x244e
#define PCI_DEVICE_ID_INTEL_82801EB_LPC 0x24d0
#define PCI_DEVICE_ID_INTEL_82801EB_SATA 0x24d1
@@ -2157,7 +2158,8 @@
#define PCI_DEVICE_ID_INTEL_82801EB_USB4 0x24de
/* Intel 82801ER (ICH5R) */
-#define PCI_DEVICE_ID_INTEL_82801ER_LAN 0x1051
+#define PCI_DEVICE_ID_INTEL_82801ER_LAN1 0x1050
+#define PCI_DEVICE_ID_INTEL_82801ER_LAN2 0x1051
#define PCI_DEVICE_ID_INTEL_82801ER_PCI 0x244e
#define PCI_DEVICE_ID_INTEL_82801ER_LPC 0x24d0
#define PCI_DEVICE_ID_INTEL_82801ER_USB1 0x24d2
diff --git a/src/mainboard/asrock/Kconfig b/src/mainboard/asrock/Kconfig
index 1e4fff9..260f048 100644
--- a/src/mainboard/asrock/Kconfig
+++ b/src/mainboard/asrock/Kconfig
@@ -25,11 +25,14 @@ config BOARD_ASROCK_939A785GMH
bool "939A785GMH/128M"
config BOARD_ASROCK_E350M1
bool "E350M1"
+config BOARD_ASROCK_P4I65GV
+ bool "P4i65GV"
endchoice
-source "src/mainboard/asrock/939a785gmh/Kconfig"
+source "src/mainboard/asrock/939a785gmh/Kconfig"
source "src/mainboard/asrock/e350m1/Kconfig"
+source "src/mainboard/asrock/p4i65gv/Kconfig"
config MAINBOARD_VENDOR
string
diff --git a/src/mainboard/asrock/p4i65gv/Kconfig b/src/mainboard/asrock/p4i65gv/Kconfig
new file mode 100644
index 0000000..21e2b3d
--- /dev/null
+++ b/src/mainboard/asrock/p4i65gv/Kconfig
@@ -0,0 +1,53 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe at hermann-uwe.de>
+##
+## This program is free software; you can redistribute it and/or modify it under the terms of the GNU General
+## Public License as published by the Free Software Foundation; version 2 of the License.
+##
+## This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
+## implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along with this program; if not, write to
+## the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+if BOARD_ASROCK_P4I65GV
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+ def_bool y
+ select ARCH_X86
+ select CPU_INTEL_SOCKET_MPGA478
+ select NORTHBRIDGE_INTEL_I865
+ select SOUTHBRIDGE_INTEL_I82801EX
+ select SUPERIO_WINBOND_W83627HF
+ select HAVE_HARD_RESET
+# select HAVE_PIRQ_TABLE
+ select UDELAY_TSC
+ select BOARD_ROMSIZE_KB_512
+ select USE_WATCHDOG_ON_BOOT
+# select HAVE_ACPI_TABLES
+# select CACHE_AS_RAM # inherited from the socket option
+
+config MAINBOARD_DIR
+ string
+ default asrock/p4i65gv
+
+config MAINBOARD_PART_NUMBER
+ string
+ default "P4i65GV"
+
+config DCACHE_RAM_BASE
+ hex
+ default 0xfff00000
+
+config DCACHE_RAM_SIZE
+ hex
+ default 0x8000 # ok?
+
+config IRQ_SLOT_COUNT
+ int
+ default 6 # no idea
+
+endif # BOARD_ASROCK_P4I65GV
diff --git a/src/mainboard/asrock/p4i65gv/Makefile.inc b/src/mainboard/asrock/p4i65gv/Makefile.inc
new file mode 100644
index 0000000..03e044d
--- /dev/null
+++ b/src/mainboard/asrock/p4i65gv/Makefile.inc
@@ -0,0 +1 @@
+driver-y += rtl8139.c
diff --git a/src/mainboard/asrock/p4i65gv/chip.h b/src/mainboard/asrock/p4i65gv/chip.h
new file mode 100644
index 0000000..e77b136
--- /dev/null
+++ b/src/mainboard/asrock/p4i65gv/chip.h
@@ -0,0 +1,22 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <uwe at hermann-uwe.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+extern struct chip_operations mainboard_ops;
+struct mainboard_config {};
diff --git a/src/mainboard/asrock/p4i65gv/devicetree.cb b/src/mainboard/asrock/p4i65gv/devicetree.cb
new file mode 100644
index 0000000..992463c
--- /dev/null
+++ b/src/mainboard/asrock/p4i65gv/devicetree.cb
@@ -0,0 +1,49 @@
+chip northbridge/intel/i865
+ device lapic_cluster 0 on
+ chip cpu/intel/socket_mPGA478
+ device lapic 0 on end
+ end
+ end
+ device pci_domain 0 on
+ device pci 0.0 on end # northbridge
+ device pci 0.1 off end # agp
+ device pci 0.2 on end # igd
+ device pnp 0.3 off end # csa
+ device pci 0.6 on end # overflow device
+
+ chip southbridge/intel/i82801ex
+ device pci 1d.0 on end # uhci #1
+ device pci 1d.1 on end # uhci #2
+ device pci 1d.2 on end # uhci #3
+ device pci 1d.3 on end # uhci #4
+ device pci 1d.7 on end # ehci
+ device pci 1e.0 on # pci bridge
+ # 01:05.0 Ethernet controller [0200]: Realtek Semiconductor Co., Ltd. RTL-8139/8139C/8139C+ [10ec:8139] (rev 10)
+ device pci 05.0 on end
+ end
+
+ device pci 1f.0 on # lpc bridge
+ chip superio/winbond/w83627hf
+ device pnp 2e.0 off end # floppy
+ device pnp 2e.1 off end # parallel
+ device pnp 2e.2 on
+ io 0x60 = 0x3f8
+ irq 0x70 = 4
+ end # com1
+ device pnp 2e.3 off end # com2
+ device pnp 2e.5 on end # keyboard
+ device pnp 2e.6 off end # ir
+ device pnp 2e.7 on end # game/gpio 1
+ device pnp 2e.8 on end # gpio 2
+ device pnp 2e.9 on end # gpio 3
+ device pnp 2e.a on end # acpi
+ device pnp 2e.b on end # hardware monitor
+ end # superio
+ end # 1f.0
+ device pci 1f.1 on end # pata
+ device pci 1f.2 on end # sata
+ device pci 1f.3 on end # smbus
+ device pci 1f.5 off end # ac97
+ end # southbridge
+ end # pci_domain
+end # northbridge
diff --git a/src/mainboard/asrock/p4i65gv/irq_tables.c b/src/mainboard/asrock/p4i65gv/irq_tables.c
new file mode 100644
index 0000000..240ab23
--- /dev/null
+++ b/src/mainboard/asrock/p4i65gv/irq_tables.c
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 200x TODO <TODO at TODO>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef GETPIR /* TODO: Drop this when copying to coreboot. */
+#include "pirq_routing.h" /* TODO: Drop this when copying to coreboot. */
+#else /* TODO: Drop this when copying to coreboot. */
+#include <arch/pirq_routing.h>
+#endif /* TODO: Drop this when copying to coreboot. */
+
+const struct irq_routing_table intel_irq_routing_table = {
+ PIRQ_SIGNATURE, /* u32 signature */
+ PIRQ_VERSION, /* u16 version */
+ 32 + 16 * 13, /* Max. number of devices on the bus */
+ 0x00, /* Interrupt router bus */
+ (0x1f << 3) | 0x0, /* Interrupt router dev */
+ 0, /* IRQs devoted exclusively to PCI usage */
+ 0x8086, /* Vendor */
+ 0x24d0, /* Device */
+ 0, /* Miniport */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
+ 0x3e, /* Checksum (has to be set to some value that
+ * would give 0 after the sum of all bytes
+ * for this structure (including checksum).
+ */
+ {
+ /* bus, dev | fn, {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */
+ {0x01, (0x08 << 3) | 0x0, {{0x68, 0xdcf8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+ {0x00, (0x1f << 3) | 0x0, {{0x62, 0xdcf8}, {0x61, 0xdcf8}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+ {0x00, (0x1d << 3) | 0x0, {{0x60, 0xdcf8}, {0x63, 0xdcf8}, {0x62, 0xdcf8}, {0x6b, 0xdcf8}}, 0x0, 0x0},
+ {0x00, (0x01 << 3) | 0x0, {{0x60, 0xdcf8}, {0x61, 0xdcf8}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+ {0x00, (0x02 << 3) | 0x0, {{0x60, 0xdcf8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+ {0x00, (0x03 << 3) | 0x0, {{0x00, 0x0000}, {0x62, 0xdcf8}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+ {0x01, (0x03 << 3) | 0x0, {{0x68, 0xdcf8}, {0x69, 0xdcf8}, {0x6a, 0xdcf8}, {0x6b, 0xdcf8}}, 0x1, 0x0},
+ {0x01, (0x01 << 3) | 0x0, {{0x6a, 0xdcf8}, {0x6b, 0xdcf8}, {0x68, 0xdcf8}, {0x69, 0xdcf8}}, 0x2, 0x0},
+ {0x01, (0x02 << 3) | 0x0, {{0x6b, 0xdcf8}, {0x68, 0xdcf8}, {0x69, 0xdcf8}, {0x6a, 0xdcf8}}, 0x3, 0x0},
+ {0x01, (0x00 << 3) | 0x0, {{0x69, 0xdcf8}, {0x6a, 0xdcf8}, {0x6b, 0xdcf8}, {0x68, 0xdcf8}}, 0x4, 0x0},
+ {0x01, (0x04 << 3) | 0x0, {{0x69, 0xdcf8}, {0x6a, 0xdcf8}, {0x6b, 0xdcf8}, {0x68, 0xdcf8}}, 0x5, 0x0},
+ {0x01, (0x0a << 3) | 0x0, {{0x6a, 0xdcf8}, {0x6b, 0xdcf8}, {0x68, 0xdcf8}, {0x69, 0xdcf8}}, 0x6, 0x0},
+ {0x01, (0x05 << 3) | 0x0, {{0x6a, 0xdcf8}, {0x6b, 0xdcf8}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+ }
+};
+
+unsigned long write_pirq_routing_table(unsigned long addr)
+{
+ return copy_pirq_routing_table(addr);
+}
diff --git a/src/mainboard/asrock/p4i65gv/mainboard.c b/src/mainboard/asrock/p4i65gv/mainboard.c
new file mode 100644
index 0000000..78aec29
--- /dev/null
+++ b/src/mainboard/asrock/p4i65gv/mainboard.c
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <uwe at hermann-uwe.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <device/device.h>
+#include "chip.h"
+
+struct chip_operations mainboard_ops = {
+ CHIP_NAME("ASRock P4i65GV Mainboard")
+};
diff --git a/src/mainboard/asrock/p4i65gv/romstage.c b/src/mainboard/asrock/p4i65gv/romstage.c
new file mode 100644
index 0000000..7f70ca0
--- /dev/null
+++ b/src/mainboard/asrock/p4i65gv/romstage.c
@@ -0,0 +1,84 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <uwe at hermann-uwe.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <device/pci_def.h>
+#include <arch/io.h>
+#include <device/pnp_def.h>
+#include <arch/romcc_io.h>
+#include <arch/hlt.h>
+#include <stdlib.h>
+#include <console/console.h>
+#include <lib.h>
+#include <cpu/x86/lapic.h>
+#include "pc80/udelay_io.c"
+//#include "lib/delay.c"
+#include "cpu/x86/bist.h"
+
+//#include "southbridge/intel/i82801ex/i82801ex.h"
+#include "southbridge/intel/i82801ex/early_smbus.c"
+#include "northbridge/intel/i865/debug.c"
+#include "northbridge/intel/i865/raminit.c"
+//#include "northbridge/intel/i865/reset_test.c"
+#include "northbridge/intel/i865/i865.h"
+#include "superio/winbond/w83627hf/early_serial.c"
+#include "watchdog.c"
+
+#define SERIAL_DEV PNP_DEV(0x2e, W83627HF_SP1)
+
+//int spd_read_byte(unsigned int device, unsigned int address)
+//static inline int spd_read_byte(unsigned device, unsigned address)
+//{
+// return smbus_read_byte(device, address);
+//}
+
+void main(unsigned long bist) {
+
+ // TODO
+ // copied from dell/s1850/romstage.c
+ /*
+ static const struct mem_controller memctrl[] = {
+ {
+ // node id?
+ .channel0 = { DIMM0, DIMM1, DIMM2, DIMM3, },
+ .channel1 = { DIMM4, DIMM5, DIMM6, DIMM7, },
+ }
+ };
+*/
+ if (bist == 0)
+ enable_lapic();
+
+ w83627hf_set_clksel_48(SERIAL_DEV);
+ w83627hf_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE);
+ console_init();
+ report_bist_failure(bist);
+
+// if (!bios_reset_detected()) /* board doesn't boot when using bios_rest_detected() */
+// {
+ enable_smbus();
+ dump_spd_registers();
+
+ disable_ich5_watchdog();
+
+ // TODO: dual-channel, e.g.:
+ // sdram_initialize(ARRAY_SIZE(memctrl), memctrl); // copied from dell/s1850/romstage.c
+ sdram_initialize();
+// }
+}
diff --git a/src/mainboard/asrock/p4i65gv/rtl8139.c b/src/mainboard/asrock/p4i65gv/rtl8139.c
new file mode 100644
index 0000000..d909af7
--- /dev/null
+++ b/src/mainboard/asrock/p4i65gv/rtl8139.c
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* This code should work for all ICH* southbridges with a NIC. */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+static void nic_init(struct device *dev)
+{
+ printk(BIOS_DEBUG, "Initializing RTL8139 Fast Ethernet\n");
+ // Nothing to do yet, but this has to be here to keep
+ // coreboot from trying to execute an option ROM.
+}
+static struct device_operations nic_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = nic_init,
+ .scan_bus = 0,
+};
+
+static const struct pci_driver rtl8139_nic __pci_driver = {
+ .ops = &nic_ops,
+ .vendor = PCI_VENDOR_ID_REALTEK,
+ .device = PCI_DEVICE_ID_REALTEK_8139,
+};
diff --git a/src/mainboard/asrock/p4i65gv/watchdog.c b/src/mainboard/asrock/p4i65gv/watchdog.c
new file mode 100644
index 0000000..8c7b0f6
--- /dev/null
+++ b/src/mainboard/asrock/p4i65gv/watchdog.c
@@ -0,0 +1,36 @@
+/* copied and adapted from src/mainboard/dell/s1850/watchdog.c */
+
+#define ICH5_WDBASE 0x800 /* PMBASE */
+#define ICH5_GPIOBASE 0x480
+
+static void disable_ich5_watchdog(void)
+{
+ /* FIXME move me somewhere more appropriate */
+ device_t dev;
+ unsigned long value, base;
+ dev = pci_locate_device(PCI_ID(0x8086, 0x24d0), 0); /* LPC bridge */
+ if (dev == PCI_DEV_INVALID) {
+ die("Missing ich5?");
+ }
+
+ /* Enable I/O space */
+ value = pci_read_config16(dev, 0x04); /* PCICMD */
+ value |= (1 << 10); /* reserved? */
+ pci_write_config16(dev, 0x04, value);
+
+ /* Set and enable acpibase */
+ pci_write_config32(dev, 0x40, ICH5_WDBASE | 1); /* PMBASE */
+ pci_write_config8(dev, 0x44, 0x10); /* ACPI_CNTL = ACPI_EN */
+ base = ICH5_WDBASE + 0x60; /* TCO offset, ich5 datasheet ch9.11 */
+
+ /* Set bit 11 in TCO1_CNT */
+ value = inw(base + 0x08);
+ value |= 1 << 11; /* enable TCO_TMR_HLT */
+ outw(value, base + 0x08);
+
+ /* Clear TCO timeout status */
+ outw(0x0008, base + 0x04); /* TCO1_STS, raise bit 3: TIMEOUT */
+ outw(0x0002, base + 0x06); /* TCO2_STS, raise bit 2: SECOND_TO_STS */
+
+ printk(BIOS_DEBUG, "Board-specific ICH5 watchdog disabled\n");
+}
diff --git a/src/mainboard/asus/Kconfig b/src/mainboard/asus/Kconfig
index 77b7997..1369a4b 100644
--- a/src/mainboard/asus/Kconfig
+++ b/src/mainboard/asus/Kconfig
@@ -55,7 +55,8 @@ config BOARD_ASUS_P2B_LS
bool "P2B-LS"
config BOARD_ASUS_P3B_F
bool "P3B-F"
-
+config BOARD_ASUS_P4P800_VM
+ bool "P4P800-VM"
endchoice
source "src/mainboard/asus/a8n_e/Kconfig"
@@ -75,6 +76,7 @@ source "src/mainboard/asus/p2b-ds/Kconfig"
source "src/mainboard/asus/p2b-f/Kconfig"
source "src/mainboard/asus/p2b-ls/Kconfig"
source "src/mainboard/asus/p3b-f/Kconfig"
+source "src/mainboard/asus/p4p800-vm/Kconfig"
config MAINBOARD_VENDOR
string
diff --git a/src/mainboard/asus/p4p800-vm/Kconfig b/src/mainboard/asus/p4p800-vm/Kconfig
new file mode 100644
index 0000000..ef93089
--- /dev/null
+++ b/src/mainboard/asus/p4p800-vm/Kconfig
@@ -0,0 +1,53 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2009 Uwe Hermann <uwe at hermann-uwe.de>
+##
+## This program is free software; you can redistribute it and/or modify it under the terms of the GNU General
+## Public License as published by the Free Software Foundation; version 2 of the License.
+##
+## This program is distributed in the hope that it will be useful, but WITHOUT ANY WARRANTY; without even the
+## implied warranty of MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU General Public License
+## for more details.
+##
+## You should have received a copy of the GNU General Public License along with this program; if not, write to
+## the Free Software Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+if BOARD_ASUS_P4P800_VM
+
+config BOARD_SPECIFIC_OPTIONS # dummy
+ def_bool y
+ select ARCH_X86
+ select CPU_INTEL_SOCKET_MPGA478
+ select NORTHBRIDGE_INTEL_I865
+ select SOUTHBRIDGE_INTEL_I82801EX
+ select SUPERIO_WINBOND_W83627THG
+ select HAVE_HARD_RESET
+# select HAVE_PIRQ_TABLE
+ select UDELAY_TSC
+ select BOARD_ROMSIZE_KB_512
+ select USE_WATCHDOG_ON_BOOT
+# select HAVE_ACPI_TABLES
+# select CACHE_AS_RAM # inherited from the socket option
+
+config MAINBOARD_DIR
+ string
+ default asus/p4p800-vm
+
+config MAINBOARD_PART_NUMBER
+ string
+ default "P4P800-VM"
+
+config DCACHE_RAM_BASE
+ hex
+ default 0xfff00000
+
+config DCACHE_RAM_SIZE
+ hex
+ default 0x8000 # ok?
+
+config IRQ_SLOT_COUNT
+ int
+ default 6 # no idea
+
+endif # BOARD_ASUS_P4P800_VM
diff --git a/src/mainboard/asus/p4p800-vm/Makefile.inc b/src/mainboard/asus/p4p800-vm/Makefile.inc
new file mode 100644
index 0000000..93aefe9
--- /dev/null
+++ b/src/mainboard/asus/p4p800-vm/Makefile.inc
@@ -0,0 +1 @@
+driver-y += e100.c
diff --git a/src/mainboard/asus/p4p800-vm/chip.h b/src/mainboard/asus/p4p800-vm/chip.h
new file mode 100644
index 0000000..e77b136
--- /dev/null
+++ b/src/mainboard/asus/p4p800-vm/chip.h
@@ -0,0 +1,22 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <uwe at hermann-uwe.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+extern struct chip_operations mainboard_ops;
+struct mainboard_config {};
diff --git a/src/mainboard/asus/p4p800-vm/devicetree.cb b/src/mainboard/asus/p4p800-vm/devicetree.cb
new file mode 100644
index 0000000..cf80f53
--- /dev/null
+++ b/src/mainboard/asus/p4p800-vm/devicetree.cb
@@ -0,0 +1,49 @@
+chip northbridge/intel/i865
+ device lapic_cluster 0 on
+ chip cpu/intel/socket_mPGA478
+ device lapic 0 on end
+ end
+ end
+ device pci_domain 0 on
+ device pci 0.0 on end # northbridge
+ device pci 0.1 off end # agp
+ device pci 0.2 on end # igd
+ device pnp 0.3 off end # csa
+ device pci 0.6 on end # overflow device
+
+ chip southbridge/intel/i82801ex
+ device pci 1d.0 on end # uhci #1
+ device pci 1d.1 on end # uhci #2
+ device pci 1d.2 on end # uhci #3
+ device pci 1d.3 on end # uhci #4
+ device pci 1d.7 on end # ehci
+ device pci 1e.0 on # pci bridge
+ # 01:08.0 Ethernet controller: Intel Corporation 82562EZ 10/100 Ethernet Controller (rev 02)
+ device pci 08.0 on end
+ end
+
+ device pci 1f.0 on # lpc bridge
+ chip superio/winbond/w83627thg
+ device pnp 2e.0 off end # floppy
+ device pnp 2e.1 off end # parallel
+ device pnp 2e.2 on
+ io 0x60 = 0x3f8
+ irq 0x70 = 4
+ end # com1
+ device pnp 2e.3 off end # com2
+ device pnp 2e.5 on end # keyboard
+ device pnp 2e.6 off end # ir
+ device pnp 2e.7 on end # game/gpio 1
+ device pnp 2e.8 on end # gpio 2
+ device pnp 2e.9 on end # gpio 3
+ device pnp 2e.a on end # acpi
+ device pnp 2e.b on end # hardware monitor
+ end # superio
+ end # 1f.0
+ device pci 1f.1 on end # pata
+ device pci 1f.2 on end # sata
+ device pci 1f.3 on end # smbus
+ device pci 1f.5 off end # ac97
+ end # southbridge
+ end # pci_domain
+end # northbridge
diff --git a/src/mainboard/asus/p4p800-vm/e100.c b/src/mainboard/asus/p4p800-vm/e100.c
new file mode 100644
index 0000000..d3c0e07
--- /dev/null
+++ b/src/mainboard/asus/p4p800-vm/e100.c
@@ -0,0 +1,46 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 coresystems GmbH
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* This code should work for all ICH* southbridges with a NIC. */
+
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+static void nic_init(struct device *dev)
+{
+ printk(BIOS_DEBUG, "Initializing Intel 82562EZ 10/100 Ethernet\n");
+ // Nothing to do yet, but this has to be here to keep
+ // coreboot from trying to execute an option ROM.
+}
+static struct device_operations nic_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = nic_init,
+ .scan_bus = 0,
+};
+
+static const struct pci_driver intel_e100_nic __pci_driver = {
+ .ops = &nic_ops,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = PCI_DEVICE_ID_INTEL_82801EB_LAN1, /* 8086:1050 */
+};
diff --git a/src/mainboard/asus/p4p800-vm/irq_tables.c b/src/mainboard/asus/p4p800-vm/irq_tables.c
new file mode 100644
index 0000000..240ab23
--- /dev/null
+++ b/src/mainboard/asus/p4p800-vm/irq_tables.c
@@ -0,0 +1,63 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 200x TODO <TODO at TODO>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#ifdef GETPIR /* TODO: Drop this when copying to coreboot. */
+#include "pirq_routing.h" /* TODO: Drop this when copying to coreboot. */
+#else /* TODO: Drop this when copying to coreboot. */
+#include <arch/pirq_routing.h>
+#endif /* TODO: Drop this when copying to coreboot. */
+
+const struct irq_routing_table intel_irq_routing_table = {
+ PIRQ_SIGNATURE, /* u32 signature */
+ PIRQ_VERSION, /* u16 version */
+ 32 + 16 * 13, /* Max. number of devices on the bus */
+ 0x00, /* Interrupt router bus */
+ (0x1f << 3) | 0x0, /* Interrupt router dev */
+ 0, /* IRQs devoted exclusively to PCI usage */
+ 0x8086, /* Vendor */
+ 0x24d0, /* Device */
+ 0, /* Miniport */
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
+ 0x3e, /* Checksum (has to be set to some value that
+ * would give 0 after the sum of all bytes
+ * for this structure (including checksum).
+ */
+ {
+ /* bus, dev | fn, {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */
+ {0x01, (0x08 << 3) | 0x0, {{0x68, 0xdcf8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+ {0x00, (0x1f << 3) | 0x0, {{0x62, 0xdcf8}, {0x61, 0xdcf8}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+ {0x00, (0x1d << 3) | 0x0, {{0x60, 0xdcf8}, {0x63, 0xdcf8}, {0x62, 0xdcf8}, {0x6b, 0xdcf8}}, 0x0, 0x0},
+ {0x00, (0x01 << 3) | 0x0, {{0x60, 0xdcf8}, {0x61, 0xdcf8}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+ {0x00, (0x02 << 3) | 0x0, {{0x60, 0xdcf8}, {0x00, 0x0000}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+ {0x00, (0x03 << 3) | 0x0, {{0x00, 0x0000}, {0x62, 0xdcf8}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+ {0x01, (0x03 << 3) | 0x0, {{0x68, 0xdcf8}, {0x69, 0xdcf8}, {0x6a, 0xdcf8}, {0x6b, 0xdcf8}}, 0x1, 0x0},
+ {0x01, (0x01 << 3) | 0x0, {{0x6a, 0xdcf8}, {0x6b, 0xdcf8}, {0x68, 0xdcf8}, {0x69, 0xdcf8}}, 0x2, 0x0},
+ {0x01, (0x02 << 3) | 0x0, {{0x6b, 0xdcf8}, {0x68, 0xdcf8}, {0x69, 0xdcf8}, {0x6a, 0xdcf8}}, 0x3, 0x0},
+ {0x01, (0x00 << 3) | 0x0, {{0x69, 0xdcf8}, {0x6a, 0xdcf8}, {0x6b, 0xdcf8}, {0x68, 0xdcf8}}, 0x4, 0x0},
+ {0x01, (0x04 << 3) | 0x0, {{0x69, 0xdcf8}, {0x6a, 0xdcf8}, {0x6b, 0xdcf8}, {0x68, 0xdcf8}}, 0x5, 0x0},
+ {0x01, (0x0a << 3) | 0x0, {{0x6a, 0xdcf8}, {0x6b, 0xdcf8}, {0x68, 0xdcf8}, {0x69, 0xdcf8}}, 0x6, 0x0},
+ {0x01, (0x05 << 3) | 0x0, {{0x6a, 0xdcf8}, {0x6b, 0xdcf8}, {0x00, 0x0000}, {0x00, 0x0000}}, 0x0, 0x0},
+ }
+};
+
+unsigned long write_pirq_routing_table(unsigned long addr)
+{
+ return copy_pirq_routing_table(addr);
+}
diff --git a/src/mainboard/asus/p4p800-vm/mainboard.c b/src/mainboard/asus/p4p800-vm/mainboard.c
new file mode 100644
index 0000000..5b47989
--- /dev/null
+++ b/src/mainboard/asus/p4p800-vm/mainboard.c
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <uwe at hermann-uwe.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <device/device.h>
+#include "chip.h"
+
+struct chip_operations mainboard_ops = {
+ CHIP_NAME("ASUS P4P800-VM Mainboard")
+};
diff --git a/src/mainboard/asus/p4p800-vm/romstage.c b/src/mainboard/asus/p4p800-vm/romstage.c
new file mode 100644
index 0000000..fad3aca
--- /dev/null
+++ b/src/mainboard/asus/p4p800-vm/romstage.c
@@ -0,0 +1,84 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007 Uwe Hermann <uwe at hermann-uwe.de>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <stdint.h>
+#include <device/pci_def.h>
+#include <arch/io.h>
+#include <device/pnp_def.h>
+#include <arch/romcc_io.h>
+#include <arch/hlt.h>
+#include <stdlib.h>
+#include <console/console.h>
+#include <lib.h>
+#include <cpu/x86/lapic.h>
+#include "pc80/udelay_io.c"
+//#include "lib/delay.c"
+#include "cpu/x86/bist.h"
+
+//#include "southbridge/intel/i82801ex/i82801ex.h"
+#include "southbridge/intel/i82801ex/early_smbus.c"
+#include "northbridge/intel/i865/debug.c"
+#include "northbridge/intel/i865/raminit.c"
+//#include "northbridge/intel/i865/reset_test.c"
+#include "northbridge/intel/i865/i865.h"
+#include "superio/winbond/w83627thg/early_serial.c"
+#include "watchdog.c"
+
+#define SERIAL_DEV PNP_DEV(0x2e, W83627THG_SP1)
+
+//int spd_read_byte(unsigned int device, unsigned int address)
+//static inline int spd_read_byte(unsigned device, unsigned address)
+//{
+// return smbus_read_byte(device, address);
+//}
+
+void main(unsigned long bist) {
+
+ // TODO
+ // copied from dell/s1850/romstage.c
+ /*
+ static const struct mem_controller memctrl[] = {
+ {
+ // node id?
+ .channel0 = { DIMM0, DIMM1, DIMM2, DIMM3, },
+ .channel1 = { DIMM4, DIMM5, DIMM6, DIMM7, },
+ }
+ };
+*/
+ if (bist == 0)
+ enable_lapic();
+
+ w83627thg_set_clksel_48(SERIAL_DEV);
+ w83627thg_enable_serial(SERIAL_DEV, CONFIG_TTYS0_BASE);
+ console_init();
+ report_bist_failure(bist);
+
+// if (!bios_reset_detected()) /* board doesn't boot when using bios_rest_detected() */
+// {
+ enable_smbus();
+ dump_spd_registers();
+
+ disable_ich5_watchdog();
+
+ // TODO: dual-channel, e.g.:
+ // sdram_initialize(ARRAY_SIZE(memctrl), memctrl); // copied from dell/s1850/romstage.c
+ sdram_initialize();
+// }
+}
diff --git a/src/mainboard/asus/p4p800-vm/watchdog.c b/src/mainboard/asus/p4p800-vm/watchdog.c
new file mode 100644
index 0000000..8c7b0f6
--- /dev/null
+++ b/src/mainboard/asus/p4p800-vm/watchdog.c
@@ -0,0 +1,36 @@
+/* copied and adapted from src/mainboard/dell/s1850/watchdog.c */
+
+#define ICH5_WDBASE 0x800 /* PMBASE */
+#define ICH5_GPIOBASE 0x480
+
+static void disable_ich5_watchdog(void)
+{
+ /* FIXME move me somewhere more appropriate */
+ device_t dev;
+ unsigned long value, base;
+ dev = pci_locate_device(PCI_ID(0x8086, 0x24d0), 0); /* LPC bridge */
+ if (dev == PCI_DEV_INVALID) {
+ die("Missing ich5?");
+ }
+
+ /* Enable I/O space */
+ value = pci_read_config16(dev, 0x04); /* PCICMD */
+ value |= (1 << 10); /* reserved? */
+ pci_write_config16(dev, 0x04, value);
+
+ /* Set and enable acpibase */
+ pci_write_config32(dev, 0x40, ICH5_WDBASE | 1); /* PMBASE */
+ pci_write_config8(dev, 0x44, 0x10); /* ACPI_CNTL = ACPI_EN */
+ base = ICH5_WDBASE + 0x60; /* TCO offset, ich5 datasheet ch9.11 */
+
+ /* Set bit 11 in TCO1_CNT */
+ value = inw(base + 0x08);
+ value |= 1 << 11; /* enable TCO_TMR_HLT */
+ outw(value, base + 0x08);
+
+ /* Clear TCO timeout status */
+ outw(0x0008, base + 0x04); /* TCO1_STS, raise bit 3: TIMEOUT */
+ outw(0x0002, base + 0x06); /* TCO2_STS, raise bit 2: SECOND_TO_STS */
+
+ printk(BIOS_DEBUG, "Board-specific ICH5 watchdog disabled\n");
+}
diff --git a/src/northbridge/intel/Kconfig b/src/northbridge/intel/Kconfig
index 1809d11..e5c8ed5 100644
--- a/src/northbridge/intel/Kconfig
+++ b/src/northbridge/intel/Kconfig
@@ -8,5 +8,6 @@ source src/northbridge/intel/i440lx/Kconfig
source src/northbridge/intel/i82810/Kconfig
source src/northbridge/intel/i82830/Kconfig
source src/northbridge/intel/i855/Kconfig
+source src/northbridge/intel/i865/Kconfig
source src/northbridge/intel/i945/Kconfig
source src/northbridge/intel/sch/Kconfig
diff --git a/src/northbridge/intel/Makefile.inc b/src/northbridge/intel/Makefile.inc
index 0d116d0..9d333b6 100644
--- a/src/northbridge/intel/Makefile.inc
+++ b/src/northbridge/intel/Makefile.inc
@@ -8,6 +8,7 @@ subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I440LX) += i440lx
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I82810) += i82810
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I82830) += i82830
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I855) += i855
+subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I865) += i865
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I945GC) += i945
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_I945GM) += i945
subdirs-$(CONFIG_NORTHBRIDGE_INTEL_SCH) += sch
diff --git a/src/northbridge/intel/i865/Kconfig b/src/northbridge/intel/i865/Kconfig
new file mode 100644
index 0000000..944f701
--- /dev/null
+++ b/src/northbridge/intel/i865/Kconfig
@@ -0,0 +1,25 @@
+config NORTHBRIDGE_INTEL_I865
+ bool
+ select HAVE_DEBUG_RAM_SETUP
+choice
+prompt "Onboard graphics"
+ default I865_VIDEO_MB_8MB
+ depends on NORTHBRIDGE_INTEL_I865
+
+config I865_VIDEO_MB_OFF
+ bool "Disabled, 0KB"
+config I865_VIDEO_MB_1MB
+ bool "Enabled, 1MB"
+config I865_VIDEO_MB_8MB
+ bool "Enabled, 8MB"
+config I865_VIDEO_MB_16MB
+ bool "Enabled, 16MB"
+endchoice
+
+config VIDEO_MB
+ int
+ default 0 if I865_VIDEO_MB_OFF
+ default 1 if I865_VIDEO_MB_1MB
+ default 8 if I865_VIDEO_MB_8MB
+ default 16 if I865_VIDEO_MB_16MB
+ depends on NORTHBRIDGE_INTEL_I865
diff --git a/src/northbridge/intel/i865/Makefile.inc b/src/northbridge/intel/i865/Makefile.inc
new file mode 100644
index 0000000..8cec43f
--- /dev/null
+++ b/src/northbridge/intel/i865/Makefile.inc
@@ -0,0 +1,2 @@
+ramstage-y += northbridge.c
+#romstage-y += early_init.c
diff --git a/src/northbridge/intel/i865/TODO b/src/northbridge/intel/i865/TODO
new file mode 100644
index 0000000..2f28af0
--- /dev/null
+++ b/src/northbridge/intel/i865/TODO
@@ -0,0 +1,16 @@
+TODO (probably incomplete)
+
+raminit.c:
+ * re-use the mchbar macro from i945 and read/write from/to it like its raminit code does
+ * GPL headers everywhere
+ * includes (is assert.h really needed?)
+ * set TOUD (from northbridge.c?)
+ * set SMFREQ and FSBFREQ (in GMCHCFG) (from northbridge.c?)?
+ * AGP (device 1) code
+ * VGA/IGD (device 2) code
+ * CSA (device 3) code?
+ * clean up/trim northbridge_set_registers()
+ * dual-channel code (and don't forget romstage.c)
+
+DONE
+* raise bits 0 (IOAE, I/O access enable) and 1 (MAE, memory access enable) in PCICMD6 (from northbridge.c?)
diff --git a/src/northbridge/intel/i865/chip.h b/src/northbridge/intel/i865/chip.h
new file mode 100644
index 0000000..6e7b21e
--- /dev/null
+++ b/src/northbridge/intel/i865/chip.h
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2006 Jon Dufresne <jon.dufresne at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+struct northbridge_intel_i865_config
+{
+};
+
+extern struct chip_operations northbridge_intel_i865_ops;
diff --git a/src/northbridge/intel/i865/debug.c b/src/northbridge/intel/i865/debug.c
new file mode 100644
index 0000000..a7935ce
--- /dev/null
+++ b/src/northbridge/intel/i865/debug.c
@@ -0,0 +1,139 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2003 Ronald G. Minnich
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+#include <spd.h>
+static void print_debug_pci_dev(unsigned dev) {
+ print_debug("PCI: ");
+ print_debug_hex8((dev >> 20) & 0xff);
+ print_debug_char(':');
+ print_debug_hex8((dev >> 15) & 0x1f);
+ print_debug_char('.');
+ print_debug_hex8((dev >> 12) & 0x07);
+}
+static inline 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("\n");
+ }
+}
+static void dump_pci_device(unsigned dev) {
+ int i;
+ print_debug_pci_dev(dev);
+ print_debug("\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("\n");
+ }
+ }
+}
+static inline void dump_pci_devices(void) {
+ device_t dev;
+ for(dev = PCI_DEV(0, 0, 0);
+ dev <= PCI_DEV(0, 0x1f, 0x7);
+ dev += PCI_DEV(0,0,1)) {
+ uint32_t id;
+ id = pci_read_config32(dev, PCI_VENDOR_ID);
+ if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
+ (((id >> 16) & 0xffff) == 0xffff) ||
+ (((id >> 16) & 0xffff) == 0x0000)) {
+ continue;
+ }
+ dump_pci_device(dev);
+ }
+}
+static inline void dump_spd_registers(void) {
+ int i;
+ print_debug("\n");
+ for(i = 0; i < 2; i++) {
+ unsigned device;
+ device = DIMM0 + 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("\n");
+ print_debug_hex8(j);
+ print_debug(": ");
+ }
+ status = smbus_read_byte(device, j);
+ if (status < 0) {
+ print_debug("bad device\n");
+ break;
+ }
+ byte = status & 0xff;
+ print_debug_hex8(byte);
+ print_debug_char(' ');
+ }
+ print_debug("\n");
+ }
+ }
+}
+static inline void dump_smbus_registers(void) {
+ int i;
+ print_debug("\n");
+ for(i = 1; i < 0x80; i++) {
+ unsigned device;
+ device = i;
+ int j;
+ print_debug("smbus: ");
+ print_debug_hex8(device);
+ for(j = 0; j < 256; j++) {
+ int status;
+ unsigned char byte;
+ if ((j & 0xf) == 0) {
+ print_debug("\n");
+ print_debug_hex8(j);
+ print_debug(": ");
+ }
+ status = smbus_read_byte(device, j);
+ if (status < 0) {
+ print_debug("bad device\n");
+ break;
+ }
+ byte = status & 0xff;
+ print_debug_hex8(byte);
+ print_debug_char(' ');
+ }
+ print_debug("\n");
+ }
+}
diff --git a/src/northbridge/intel/i865/i865.h b/src/northbridge/intel/i865/i865.h
new file mode 100644
index 0000000..51cf0bc
--- /dev/null
+++ b/src/northbridge/intel/i865/i865.h
@@ -0,0 +1,89 @@
+/* TODO:
+ * AGP #defines
+ * GPL header
+ */
+
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2010 Travelping GmbH <info at travelping.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+/* size, default value */
+/* DRAM Controller (device 0) */
+#define APBASE 0x10 /* 32 bit, 0x8 */
+// #define AGPM 0x51 /* 8 bit, 0x0 */
+// #define ESMRAMC 0x9e /* 8 bit, 0x38 */
+// #define ACAPID 0xa0 /* 32bit, 0x300002 (RO) */
+// #define AGPSTAT 0xa4 /* 32bit, AGP 2.0: 0x1f004217 (RO) or AGP 3.0: 0x1f004a13 (RO) */
+// #define AGPCMD 0xa8 /* 32bit, AGP 2.0: 0x0 or AGP 3.0: 0xa00 */
+// #define AGPCTRL 0xb0 /* 32bit, 0x0 */
+#define AMTT 0xbc /* 8 bit, 0x10 */
+#define APSIZE 0xb4 /* 8 bit, 0x0 */
+// #define ATTBASE 0xb8 /* 32 bit, 0x0 */
+#define TOUD 0xc4 /* 16 bit, 0x400 */
+#define GMCHCFG 0xc6 /* 16 bit, 0x0 */
+#define ERRSTS 0xc8 /* 16 bit, 0x0 */
+// #define ERRCMD 0xca /* 16 bit, 0x0 */
+// #define FDHC 0x97 /* 8 bit, 0x0 */
+// #define FPLLCONT 0x60 /* 8 bit, 0x0 */
+#define GC 0x52 /* 8 bit (looks wrong), 0x1000 */
+#define LPTT 0xbd /* 8 bit, 0x10 */
+#define PCISTS 0x10 /* 16 bit, 0x90 */
+// #define SMRAM 0x9D /* 8 bit, 0x2 */
+#define SVID 0x2c /* 16 bit, 0x0 */
+#define SID 0x2e /* 16 bit, 0x0 */
+// #define CSABCONT 0x53 /* 8 bit, 0x0 */
+#define VID 0x0 /* 16 bit, 0x8086 */
+#define DID 0x2 /* 16 bit, 0x2570 */
+/* PCI-to-AGP bridge (device 1) */
+// #define PCICMD1 0x04 /* 16 bit, 0x0 */
+// #define SMLT1 0x0d /* 8 bit, 0x0 */
+// #define SBUSN1 0x19 /* 8 bit, 0x0 */
+// #define SUBUSN1 0x1a /* 8 bit, 0x0 */
+// #define PMBASE1 0x24 /* 16 bit, 0xfff0 */
+// #define PMLIMIT1 0x26 /* 16 bit, 0x0 */
+// #define BCTRL1 0x3e /* 8 bit, 0x0 */
+// #define ERRCMD1 0x40 /* 8 bit, 0x0 */
+
+/* Integrated Graphics Device (device 2) */
+// #define PCICMD2 0x04 /* 16 bit, 0x0 */
+// #define GMADR 0x10 /* 32 bit, 0x8 */
+// #define MMADR 0x14 /* 32 bit, 0x0 */
+// #define IOBAR 0x18 /* 32 bit, 0x1 */
+// #define SVID2 0x2c /* 16 bit, 0x0 */
+// #define SID2 0x2e /* 16 bit, 0x0 */
+// #define INTRLINE 0x3c /* 8 bit, 0x0 */
+// #define PMCS 0xd4 /* 16 bit, 0x0 */
+// #define SWSMI 0xe0 /* 16 bit, 0x0 */
+
+/* PCI-to-CSA bridge (device 3) */
+// #define PCICMD3 0x04 /* 16 bit, 0x0 */
+// #define IOBASE3 0x1c /* 8 bit, 0xf0 */
+// #define IOLIMIT3 0x1d /* 8 bit, 0x0 */
+// #define MBASE3 0x20 /* 16 bit, 0xfff0 */
+// #define MLIMIT3 0x22 /* 16 bit, 0x0 */
+// #define PMBASE3 0x24 /* 16 bit, 0xfff0 */
+// #define PMLIMIT3 0x26 /* 16 bit, 0x0 */
+// #define BCTRL3 0x3e /* 8 bit, 0x0 */
+// #define CSACNTRL 0x50 /* 32 bit, 0xe042802 */
+
+/* Overflow device (device 6) */
+#define PCICMD6 0x04 /* 16 bit (looks wrong), 0x0 */
+#define BAR6 0x10 /* 32 bit, 0x0 */
+// #define SVID6 0x2c /* 16 bit, 0x0 */
+// #define SID6 0x2e /* 16 bit, 0x0 */
diff --git a/src/northbridge/intel/i865/northbridge.c b/src/northbridge/intel/i865/northbridge.c
new file mode 100644
index 0000000..c249be3
--- /dev/null
+++ b/src/northbridge/intel/i865/northbridge.c
@@ -0,0 +1,171 @@
+/* TODO:
+ * CSA (device 3) code
+ * set all subsytem IDs (SID*, SVID*)
+ */
+
+ /*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2003 Ronald G. Minnich
+ * Copyright (C) 2003-2004 Eric W. Biederman
+ * Copyright (C) 2006 Jon Dufresne <jon.dufresne at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include <console/console.h>
+#include <arch/io.h>
+#include <stdint.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <stdlib.h>
+#include <string.h>
+#include <bitops.h>
+#include <cpu/x86/cache.h>
+#include <cpu/cpu.h>
+#include "chip.h"
+#include "i865.h"
+#include "raminit.h"
+
+static void northbridge_init(device_t dev)
+{
+ printk(BIOS_SPEW, "Northbridge init\n");
+}
+
+static struct device_operations northbridge_operations = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = northbridge_init,
+ .enable = 0,
+ .ops_pci = 0,
+};
+
+static const struct pci_driver northbridge_driver __pci_driver = {
+ .ops = &northbridge_operations,
+ .vendor = PCI_VENDOR_ID_INTEL,
+ .device = 0x2570,
+};
+
+#if CONFIG_WRITE_HIGH_TABLES==1
+#define HIGH_TABLES_SIZE 64 // maximum size of high tables in KB
+extern uint64_t high_tables_base, high_tables_size;
+#endif
+static void pci_domain_set_resources(device_t dev)
+{
+ device_t mc_dev;
+ uint32_t pci_tolm;
+
+ printk(BIOS_DEBUG, "Entered with dev vid = %x\n", dev->vendor);
+ printk(BIOS_DEBUG, "Entered with dev did = %x\n", dev->device);
+
+ pci_tolm = find_pci_tolm(dev->link_list);
+ mc_dev = dev->link_list->children->sibling;
+ printk(BIOS_DEBUG, "MC dev vendor = %x\n", mc_dev->vendor);
+ printk(BIOS_DEBUG, "MC dev device = %x\n", mc_dev->device);
+
+ if (mc_dev) {
+ /* Figure out which areas are/should be occupied by RAM.
+ * This is all computed in kilobytes and converted to/from
+ * the memory controller right at the edges.
+ * Having different variables in different units is
+ * too confusing to get right. Kilobytes are good up to
+ * 4 Terabytes of RAM...
+ */
+ unsigned long tomk, tolmk;
+ int idx;
+
+ /* Get the value of the highest DRB. This tells the end of
+ * the physical memory. The units are ticks of 64 MB
+ * i.e. 1 means 64 MB.
+ */
+ //tomk = (unsigned long)pci_read_config8(dev_find_slot(0, PCI_DEVFN(0, 0)), DRB + 7);
+// tomk = BAR6_8(DRB + 7);
+ tomk = MCHBAR8(DRB + 7);
+ tomk = tomk * 64 * 1024;
+ /* add vga_mem detection */
+ tomk = tomk - 16 * 1024; // 16 MB, graphics mode select (GMS)
+ /* Compute the top of Low memory */
+ tolmk = pci_tolm >> 10;
+ if (tolmk >= tomk) {
+ /* The PCI hole does not overlap memory
+ */
+ tolmk = tomk;
+ }
+ /* Write the ram configuration registers,
+ * preserving the reserved bits.
+ */
+
+ /* Report the memory regions */
+ printk(BIOS_DEBUG, "tomk = %ld\n", tomk);
+ printk(BIOS_DEBUG, "tolmk = %ld\n", tolmk);
+
+ idx = 10;
+ /* avoid pam region */
+ ram_resource(dev, idx++, 0, 640);
+ /* ram_resource(dev, idx++, 1024, tolmk - 1024); */
+ ram_resource(dev, idx++, 768, tolmk - 768);
+
+#if CONFIG_WRITE_HIGH_TABLES==1
+ /* Leave some space for ACPI, PIRQ and MP tables */
+ high_tables_base = (tomk - HIGH_TABLES_SIZE) * 1024;
+ high_tables_size = HIGH_TABLES_SIZE * 1024;
+#endif
+ }
+ assign_resources(dev->link_list);
+}
+
+static struct device_operations pci_domain_ops = {
+ .read_resources = pci_domain_read_resources,
+ .set_resources = pci_domain_set_resources,
+ .enable_resources = NULL,
+ .init = NULL,
+ .scan_bus = pci_domain_scan_bus,
+};
+
+static void cpu_bus_init(device_t dev)
+{
+ initialize_cpus(dev->link_list);
+}
+
+static void cpu_bus_noop(device_t dev)
+{
+}
+
+static struct device_operations cpu_bus_ops = {
+ .read_resources = cpu_bus_noop,
+ .set_resources = cpu_bus_noop,
+ .enable_resources = cpu_bus_noop,
+ .init = cpu_bus_init,
+ .scan_bus = 0,
+};
+
+static void enable_dev(struct device *dev)
+{
+ /* Set the operations if it is a special bus type */
+ if (dev->path.type == DEVICE_PATH_PCI_DOMAIN) {
+ dev->ops = &pci_domain_ops;
+ pci_set_method(dev);
+ }
+ else if (dev->path.type == DEVICE_PATH_APIC_CLUSTER) {
+ dev->ops = &cpu_bus_ops;
+ }
+}
+
+struct chip_operations northbridge_intel_i865_ops = {
+ CHIP_NAME("Intel 865 Northbridge")
+ .enable_dev = enable_dev,
+};
diff --git a/src/northbridge/intel/i865/raminit.c b/src/northbridge/intel/i865/raminit.c
new file mode 100644
index 0000000..91e3144
--- /dev/null
+++ b/src/northbridge/intel/i865/raminit.c
@@ -0,0 +1,1031 @@
+#include <spd.h>
+#include <stdlib.h>
+#include <sdram_mode.h>
+
+#include "i865.h"
+#include "raminit.h"
+
+struct dimm_size {
+ unsigned int side1;
+ unsigned int side2;
+};
+
+static const uint32_t refresh_frequency[] = {
+ /* Relative frequency (array value) of each E7501 Refresh Mode Select
+ * (RMS) value (array index)
+ * 0 == least frequent refresh (longest interval between refreshes)
+ * [0] disabled -> 0
+ * [1] 15.6 usec -> 2
+ * [2] 7.8 usec -> 3
+ * [3] 64 usec -> 1
+ * [4] reserved -> 0
+ * [5] reserved -> 0
+ * [6] reserved -> 0
+ * [7] 64 clocks -> 4
+ */
+ 0, 2, 3, 1, 0, 0, 0, 4
+};
+
+static const uint32_t refresh_rate_map[] = {
+ /* Map the JEDEC spd refresh rates (array index) to i855 Refresh Mode
+ * Select values (array value)
+ * These are all the rates defined by JESD21-C Appendix D, Rev. 1.0
+ * The i855 supports only 15.6 us (1), 7.8 us (2) and
+ * 64 clock (481 ns) (7) refresh.
+ * [0] == 15.625 us -> 15.6 us
+ * [1] == 3.9 us -> 481 ns
+ * [2] == 7.8 us -> 7.8 us
+ * [3] == 31.3 us -> 15.6 us
+ * [4] == 62.5 us -> 15.6 us
+ * [5] == 125 us -> 15.6 us
+ */
+ 1, 7, 2, 1, 1, 1
+};
+
+#define MAX_SPD_REFRESH_RATE ((sizeof(refresh_rate_map) / sizeof(uint32_t)) - 1)
+
+static inline int spd_read_byte(unsigned device, unsigned address)
+//static int spd_read_byte(unsigned device, unsigned address)
+{
+ return smbus_read_byte(device, address);
+}
+
+static void set_initialization_complete(void)
+{
+ printk(BIOS_DEBUG, "Setting initialization complete (DRC bit 29)\n");
+ MCHBAR32(DRC) |= RAM_INITIALIZATION_COMPLETE;
+}
+
+//static void do_ram_command(u32 command)
+static void do_ram_command(uint8_t command, uint16_t jedec_mode_bits)
+{
+ int i;
+ u32 reg32;
+// uint8_t dimm_start_32M_multiple = 0;
+ uint8_t dimm_start_64M_multiple = 0;
+ uint16_t i855_mode_bits = jedec_mode_bits;
+
+ /* Configure the RAM command. */
+// reg32 = pci_read_config32(NORTHBRIDGE_MMC, DRC);
+ reg32 = MCHBAR32(DRC);
+ reg32 &= ~(7 << 4);
+ reg32 |= (command << 4);
+ printk(BIOS_DEBUG, " Sending RAM command 0x%08x\n", reg32);
+// pci_write_config32(NORTHBRIDGE_MMC, DRC, reg32);
+ MCHBAR32(DRC) = reg32;
+
+ // RAM_COMMAND_NORMAL is an exception.
+ // It affects only the memory controller and does not need to be "sent" to the DIMMs.
+
+ if (command != RAM_COMMAND_NORMAL) {
+
+ // Send the command to all DIMMs by accessing a memory location within each
+ // NOTE: for mode select commands, some of the location address bits
+ // are part of the command
+
+ // Map JEDEC mode bits to i855
+ if (command == RAM_COMMAND_MRS || command == RAM_COMMAND_EMRS) {
+ /* Host address lines [13:3] map to DIMM address lines [11, 9:0] */
+ // i855_mode_bits = ((jedec_mode_bits & 0x800) << (13 - 11)) | ((jedec_mode_bits & 0x3ff) << (12 - 9));
+ /* Host address lines [13:3] map to DIMM address lines [5:1] */
+ // i855_mode_bits = ((jedec_mode_bits & 0x800) << (13 - 11)) | ((jedec_mode_bits & 0x3ff) << (6 - 1));
+ i855_mode_bits = ((jedec_mode_bits & 0x800) << (13 - 11)) | ((jedec_mode_bits & 0x3f) << (6 - 1));
+ }
+
+ for (i = 0; i < (DIMM_SOCKETS * 2); ++i) {
+// uint8_t dimm_end_32M_multiple = pci_read_config8(NORTHBRIDGE_MMC, DRB + i);
+ /* i865 uses a granularity of 64 megabyte */
+ uint8_t dimm_end_64M_multiple = MCHBAR8(DRB + i);
+// if (dimm_end_32M_multiple > dimm_start_32M_multiple) {
+ if (dimm_end_64M_multiple > dimm_start_64M_multiple) {
+
+// uint32_t dimm_start_address = dimm_start_32M_multiple << 25;
+ uint32_t dimm_start_address = dimm_start_64M_multiple << 25;
+ printk(BIOS_DEBUG, " Sending RAM command to 0x%08x\n", dimm_start_address + i855_mode_bits);
+ //read32(dimm_start_address + i855_mode_bits);
+ printk(BIOS_DEBUG, " /* skipping read32() */\n");
+ printk(BIOS_DEBUG, " Sent. dimm_start_address = 0x%x and i855_mode_bits = 0x%x\n", dimm_start_address, i855_mode_bits);
+
+ // Set the start of the next DIMM
+// dimm_start_32M_multiple = dimm_end_32M_multiple;
+ dimm_start_64M_multiple = dimm_end_64M_multiple;
+ }
+ }
+ }
+}
+
+static void sdram_enable(void)
+{
+ int i;
+
+ print_debug("Ram enable 1\n");
+ delay();
+ delay();
+
+ /* NOP command */
+ printk(BIOS_DEBUG, " NOP\n");
+ do_ram_command(RAM_COMMAND_NOP, 0);
+ delay();
+ delay();
+ delay();
+
+ /* Pre-charge all banks (at least 200 us after NOP) */
+ printk(BIOS_DEBUG, " Pre-charging all banks\n");
+ do_ram_command(RAM_COMMAND_PRECHARGE, 0);
+ delay();
+ delay();
+ delay();
+
+ printk(BIOS_DEBUG, "Ram enable 4\n");
+ do_ram_command(RAM_COMMAND_EMRS, SDRAM_EXTMODE_DLL_ENABLE);
+ delay();
+ delay();
+ delay();
+
+ print_debug("Ram enable 5\n");
+ do_ram_command(RAM_COMMAND_MRS, VG85X_MODE | SDRAM_MODE_DLL_RESET);
+
+ print_debug("Ram enable 6\n");
+ do_ram_command(RAM_COMMAND_PRECHARGE, 0);
+ delay();
+ delay();
+ delay();
+
+ /* 8 CBR refreshes (Auto Refresh) */
+ printk(BIOS_DEBUG, " 8 CBR refreshes\n");
+ for(i = 0; i < 8; i++) {
+ do_ram_command(RAM_COMMAND_CBR, 0);
+ delay();
+ delay();
+ delay();
+ }
+
+ printk(BIOS_DEBUG, "Ram enable 8\n");
+ do_ram_command(RAM_COMMAND_MRS, VG85X_MODE | SDRAM_MODE_NORMAL);
+
+ /* Set GME-M Mode Select bits back to NORMAL operation mode */
+ printk(BIOS_DEBUG, " Normal operation mode\n");
+ do_ram_command(RAM_COMMAND_NORMAL, 0);
+/* delay();
+ delay();
+ delay();
+
+ print_debug("Ram enable 9\n");
+ set_initialize_complete();
+
+ delay();
+ delay();
+ delay();
+ delay();
+ delay();
+
+ print_debug("After configuration:\n");
+*/
+ /* dump_pci_devices(); */
+
+ /*
+ print_debug("\n\n***** RAM TEST *****\n");
+ ram_check(0, 0xa0000);
+ ram_check(0x100000, 0x40000000);
+ */
+}
+
+//static void ram_read32(u8 dimm_start, u32 offset)
+//{
+ /* not implemented */
+//}
+
+//static void initialize_dimm_rows(void)
+//{
+ /* copied from i82830/raminit.c */
+ /* not implemented */
+//}
+
+static void die_on_spd_error(int spd_return_value)
+{
+ if (spd_return_value < 0)
+ printk(BIOS_DEBUG, "Error reading SPD info: got %d\n", spd_return_value);
+/*
+ if (spd_return_value < 0)
+ die("Error reading SPD info\n");
+*/
+}
+
+static struct dimm_size sdram_spd_get_page_size(u8 dimm_socket_address)
+{
+ uint16_t module_data_width;
+ int value;
+ struct dimm_size pgsz;
+
+ pgsz.side1 = 0;
+ pgsz.side2 = 0;
+
+ // Side 1
+ value = spd_read_byte(dimm_socket_address, SPD_NUM_COLUMNS);
+ die_on_spd_error(value);
+
+ pgsz.side1 = value & 0xf; // # columns in bank 1
+
+ /* Get the module data width and convert it to a power of two */
+ value = spd_read_byte(dimm_socket_address, SPD_MODULE_DATA_WIDTH_MSB);
+ die_on_spd_error(value);
+
+ module_data_width = (value & 0xff) << 8;
+
+ value = spd_read_byte(dimm_socket_address, SPD_MODULE_DATA_WIDTH_LSB);
+ die_on_spd_error(value);
+
+ module_data_width |= (value & 0xff);
+
+ pgsz.side1 += log2(module_data_width);
+
+ /* side two */
+ value = spd_read_byte(dimm_socket_address, SPD_NUM_DIMM_BANKS);
+ die_on_spd_error(value);
+
+ if (value > 2)
+ printk(BIOS_DEBUG, "Bad SPD value\n");
+
+ if (value == 2) {
+ pgsz.side2 = pgsz.side1; // Assume symmetric banks until we know differently
+ value = spd_read_byte(dimm_socket_address, SPD_NUM_COLUMNS);
+ die_on_spd_error(value);
+
+ if ((value & 0xf0) != 0) {
+ // Asymmetric banks
+ pgsz.side2 -= value & 0xf; /* Subtract out columns on side 1 */
+ pgsz.side2 += (value >> 4) & 0xf; /* Add in columns on side 2 */
+ }
+ }
+
+ return pgsz;
+}
+
+/**
+ * Read the width in bits of each DIMM side's DRAMs via SPD (i.e. 4, 8, 16).
+ *
+ * @param dimm_socket_address SMBus address of DIMM socket to interrogate.
+ * @return Width in bits of each DIMM side's DRAMs.
+ */
+static struct dimm_size sdram_spd_get_width(u8 dimm_socket_address)
+{
+ int value;
+ struct dimm_size width;
+
+ width.side1 = 0;
+ width.side2 = 0;
+
+ value = spd_read_byte(dimm_socket_address, SPD_PRIMARY_SDRAM_WIDTH);
+ die_on_spd_error(value);
+
+ width.side1 = value & 0x7f; // Mask off bank 2 flag
+
+ if (value & 0x80) {
+ width.side2 = width.side1 << 1; // Bank 2 exists and is double-width
+ } else {
+ // If bank 2 exists, it's the same width as bank 1
+ value = spd_read_byte(dimm_socket_address, SPD_NUM_DIMM_BANKS);
+ die_on_spd_error(value);
+
+ switch (value) {
+ case 2:
+ width.side2 = width.side1;
+ break;
+
+ default:
+ break;
+ }
+ }
+
+ return width;
+}
+
+/**
+ * Calculate the log base 2 size in bits of both DIMM sides.
+ *
+ * log2(# bits) = (# columns) + log2(data width) +
+ * (# rows) + log2(banks per SDRAM)
+ *
+ * Note that it might be easier to use SPD 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
+ * asymmetric DIMM.
+ *
+ * @param dimm SMBus address of DIMM socket to interrogate.
+ * @return log2(number of bits) for each side of the DIMM.
+ */
+static struct dimm_size spd_get_dimm_size(unsigned dimm)
+{
+ int value;
+
+ // Start with log2(page size)
+ struct dimm_size sz = sdram_spd_get_page_size(dimm);
+
+ if (sz.side1 > 0) {
+ value = spd_read_byte(dimm, SPD_NUM_ROWS);
+ die_on_spd_error(value);
+
+ sz.side1 += value & 0xf;
+
+ if (sz.side2 > 0) {
+ // Double-sided DIMM
+ if (value & 0xF0)
+ sz.side2 += value >> 4; // Asymmetric
+ else
+ sz.side2 += value; // Symmetric
+ }
+
+ value = spd_read_byte(dimm, SPD_NUM_BANKS_PER_SDRAM);
+ die_on_spd_error(value);
+
+ value = log2(value);
+ sz.side1 += value;
+ if (sz.side2 > 0)
+ sz.side2 += value;
+ }
+
+ return sz;
+}
+
+// static void set_dram_row_boundaries(void) { /* TODO */ }
+// static void set_dram_row_attributes(void) { /* TODO */ }
+// static void set_dram_timing(void) { /* TODO */ }
+// static void sdram_set_registers(void) { /* TODO */ }
+
+static uint8_t spd_get_supported_dimms(void)
+{
+ int i;
+ uint8_t dimm_mask = 0;
+
+// for (i = 0; i < DIMM_SOCKETS; i++) {
+ for (i = 0; i < (2 * DIMM_SOCKETS); i++) {
+ u8 dimm = DIMM0 + i;
+
+ struct dimm_size page_size;
+ struct dimm_size sdram_width;
+
+ int spd_value;
+
+ if (dimm == 0)
+ continue;
+
+ if (spd_read_byte(dimm, SPD_MEMORY_TYPE) != SPD_MEMORY_TYPE_SDRAM_DDR)
+ // print a little warning, maybe?
+ continue;
+
+ if ((spd_value = spd_read_byte(dimm, SPD_MODULE_VOLTAGE)) != SPD_VOLTAGE_SSTL2) {
+ printk(BIOS_DEBUG, "Skipping DIMM with unsupported voltage: %02x\n", spd_value);
+ continue;
+ }
+
+ page_size = sdram_spd_get_page_size(dimm);
+ sdram_width = sdram_spd_get_width(dimm);
+
+ // Validate DIMM page size
+ // The i855 only supports page sizes of 4, 8, 16 KB per channel
+ // NOTE: 4 KB = 32 Kb = 2^15
+ // 16 KB = 128 Kb = 2^17
+
+ if ((page_size.side1 < 15) || (page_size.side1 > 17)) {
+ printk(BIOS_DEBUG, "Skipping DIMM with unsupported page size: %d\n", page_size.side1);
+ continue;
+ }
+
+ // If DIMM is double-sided, verify side2 page size
+ if (page_size.side2 != 0) {
+ if ((page_size.side2 < 15) || (page_size.side2 > 17)) {
+ printk(BIOS_DEBUG, "Skipping DIMM with unsupported page size: %d\n", page_size.side2);
+ continue;
+ }
+ }
+ // Validate SDRAM width
+ // The i855 only supports x8 and x16 devices
+ if ((sdram_width.side1 != 8) && (sdram_width.side1 != 16)) {
+ printk(BIOS_DEBUG, "Skipping DIMM with unsupported width: %d\n", sdram_width.side2);
+ continue;
+ }
+
+ // If DIMM is double-sided, verify side2 width
+ if (sdram_width.side2 != 0) {
+ if ((sdram_width.side2 != 8)
+ && (sdram_width.side2 != 16)) {
+ printk(BIOS_DEBUG, "Skipping DIMM with unsupported width: %d\n", sdram_width.side2);
+ continue;
+ }
+ }
+ // Made it through all the checks, this DIMM is usable
+ dimm_mask |= (1 << i);
+ }
+
+ return dimm_mask;
+}
+
+static void spd_set_row_attributes(uint8_t dimm_mask)
+{
+ int i;
+ uint16_t row_attributes = 0;
+
+ for (i = 0; i < DIMM_SOCKETS; i++) {
+ u8 dimm = DIMM0 + i;
+ struct dimm_size page_size;
+ struct dimm_size sdram_width;
+
+ if (!(dimm_mask & (1 << i))) {
+// row_attributes |= 0x77 << (i << 3);
+ row_attributes |= 0x0 << (i << 3); // default value of DRA on i865 is 0x0
+ continue; // This DIMM not usable
+ }
+
+ // Get the relevant parameters via SPD
+ page_size = sdram_spd_get_page_size(dimm);
+ sdram_width = sdram_spd_get_width(dimm);
+
+ // Update the DRAM Row Attributes.
+ // Page size is encoded as log2(page size in bits) - log2(2 KB) or 4 KB == 1, 8 KB == 3, 16KB == 3
+// i865: Page size is encoded as log2(page size in bits) - log2(2 KB) or 4 KB == 0, 8 KB == 1, 16KB == 2, 32KB == 3
+ // NOTE: 2 KB = 16 Kb = 2^14
+// row_attributes |= (page_size.side1 - 14) << (i << 3); // Side 1 of each DIMM is an EVEN row
+ // i865: NOTE: 4 KB = 32 Kb = 2^15
+ row_attributes |= (page_size.side1 - 15) << (i << 3); // Side 1 of each DIMM is an EVEN row
+
+ if (sdram_width.side2 > 0)
+// row_attributes |= (page_size.side2 - 14) << ((i << 3) + 4); // Side 2 is ODD
+ row_attributes |= (page_size.side2 - 15) << ((i << 3) + 4); // Side 2 is ODD
+// else
+// row_attributes |= 7 << ((i << 3) + 4); // "not populated", i865 doesn't have that bit
+
+ /* on the asrock pi465gv (rev g/a 1.11),
+ physical ram slots "DDR2" and "DDR1"
+ are logically slots 2 and 1 (or 1 and 0) */
+// printk(BIOS_DEBUG, "DRA%d: 0x%x\n", i, row_attributes);
+// printk(BIOS_DEBUG, "DRA: row %d,%d: 0x%x\n", i, i + 1, row_attributes);
+ printk(BIOS_DEBUG, "DRA: row %d,%d: 0x%x\n", i * 2, i * 2 + 1, row_attributes);
+ MCHBAR8(DRA + i) = row_attributes;
+
+ /* go to the next DIMM */
+ }
+
+// PRINTK_DEBUG("DRA: %04x\n", row_attributes);
+
+ /* Write the new row attributes register */
+// pci_write_config16(NORTHBRIDGE_MMC, DRA, row_attributes);
+}
+
+static void spd_set_dram_controller_mode(uint8_t dimm_mask)
+{
+ int i;
+
+ // Initial settings
+// u32 controller_mode = pci_read_config32(NORTHBRIDGE_MMC, DRC);
+ u32 controller_mode = MCHBAR32(DRC);
+// u32 system_refresh_mode = (controller_mode >> 7) & 7;
+ u32 system_refresh_mode = (controller_mode >> 8) & 7; // i865: RMS is at bits 10:8
+
+// controller_mode |= (1 << 20); // ECC
+// controller_mode |= (1 << 15); // RAS lockout
+// controller_mode |= (1 << 12); // Address Tri-state enable (ADRTRIEN), FIXME: how is this detected?????
+// controller_mode |= (2 << 10); // FIXME: Undocumented, really needed?????
+
+// for (i = 0; i < DIMM_SOCKETS; i++) {
+ for (i = 0; i < (2 * DIMM_SOCKETS); i++) {
+ u8 dimm = DIMM0 + i;
+ uint32_t dimm_refresh_mode;
+ int value;
+// u8 tRCD, tRP;
+
+ if (!(dimm_mask & (1 << i))) {
+ continue; // This DIMM not usable
+ }
+
+ // Disable ECC mode if any one of the DIMMs does not support ECC
+// no ECC on i865, disabling
+// value = spd_read_byte(dimm, SPD_DIMM_CONFIG_TYPE);
+// die_on_spd_error(value);
+// if (value != ERROR_SCHEME_ECC)
+// controller_mode &= ~(3 << 20);
+
+ value = spd_read_byte(dimm, SPD_REFRESH);
+ die_on_spd_error(value);
+ value &= 0x7f; // Mask off self-refresh bit
+ if (value > MAX_SPD_REFRESH_RATE) {
+ print_err("unsupported refresh rate\n");
+ continue;
+ }
+ // Get the appropriate i855 refresh mode for this DIMM
+ dimm_refresh_mode = refresh_rate_map[value];
+ if (dimm_refresh_mode > 7) {
+ print_err("unsupported refresh rate\n");
+ continue;
+ }
+ // If this DIMM requires more frequent refresh than others,
+ // update the system setting
+ if (refresh_frequency[dimm_refresh_mode] >
+ refresh_frequency[system_refresh_mode])
+ system_refresh_mode = dimm_refresh_mode;
+
+ /* FIXME: is this correct? */
+// tRCD = spd_read_byte(dimm, SPD_tRCD);
+// tRP = spd_read_byte(dimm, SPD_tRP);
+// no RAS lockout on i865
+// if (tRCD != tRP) {
+// PRINTK_DEBUG(" Disabling RAS lockouk due to tRCD (%d) != tRP (%d)\n", tRCD, tRP);
+// printk(BIOS_DEBUG, " Disabling RAS lockouk due to tRCD (%d) != tRP (%d)\n", tRCD, tRP);
+// controller_mode &= ~(1 << 15);
+// }
+
+ /* go to the next DIMM */
+ }
+
+// controller_mode &= ~(7 << 7);
+// controller_mode |= (system_refresh_mode << 7);
+ controller_mode &= ~(7 << 8);
+ controller_mode |= (system_refresh_mode << 8);
+// PRINTK_DEBUG("DRC: %08x\n", controller_mode);
+ printk(BIOS_DEBUG, "DRC: %08x\n", controller_mode);
+
+// pci_write_config32(NORTHBRIDGE_MMC, DRC, controller_mode);
+ MCHBAR32(DRC) = controller_mode;
+}
+
+static void spd_set_dram_timing(uint8_t dimm_mask)
+{
+ int i;
+ u32 dram_timing;
+
+ // CAS# latency bitmasks in SPD_ACCEPTABLE_CAS_LATENCIES format
+ // NOTE: i82822 supports only 2.0 and 2.5
+// uint32_t system_compatible_cas_latencies = SPD_CAS_LATENCY_2_0 | SPD_CAS_LATENCY_2_5;
+
+/* SPD_CAS_LATENCY_2_0 | SPD_CAS_LATENCY_2_5 | SPD_CAS_LATENCY_3_0 == 0x1c */
+ uint32_t system_compatible_cas_latencies = SPD_CAS_LATENCY_2_0 | SPD_CAS_LATENCY_2_5 | SPD_CAS_LATENCY_3_0;
+// uint32_t system_compatible_cas_latencies = DRT_CAS_2_0 | DRT_CAS_2_5 | DRT_CAS_3_0;
+ uint8_t slowest_row_precharge = 0;
+ uint8_t slowest_ras_cas_delay = 0;
+ uint8_t slowest_active_to_precharge_delay = 0;
+
+// for (i = 0; i < DIMM_SOCKETS; i++) {
+ for (i = 0; i < (2 * DIMM_SOCKETS); i++) {
+ u8 dimm = DIMM0 + i;
+ int value;
+ uint32_t current_cas_latency;
+ uint32_t dimm_compatible_cas_latencies;
+ if (!(dimm_mask & (1 << i)))
+ continue; // This DIMM not usable
+
+ value = spd_read_byte(dimm, SPD_ACCEPTABLE_CAS_LATENCIES);
+ printk(BIOS_DEBUG, "SPD_ACCEPTABLE_CAS_LATENCIES: %d\n", value);
+ die_on_spd_error(value);
+
+ dimm_compatible_cas_latencies = value & 0x7f; // Start with all supported by DIMM
+ printk(BIOS_DEBUG, "dimm_compatible_cas_latencies #1: %d\n", dimm_compatible_cas_latencies);
+
+ current_cas_latency = 1 << log2(dimm_compatible_cas_latencies); // Max supported by DIMM
+ printk(BIOS_DEBUG, "current_cas_latency: %d\n", current_cas_latency);
+
+ // Can we support the highest CAS# latency?
+ value = spd_read_byte(dimm, SPD_MIN_CYCLE_TIME_AT_CAS_MAX);
+ die_on_spd_error(value);
+ printk(BIOS_DEBUG, "SPD_MIN_CYCLE_TIME_AT_CAS_MAX: %d.%d\n", value >> 4, value & 0xf);
+
+ // NOTE: At 133 MHz, 1 clock == 7.52 ns
+ if (value > 0x75) {
+ // Our bus is too fast for this CAS# latency
+ // Remove it from the bitmask of those supported by the DIMM that are compatible
+ dimm_compatible_cas_latencies &= ~current_cas_latency;
+ printk(BIOS_DEBUG, "dimm_compatible_cas_latencies #2: %d\n", dimm_compatible_cas_latencies);
+ }
+ // Can we support the next-highest CAS# latency (max - 0.5)?
+
+ current_cas_latency >>= 1;
+ if (current_cas_latency != 0) {
+ value = spd_read_byte(dimm, SPD_SDRAM_CYCLE_TIME_2ND);
+ die_on_spd_error(value);
+ printk(BIOS_DEBUG, "SPD_SDRAM_CYCLE_TIME_2ND: %d.%d\n", value >> 4, value & 0xf);
+ if (value > 0x75) {
+ dimm_compatible_cas_latencies &= ~current_cas_latency;
+ printk(BIOS_DEBUG, "dimm_compatible_cas_latencies #2: %d\n", dimm_compatible_cas_latencies);
+ }
+ }
+ // Can we support the next-highest CAS# latency (max - 1.0)?
+ current_cas_latency >>= 1;
+ if (current_cas_latency != 0) {
+ value = spd_read_byte(dimm, SPD_SDRAM_CYCLE_TIME_3RD);
+ printk(BIOS_DEBUG, "SPD_SDRAM_CYCLE_TIME_3RD: %d.%d\n", value >> 4, value & 0xf);
+ die_on_spd_error(value);
+ if (value > 0x75) {
+ dimm_compatible_cas_latencies &= ~current_cas_latency;
+ printk(BIOS_DEBUG, "dimm_compatible_cas_latencies #2: %d\n", dimm_compatible_cas_latencies);
+ }
+ }
+ // Restrict the system to CAS# latencies compatible with this DIMM
+ system_compatible_cas_latencies &= dimm_compatible_cas_latencies;
+
+ value = spd_read_byte(dimm, SPD_MIN_ROW_PRECHARGE_TIME);
+ die_on_spd_error(value);
+ if (value > slowest_row_precharge)
+ slowest_row_precharge = value;
+
+ value = spd_read_byte(dimm, SPD_MIN_RAS_TO_CAS_DELAY);
+ die_on_spd_error(value);
+ if (value > slowest_ras_cas_delay)
+ slowest_ras_cas_delay = value;
+
+ value = spd_read_byte(dimm, SPD_MIN_ACTIVE_TO_PRECHARGE_DELAY);
+ die_on_spd_error(value);
+ if (value > slowest_active_to_precharge_delay)
+ slowest_active_to_precharge_delay = value;
+
+ /* go to the next DIMM */
+ }
+ printk(BIOS_DEBUG, "CAS latency: %d\n", system_compatible_cas_latencies);
+
+// dram_timing = pci_read_config32(NORTHBRIDGE_MMC, DRT);
+ dram_timing = MCHBAR32(DRT);
+// dram_timing &= ~(DRT_CAS_MASK | DRT_TRP_MASK | DRT_RCD_MASK);
+ dram_timing &= ~(DRT_CAS_MASK | DRT_TRP_MASK | DRT_TRCD_MASK);
+ printk(BIOS_DEBUG, "DRT: %08x\n", dram_timing);
+
+ if (system_compatible_cas_latencies & SPD_CAS_LATENCY_2_0) {
+ dram_timing |= DRT_CAS_2_0;
+ } else if (system_compatible_cas_latencies & SPD_CAS_LATENCY_2_5) {
+ dram_timing |= DRT_CAS_2_5;
+ } else if (system_compatible_cas_latencies & SPD_CAS_LATENCY_3_0) {
+ dram_timing |= DRT_CAS_3_0;
+ } else
+ die("No CAS# latencies compatible with all DIMMs!!\n");
+
+// uint32_t current_cas_latency = dram_timing & DRT_CAS_MASK;
+
+ /* tRP */
+
+ printk(BIOS_DEBUG, "slowest_row_precharge: %d.%d\n", slowest_row_precharge >> 2, slowest_row_precharge & 0x3);
+ // i855 supports only 2, 3 or 4 clocks for tRP
+ if (slowest_row_precharge > (30 << 2)) // 30 = 11110b = tRCD = 2 dram clocks, tCL = reserved
+ die("unsupported DIMM tRP"); // > 30.0 ns: 5 or more clocks
+ else if (slowest_row_precharge > ( (22 << 2) | (2 << 0) ))
+ // 22 = 10110b = tRCD = 2 dram clocks, tCL = 2
+ // 2 = 10b = 2 dram clocks (tRP)
+ dram_timing |= DRT_TRP_4; // > 22.5 ns: 4 or more clocks
+ else if (slowest_row_precharge > (15 << 2)) // 15 = 1111b = tRCD = reserved, tCL = 2
+ dram_timing |= DRT_TRP_3; // > 15.0 ns: 3 clocks
+ else
+ dram_timing |= DRT_TRP_2; // <= 15.0 ns: 2 clocks
+
+ /* tRCD */
+
+ printk(BIOS_DEBUG, "slowest_ras_cas_delay: %d.%d\n", slowest_ras_cas_delay >> 2, slowest_ras_cas_delay & 0x3);
+ // i855 supports only 2, 3 or 4 clocks for tRCD
+ if (slowest_ras_cas_delay > ((30 << 2)))
+ die("unsupported DIMM tRCD"); // > 30.0 ns: 5 or more clocks
+ else if (slowest_ras_cas_delay > ((22 << 2) | (2 << 0)))
+// dram_timing |= DRT_RCD_4; // > 22.5 ns: 4 or more clocks
+ dram_timing |= DRT_TRCD_4; // > 22.5 ns: 4 or more clocks
+ else if (slowest_ras_cas_delay > (15 << 2))
+// dram_timing |= DRT_RCD_3; // > 15.0 ns: 3 clocks
+ dram_timing |= DRT_TRCD_3; // > 15.0 ns: 3 clocks
+ else
+// dram_timing |= DRT_RCD_2; // <= 15.0 ns: 2 clocks
+ dram_timing |= DRT_TRCD_2; // <= 15.0 ns: 2 clocks
+
+ /* tRAS, min */
+
+ printk(BIOS_DEBUG, "slowest_active_to_precharge_delay: %d\n", slowest_active_to_precharge_delay);
+ // i855 supports only 5, 6, 7 or 8 clocks for tRAS
+ // 5 clocks ~= 37.6 ns, 6 clocks ~= 45.1 ns, 7 clocks ~= 52.6 ns, 8 clocks ~= 60.1 ns
+ // TODO
+ if (slowest_active_to_precharge_delay > 60)
+ die("unsupported DIMM tRAS"); // > 52 ns: 8 or more clocks
+ else if (slowest_active_to_precharge_delay > 52)
+ dram_timing |= DRT_TRAS_MIN_8; // 46-52 ns: 7 clocks
+ else if (slowest_active_to_precharge_delay > 45)
+ dram_timing |= DRT_TRAS_MIN_7; // 46-52 ns: 7 clocks
+ else if (slowest_active_to_precharge_delay > 37)
+ dram_timing |= DRT_TRAS_MIN_6; // 38-45 ns: 6 clocks
+ else
+ dram_timing |= DRT_TRAS_MIN_5; // < 38 ns: 5 clocks
+
+ /* FIXME: guess work starts here...
+ *
+ * Intel refers to DQ turn-arround values for back to calculate the values,
+ * but i have no idea what this means
+ */
+
+ /*
+ * Back to Back Read-Write command spacing (DDR, different Rows/Bank)
+ */
+ /* Set to a 3 clock back to back read to write turn around.
+ * 2 is a good delay if the CAS latency is 2.0 */
+// dram_timing &= ~(3 << 28);
+// if (current_cas_latency == DRT_CAS_2_0)
+// dram_timing |= (2 << 28); // 2 clocks
+// else
+// dram_timing |= (1 << 28); // 3 clocks
+
+ /*
+ * Back to Back Read-Write command spacing (DDR, same or different Rows/Bank)
+ */
+// dram_timing &= ~(3 << 26);
+// if (current_cas_latency == DRT_CAS_2_0)
+// dram_timing |= (2 << 26); // 5 clocks
+// else
+// dram_timing |= (1 << 26); // 6 clocks
+
+ /*
+ * Back To Back Read-Read commands spacing (DDR, different Rows):
+ */
+// dram_timing &= ~(1 << 25);
+// dram_timing |= (1 << 25); // 3 clocks
+
+ printk(BIOS_DEBUG, "DRT: %08x\n", dram_timing);
+// pci_write_config32(NORTHBRIDGE_MMC, DRT, dram_timing);
+ MCHBAR32(DRT) = dram_timing;
+}
+
+static void spd_set_dram_size(uint8_t dimm_mask)
+{
+ int i;
+ int total_dram = 0;
+ uint32_t drb_reg = 0;
+
+// for (i = 0; i < DIMM_SOCKETS; i++) {
+ for (i = 0; i < (2 * DIMM_SOCKETS); i++) {
+ u8 dimm = DIMM0 + i;
+ struct dimm_size sz;
+
+ if (!(dimm_mask & (1 << i))) {
+ /* fill values even for not present DIMMs */
+// drb_reg |= (total_dram << (i * 16));
+// drb_reg |= (total_dram << ((i * 16) + 8));
+ drb_reg |= (total_dram << (i * 32));
+ drb_reg |= (total_dram << ((i * 32) + 8));
+
+ continue; // This DIMM not usable
+ }
+ sz = spd_get_dimm_size(dimm);
+
+// total_dram += (1 << (sz.side1 - 28));
+// drb_reg |= (total_dram << (i * 16));
+ total_dram += (1 << (sz.side1 - 30));
+ drb_reg |= (total_dram << (i * 32));
+
+// total_dram += (1 << (sz.side2 - 28));
+// drb_reg |= (total_dram << ((i * 16) + 8));
+ total_dram += (1 << (sz.side2 - 30));
+ drb_reg |= (total_dram << ((i * 32) + 8));
+
+ printk(BIOS_DEBUG, "DRB: %08x\n", drb_reg);
+ MCHBAR8(DRB + i) = drb_reg;
+ }
+// printk(BIOS_DEBUG, "DRB: %08x\n", drb_reg);
+// pci_write_config32(NORTHBRIDGE_MMC, DRB, drb_reg);
+}
+
+static void enable_refresh(void)
+{
+ printk(BIOS_DEBUG, "Enabling refresh (RAM_COMMAND_REFRESH)\n");
+ MCHBAR32(DRC) |= RAM_COMMAND_REFRESH << 8;
+}
+
+/* from src/northbridge/intel/i945/raminit.c and util/inteltool/memory.c */
+static void sdram_dump_mchbar_registers(void)
+{
+ int i;
+
+ printk(BIOS_DEBUG, "Dumping MCHBAR registers:\n");
+ for (i = 0; i < 0xffff; i += 4) {
+ if ( (MCHBAR32(i) == 0) || (MCHBAR32(i) == 0xffffffff) )
+ continue;
+ switch (i) {
+ case (DRB + 0):
+ printk(BIOS_DEBUG, " DRB0: 0x%x\n", MCHBAR32(i));
+ case (DRB + 1):
+ printk(BIOS_DEBUG, " DRB1: 0x%x\n", MCHBAR32(i));
+ case (DRB + 2):
+ printk(BIOS_DEBUG, " DRB2: 0x%x\n", MCHBAR32(i));
+ case (DRB + 3):
+ printk(BIOS_DEBUG, " DRB3: 0x%x\n", MCHBAR32(i));
+ case (DRB + 4):
+ printk(BIOS_DEBUG, " DRB4: 0x%x\n", MCHBAR32(i));
+ case (DRB + 5):
+ printk(BIOS_DEBUG, " DRB5: 0x%x\n", MCHBAR32(i));
+ case (DRB + 6):
+ printk(BIOS_DEBUG, " DRB6: 0x%x\n", MCHBAR32(i));
+ case (DRB + 7):
+ printk(BIOS_DEBUG, " DRB7: 0x%x\n", MCHBAR32(i));
+
+ case (DRA + 0):
+ printk(BIOS_DEBUG, " DRA0: 0x%x\n", MCHBAR32(i));
+ case (DRA + 1):
+ printk(BIOS_DEBUG, " DRA1: 0x%x\n", MCHBAR32(i));
+ case (DRA + 2):
+ printk(BIOS_DEBUG, " DRA2: 0x%x\n", MCHBAR32(i));
+ case (DRA + 3):
+ printk(BIOS_DEBUG, " DRA3: 0x%x\n", MCHBAR32(i));
+ case (DRA + 4):
+ printk(BIOS_DEBUG, " DRA4: 0x%x\n", MCHBAR32(i));
+ case (DRA + 5):
+ printk(BIOS_DEBUG, " DRA5: 0x%x\n", MCHBAR32(i));
+ case (DRA + 6):
+ printk(BIOS_DEBUG, " DRA6: 0x%x\n", MCHBAR32(i));
+ case (DRA + 7):
+ printk(BIOS_DEBUG, " DRA7: 0x%x\n", MCHBAR32(i));
+
+ case DRT:
+ printk(BIOS_DEBUG, " DRT: 0x%x\n", MCHBAR32(i));
+ case DRC:
+ printk(BIOS_DEBUG, " DRC: 0x%x\n", MCHBAR32(i));
+ default:
+ printk(BIOS_DEBUG, "0x%x: 0x%x\n", i, MCHBAR32(i));
+ }
+ }
+}
+
+static void early_northbridge_set_registers(void)
+{
+ u8 reg8;
+
+ /* Undocumented register */
+ reg8 = pci_read_config8(NORTHBRIDGE, 0xf4);
+
+ /*
+ Writing 0x2 to northbridge register 0xf4
+ exposes the PCI registers of device 6.
+ */
+ //reg8 |= 0x2; /* guesswork: the default value is 0x0 */
+ reg8 = 0x2;
+
+ printk(BIOS_DEBUG, "Enabling access to (the registers of) device 6\n");
+ pci_write_config8(NORTHBRIDGE, 0xf4, reg8);
+
+ printk(BIOS_DEBUG, "Configuring BAR6 as 0x%x\n", DEFAULT_MCHBAR);
+ pci_write_config32(NORTHBRIDGE_MMC, BAR6, DEFAULT_MCHBAR);
+
+ printk(BIOS_DEBUG, "Enabling Memory Access Enable (MAE) in PCICMD6\n");
+ pci_write_config16(NORTHBRIDGE_MMC, PCICMD6, 0x2);
+}
+
+static void northbridge_set_pam(void)
+{
+ printk(BIOS_DEBUG, "Configuring PAM0..PAM6\n");
+ pci_write_config8(NORTHBRIDGE, PAM0, 0x10);
+ pci_write_config8(NORTHBRIDGE, PAM1, 0x11);
+ pci_write_config8(NORTHBRIDGE, PAM2, 0x1);
+ pci_write_config8(NORTHBRIDGE, PAM3, 0x0);
+ pci_write_config8(NORTHBRIDGE, PAM4, 0x0);
+ pci_write_config8(NORTHBRIDGE, PAM5, 0x33);
+ pci_write_config8(NORTHBRIDGE, PAM6, 0x33);
+}
+
+static void northbridge_set_registers(void)
+{
+ printk(BIOS_DEBUG, "Configuring APBASE\n");
+ pci_write_config32(NORTHBRIDGE, APBASE, 0xfe800008);
+
+ printk(BIOS_DEBUG, "Configuring APSIZE\n");
+ pci_write_config8(NORTHBRIDGE, APSIZE, 0x3f);
+
+ printk(BIOS_DEBUG, "Configuring GC\n"); /* IVD=0, IGDIS=0, GMS=8 megabyte */
+ pci_write_config8(NORTHBRIDGE, GC, 0x34);
+
+ printk(BIOS_DEBUG, "Configuring AMTT\n");
+ pci_write_config8(NORTHBRIDGE, AMTT, 0x20);
+
+ printk(BIOS_DEBUG, "Configuring LPTT\n");
+ pci_write_config8(NORTHBRIDGE, LPTT, 0x10);
+
+ printk(BIOS_DEBUG, "Configuring GMCHCFG\n");
+ pci_write_config16(NORTHBRIDGE, GMCHCFG, 0x40d);
+
+ printk(BIOS_DEBUG, "Configuring TOUD\n");
+ pci_write_config16(NORTHBRIDGE, TOUD, 0x1f80);
+
+ printk(BIOS_DEBUG, "Configuring PCISTS\n");
+ pci_write_config16(NORTHBRIDGE, PCISTS, 0x2009);
+
+ printk(BIOS_DEBUG, "Writing SVID and SID\n");
+ pci_write_config16(NORTHBRIDGE, SVID, 0x1849);
+ pci_write_config16(NORTHBRIDGE, SID, 0x2570);
+
+ printk(BIOS_DEBUG, "Configuring ERRSTS\n");
+ pci_write_config16(NORTHBRIDGE, ERRSTS, 0x100);
+}
+
+static void northbridge_set_undocumented_registers(void)
+{
+ u8 reg8;
+
+ printk(BIOS_DEBUG, "Configuring undocumented register 0x54\n");
+ /*
+ guesswork, the default value is 0x18 and 0x1c is the value from lspci -nnvvvxxx.
+ conclusion: add 0x4 */
+ reg8 = pci_read_config8(NORTHBRIDGE, 0x54);
+ reg8 |= 0x4;
+ pci_write_config8(NORTHBRIDGE, 0x54, reg8);
+
+ printk(BIOS_DEBUG, "Configuring undocumented register 0x9d\n");
+ reg8 = pci_read_config8(NORTHBRIDGE, 0xc9d);
+ reg8 |= 0x8;
+ pci_write_config8(NORTHBRIDGE, 0x9d, reg8);
+}
+
+//static void hardcoded_initialization(void)
+//{
+ // int i;
+
+// printk(BIOS_DEBUG, "Configuring DRT\n");
+// MCHBAR32(DRT) = 0x56e40d00; /* single-channel, 512MB in the first (physical) slot */
+// printk(BIOS_DEBUG, " DRT after configuring (should be 0x56e40d00): 0x%x\n", MCHBAR32(DRT));
+
+// printk(BIOS_DEBUG, "Configuring DRB0..DRB7\n");
+
+ /* single-channel, 512MB in the first (physical) slot */
+// MCHBAR8(DRB + 0) = 0x4;
+// MCHBAR8(DRB + 1) = 0x8;
+// MCHBAR8(DRB + 2) = 0x8;
+// MCHBAR8(DRB + 3) = 0x8;
+// MCHBAR8(DRB + 4) = 0x8;
+// MCHBAR8(DRB + 5) = 0x8;
+// MCHBAR8(DRB + 6) = 0x8;
+// MCHBAR8(DRB + 7) = 0x8;
+ // for (i = 0; i < 8; i++) {
+ // printk(BIOS_DEBUG, " DRB%i after configuring (should be 0x4 for DRB0, 0x8 for DRB1-7): 0x%x\n", i, MCHBAR8(DRB + i));
+ // }
+
+// printk(BIOS_DEBUG, "Configuring DRA0..DRA7\n");
+
+ /* single-channel, 512MB in the first (physical) slot */
+// MCHBAR8(DRA + 0) = 0x0;
+// MCHBAR8(DRA + 1) = 0x11; // 8 kilobyte on each row
+// MCHBAR8(DRA + 2) = 0x0;
+// MCHBAR8(DRA + 3) = 0x0;
+ // for (i = 0; i < 8; i++) {
+ // printk(BIOS_DEBUG, " DRA%i after configuring (should be 0x0 for DRA0, DRA2 and DRA3, 0x11 for DRA1: 0x%x\n",
+ // i, MCHBAR8(DRA + i));
+ // }
+
+ // BAR6_32(DRC) = 0x20104271;
+
+ // printk(BIOS_DEBUG, "All aboard the undocumented registers train :(\n");
+
+/*
+ MCHBAR32(0x6c) = 0xa801;
+ MCHBAR32(0xb0) = 0x40830;
+ MCHBAR32(0x100) = 0x89b;
+ MCHBAR32(0x104) = 0x4ad;
+ MCHBAR32(0x130) = 0x88d;
+ MCHBAR32(0x138) = 0x210843c;
+ MCHBAR32(0x140) = 0x1721c;
+ MCHBAR32(0x144) = 0xe380fff;
+ MCHBAR32(0x170) = 0x1a00018b;
+ MCHBAR32(0x1a0) = 0x3d0524fd;
+ MCHBAR32(0x200) = 0x1;
+ MCHBAR32(0x208) = 0x3937;
+ MCHBAR32(0x300) = 0x32;
+ MCHBAR32(0x800) = 0xdddddddd;
+*/
+ // sdram_dump_mchbar_registers(); // from i945
+//}
+
+static void sdram_initialize(void)
+//void sdram_initialize(void)
+{
+ /* First things first. */
+ early_northbridge_set_registers();
+
+ uint8_t dimm_mask;
+
+ printk(BIOS_DEBUG, "Reading SPD data...\n");
+ dimm_mask = spd_get_supported_dimms();
+
+ if (dimm_mask == 0) {
+ printk(BIOS_DEBUG, "No usable memory for this controller\n");
+ }
+ else {
+ printk(BIOS_DEBUG, "DIMM mask: 0x%x\n", dimm_mask);
+
+ spd_set_row_attributes(dimm_mask); // done?
+ spd_set_dram_controller_mode(dimm_mask); // TODO
+ spd_set_dram_timing(dimm_mask); // TODO: tRAS
+ spd_set_dram_size(dimm_mask); // TODO
+ }
+
+ sdram_enable();
+
+ enable_refresh();
+
+ set_initialization_complete();
+
+ /* Setup Initial Northbridge Registers */
+ northbridge_set_pam();
+ northbridge_set_registers();
+ northbridge_set_undocumented_registers();
+
+ sdram_dump_mchbar_registers();
+
+ printk(BIOS_DEBUG, "Northbridge following SDRAM init:\n");
+
+ dump_pci_device(NORTHBRIDGE);
+ dump_pci_device(NORTHBRIDGE_MMC);
+// dump_pci_device(PCI_DEV(0, 0x1e, 0));
+// dump_pci_device(PCI_DEV(0, 0x1f, 0));
+// dump_pci_device(PCI_DEV(0, 0x1f, 3));
+}
diff --git a/src/northbridge/intel/i865/raminit.h b/src/northbridge/intel/i865/raminit.h
new file mode 100644
index 0000000..bf47053
--- /dev/null
+++ b/src/northbridge/intel/i865/raminit.h
@@ -0,0 +1,181 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2006 Jon Dufresne <jon.dufresne at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+// #ifndef NORTHBRIDGE_INTEL_I865_RAMINIT_H
+// #define NORTHBRIDGE_INTEL_I865_RAMINIT_H
+#ifndef RAMINIT_H
+#define RAMINIT_H
+
+#define DIMM_SOCKETS 4
+
+/* i865 Northbridge PCI devices */
+#define NORTHBRIDGE PCI_DEV(0, 0, 0)
+#define NORTHBRIDGE_MMC PCI_DEV(0, 6, 0) // Overflow device
+
+/*-----------------------------------------------------------------------------
+Macros and definitions:
+-----------------------------------------------------------------------------*/
+//#define VALIDATE_DIMM_COMPATIBILITY
+
+#define delay() udelay(200)
+
+/* should dispose of this. */
+// burst length can be 4 or 8 in single-channel or 8 in dual-channel
+// interleaved bursts versus sequential bursts.. no idea about the capabilities of i865, so I left it out
+//#define VG86X_MODE (SDRAM_BURST_4 | SDRAM_BURST_INTERLEAVED | SDRAM_CAS_2_5)
+//#define VG86X_MODE (SDRAM_BURST_4 | SDRAM_CAS_3) // SDRAM_CAS_* == tCL?
+#define VG85X_MODE (SDRAM_BURST_4 | SDRAM_BURST_INTERLEAVED | SDRAM_CAS_2_5)
+
+/* Main Memory Control */
+#define DEFAULT_MCHBAR 0xfecf0000 /* ? KB */
+
+#define MCHBAR8(x) *((volatile u8 *)(DEFAULT_MCHBAR + x))
+//#define MCHBAR16(x) *((volatile u16 *)(DEFAULT_MCHBAR + x)) // unused
+#define MCHBAR32(x) *((volatile u32 *)(DEFAULT_MCHBAR + x))
+
+/* Memory mapped registers */
+#define DRB 0x0 /* DRAM Row 0-7 Boundary */
+#define DRA 0x10 /* DRAM Row 0-7 Attribute */
+#define DRT 0x60 /* DRAM Timing */
+#define DRC 0x68 /* DRAM Controller Mode */
+
+/* Northbridge (device 0) */
+#define PAM0 0x90 /* Programmable Attribute Map #0 */
+#define PAM1 0x91 /* Programmable Attribute Map #1 */
+#define PAM2 0x92 /* Programmable Attribute Map #2 */
+#define PAM3 0x93 /* Programmable Attribute Map #3 */
+#define PAM4 0x94 /* Programmable Attribute Map #4 */
+#define PAM5 0x95 /* Programmable Attribute Map #5 */
+#define PAM6 0x96 /* Programmable Attribute Map #6 */
+
+/* DRC[29] - Initialization Complete (IC) */
+//#define RAM_COMMAND_IC 0x1
+//#define DRC_DONE (RAM_COMMAND_IC << 29)
+#define RAM_INITIALIZATION_COMPLETE (1 << 29)
+
+/* DRC[22:21] - Number of Channels (CHAN) */
+// TODO: rename to DRC_*_CHANNEL_* ?
+#define RAM_SINGLE_CHANNEL 0x0
+#define RAM_DUAL_CHANNEL_LINEAR 0x1
+#define RAM_DUAL_CHANNEL_TILEAR 0x2
+
+/* DRC[10:8] - Refresh Mode Select (RMS)
+ * 0x1 for Refresh interval 15.6 us
+ * 0x2 for Refresh interval 7.8 us
+ * 0x3 for Refresh interval 64 usec
+ * 0x7 for Refresh interval 64 Clocks. (Fast Refresh Mode)
+ */
+// TODO: rename to DRC_RMS_* ?
+// #define RAM_RMS_15_6 0x1 /* usec */
+// #define RAM_RMS_7_8 0x2 /* usec */
+// #define RAM_RMS_64 0x3 /* usec */
+// #define RAM_RMS_FAST 0x7 /* clocks */
+#define RAM_COMMAND_REFRESH 0x1
+
+/* DRC[6:4] - Mode Select (SMS) */
+// TODO: mask?
+// TODO: rename to DRC_SMS_* ?
+#define RAM_COMMAND_POST_RESET 0x0
+#define RAM_COMMAND_NOP 0x1
+#define RAM_COMMAND_PRECHARGE 0x2
+#define RAM_COMMAND_MRS 0x3
+#define RAM_COMMAND_EMRS 0x4
+#define RAM_COMMAND_CBR 0x6
+#define RAM_COMMAND_NORMAL 0x7
+
+/* Activate to Precharge delay (tRAS) */
+#define DRT_TRAS_MAX_70 (1 << 10)
+#define DRT_TRAS_MAX_120 (0 << 10)
+#define DRT_TRAS_MIN_MASK (5 << 7) // conflicts with DRT_TRAS_MIN_5
+#define DRT_TRAS_MIN_10 (0 << 7)
+#define DRT_TRAS_MIN_9 (1 << 7)
+#define DRT_TRAS_MIN_8 (2 << 7)
+#define DRT_TRAS_MIN_7 (3 << 7)
+#define DRT_TRAS_MIN_6 (4 << 7)
+#define DRT_TRAS_MIN_5 (5 << 7)
+
+/* CAS# latency (tCL) */
+#define DRT_TCL_MASK (3 << 5)
+#define DRT_TCL_2_0 (1 << 5)
+#define DRT_TCL_2_5 (0 << 5)
+#define DRT_TCL_3_0 (2 << 5)
+
+/* DRAM RAS# to CAS delay (tRCD) */
+#define DRT_TRCD_MASK (3 << 2)
+#define DRT_TRCD_4 (0 << 2)
+#define DRT_TRCD_3 (1 << 2)
+#define DRT_TRCD_2 (2 << 2)
+
+/* DRAM RAS# precharge (tRP) */
+#define DRT_TRP_MASK 3
+#define DRT_TRP_4 0
+#define DRT_TRP_3 1
+#define DRT_TRP_2 2
+
+// moved from i855.h
+#define DRT_CAS_MASK (3 << 5)
+#define DRT_CAS_2_0 (1 << 5)
+#define DRT_CAS_2_5 (0 << 5)
+#define DRT_CAS_3_0 (2 << 5)
+
+struct sys_info { // copied from i945, not yet used
+ u16 memory_frequency; /* 400, 533 or 667 */
+ u16 fsb_frequency; /* 400, 533 or 667 */
+
+ u8 trp; /* calculated by sdram_detect_smallest_tRP() */
+ u8 trcd; /* calculated by sdram_detect_smallest_tRCD() */
+ u8 tras; /* calculated by sdram_detect_smallest_tRAS() */
+ // u8 trfc; /* calculated by sdram_detect_smallest_tRFC() */
+ // u8 twr; /* calculated by sdram_detect_smallest_tWR() */
+
+ u8 cas; /* 3, 4 or 5 */
+ u8 refresh; /* 0 = 15.6us, 1 = 7.8us */
+
+ u8 dual_channel; /* 0 or 1 */
+ u8 interleaved;
+
+ // u8 mvco4x; /* 0 (8x) or 1 (4x) */
+ // u8 clkcfg_bit7;
+ // u8 boot_path;
+// #define BOOT_PATH_NORMAL 0
+// #define BOOT_PATH_RESET 1
+// #define BOOT_PATH_RESUME 2
+
+ // u8 package; /* 0 = planar, 1 = stacked */
+// #define SYSINFO_PACKAGE_PLANAR 0x00
+// #define SYSINFO_PACKAGE_STACKED 0x01
+ u8 dimm[2 * DIMM_SOCKETS];
+#define SYSINFO_DIMM_X16DS 0x00
+#define SYSINFO_DIMM_X8DS 0x01
+#define SYSINFO_DIMM_X16SS 0x02
+#define SYSINFO_DIMM_X8DDS 0x03
+#define SYSINFO_DIMM_NOT_POPULATED 0x04
+
+ u8 banks[2 * DIMM_SOCKETS];
+
+ u8 banksize[2 * 2 * DIMM_SOCKETS];
+ const u8 *spd_addresses;
+
+} __attribute__ ((packed));
+
+
+//void sdram_initialize(void);
+
+#endif /* NORTHBRIDGE_INTEL_I865_RAMINIT_H */
diff --git a/src/northbridge/intel/i865/reset_test.c b/src/northbridge/intel/i865/reset_test.c
new file mode 100644
index 0000000..c465c53
--- /dev/null
+++ b/src/northbridge/intel/i865/reset_test.c
@@ -0,0 +1,38 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2006 Jon Dufresne <jon.dufresne at gmail.com>
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ * You should have received a copy of the GNU General Public License
+ * along with this program; if not, write to the Free Software
+ * Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+ */
+
+#include "raminit.h"
+
+ /* If I have already booted once skip a bunch of initialization */
+ /* To see if I have already booted I check to see if memory
+ * has been enabled.
+ */
+static int bios_reset_detected(void)
+{
+ uint32_t dword;
+
+ dword = BAR6_32(DRC);
+
+ if( (dword & DRC_DONE) != 0 ) {
+ return 1;
+ }
+
+ return 0;
+}
diff --git a/src/southbridge/intel/i82801ex/early_smbus.c b/src/southbridge/intel/i82801ex/early_smbus.c
index cdf1f62..1c67c51 100644
--- a/src/southbridge/intel/i82801ex/early_smbus.c
+++ b/src/southbridge/intel/i82801ex/early_smbus.c
@@ -1,6 +1,6 @@
#include "smbus.h"
-#define SMBUS_IO_BASE 0x0f00
+//#define SMBUS_IO_BASE 0x0f00
static void enable_smbus(void)
{
@@ -9,7 +9,7 @@ static void enable_smbus(void)
print_spew("SMBus controller enabled\n");
pci_write_config32(dev, 0x20, SMBUS_IO_BASE | 1);
- print_debug_hex32(pci_read_config32(dev, 0x20));
+ printk(BIOS_DEBUG, "SMB_BASE = 0x%x\n", pci_read_config32(dev, SMB_BASE));
/* Set smbus enable */
pci_write_config8(dev, 0x40, 1);
/* Set smbus iospace enable */
diff --git a/src/southbridge/intel/i82801ex/smbus.h b/src/southbridge/intel/i82801ex/smbus.h
index f330c0a..0fa6b84 100644
--- a/src/southbridge/intel/i82801ex/smbus.h
+++ b/src/southbridge/intel/i82801ex/smbus.h
@@ -1,5 +1,8 @@
#include <device/smbus_def.h>
+#define SMBUS_IO_BASE 0x400
+#define SMB_BASE 0x20
+
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
diff --git a/src/superio/winbond/w83627thg/early_serial.c b/src/superio/winbond/w83627thg/early_serial.c
index 559e982..a54139f 100644
--- a/src/superio/winbond/w83627thg/early_serial.c
+++ b/src/superio/winbond/w83627thg/early_serial.c
@@ -45,3 +45,14 @@ static void inline w83627thg_enable_serial(device_t dev, u16 iobase)
pnp_set_enable(dev, 1);
pnp_exit_ext_func_mode(dev);
}
+
+static void w83627thg_set_clksel_48(device_t dev)
+{
+ u8 reg8;
+
+ pnp_enter_ext_func_mode(dev);
+ reg8 = pnp_read_config(dev, 0x24);
+ reg8 |= (1 << 6); /* Set CLKSEL (clock input on pin 1) to 48MHz. */
+ pnp_write_config(dev, 0x24, reg8);
+ pnp_exit_ext_func_mode(dev);
+}
More information about the coreboot
mailing list