summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
-rw-r--r--src/cpu/via/car/cache_as_ram_post.c106
-rw-r--r--src/cpu/via/model_c7/Config.lb4
-rw-r--r--src/cpu/via/model_c7/model_c7_init.c11
-rw-r--r--src/cpu/x86/car/copy_and_run.c5
-rw-r--r--src/include/pc80/i8259.h24
-rw-r--r--src/include/spd_ddr2.h12
-rw-r--r--src/mainboard/via/vt8454c/Config.lb198
-rw-r--r--src/mainboard/via/vt8454c/Options.lb246
-rw-r--r--src/mainboard/via/vt8454c/acpi_tables.c205
-rw-r--r--src/mainboard/via/vt8454c/auto.c127
-rw-r--r--src/mainboard/via/vt8454c/chip.h26
-rw-r--r--src/mainboard/via/vt8454c/cmos.layout67
-rw-r--r--src/mainboard/via/vt8454c/debug.c108
-rw-r--r--src/mainboard/via/vt8454c/dmi.h31
-rw-r--r--src/mainboard/via/vt8454c/dsdt.dsl341
-rw-r--r--src/mainboard/via/vt8454c/fadt.c156
-rw-r--r--src/mainboard/via/vt8454c/irq-p2p-bridge.dsl88
-rw-r--r--src/mainboard/via/vt8454c/irq.dsl143
-rw-r--r--src/mainboard/via/vt8454c/irq_tables.c61
-rw-r--r--src/mainboard/via/vt8454c/mainboard.c28
-rw-r--r--src/mainboard/via/vt8454c/mptable.c104
-rw-r--r--src/mainboard/via/vt8454c/reset.c28
-rw-r--r--src/northbridge/via/cx700/Config.lb28
-rw-r--r--src/northbridge/via/cx700/chip.h23
-rw-r--r--src/northbridge/via/cx700/cx700_agp.c91
-rw-r--r--src/northbridge/via/cx700/cx700_early_serial.c102
-rw-r--r--src/northbridge/via/cx700/cx700_early_smbus.c268
-rw-r--r--src/northbridge/via/cx700/cx700_lpc.c397
-rw-r--r--src/northbridge/via/cx700/cx700_registers.h272
-rw-r--r--src/northbridge/via/cx700/cx700_reset.c25
-rw-r--r--src/northbridge/via/cx700/cx700_sata.c160
-rw-r--r--src/northbridge/via/cx700/cx700_usb.c56
-rw-r--r--src/northbridge/via/cx700/cx700_vga.c119
-rw-r--r--src/northbridge/via/cx700/northbridge.c182
-rw-r--r--src/northbridge/via/cx700/northbridge.h25
-rw-r--r--src/northbridge/via/cx700/raminit.c1480
-rw-r--r--src/northbridge/via/cx700/raminit.h28
-rw-r--r--src/northbridge/via/cx700/vgabios.c783
-rw-r--r--src/pc80/udelay_io.c2
-rw-r--r--targets/via/vt8454c/Config-abuild.lb44
-rw-r--r--targets/via/vt8454c/Config.lb45
41 files changed, 6243 insertions, 6 deletions
diff --git a/src/cpu/via/car/cache_as_ram_post.c b/src/cpu/via/car/cache_as_ram_post.c
new file mode 100644
index 0000000000..99e0dd89ec
--- /dev/null
+++ b/src/cpu/via/car/cache_as_ram_post.c
@@ -0,0 +1,106 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2008 VIA Technologies, Inc.
+ * (Written by Jason Zhao <jasonzhao@viatech.com.cn> for VIA)
+ *
+ * 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
+ */
+
+ __asm__ volatile (
+ /*
+ FIXME : backup stack in CACHE_AS_RAM into mmx and sse and after we get STACK up, we restore that.
+ It is only needed if we want to go back
+ */
+
+ /* We don't need cache as ram for now on */
+ /* disable cache */
+ "movl %cr0, %eax\n\t"
+ "orl $(0x1<<30),%eax\n\t"
+ "movl %eax, %cr0\n\t"
+
+
+ /* Set the default memory type and disable fixed and enable variable MTRRs */
+ "movl $0x2ff, %ecx\n\t"
+ //"movl $MTRRdefType_MSR, %ecx\n\t"
+ "xorl %edx, %edx\n\t"
+ /* Enable Variable and Disable Fixed MTRRs */
+ "movl $0x00000800, %eax\n\t"
+ "wrmsr\n\t"
+
+ /* enable caching for first 1M using variable mtrr */
+ "movl $0x200, %ecx\n\t"
+ "xorl %edx, %edx\n\t"
+ "movl $(0 | 6), %eax\n\t"
+ //"movl $(0 | MTRR_TYPE_WRBACK), %eax\n\t"
+ "wrmsr\n\t"
+
+/*Jasonzhao@viatech.com.cn, I enable cache for 0-7ffff, 80000-9ffff, e0000-fffff;
+if 1M cacheable,then when S3 resume, there is stange color on screen for 2 sec.
+suppose problem of a0000-dfffff and cache .
+and in x86_setup_fixed_mtrrs()(mtrr.c), 0-256M is set cacheable.*/
+
+ "movl $0x201, %ecx\n\t"
+ "movl $0x0000000f, %edx\n\t" /* AMD 40 bit 0xff*/
+ "movl $((~(( 0 + 0x80000) - 1)) | 0x800), %eax\n\t"
+ "wrmsr\n\t"
+
+ "movl $0x202, %ecx\n\t"
+ "xorl %edx, %edx\n\t"
+ "movl $(0x80000 | 6), %eax\n\t"
+ "orl $(0 | 6), %eax\n\t"
+ "wrmsr\n\t"
+
+ "movl $0x203, %ecx\n\t"
+ "movl $0x0000000f, %edx\n\t" /* AMD 40 bit 0xff*/
+ "movl $((~(( 0 + 0x20000) - 1)) | 0x800), %eax\n\t"
+ "wrmsr\n\t"
+
+ "movl $0x204, %ecx\n\t"
+ "xorl %edx, %edx\n\t"
+ "movl $(0xc0000 | 6), %eax\n\t"
+ "orl $(0 | 6), %eax\n\t"
+ "wrmsr\n\t"
+
+ "movl $0x205, %ecx\n\t"
+ "movl $0x0000000f, %edx\n\t" /* AMD 40 bit 0xff*/
+ "movl $((~(( 0 + 0x40000) - 1)) | 0x800), %eax\n\t"
+ "wrmsr\n\t"
+
+ /*jasonzhao@viatech.com.cn add this 2008-11-27, cache XIP_ROM_BASE-SIZE to speedup the coreboot code*/
+ "movl $0x206, %ecx\n\t"
+ "xorl %edx, %edx\n\t"
+ "movl $XIP_ROM_BASE,%eax\n\t"
+ "orl $(0 | 6), %eax\n\t"
+ "wrmsr\n\t"
+
+ "movl $0x207, %ecx\n\t"
+ "xorl %edx, %edx\n\t"
+ "movl $XIP_ROM_SIZE,%eax\n\t"
+ "decl %eax\n\t"
+ "notl %eax\n\t"
+ "orl $(0 | 0x800), %eax\n\t"
+ "wrmsr\n\t"
+
+ /* enable cache */
+ "movl %cr0, %eax\n\t"
+ "andl $0x9fffffff,%eax\n\t"
+ "movl %eax, %cr0\n\t"
+ "invd\n\t"
+
+ /*
+ FIXME: I hope we don't need to change esp and ebp value here, so we can restore value from mmx sse back
+ But the problem is the range is some io related, So don't go back
+ */
+ );
diff --git a/src/cpu/via/model_c7/Config.lb b/src/cpu/via/model_c7/Config.lb
index d956832162..a95697dd4d 100644
--- a/src/cpu/via/model_c7/Config.lb
+++ b/src/cpu/via/model_c7/Config.lb
@@ -5,8 +5,8 @@
#
# 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.
+# 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
diff --git a/src/cpu/via/model_c7/model_c7_init.c b/src/cpu/via/model_c7/model_c7_init.c
index c32c9b5220..d9d59d1c58 100644
--- a/src/cpu/via/model_c7/model_c7_init.c
+++ b/src/cpu/via/model_c7/model_c7_init.c
@@ -1,12 +1,12 @@
/*
* This file is part of the coreboot project.
*
- * (C) 2007-2008 coresystems GmbH
+ * (C) 2007-2009 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.
+ * 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
@@ -195,6 +195,11 @@ static void model_c7_init(device_t dev)
/* Gear up */
set_c7_speed(c.x86_model);
+ /* Enable APIC */
+ msr = rdmsr(0x1107);
+ msr.lo |= 1<<24;
+ wrmsr(0x1107, msr);
+
/* Turn on cache */
x86_enable_cache();
diff --git a/src/cpu/x86/car/copy_and_run.c b/src/cpu/x86/car/copy_and_run.c
index bd2662e0c0..7a070ee648 100644
--- a/src/cpu/x86/car/copy_and_run.c
+++ b/src/cpu/x86/car/copy_and_run.c
@@ -56,6 +56,11 @@ static void copy_and_run(unsigned cpu_reset)
#else
print_spew("coreboot_ram.bin length = "); print_spew_hex32(olen); print_spew("\r\n");
#endif
+#ifdef CONFIG_DEACTIVATE_CAR
+ print_debug("Deactivating CAR");
+#include CONFIG_DEACTIVATE_CAR_FILE
+ print_debug(" - Done.\r\n");
+#endif
print_debug("Jumping to coreboot.\r\n");
if(cpu_reset == 1 ) {
diff --git a/src/include/pc80/i8259.h b/src/include/pc80/i8259.h
index 10a3fc8071..48e8df58d9 100644
--- a/src/include/pc80/i8259.h
+++ b/src/include/pc80/i8259.h
@@ -1 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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
+ */
+
+#ifndef PC80_I8259_H
+#define PC80_I8259_H
+
void setup_i8259(void);
+
+#endif /* PC80_I8259_H */
diff --git a/src/include/spd_ddr2.h b/src/include/spd_ddr2.h
index a1deb36c96..09851f9715 100644
--- a/src/include/spd_ddr2.h
+++ b/src/include/spd_ddr2.h
@@ -2,6 +2,7 @@
* This file is part of the coreboot project.
*
* Copyright (C) 2007 Advanced Micro Devices, Inc.
+ * Copyright (C) 2007-2009 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
@@ -29,6 +30,7 @@
#define SPD_DIMM_TYPE_uDIMM (1<<3)
#define SPD_DIMM_TYPE_mRDIMM (1<<4)
#define SPD_DIMM_TYPE_mUDIMM (1<<5)
+
#define SPD_MOD_ATTRIB 21
#define SPD_MOD_ATTRIB_DIFCK 0x20
#define SPD_MOD_ATTRIB_REGADC 0x11 /* x */
@@ -39,6 +41,15 @@
#define SPD_DIMM_CONF_TYPE_ECC 0x02
#define SPD_DIMM_CONF_TYPE_ADDR_PARITY 0x04 /* ? */
+#define SPD_CAS_LAT_MIN_X_1 23
+#define SPD_CAS_LAT_MAX_X_1 24
+#define SPD_CAS_LAT_MIN_X_2 25
+#define SPD_CAS_LAT_MAX_X_2 26
+
+#define SPD_BURST_LENGTHS 16
+ #define SPD_BURST_LENGTHS_4 (1<<2)
+ #define SPD_BURST_LENGTHS_8 (1<<3)
+
#define SPD_ROW_NUM 3 /* Number of Row addresses */
#define SPD_COL_NUM 4 /* Number of Column addresses */
#define SPD_BANK_NUM 17 /* SDRAM Device attributes - Number of Banks on
@@ -82,6 +93,7 @@
#define SPD_TWTR 37 /* x */
#define SPD_TRTP 38 /* x */
+#define SPD_EX_TRC_TRFC 40
#define SPD_TRC 41 /* add byte 0x40 bit [3:1] , so final val41+ table[((val40>>1) & 0x7)] ... table[]={0, 0.25, 0.33, 0.5, 0.75, 0, 0}*/
#define SPD_TRFC 42 /* add byte 0x40 bit [6:4] , so final val42+ table[((val40>>4) & 0x7)] + (val40 & 1)*256*/
diff --git a/src/mainboard/via/vt8454c/Config.lb b/src/mainboard/via/vt8454c/Config.lb
new file mode 100644
index 0000000000..5cda9d228e
--- /dev/null
+++ b/src/mainboard/via/vt8454c/Config.lb
@@ -0,0 +1,198 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2007-2009 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; 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
+##
+
+##
+## Compute the location and size of where this firmware image
+## (coreboot plus bootloader) will live in the boot rom chip.
+##
+if USE_FALLBACK_IMAGE
+ default ROM_SECTION_SIZE = FALLBACK_SIZE
+ default ROM_SECTION_OFFSET = ( ROM_SIZE - FALLBACK_SIZE )
+else
+ default ROM_SECTION_SIZE = ( ROM_SIZE - FALLBACK_SIZE )
+ default ROM_SECTION_OFFSET = 0
+end
+
+##
+## Compute the start location and size size of
+## The coreboot bootloader.
+##
+default PAYLOAD_SIZE = ( ROM_SECTION_SIZE - ROM_IMAGE_SIZE )
+default CONFIG_ROM_PAYLOAD_START = (0xffffffff - ROM_SIZE + ROM_SECTION_OFFSET + 1)
+
+##
+## Compute where this copy of coreboot will start in the boot rom
+##
+default _ROMBASE = ( CONFIG_ROM_PAYLOAD_START + PAYLOAD_SIZE )
+
+##
+## Compute a range of ROM that can cached to speed up coreboot,
+## execution speed.
+##
+## XIP_ROM_SIZE must be a power of 2.
+## XIP_ROM_BASE must be a multiple of XIP_ROM_SIZE
+##
+default XIP_ROM_SIZE=65536
+default XIP_ROM_BASE = ( _ROMBASE + ROM_IMAGE_SIZE - XIP_ROM_SIZE )
+
+##
+## Set all of the defaults for an x86 architecture
+##
+
+arch i386 end
+
+##
+## Build the objects we have code for in this directory.
+##
+
+driver mainboard.o
+
+if HAVE_MP_TABLE
+ object mptable.o
+end
+
+if HAVE_PIRQ_TABLE
+ object irq_tables.o
+end
+
+if HAVE_ACPI_TABLES
+ object fadt.o
+ object acpi_tables.o
+ makerule dsdt.c
+ depends "$(MAINBOARD)/dsdt.dsl"
+ action "iasl -p dsdt -tc $(MAINBOARD)/dsdt.dsl"
+ action "mv dsdt.hex dsdt.c"
+ end
+ object ./dsdt.o
+end
+
+##
+## Romcc output
+##
+makerule ./auto.inc
+ depends "$(MAINBOARD)/auto.c option_table.h"
+ action "$(CC) $(DISTRO_CFLAGS) $(CFLAGS) $(CPPFLAGS) $(DEBUG_CFLAGS) -I$(TOP)/src -I. -nostdinc -nostdlib -fno-builtin -Wall -Os -c -S $(MAINBOARD)/auto.c -o $@"
+ action "perl -e 's/\.rodata/.rom.data/g' -pi $@"
+ action "perl -e 's/\.text/.section .rom.text/g' -pi $@"
+end
+
+##
+## Build our 16 bit and 32 bit coreboot entry code
+##
+mainboardinit cpu/x86/16bit/entry16.inc
+mainboardinit cpu/x86/32bit/entry32.inc
+ldscript /cpu/x86/16bit/entry16.lds
+ldscript /cpu/x86/32bit/entry32.lds
+
+##
+## Build our reset vector (This is where coreboot is entered)
+##
+if USE_FALLBACK_IMAGE
+ mainboardinit cpu/x86/16bit/reset16.inc
+ ldscript /cpu/x86/16bit/reset16.lds
+else
+ mainboardinit cpu/x86/32bit/reset32.inc
+ ldscript /cpu/x86/32bit/reset32.lds
+end
+
+mainboardinit cpu/via/car/cache_as_ram.inc
+
+##
+## Include an id string (For safe flashing)
+##
+mainboardinit arch/i386/lib/id.inc
+ldscript /arch/i386/lib/id.lds
+
+###
+### O.k. We aren't just an intermediary anymore!
+###
+
+##
+## Setup RAM
+##
+mainboardinit cpu/x86/fpu/enable_fpu.inc
+mainboardinit ./auto.inc
+
+##
+## Include the secondary Configuration files
+##
+dir /pc80
+config chip.h
+
+chip northbridge/via/cx700
+ device apic_cluster 0 on
+ chip cpu/via/model_c7
+ device apic 0 on end
+ end
+ end
+ device pci_domain 0 on
+ device pci 0.0 on end # AGP Bridge
+ device pci 0.1 on end # Error Reporting
+ device pci 0.2 on end # Host Bus Control
+ device pci 0.3 on end # Memory Controller
+ device pci 0.4 on end # Power Management
+ device pci 0.7 on end # V-Link Controller
+ device pci 1.0 on # PCI Bridge
+ chip drivers/pci/onboard
+ device pci 0.0 on end
+ #register "rom_address" = "0xfffc0000" #256k image
+ register "rom_address" = "0xfff80000" #512k image
+ #register "rom_address" = "0xfff00000" #1024k image
+ end # Onboard Video
+ end # PCI Bridge
+ device pci f.0 on end # IDE/SATA
+ #device pci f.1 on end # IDE
+ device pci 10.0 on end # USB 1.1
+ device pci 10.1 on end # USB 1.1
+ device pci 10.2 on end # USB 1.1
+ device pci 10.4 on end # USB 2.0
+ device pci 11.0 on # Southbridge LPC
+ chip superio/via/vt1211
+ device pnp 2e.0 on # Floppy
+ io 0x60 = 0x3f0
+ irq 0x70 = 6
+ drq 0x74 = 2
+ end
+ device pnp 2e.1 on # Parallel Port
+ io 0x60 = 0x378
+ irq 0x70 = 7
+ drq 0x74 = 3
+ end
+ device pnp 2e.2 on # COM1
+ io 0x60 = 0x3f8
+ irq 0x70 = 4
+ end
+ device pnp 2e.3 on # COM2
+ io 0x60 = 0x2f8
+ irq 0x70 = 3
+ end
+ device pnp 2e.b on # HWM
+ io 0x60 = 0xec00
+ end
+ end # superio
+ end # pci 11.0
+ # 1-4 non existant
+ #device pci 11.5 on end # AC97 Audio
+ #device pci 11.6 off end # AC97 Modem
+ #device pci 12.0 on end # Ethernet
+ end # pci domain 0
+end # cx700
+
diff --git a/src/mainboard/via/vt8454c/Options.lb b/src/mainboard/via/vt8454c/Options.lb
new file mode 100644
index 0000000000..4a319725f1
--- /dev/null
+++ b/src/mainboard/via/vt8454c/Options.lb
@@ -0,0 +1,246 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2007-2009 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; 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
+##
+
+uses HAVE_MP_TABLE
+uses HAVE_PIRQ_TABLE
+uses IRQ_SLOT_COUNT
+uses HAVE_ACPI_TABLES
+uses HAVE_OPTION_TABLE
+uses USE_OPTION_TABLE
+
+uses USE_FALLBACK_IMAGE
+uses HAVE_FALLBACK_BOOT
+uses HAVE_HARD_RESET
+uses MAINBOARD
+uses MAINBOARD_VENDOR
+uses MAINBOARD_PART_NUMBER
+uses COREBOOT_EXTRA_VERSION
+uses ARCH
+uses FALLBACK_SIZE
+uses STACK_SIZE
+uses HEAP_SIZE
+uses ROM_SIZE
+uses ROM_SECTION_SIZE
+uses ROM_IMAGE_SIZE
+uses ROM_SECTION_SIZE
+uses ROM_SECTION_OFFSET
+
+uses CONFIG_COMPRESS
+uses CONFIG_ROM_PAYLOAD
+uses CONFIG_ROM_PAYLOAD_START
+uses CONFIG_COMPRESSED_PAYLOAD_NRV2B
+uses CONFIG_COMPRESSED_PAYLOAD_LZMA
+uses PAYLOAD_SIZE
+
+uses _ROMBASE
+uses _RAMBASE
+uses XIP_ROM_SIZE
+uses XIP_ROM_BASE
+uses CONFIG_CBFS
+
+# compiler specifics
+uses CROSS_COMPILE
+uses CC
+uses HOSTCC
+uses OBJCOPY
+
+# Console specifics
+uses DEFAULT_CONSOLE_LOGLEVEL
+uses MAXIMUM_CONSOLE_LOGLEVEL
+uses CONFIG_CONSOLE_SERIAL8250
+uses TTYS0_BAUD
+uses TTYS0_BASE
+uses TTYS0_LCS
+
+uses CONFIG_UDELAY_TSC
+uses CONFIG_TSC_X86RDTSC_CALIBRATE_WITH_TIMER2
+uses CONFIG_PCI_ROM_RUN
+uses CONFIG_CONSOLE_VGA
+uses CONFIG_MAX_PCI_BUSES
+uses CONFIG_SMP
+uses CONFIG_IOAPIC
+
+uses CONFIG_GDB_STUB
+
+uses USE_DCACHE_RAM
+uses DCACHE_RAM_BASE
+uses DCACHE_RAM_SIZE
+uses CONFIG_USE_PRINTK_IN_CAR
+
+## ROM_SIZE is the size of boot ROM that this board will use.
+default ROM_SIZE = 256*1024
+
+default USE_DCACHE_RAM=1
+default DCACHE_RAM_BASE=0xffef0000
+#default DCACHE_RAM_BASE=0xffbf0000
+#default DCACHE_RAM_BASE=0xfec00000
+default DCACHE_RAM_SIZE=0x8000
+default CONFIG_USE_PRINTK_IN_CAR=1
+
+###
+### Leave this to 0; VGA is handled by seperate code.
+###
+default CONFIG_PCI_ROM_RUN=0
+default CONFIG_CONSOLE_VGA=0
+
+##
+## Build code for the fallback boot
+##
+default HAVE_FALLBACK_BOOT=1
+
+##
+## Use TSC for udelay.
+##
+default CONFIG_UDELAY_TSC=1
+default CONFIG_TSC_X86RDTSC_CALIBRATE_WITH_TIMER2=1
+
+##
+## Build code to reset the motherboard from linuxBIOS
+##
+default HAVE_HARD_RESET=1
+
+##
+## Build code to export a programmable irq routing table
+##
+default HAVE_PIRQ_TABLE=1
+default IRQ_SLOT_COUNT=15
+
+##
+## Build code to export an x86 MP table
+## Useful for specifying IRQ routing values
+##
+default HAVE_MP_TABLE=1
+
+##
+## Build code to load acpi tables
+##
+default HAVE_ACPI_TABLES=1
+
+##
+## Build code to export a CMOS option table
+##
+default HAVE_OPTION_TABLE=1
+
+
+##
+## Build code to setup a generic IOAPIC
+##
+default CONFIG_SMP=1
+default CONFIG_IOAPIC=1
+
+###
+### LinuxBIOS layout values
+###
+
+## ROM_IMAGE_SIZE is the amount of space to allow linuxBIOS to occupy.
+default ROM_IMAGE_SIZE = 65536
+default FALLBACK_SIZE = 131072
+
+##
+## Use a small 8K stack
+##
+default STACK_SIZE=0x2000
+
+##
+## Use a small 16K heap
+##
+default HEAP_SIZE=0x4000
+
+##
+## Only use the option table in a normal image
+##
+#default USE_OPTION_TABLE = !USE_FALLBACK_IMAGE
+default USE_OPTION_TABLE = 0
+
+default _RAMBASE = 0x00004000
+
+default CONFIG_ROM_PAYLOAD = 1
+
+##
+## The default compiler
+##
+default CROSS_COMPILE=""
+default CC="$(CROSS_COMPILE)gcc -m32"
+default HOSTCC="gcc"
+
+##
+## Set this to the max PCI bus number you
+## would ever use for PCI config IO.
+## Setting this number very high will make
+## pci_locate_device take a long time when
+## it can't find a device.
+##
+default CONFIG_MAX_PCI_BUSES = 0x80
+
+##
+## Disable the gdb stub by default
+##
+default CONFIG_GDB_STUB=0
+
+##
+## The Serial Console
+##
+
+# To Enable the Serial Console
+default CONFIG_CONSOLE_SERIAL8250=1
+
+## Select the serial console baud rate
+default TTYS0_BAUD=115200
+#default TTYS0_BAUD=57600
+#default TTYS0_BAUD=38400
+#default TTYS0_BAUD=19200
+#default TTYS0_BAUD=9600
+#default TTYS0_BAUD=4800
+#default TTYS0_BAUD=2400
+#default TTYS0_BAUD=1200
+
+# Select the serial console base port
+default TTYS0_BASE=0x3f8
+
+# Select the serial protocol
+# This defaults to 8 data bits, 1 stop bit, and no parity
+default TTYS0_LCS=0x3
+
+##
+## Select the coreboot loglevel
+##
+## EMERG 1 system is unusable
+## ALERT 2 action must be taken immediately
+## CRIT 3 critical conditions
+## ERR 4 error conditions
+## WARNING 5 warning conditions
+## NOTICE 6 normal but significant condition
+## INFO 7 informational
+## DEBUG 8 debug-level messages
+## SPEW 9 Way too many details
+
+## Request this level of debugging output
+default DEFAULT_CONSOLE_LOGLEVEL=5
+## At a maximum only compile in this level of debugging
+default MAXIMUM_CONSOLE_LOGLEVEL=5
+
+#
+# CBFS
+#
+default CONFIG_CBFS=0
+
+end
+
diff --git a/src/mainboard/via/vt8454c/acpi_tables.c b/src/mainboard/via/vt8454c/acpi_tables.c
new file mode 100644
index 0000000000..edf8d7e207
--- /dev/null
+++ b/src/mainboard/via/vt8454c/acpi_tables.c
@@ -0,0 +1,205 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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 <string.h>
+#include <console/console.h>
+#include <arch/acpi.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include "dmi.h"
+
+extern unsigned char AmlCode[];
+
+unsigned long acpi_fill_mcfg(unsigned long current)
+{
+ device_t dev;
+ u64 mmcfg;
+
+ dev = dev_find_device(0x1106, 0x324b, 0); // 0:0x13.0
+ if (!dev)
+ return current;
+
+ // MMCFG not supported or not enabled.
+ if ((pci_read_config8(dev, 0x40) & 0xC0) != 0xC0)
+ return current;
+
+ mmcfg = ((u64) pci_read_config8(dev, 0x41)) << 28;
+ if (!mmcfg)
+ return current;
+
+ current += acpi_create_mcfg_mmconfig((acpi_mcfg_mmconfig_t *) current, mmcfg, 0x0, 0x0, 0xff);
+
+ return current;
+}
+
+
+void acpi_create_via_hpet(acpi_hpet_t * hpet)
+{
+#define HPET_ADDR 0xfe800000ULL
+ acpi_header_t *header = &(hpet->header);
+ acpi_addr_t *addr = &(hpet->addr);
+
+ memset((void *) hpet, 0, sizeof(acpi_hpet_t));
+
+ /* fill out header fields */
+ memcpy(header->signature, HPET_NAME, 4);
+ memcpy(header->oem_id, OEM_ID, 6);
+ memcpy(header->oem_table_id, "COREBOOT", 8);
+ memcpy(header->asl_compiler_id, ASLC, 4);
+
+ header->length = sizeof(acpi_hpet_t);
+ header->revision = 1;
+
+ /* fill out HPET address */
+ // XXX factory bios just puts an address here -- who's right?
+ addr->space_id = 0; /* Memory */
+ addr->bit_width = 64;
+ addr->bit_offset = 0;
+ addr->addrl = HPET_ADDR & 0xffffffff;
+ addr->addrh = HPET_ADDR >> 32;
+
+ hpet->id = 0x11068201; /* VIA */
+ hpet->number = 0x00;
+ hpet->min_tick = 0x0090;
+
+ header->checksum =
+ acpi_checksum((void *) hpet, sizeof(acpi_hpet_t));
+}
+
+
+
+#define IO_APIC_ADDR 0xfec00000UL
+
+unsigned long acpi_fill_madt(unsigned long current)
+{
+ /* Local Apic */
+ current += acpi_create_madt_lapic((acpi_madt_lapic_t *) current, 0, 0);
+
+ /* IOAPIC */
+ current += acpi_create_madt_ioapic((acpi_madt_ioapic_t *) current, 2, IO_APIC_ADDR, 0);
+
+ /* INT_SRC_OVR */
+ current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) current, 0, 0, 2, 0);
+ current += acpi_create_madt_irqoverride((acpi_madt_irqoverride_t *) current, 0, 9, 9, 0x000f); // low/level
+
+ /* LAPIC_NMI */
+ current += acpi_create_madt_lapic_nmi((acpi_madt_lapic_nmi_t *) current, 0, 0x0005, 1); // high/edge
+
+ return current;
+}
+
+unsigned long acpi_fill_slit(unsigned long current)
+{
+ // Not implemented
+ return current;
+}
+
+unsigned long acpi_fill_srat(unsigned long current)
+{
+ /* No NUMA, no SRAT */
+ return current;
+}
+
+unsigned long write_acpi_tables(unsigned long start)
+{
+ unsigned long current;
+ acpi_rsdp_t *rsdp;
+ acpi_rsdt_t *rsdt;
+ acpi_hpet_t *hpet;
+ acpi_madt_t *madt;
+ acpi_mcfg_t *mcfg;
+ acpi_fadt_t *fadt;
+ acpi_facs_t *facs;
+ acpi_header_t *dsdt;
+
+ /* Align ACPI tables to 16byte */
+ start = (start + 0x0f) & -0x10;
+ current = start;
+
+ printk_info("ACPI: Writing ACPI tables at %lx.\n", start);
+
+ /* We need at least an RSDP and an RSDT Table */
+ rsdp = (acpi_rsdp_t *) current;
+ current += sizeof(acpi_rsdp_t);
+ rsdt = (acpi_rsdt_t *) current;
+ current += sizeof(acpi_rsdt_t);
+
+ /* clear all table memory */
+ memset((void *) start, 0, current - start);
+
+ acpi_write_rsdp(rsdp, rsdt);
+ acpi_write_rsdt(rsdt);
+
+ /*
+ * We explicitly add these tables later on:
+ */
+
+ printk_debug("ACPI: * HPET\n");
+
+ hpet = (acpi_hpet_t *) current;
+ current += sizeof(acpi_hpet_t);
+ acpi_create_via_hpet(hpet);
+ acpi_add_table(rsdt, hpet);
+
+ /* If we want to use HPET Timers Linux wants an MADT */
+ printk_debug("ACPI: * MADT\n");
+
+ madt = (acpi_madt_t *) current;
+ acpi_create_madt(madt);
+ current += madt->header.length;
+ acpi_add_table(rsdt, madt);
+
+ printk_debug("ACPI: * MCFG\n");
+ mcfg = (acpi_mcfg_t *) current;
+ acpi_create_mcfg(mcfg);
+ current += mcfg->header.length;
+ acpi_add_table(rsdt, mcfg);
+
+ printk_debug("ACPI: * FACS\n");
+ facs = (acpi_facs_t *) current;
+ current += sizeof(acpi_facs_t);
+ acpi_create_facs(facs);
+
+ dsdt = (acpi_header_t *) current;
+ current += ((acpi_header_t *) AmlCode)->length;
+ memcpy((void *) dsdt, (void *) AmlCode,
+ ((acpi_header_t *) AmlCode)->length);
+#if DONT_TRUST_IASL
+ dsdt->checksum = 0; // don't trust intel iasl compiler to get this right
+ dsdt->checksum = acpi_checksum(dsdt, dsdt->length);
+#endif
+ printk_debug("ACPI: * DSDT @ %08x Length %x\n", dsdt,
+ dsdt->length);
+ printk_debug("ACPI: * FADT\n");
+
+ fadt = (acpi_fadt_t *) current;
+ current += sizeof(acpi_fadt_t);
+
+ acpi_create_fadt(fadt, facs, dsdt);
+ acpi_add_table(rsdt, fadt);
+
+ printk_debug("ACPI: * DMI (Linux workaround)\n");
+ memcpy((void *)0xfff80, dmi_table, DMI_TABLE_SIZE);
+
+ printk_info("ACPI: done.\n");
+ return current;
+}
diff --git a/src/mainboard/via/vt8454c/auto.c b/src/mainboard/via/vt8454c/auto.c
new file mode 100644
index 0000000000..1812fca139
--- /dev/null
+++ b/src/mainboard/via/vt8454c/auto.c
@@ -0,0 +1,127 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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
+ */
+
+#define ASSEMBLY 1
+
+#include <stdint.h>
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <arch/io.h>
+#include <device/pnp_def.h>
+#include <arch/romcc_io.h>
+#include <arch/hlt.h>
+#include "pc80/serial.c"
+#include "arch/i386/lib/console.c"
+#include "ram/ramtest.c"
+#include "northbridge/via/cx700/raminit.h"
+#include "cpu/x86/mtrr/earlymtrr.c"
+#include "cpu/x86/bist.h"
+
+#define CONFIG_DEACTIVATE_CAR 1
+#define CONFIG_DEACTIVATE_CAR_FILE "cpu/via/car/cache_as_ram_post.c"
+#include "cpu/x86/car/copy_and_run.c"
+#include "pc80/udelay_io.c"
+#include "lib/delay.c"
+#include "cpu/x86/lapic/boot_cpu.c"
+#include "northbridge/via/cx700/cx700_early_smbus.c"
+#include "debug.c"
+
+#include "northbridge/via/cx700/cx700_early_serial.c"
+#include "northbridge/via/cx700/raminit.c"
+
+static void enable_mainboard_devices(void)
+{
+ device_t dev;
+
+ dev = pci_locate_device(PCI_ID(0x1106, 0x8324), 0);
+ if (dev == PCI_DEV_INVALID) {
+ die("LPC bridge not found!!!\n");
+ }
+ // Disable GP3
+ pci_write_config8(dev, 0x98, 0x00);
+
+ // Disable mc97
+ pci_write_config8(dev, 0x50, 0x80);
+
+ // Disable internal KBC Configuration
+ pci_write_config8(dev, 0x51, 0x2d);
+ pci_write_config8(dev, 0x58, 0x42);
+ pci_write_config8(dev, 0x59, 0x80);
+ pci_write_config8(dev, 0x5b, 0x01);
+
+ // Enable P2P Bridge Header for External PCI BUS.
+ dev = pci_locate_device(PCI_ID(0x1106, 0x324e), 0);
+ if (dev == PCI_DEV_INVALID) {
+ die("P2P bridge not found!!!\n");
+ }
+ pci_write_config8(dev, 0x4f, 0x41);
+
+ // Switch SATA to non-RAID mode
+ dev = pci_locate_device(PCI_ID(0x1106, 0x0581), 0);
+ if (dev != PCI_DEV_INVALID) {
+ pci_write_config16(dev, 0xBA, 0x5324);
+ }
+}
+
+static void enable_shadow_ram(const struct mem_controller *ctrl)
+{
+ u8 shadowreg;
+
+ pci_write_config8(PCI_DEV(0, 0, 3), 0x80, 0x2a);
+
+ /* 0xf0000-0xfffff - ACPI tables */
+ shadowreg = pci_read_config8(PCI_DEV(0, 0, 3), 0x83);
+ shadowreg |= 0x30;
+ pci_write_config8(PCI_DEV(0, 0, 3), 0x83, shadowreg);
+}
+
+static void main(unsigned long bist)
+{
+ /* Set statically so it should work with cx700 as well */
+ static const struct mem_controller cx700[] = {
+ {
+ .channel0 = {0x50, 0x51},
+ },
+ };
+
+ enable_smbus();
+
+ enable_cx700_serial();
+ uart_init();
+ console_init();
+
+ /* Halt if there was a built in self test failure */
+ report_bist_failure(bist);
+
+ enable_mainboard_devices();
+
+ /* Allows access to all northbridge devices */
+ pci_write_config8(PCI_DEV(0, 0, 0), 0x4f, 0x01);
+
+ sdram_set_registers(cx700);
+ enable_shadow_ram(cx700);
+ sdram_enable(cx700);
+ copy_and_run(0);
+}
+
+void amd64_main(unsigned long bist) {
+ main(bist);
+}
diff --git a/src/mainboard/via/vt8454c/chip.h b/src/mainboard/via/vt8454c/chip.h
new file mode 100644
index 0000000000..ac8c5eb62d
--- /dev/null
+++ b/src/mainboard/via/vt8454c/chip.h
@@ -0,0 +1,26 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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
+ */
+
+extern struct chip_operations mainboard_ops;
+
+struct mainboard_config {
+ int nothing;
+};
diff --git a/src/mainboard/via/vt8454c/cmos.layout b/src/mainboard/via/vt8454c/cmos.layout
new file mode 100644
index 0000000000..e80bb94d9d
--- /dev/null
+++ b/src/mainboard/via/vt8454c/cmos.layout
@@ -0,0 +1,67 @@
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2007-2009 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; 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
+##
+
+entries
+
+#start-bit length config config-ID name
+0 384 r 0 reserved_memory
+384 1 e 4 boot_option
+385 1 e 4 last_boot
+386 1 e 1 ECC_memory
+388 4 r 0 reboot_bits
+392 3 e 5 baud_rate
+400 1 e 1 power_on_after_fail
+412 4 e 6 debug_level
+1008 16 h 0 check_sum
+
+enumerations
+
+#ID value text
+1 0 Disable
+1 1 Enable
+2 0 Enable
+2 1 Disable
+4 0 Fallback
+4 1 Normal
+5 0 115200
+5 1 57600
+5 2 38400
+5 3 19200
+5 4 9600
+5 5 4800
+5 6 2400
+5 7 1200
+6 6 Notice
+6 7 Info
+6 8 Debug
+6 9 Spew
+7 0 Network
+7 1 HDD
+7 2 Floppy
+7 8 Fallback_Network
+7 9 Fallback_HDD
+7 10 Fallback_Floppy
+#7 3 ROM
+
+checksums
+
+checksum 392 1007 1008
+
+
diff --git a/src/mainboard/via/vt8454c/debug.c b/src/mainboard/via/vt8454c/debug.c
new file mode 100644
index 0000000000..54d8cf34e5
--- /dev/null
+++ b/src/mainboard/via/vt8454c/debug.c
@@ -0,0 +1,108 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * (C) 2007-2009 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; 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
+ */
+
+static void print_debug_pci_dev(unsigned dev)
+{
+ print_debug("PCI: ");
+ print_debug_hex8((dev >> 16) & 0xff);
+ print_debug_char(':');
+ print_debug_hex8((dev >> 11) & 0x1f);
+ print_debug_char('.');
+ print_debug_hex8((dev >> 8) & 7);
+}
+
+static void print_pci_devices(void)
+{
+ device_t dev;
+ for (dev = PCI_DEV(0, 0, 0);
+ dev <= PCI_DEV(0, 0x1f, 0x7); dev += PCI_DEV(0, 0, 1)) {
+ u32 id;
+ id = pci_read_config32(dev, PCI_VENDOR_ID);
+ if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff)
+ || (((id >> 16) & 0xffff) == 0xffff)
+ || (((id >> 16) & 0xffff) == 0x0000)) {
+ continue;
+ }
+ print_debug_pci_dev(dev);
+ print_debug("\r\n");
+ }
+}
+
+static void dump_pci_device(unsigned dev)
+{
+ int i;
+ print_debug_pci_dev(dev);
+ print_debug("\r\n");
+
+ for (i = 0; i <= 255; i++) {
+ unsigned char val;
+ if ((i & 0x0f) == 0) {
+ print_debug_hex8(i);
+ print_debug_char(':');
+ }
+ val = pci_read_config8(dev, i);
+ print_debug_char(' ');
+ print_debug_hex8(val);
+ if ((i & 0x0f) == 0x0f) {
+ print_debug("\r\n");
+ }
+ }
+}
+
+static void dump_pci_devices(void)
+{
+ device_t dev;
+ for (dev = PCI_DEV(0, 0, 0);
+ dev <= PCI_DEV(0, 0x1f, 0x7); dev += PCI_DEV(0, 0, 1)) {
+ u32 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 void dump_io_resources(unsigned port)
+{
+
+ int i;
+ udelay(2000);
+ print_debug_hex16(port);
+ print_debug(":\r\n");
+ for (i = 0; i < 256; i++) {
+ u8 val;
+ if ((i & 0x0f) == 0) {
+ print_debug_hex8(i);
+ print_debug_char(':');
+ }
+ val = inb(port);
+ print_debug_char(' ');
+ print_debug_hex8(val);
+ if ((i & 0x0f) == 0x0f) {
+ print_debug("\r\n");
+ }
+ port++;
+ }
+}
diff --git a/src/mainboard/via/vt8454c/dmi.h b/src/mainboard/via/vt8454c/dmi.h
new file mode 100644
index 0000000000..17563f24c8
--- /dev/null
+++ b/src/mainboard/via/vt8454c/dmi.h
@@ -0,0 +1,31 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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
+ */
+
+#define DMI_TABLE_SIZE 0x55
+
+static u8 dmi_table[DMI_TABLE_SIZE] = {
+ 0x5f, 0x53, 0x4d, 0x5f, 0x2d, 0x1f, 0x02, 0x03, 0x51, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x5f, 0x44, 0x4d, 0x49, 0x5f, 0xeb, 0xa8, 0x03, 0xa0, 0xff, 0x0f, 0x00, 0x01, 0x00, 0x23, 0x00,
+ 0x00, 0x14, 0x00, 0x00, 0x01, 0x02, 0x00, 0xe0, 0x03, 0x07, 0x90, 0xde, 0xcb, 0x7f, 0x00, 0x00,
+ 0x00, 0x00, 0x37, 0x01, 0x63, 0x6f, 0x72, 0x65, 0x73, 0x79, 0x73, 0x74, 0x65, 0x6d, 0x73, 0x20,
+ 0x47, 0x6d, 0x62, 0x48, 0x00, 0x32, 0x2e, 0x30, 0x00, 0x30, 0x33, 0x2f, 0x31, 0x33, 0x2f, 0x32,
+ 0x30, 0x30, 0x38, 0x00, 0x00
+};
diff --git a/src/mainboard/via/vt8454c/dsdt.dsl b/src/mainboard/via/vt8454c/dsdt.dsl
new file mode 100644
index 0000000000..150fbcf5f9
--- /dev/null
+++ b/src/mainboard/via/vt8454c/dsdt.dsl
@@ -0,0 +1,341 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2004 Nick Barker <Nick.Barker9@btinternet.com>
+ * Copyright (C) 2007-2009 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; 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
+ */
+
+DefinitionBlock ("dsdt.aml", "DSDT", 1, "CX700 ", "COREBOOT", 0x00000001)
+{
+ /*
+ * Define the main processor
+ */
+ Scope (\_PR)
+ {
+ Processor (\_PR.CPU0, 0x00, 0x00000410, 0x06) {}
+ }
+
+ /* For now only define 2 power states:
+ * - S0 which is fully on
+ * - S5 which is soft off
+ * any others would involve declaring the wake up methods
+ */
+ Name (\_S0, Package () {0x00, 0x00, 0x00, 0x00 })
+ Name (\_S5, Package () {0x02, 0x02, 0x00, 0x00 })
+
+ Scope (\) {
+ Name (PICF , 0) // Global flag indicating whether to use PIC or APIC mode
+ Method ( _PIC,1) // The OS is calling this
+ {
+ Store( Arg0 , PICF)
+ }
+ } // end of \ scope
+
+ /* Root of the bus hierarchy */
+ Scope (\_SB)
+ {
+ /* Define how interrupt Link A is plumbed in */
+ Device (LNKA)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x01)
+
+ /* Status - always return ready */
+ Method (_STA, 0, NotSerialized)
+ {
+ Return (0x0B)
+ }
+
+ /* Current Resources - return irq set up in BIOS */
+ Method (_CRS, 0, NotSerialized)
+ {
+ Name (CRSP, ResourceTemplate () {
+ IRQ (Level, ActiveLow, Shared) {11}
+ })
+ Name (CRSA, ResourceTemplate () {
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared) {16}
+ })
+
+ If (LNot (PICF)) {
+ Return (CRSP)
+ } Else {
+ Return (CRSA)
+ }
+ }
+ /* Possible Resources - return the range of irqs
+ * we are using for PCI - only here to keep Linux ACPI
+ * happy
+ */
+ Method (_PRS, 0, NotSerialized)
+ {
+ Name (PRSP, ResourceTemplate () {
+ IRQ (Level, ActiveLow, Shared) {3,4,6,7,10,11,12}
+ })
+ Name (PRSA, ResourceTemplate () {
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared) {16,17,18,19,20,21,22,23}
+ })
+
+ If (LNot (PICF)) {
+ Return (PRSP)
+ } Else {
+ Return (PRSA)
+ }
+
+ }
+ /* Set Resources - dummy function to keep Linux ACPI happy
+ * Linux is more than happy not to tinker with irq
+ * assignments as long as the CRS and STA functions
+ * return good values
+ */
+ Method (_SRS, 1, NotSerialized ) {}
+ /* Disable - dummy function to keep Linux ACPI happy */
+ Method (_DIS, 0, NotSerialized ) {}
+
+ } // End of LNKA
+
+ /* Define how interrupt Link B is plumbed in */
+ Device (LNKB)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x02)
+
+ /* Status - always return ready */
+ Method (_STA, 0, NotSerialized)
+ {
+ Return (0x0B)
+ }
+
+ /* Current Resources - return irq set up in BIOS */
+ Method (_CRS, 0, NotSerialized)
+ {
+ Name (CRSP, ResourceTemplate () {
+ IRQ (Level, ActiveLow, Shared) {11}
+ })
+ Name (CRSA, ResourceTemplate () {
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared) {17}
+ })
+
+ If (LNot (PICF)) {
+ Return (CRSP)
+ } Else {
+ Return (CRSA)
+ }
+ }
+ /* Possible Resources - return the range of irqs
+ * we are using for PCI - only here to keep Linux ACPI
+ * happy
+ */
+ Method (_PRS, 0, NotSerialized)
+ {
+ Name (PRSP, ResourceTemplate () {
+ IRQ (Level, ActiveLow, Shared) {3,4,6,7,10,11,12}
+ })
+ Name (PRSA, ResourceTemplate () {
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared) {16,17,18,19,20,21,22,23}
+ })
+
+ If (LNot (PICF)) {
+ Return (PRSP)
+ } Else {
+ Return (PRSA)
+ }
+
+ }
+
+ /* Set Resources - dummy function to keep Linux ACPI happy
+ * Linux is more than happy not to tinker with irq
+ * assignments as long as the CRS and STA functions
+ * return good values
+ */
+ Method (_SRS, 1, NotSerialized ) {}
+ /* Disable - dummy function to keep Linux ACPI happy */
+ Method (_DIS, 0, NotSerialized ) {}
+
+ } // End of LNKB
+
+ /* Define how interrupt Link C is plumbed in */
+ Device (LNKC)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x03)
+
+ /* Status - always return ready */
+ Method (_STA, 0, NotSerialized)
+ {
+ Return (0x0B)
+ }
+
+ /* Current Resources - return irq set up in BIOS */
+ Method (_CRS, 0, NotSerialized)
+ {
+ Name (CRSP, ResourceTemplate () {
+ IRQ (Level, ActiveLow, Shared) {10}
+ })
+ Name (CRSA, ResourceTemplate () {
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared) {18}
+ })
+
+ If (LNot (PICF)) {
+ Return (CRSP)
+ } Else {
+ Return (CRSA)
+ }
+ }
+ /* Possible Resources - return the range of irqs
+ * we are using for PCI - only here to keep Linux ACPI
+ * happy
+ */
+ Method (_PRS, 0, NotSerialized)
+ {
+ Name (PRSP, ResourceTemplate () {
+ IRQ (Level, ActiveLow, Shared) {3,4,6,7,10,11,12}
+ })
+ Name (PRSA, ResourceTemplate () {
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared) {16,17,18,19,20,21,22,23}
+ })
+
+ If (LNot (PICF)) {
+ Return (PRSP)
+ } Else {
+ Return (PRSA)
+ }
+
+ }
+
+ /* Set Resources - dummy function to keep Linux ACPI happy
+ * Linux is more than happy not to tinker with irq
+ * assignments as long as the CRS and STA functions
+ * return good values
+ */
+ Method (_SRS, 1, NotSerialized ) {}
+ /* Disable - dummy function to keep Linux ACPI happy */
+ Method (_DIS, 0, NotSerialized ) {}
+
+ } // End of LNKC
+
+ /* Define how interrupt Link D is plumbed in */
+ Device (LNKD)
+ {
+ Name (_HID, EisaId ("PNP0C0F"))
+ Name (_UID, 0x04)
+
+ /* Status - always return ready */
+ Method (_STA, 0, NotSerialized)
+ {
+ Return (0x0B)
+ }
+
+ /* Current Resources - return irq set up in BIOS */
+ Method (_CRS, 0, NotSerialized)
+ {
+ Name (CRSP, ResourceTemplate () {
+ IRQ (Level, ActiveLow, Shared) {10}
+ })
+ Name (CRSA, ResourceTemplate () {
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared) {19}
+ })
+
+ If (LNot (PICF)) {
+ Return (CRSP)
+ } Else {
+ Return (CRSA)
+ }
+ }
+ /* Possible Resources - return the range of irqs
+ * we are using for PCI - only here to keep Linux ACPI
+ * happy
+ */
+ Method (_PRS, 0, NotSerialized)
+ {
+ Name (PRSP, ResourceTemplate () {
+ IRQ (Level, ActiveLow, Shared) {3,4,6,7,10,11,12}
+ })
+ Name (PRSA, ResourceTemplate () {
+ Interrupt (ResourceConsumer, Level, ActiveLow, Shared) {16,17,18,19,20,21,22,23}
+ })
+
+ If (LNot (PICF)) {
+ Return (PRSP)
+ } Else {
+ Return (PRSA)
+ }
+
+ }
+
+ /* Set Resources - dummy function to keep Linux ACPI happy
+ * Linux is more than happy not to tinker with irq
+ * assignments as long as the CRS and STA functions
+ * return good values
+ */
+ Method (_SRS, 1, NotSerialized ) {}
+ /* Disable - dummy function to keep Linux ACPI happy */
+ Method (_DIS, 0, NotSerialized ) {}
+
+ } // End of LNKD
+
+ /* PCI Root Bridge */
+ Device (PCI0)
+ {
+ Name (_HID, EisaId ("PNP0A08"))
+ Name (_CID, EisaId ("PNP0A03"))
+ Name (_ADR, 0x00)
+ Name (_UID, 0x00)
+ Name (_BBN, 0x00)
+
+ // Mainboard specific IRQ routing
+ Include ("irq.dsl")
+
+ /* PCI Routing Table */
+ Method (_PRT, 0, NotSerialized)
+ {
+ If (LNot (PICF))
+ {
+ Return (PICM)
+ }
+ Else
+ {
+ Return (APIC)
+ }
+ }
+
+ Device (P2PB) /* PCI to PCI bridge */
+ {
+ Name (_ADR, 0x00130001)
+
+ Include ("irq-p2p-bridge.dsl")
+ Method (_PRT, 0, NotSerialized)
+ {
+ If (LNot (PICF))
+ {
+ Return (PICM)
+ }
+ Else
+ {
+ Return (APIC)
+ }
+ }
+ /* Status - always return ready */
+ Method (_STA, 0, NotSerialized)
+ {
+ Return (0x0F)
+ }
+ }
+ } // End of PCI0
+ } // End of _SB
+} // End of Definition Block
+
diff --git a/src/mainboard/via/vt8454c/fadt.c b/src/mainboard/via/vt8454c/fadt.c
new file mode 100644
index 0000000000..3954974075
--- /dev/null
+++ b/src/mainboard/via/vt8454c/fadt.c
@@ -0,0 +1,156 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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 <string.h>
+#include <arch/acpi.h>
+
+void acpi_create_fadt(acpi_fadt_t * fadt, acpi_facs_t * facs, void *dsdt)
+{
+ acpi_header_t *header = &(fadt->header);
+
+ memset((void *) fadt, 0, sizeof(acpi_fadt_t));
+ memcpy(header->signature, "FACP", 4);
+ header->length = 244;
+ header->revision = 1;
+ memcpy(header->oem_id, "CX700 ", 6);
+ memcpy(header->oem_table_id, "COREBOOT", 8);
+ memcpy(header->asl_compiler_id, "CORE", 4);
+ header->asl_compiler_revision = 0;
+
+ fadt->firmware_ctrl = (unsigned long) facs;
+ fadt->dsdt = (unsigned long) dsdt;
+ fadt->preferred_pm_profile = 0;
+ fadt->sci_int = 0x9;
+ fadt->smi_cmd = 0x0;
+ fadt->acpi_enable = 0xA1;
+ fadt->acpi_disable = 0xA0;
+ fadt->s4bios_req = 0x0;
+ fadt->pstate_cnt = 0x0;
+
+ fadt->pm1a_evt_blk = 0x400;
+ fadt->pm1b_evt_blk = 0x0;
+ fadt->pm1a_cnt_blk = 0x404;
+ fadt->pm1b_cnt_blk = 0x0;
+ fadt->pm2_cnt_blk = 0x22;
+ fadt->pm_tmr_blk = 0x408;
+ fadt->gpe0_blk = 0x420;
+ fadt->gpe1_blk = 0x450;
+
+ fadt->pm1_evt_len = 4;
+ fadt->pm1_cnt_len = 2;
+ fadt->pm2_cnt_len = 1;
+ fadt->pm_tmr_len = 4;
+ fadt->gpe0_blk_len = 4;
+ fadt->gpe1_blk_len = 4;
+ fadt->gpe1_base = 0x10;
+ fadt->cst_cnt = 0;
+ fadt->p_lvl2_lat = 101;
+ fadt->p_lvl3_lat = 1001;
+ fadt->flush_size = 0;
+ fadt->flush_stride = 0;
+ fadt->duty_offset = 0;
+ fadt->duty_width = 1;
+ fadt->day_alrm = 0x7d;
+ fadt->mon_alrm = 0x7e;
+ fadt->century = 0x32;
+ fadt->iapc_boot_arch = 0x0;
+ fadt->flags = 0x44a5;
+
+ fadt->reset_reg.space_id = 0;
+ fadt->reset_reg.bit_width = 0;
+ fadt->reset_reg.bit_offset = 0;
+ fadt->reset_reg.resv = 0;
+ fadt->reset_reg.addrl = 0x0;
+ fadt->reset_reg.addrh = 0x0;
+
+ fadt->reset_value = 0;
+ fadt->x_firmware_ctl_l = (unsigned long) facs;
+ fadt->x_firmware_ctl_h = 0;
+ fadt->x_dsdt_l = (unsigned long) dsdt;
+ fadt->x_dsdt_h = 0;
+
+ fadt->x_pm1a_evt_blk.space_id = 1;
+ fadt->x_pm1a_evt_blk.bit_width = 4;
+ fadt->x_pm1a_evt_blk.bit_offset = 0;
+ fadt->x_pm1a_evt_blk.resv = 0;
+ fadt->x_pm1a_evt_blk.addrl = 0x400;
+ fadt->x_pm1a_evt_blk.addrh = 0x0;
+
+
+ fadt->x_pm1b_evt_blk.space_id = 1;
+ fadt->x_pm1b_evt_blk.bit_width = 4;
+ fadt->x_pm1b_evt_blk.bit_offset = 0;
+ fadt->x_pm1b_evt_blk.resv = 0;
+ fadt->x_pm1b_evt_blk.addrl = 0x0;
+ fadt->x_pm1b_evt_blk.addrh = 0x0;
+
+
+ fadt->x_pm1a_cnt_blk.space_id = 1;
+ fadt->x_pm1a_cnt_blk.bit_width = 2;
+ fadt->x_pm1a_cnt_blk.bit_offset = 0;
+ fadt->x_pm1a_cnt_blk.resv = 0;
+ fadt->x_pm1a_cnt_blk.addrl = 0x404;
+ fadt->x_pm1a_cnt_blk.addrh = 0x0;
+
+
+ fadt->x_pm1b_cnt_blk.space_id = 1;
+ fadt->x_pm1b_cnt_blk.bit_width = 2;
+ fadt->x_pm1b_cnt_blk.bit_offset = 0;
+ fadt->x_pm1b_cnt_blk.resv = 0;
+ fadt->x_pm1b_cnt_blk.addrl = 0x0;
+ fadt->x_pm1b_cnt_blk.addrh = 0x0;
+
+
+ fadt->x_pm2_cnt_blk.space_id = 1;
+ fadt->x_pm2_cnt_blk.bit_width = 0;
+ fadt->x_pm2_cnt_blk.bit_offset = 0;
+ fadt->x_pm2_cnt_blk.resv = 0;
+ fadt->x_pm2_cnt_blk.addrl = 0x0;
+ fadt->x_pm2_cnt_blk.addrh = 0x0;
+
+
+ fadt->x_pm_tmr_blk.space_id = 1;
+ fadt->x_pm_tmr_blk.bit_width = 4;
+ fadt->x_pm_tmr_blk.bit_offset = 0;
+ fadt->x_pm_tmr_blk.resv = 0;
+ fadt->x_pm_tmr_blk.addrl = 0x408;
+ fadt->x_pm_tmr_blk.addrh = 0x0;
+
+
+ fadt->x_gpe0_blk.space_id = 1;
+ fadt->x_gpe0_blk.bit_width = 0;
+ fadt->x_gpe0_blk.bit_offset = 0;
+ fadt->x_gpe0_blk.resv = 0;
+ fadt->x_gpe0_blk.addrl = 0x420;
+ fadt->x_gpe0_blk.addrh = 0x0;
+
+
+ fadt->x_gpe1_blk.space_id = 1;
+ fadt->x_gpe1_blk.bit_width = 0;
+ fadt->x_gpe1_blk.bit_offset = 0;
+ fadt->x_gpe1_blk.resv = 0;
+ fadt->x_gpe1_blk.addrl = 0x0;
+ fadt->x_gpe1_blk.addrh = 0x0;
+
+ header->checksum =
+ acpi_checksum((void *) fadt, sizeof(acpi_fadt_t));
+
+}
diff --git a/src/mainboard/via/vt8454c/irq-p2p-bridge.dsl b/src/mainboard/via/vt8454c/irq-p2p-bridge.dsl
new file mode 100644
index 0000000000..4a294bcbaa
--- /dev/null
+++ b/src/mainboard/via/vt8454c/irq-p2p-bridge.dsl
@@ -0,0 +1,88 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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
+ */
+
+Name (PICM, Package () {
+ // _ADR PIN SRC IDX
+
+ Package () { 0x0003FFFF, 0x00, LNKA, 0x00 },
+ Package () { 0x0003FFFF, 0x01, LNKB, 0x00 },
+ Package () { 0x0003FFFF, 0x02, LNKC, 0x00 },
+ Package () { 0x0003FFFF, 0x03, LNKD, 0x00 },
+
+ Package () { 0x0004FFFF, 0x00, LNKB, 0x00 },
+ Package () { 0x0004FFFF, 0x01, LNKC, 0x00 },
+ Package () { 0x0004FFFF, 0x02, LNKD, 0x00 },
+ Package () { 0x0004FFFF, 0x03, LNKA, 0x00 },
+
+ Package () { 0x0005FFFF, 0x00, LNKC, 0x00 },
+ Package () { 0x0005FFFF, 0x01, LNKD, 0x00 },
+ Package () { 0x0005FFFF, 0x02, LNKA, 0x00 },
+ Package () { 0x0005FFFF, 0x03, LNKB, 0x00 },
+
+ Package () { 0x0006FFFF, 0x00, LNKD, 0x00 },
+ Package () { 0x0006FFFF, 0x01, LNKA, 0x00 },
+ Package () { 0x0006FFFF, 0x02, LNKB, 0x00 },
+ Package () { 0x0006FFFF, 0x03, LNKC, 0x00 },
+
+ Package () { 0x0007FFFF, 0x00, LNKA, 0x00 },
+ Package () { 0x0007FFFF, 0x01, LNKB, 0x00 },
+ Package () { 0x0007FFFF, 0x02, LNKC, 0x00 },
+ Package () { 0x0007FFFF, 0x03, LNKD, 0x00 },
+
+ Package () { 0x0008FFFF, 0x00, LNKB, 0x00 },
+ Package () { 0x0008FFFF, 0x01, LNKC, 0x00 },
+ Package () { 0x0008FFFF, 0x02, LNKD, 0x00 },
+ Package () { 0x0008FFFF, 0x03, LNKA, 0x00 },
+})
+
+Name (APIC, Package () {
+ Package () { 0x0003FFFF, 0x00, 0x00, 0x10 },
+ Package () { 0x0003FFFF, 0x01, 0x00, 0x11 },
+ Package () { 0x0003FFFF, 0x02, 0x00, 0x12 },
+ Package () { 0x0003FFFF, 0x03, 0x00, 0x13 },
+
+ Package () { 0x0004FFFF, 0x00, 0x00, 0x11 },
+ Package () { 0x0004FFFF, 0x01, 0x00, 0x12 },
+ Package () { 0x0004FFFF, 0x02, 0x00, 0x13 },
+ Package () { 0x0004FFFF, 0x03, 0x00, 0x10 },
+
+ Package () { 0x0005FFFF, 0x00, 0x00, 0x12 },
+ Package () { 0x0005FFFF, 0x01, 0x00, 0x13 },
+ Package () { 0x0005FFFF, 0x02, 0x00, 0x10 },
+ Package () { 0x0005FFFF, 0x03, 0x00, 0x11 },
+
+ Package () { 0x0006FFFF, 0x00, 0x00, 0x13 },
+ Package () { 0x0006FFFF, 0x01, 0x00, 0x10 },
+ Package () { 0x0006FFFF, 0x02, 0x00, 0x11 },
+ Package () { 0x0006FFFF, 0x03, 0x00, 0x12 },
+
+ Package () { 0x0007FFFF, 0x00, 0x00, 0x10 },
+ Package () { 0x0007FFFF, 0x01, 0x00, 0x11 },
+ Package () { 0x0007FFFF, 0x02, 0x00, 0x12 },
+ Package () { 0x0007FFFF, 0x03, 0x00, 0x13 },
+
+ Package () { 0x0008FFFF, 0x00, 0x00, 0x11 },
+ Package () { 0x0008FFFF, 0x01, 0x00, 0x12 },
+ Package () { 0x0008FFFF, 0x02, 0x00, 0x13 },
+ Package () { 0x0008FFFF, 0x03, 0x00, 0x10 },
+})
+
+
diff --git a/src/mainboard/via/vt8454c/irq.dsl b/src/mainboard/via/vt8454c/irq.dsl
new file mode 100644
index 0000000000..63e64e61c0
--- /dev/null
+++ b/src/mainboard/via/vt8454c/irq.dsl
@@ -0,0 +1,143 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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
+ */
+
+Name (PICM, Package () {
+ // _ADR PIN SRC IDX
+
+ Package () { 0x0001FFFF, 0x00, LNKA, 0x00 },
+ Package () { 0x0001FFFF, 0x01, LNKB, 0x00 },
+ Package () { 0x0001FFFF, 0x02, LNKC, 0x00 },
+ Package () { 0x0001FFFF, 0x03, LNKD, 0x00 },
+
+ Package () { 0x0008FFFF, 0x00, LNKB, 0x00 },
+ Package () { 0x0008FFFF, 0x01, LNKC, 0x00 },
+ Package () { 0x0008FFFF, 0x02, LNKD, 0x00 },
+ Package () { 0x0008FFFF, 0x03, LNKA, 0x00 },
+
+ Package () { 0x0009FFFF, 0x00, LNKC, 0x00 },
+ Package () { 0x0009FFFF, 0x01, LNKD, 0x00 },
+ Package () { 0x0009FFFF, 0x02, LNKA, 0x00 },
+ Package () { 0x0009FFFF, 0x03, LNKB, 0x00 },
+
+ Package () { 0x000AFFFF, 0x00, LNKD, 0x00 },
+ Package () { 0x000AFFFF, 0x01, LNKA, 0x00 },
+ Package () { 0x000AFFFF, 0x02, LNKB, 0x00 },
+ Package () { 0x000AFFFF, 0x03, LNKC, 0x00 },
+
+ Package () { 0x000BFFFF, 0x00, LNKD, 0x00 },
+ Package () { 0x000BFFFF, 0x01, LNKA, 0x00 },
+ Package () { 0x000BFFFF, 0x02, LNKB, 0x00 },
+ Package () { 0x000BFFFF, 0x03, LNKC, 0x00 },
+
+ Package () { 0x000CFFFF, 0x00, LNKA, 0x00 },
+ Package () { 0x000CFFFF, 0x01, LNKB, 0x00 },
+ Package () { 0x000CFFFF, 0x02, LNKC, 0x00 },
+ Package () { 0x000CFFFF, 0x03, LNKD, 0x00 },
+
+ Package () { 0x000DFFFF, 0x00, LNKA, 0x00 },
+ Package () { 0x000DFFFF, 0x01, LNKB, 0x00 },
+ Package () { 0x000DFFFF, 0x02, LNKC, 0x00 },
+ Package () { 0x000DFFFF, 0x03, LNKD, 0x00 },
+
+ Package () { 0x000FFFFF, 0x00, LNKA, 0x00 },
+ Package () { 0x000FFFFF, 0x01, LNKB, 0x00 },
+ Package () { 0x000FFFFF, 0x02, LNKC, 0x00 },
+ Package () { 0x000FFFFF, 0x03, LNKD, 0x00 },
+
+ /* USB controller */
+ Package () { 0x0010FFFF, 0x00, LNKA, 0x00 },
+ Package () { 0x0010FFFF, 0x01, LNKB, 0x00 },
+ Package () { 0x0010FFFF, 0x02, LNKC, 0x00 },
+ Package () { 0x0010FFFF, 0x03, LNKD, 0x00 },
+
+ Package () { 0x0011FFFF, 0x00, LNKA, 0x00 },
+ Package () { 0x0011FFFF, 0x01, LNKB, 0x00 },
+ Package () { 0x0011FFFF, 0x02, LNKC, 0x00 },
+ Package () { 0x0011FFFF, 0x03, LNKD, 0x00 },
+
+ Package () { 0x0012FFFF, 0x00, LNKA, 0x00 },
+ Package () { 0x0012FFFF, 0x01, LNKB, 0x00 },
+ Package () { 0x0012FFFF, 0x02, LNKC, 0x00 },
+ Package () { 0x0012FFFF, 0x03, LNKD, 0x00 }
+})
+
+Name (APIC, Package () {
+ Package () { 0x0001FFFF, 0x00, 0x00, 0x10 },
+ Package () { 0x0001FFFF, 0x01, 0x00, 0x11 },
+ Package () { 0x0001FFFF, 0x02, 0x00, 0x12 },
+ Package () { 0x0001FFFF, 0x03, 0x00, 0x13 },
+
+ Package () { 0x0008FFFF, 0x00, 0x00, 0x11 },
+ Package () { 0x0008FFFF, 0x01, 0x00, 0x12 },
+ Package () { 0x0008FFFF, 0x02, 0x00, 0x13 },
+ Package () { 0x0008FFFF, 0x03, 0x00, 0x10 },
+
+ Package () { 0x0009FFFF, 0x00, 0x00, 0x12 },
+ Package () { 0x0009FFFF, 0x01, 0x00, 0x13 },
+ Package () { 0x0009FFFF, 0x02, 0x00, 0x10 },
+ Package () { 0x0009FFFF, 0x03, 0x00, 0x11 },
+
+ Package () { 0x000AFFFF, 0x00, 0x00, 0x13 },
+ Package () { 0x000AFFFF, 0x01, 0x00, 0x10 },
+ Package () { 0x000AFFFF, 0x02, 0x00, 0x11 },
+ Package () { 0x000AFFFF, 0x03, 0x00, 0x12 },
+
+ Package () { 0x000BFFFF, 0x00, 0x00, 0x13 },
+ Package () { 0x000BFFFF, 0x01, 0x00, 0x10 },
+ Package () { 0x000BFFFF, 0x02, 0x00, 0x11 },
+ Package () { 0x000BFFFF, 0x03, 0x00, 0x12 },
+
+ Package () { 0x000CFFFF, 0x00, 0x00, 0x10 },
+ Package () { 0x000CFFFF, 0x01, 0x00, 0x11 },
+ Package () { 0x000CFFFF, 0x02, 0x00, 0x12 },
+ Package () { 0x000CFFFF, 0x03, 0x00, 0x13 },
+
+ Package () { 0x000DFFFF, 0x00, 0x00, 0x10 },
+ Package () { 0x000DFFFF, 0x01, 0x00, 0x11 },
+ Package () { 0x000DFFFF, 0x02, 0x00, 0x12 },
+ Package () { 0x000DFFFF, 0x03, 0x00, 0x13 },
+
+ Package () { 0x000FFFFF, 0x00, LNKA, 0x00 },
+ Package () { 0x000FFFFF, 0x01, LNKA, 0x00 },
+ Package () { 0x000FFFFF, 0x02, LNKA, 0x00 },
+ Package () { 0x000FFFFF, 0x03, LNKA, 0x00 },
+
+ /* USB controller. Hardwired in internal
+ APIC mode, see PM pg. 137,
+ "miscellaneous controls", footnote to
+ "IDE interrupt select" */
+ Package () { 0x0010FFFF, 0x00, 0x00, 0x14 },
+ Package () { 0x0010FFFF, 0x01, 0x00, 0x16 },
+ Package () { 0x0010FFFF, 0x02, 0x00, 0x15 },
+ Package () { 0x0010FFFF, 0x03, 0x00, 0x17 },
+
+ Package () { 0x0011FFFF, 0x00, LNKA, 0x00 },
+ Package () { 0x0011FFFF, 0x01, LNKB, 0x00 },
+ Package () { 0x0011FFFF, 0x02, LNKC, 0x00 },
+ Package () { 0x0011FFFF, 0x03, LNKD, 0x00 },
+
+ Package () { 0x0012FFFF, 0x00, LNKD, 0x00 },
+ Package () { 0x0012FFFF, 0x01, LNKD, 0x00 },
+ Package () { 0x0012FFFF, 0x02, LNKD, 0x00 },
+ Package () { 0x0012FFFF, 0x03, LNKD, 0x00 },
+})
+
+
diff --git a/src/mainboard/via/vt8454c/irq_tables.c b/src/mainboard/via/vt8454c/irq_tables.c
new file mode 100644
index 0000000000..40d1ebb691
--- /dev/null
+++ b/src/mainboard/via/vt8454c/irq_tables.c
@@ -0,0 +1,61 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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 <arch/pirq_routing.h>
+
+const struct irq_routing_table intel_irq_routing_table = {
+ PIRQ_SIGNATURE, /* u32 signature */
+ PIRQ_VERSION, /* u16 version */
+ 32 + 16 * IRQ_SLOT_COUNT, /* There can be total 15 devices on the bus */
+ 0x00, /* Where the interrupt router lies (bus) */
+ (0x11 << 3) | 0x0, /* Where the interrupt router lies (dev) */
+ 0xc20, /* IRQs devoted exclusively to PCI usage */
+ 0x1106, /* Vendor */
+ 0x596, /* Device */
+ 0, /* Crap (miniport) */
+ {0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0}, /* u8 rfu[11] */
+ 0x84, /* u8 checksum. This 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 */
+ {0x00, (0x08 << 3) | 0x0, {{0x01, 0xdeb8}, {0x02, 0xdeb8}, {0x03, 0xdeb8}, {0x05, 0x0deb8}}, 0x1, 0x0},
+ {0x00, (0x09 << 3) | 0x0, {{0x02, 0xdeb8}, {0x03, 0xdeb8}, {0x05, 0xdeb8}, {0x01, 0x0deb8}}, 0x2, 0x0},
+ {0x00, (0x0a << 3) | 0x0, {{0x03, 0xdeb8}, {0x05, 0xdeb8}, {0x01, 0xdeb8}, {0x02, 0x0deb8}}, 0x3, 0x0},
+ {0x02, (0x03 << 3) | 0x0, {{0x01, 0xdeb8}, {0x02, 0xdeb8}, {0x03, 0xdeb8}, {0x05, 0x0deb8}}, 0x4, 0x0},
+ {0x02, (0x04 << 3) | 0x0, {{0x02, 0xdeb8}, {0x03, 0xdeb8}, {0x05, 0xdeb8}, {0x01, 0x0deb8}}, 0x5, 0x0},
+ {0x02, (0x05 << 3) | 0x0, {{0x03, 0xdeb8}, {0x05, 0xdeb8}, {0x01, 0xdeb8}, {0x02, 0x0deb8}}, 0x6, 0x0},
+ {0x02, (0x06 << 3) | 0x0, {{0x05, 0xdeb8}, {0x01, 0xdeb8}, {0x02, 0xdeb8}, {0x03, 0x0deb8}}, 0x7, 0x0},
+ {0x02, (0x07 << 3) | 0x0, {{0x01, 0xdeb8}, {0x02, 0xdeb8}, {0x03, 0xdeb8}, {0x05, 0x0deb8}}, 0x8, 0x0},
+ {0x02, (0x08 << 3) | 0x0, {{0x03, 0xdeb8}, {0x05, 0xdeb8}, {0x01, 0xdeb8}, {0x02, 0x0deb8}}, 0x9, 0x0},
+ {0x00, (0x01 << 3) | 0x0, {{0x02, 0xdeb8}, {0x02, 0xdeb8}, {0x02, 0xdeb8}, {0x02, 0x0deb8}}, 0x0, 0x0},
+ {0x80, (0x01 << 3) | 0x0, {{0x02, 0xdeb8}, {0x02, 0xdeb8}, {0x02, 0xdeb8}, {0x02, 0x0deb8}}, 0x0, 0x0},
+ {0x00, (0x11 << 3) | 0x0, {{0x00, 0xdeb8}, {0x00, 0xdeb8}, {0x03, 0xdeb8}, {0x05, 0x0deb8}}, 0x0, 0x0},
+ {0x00, (0x0f << 3) | 0x0, {{0x01, 0xdeb8}, {0x02, 0xdeb8}, {0x03, 0xdeb8}, {0x05, 0x0deb8}}, 0x0, 0x0},
+ {0x00, (0x01 << 3) | 0x0, {{0x01, 0xdeb8}, {0x02, 0xdeb8}, {0x03, 0xdeb8}, {0x05, 0x0deb8}}, 0x0, 0x0},
+ {0x00, (0x10 << 3) | 0x0, {{0x01, 0xdeb8}, {0x02, 0xdeb8}, {0x03, 0xdeb8}, {0x05, 0x0deb8}}, 0x0, 0x0}
+ }
+};
+
+inline unsigned long write_pirq_routing_table(unsigned long addr)
+{
+ return copy_pirq_routing_table(addr);
+}
diff --git a/src/mainboard/via/vt8454c/mainboard.c b/src/mainboard/via/vt8454c/mainboard.c
new file mode 100644
index 0000000000..e931ccdafb
--- /dev/null
+++ b/src/mainboard/via/vt8454c/mainboard.c
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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 <device/device.h>
+#include "chip.h"
+
+struct chip_operations mainboard_ops = {
+ CHIP_NAME("VIA VT8454c Mainboard")
+};
+
diff --git a/src/mainboard/via/vt8454c/mptable.c b/src/mainboard/via/vt8454c/mptable.c
new file mode 100644
index 0000000000..e060d67ddd
--- /dev/null
+++ b/src/mainboard/via/vt8454c/mptable.c
@@ -0,0 +1,104 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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 <device/device.h>
+#include <device/pci.h>
+#include <arch/smp/mpspec.h>
+#include <cpu/x86/lapic.h>
+#include <console/console.h>
+#include <string.h>
+#include <stdint.h>
+
+void *smp_write_config_table(void *v)
+{
+ static const char sig[4] = MPC_SIGNATURE;
+ static const char oem[8] = "COREBOOT";
+ static const char productid[12] = "VIA VT8454C ";
+ struct mp_config_table *mc;
+
+ mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
+ memset(mc, 0, sizeof(*mc));
+
+ memcpy(mc->mpc_signature, sig, sizeof(sig));
+ mc->mpc_length = sizeof(*mc); /* initially just the header */
+ mc->mpc_spec = 0x04;
+ mc->mpc_checksum = 0; /* not yet computed */
+ memcpy(mc->mpc_oem, oem, sizeof(oem));
+ memcpy(mc->mpc_productid, productid, sizeof(productid));
+ mc->mpc_oemptr = 0;
+ mc->mpc_oemsize = 0;
+ mc->mpc_entry_count = 0; /* No entries yet... */
+ mc->mpc_lapic = LAPIC_ADDR;
+ mc->mpe_length = 0;
+ mc->mpe_checksum = 0;
+ mc->reserved = 0;
+
+ smp_write_processors(mc);
+
+ /*Bus: Bus ID Type */
+ smp_write_bus(mc, 0, "PCI ");
+ smp_write_bus(mc, 1, "PCI ");
+ smp_write_bus(mc, 2, "PCI ");
+ smp_write_bus(mc, 128, "PCI ");
+ smp_write_bus(mc, 129, "ISA ");
+
+ /* I/O APICs: APIC ID Version State Address */
+ smp_write_ioapic(mc, 2, 17, 0xfec00000);
+
+ /* I/O Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# */
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW, 0x0, 0x40, 0x2, 0x14);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW, 0x0, 0x41, 0x2, 0x16);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW, 0x0, 0x42, 0x2, 0x15);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW, 0x0, 0x43, 0x2, 0x17);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW, 0x80, 0x4, 0x2, 0x11);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW, 0x1, 0x0, 0x2, 0x11);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL | MP_IRQ_POLARITY_LOW, 0x2, 0x10, 0x2, 0x11);
+ smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT, 0x81, 0x0, 0x2, 0x0);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT, 0x81, 0x1, 0x2, 0x1);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT, 0x81, 0x0, 0x2, 0x2);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT, 0x81, 0x3, 0x2, 0x3);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT, 0x81, 0x4, 0x2, 0x4);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT, 0x81, 0x6, 0x2, 0x6);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT, 0x81, 0x7, 0x2, 0x7);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE | MP_IRQ_POLARITY_HIGH, 0x81, 0x8, 0x2, 0x8);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT, 0x81, 0x9, 0x2, 0x9);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT, 0x81, 0xc, 0x2, 0xc);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT, 0x81, 0xd, 0x2, 0xd);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT, 0x81, 0xe, 0x2, 0xe);
+ smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT, 0x81, 0xf, 0x2, 0xf);
+
+ /*Local Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# */
+ smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT, 0x0, 0x0, MP_APIC_ALL, 0x0);
+ smp_write_intsrc(mc, mp_NMI, MP_IRQ_TRIGGER_DEFAULT | MP_IRQ_POLARITY_DEFAULT, 0x0, 0x0, MP_APIC_ALL, 0x1);
+
+ /* Compute the checksums */
+ mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length);
+ mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length);
+ printk_debug("Wrote the mp table end at: %p - %p\n", mc, smp_next_mpe_entry(mc));
+ return smp_next_mpe_entry(mc);
+}
+
+unsigned long write_smp_table(unsigned long addr)
+{
+ void *v;
+ v = smp_write_floating_table(addr);
+ return (unsigned long)smp_write_config_table(v);
+}
diff --git a/src/mainboard/via/vt8454c/reset.c b/src/mainboard/via/vt8454c/reset.c
new file mode 100644
index 0000000000..e1d879fa5a
--- /dev/null
+++ b/src/mainboard/via/vt8454c/reset.c
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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 "arch/romcc_io.h"
+
+void hard_reset(void)
+{
+ set_bios_reset();
+ outb(0x06, 0x0cf9);
+}
diff --git a/src/northbridge/via/cx700/Config.lb b/src/northbridge/via/cx700/Config.lb
new file mode 100644
index 0000000000..f4e558033e
--- /dev/null
+++ b/src/northbridge/via/cx700/Config.lb
@@ -0,0 +1,28 @@
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2007-2009 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; 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
+
+config chip.h
+
+object cx700_reset.o
+object northbridge.o
+object vgabios.o
+
+driver cx700_agp.o
+driver cx700_lpc.o
+driver cx700_sata.o
+driver cx700_vga.o
+
diff --git a/src/northbridge/via/cx700/chip.h b/src/northbridge/via/cx700/chip.h
new file mode 100644
index 0000000000..7b7aca8e89
--- /dev/null
+++ b/src/northbridge/via/cx700/chip.h
@@ -0,0 +1,23 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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
+ */
+
+struct northbridge_via_cx700_config {
+};
+
+extern struct chip_operations northbridge_via_cx700_ops;
diff --git a/src/northbridge/via/cx700/cx700_agp.c b/src/northbridge/via/cx700/cx700_agp.c
new file mode 100644
index 0000000000..0166ee135a
--- /dev/null
+++ b/src/northbridge/via/cx700/cx700_agp.c
@@ -0,0 +1,91 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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 <console/console.h>
+#include <arch/io.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+/* This is the AGP 3.0 "bridge" @ Bus 0 Device 1 Func 0 */
+
+static void agp_bridge_init(device_t dev)
+{
+
+ device_t north_dev;
+ u8 reg8;
+ north_dev = dev_find_device(PCI_VENDOR_ID_VIA, 0x3324, 0);
+
+ pci_write_config8(north_dev, 0xa0, 0x1); // Enable CPU Direct Access Frame Buffer
+
+ pci_write_config8(north_dev, 0xa2, 0x4a);
+
+ reg8 = pci_read_config8(north_dev, 0xc0);
+ reg8 |= 0x1;
+ pci_write_config8(north_dev, 0xc0, reg8);
+
+ /*
+ * Since Internal Graphic already set to AGP3.0 compatible in its Capability Pointer
+ * We must set RAGP8X=1 B0D0F0 Rx84[3]=1 from backdoor register B0D0F0 RxB5[1:0]=11b
+ */
+ north_dev = dev_find_device(PCI_VENDOR_ID_VIA, 0x0324, 0);
+ reg8 = pci_read_config8(north_dev, 0xb5);
+ reg8 |= 0x3;
+ pci_write_config8(north_dev, 0xb5, reg8);
+ pci_write_config8(north_dev, 0x94, 0x20);
+ pci_write_config8(north_dev, 0x13, 0xd0);
+
+ pci_write_config16(dev, 0x4, 0x0007);
+
+ pci_write_config8(dev, 0x19, 0x01);
+ pci_write_config8(dev, 0x1a, 0x01);
+ pci_write_config8(dev, 0x1c, 0xe0);
+ pci_write_config8(dev, 0x1d, 0xe0);
+ pci_write_config16(dev, 0x1e, 0xa220);
+
+ pci_write_config16(dev, 0x20, 0xdd00);
+ pci_write_config16(dev, 0x22, 0xdef0);
+ pci_write_config16(dev, 0x24, 0xa000);
+ pci_write_config16(dev, 0x26, 0xbff0);
+
+ pci_write_config8(dev, 0x3e, 0x0c);
+ pci_write_config8(dev, 0x40, 0x8b);
+ pci_write_config8(dev, 0x41, 0x43);
+ pci_write_config8(dev, 0x42, 0x62);
+ pci_write_config8(dev, 0x43, 0x44);
+ pci_write_config8(dev, 0x44, 0x34);
+}
+
+static void cx700_noop(device_t dev)
+{
+}
+
+static struct device_operations agp_bridge_operations = {
+ .read_resources = cx700_noop,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_bus_enable_resources,
+ .init = agp_bridge_init,
+ .scan_bus = pci_scan_bridge,
+};
+
+static const struct pci_driver agp_bridge_driver __pci_driver = {
+ .ops = &agp_bridge_operations,
+ .vendor = PCI_VENDOR_ID_VIA,
+ .device = 0xb198,
+};
diff --git a/src/northbridge/via/cx700/cx700_early_serial.c b/src/northbridge/via/cx700/cx700_early_serial.c
new file mode 100644
index 0000000000..a0d7301e20
--- /dev/null
+++ b/src/northbridge/via/cx700/cx700_early_serial.c
@@ -0,0 +1,102 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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
+ */
+
+/*
+ * Enable the serial devices on the VIA CX700
+ */
+
+#include <arch/romcc_io.h>
+
+static void cx700_writepnpaddr(u8 val)
+{
+ outb(val, 0x2e);
+ outb(val, 0xeb);
+}
+
+static void cx700_writepnpdata(u8 val)
+{
+ outb(val, 0x2f);
+ outb(val, 0xeb);
+}
+
+static void cx700_writesiobyte(u16 reg, u8 val)
+{
+ outb(val, reg);
+}
+
+static void cx700_writesioword(u16 reg, u16 val)
+{
+ outw(val, reg);
+}
+
+static void enable_cx700_serial(void)
+{
+ outb(6, 0x80);
+
+ // WTH?
+ outb(0x03, 0x22);
+
+ // Set UART1 I/O Base Address
+ pci_write_config8(PCI_DEV(0, 17, 0), 0xb4, 0x7e);
+
+ // UART1 Enable
+ pci_write_config8(PCI_DEV(0, 17, 0), 0xb0, 0x10);
+
+ // turn on pnp
+ cx700_writepnpaddr(0x87);
+ cx700_writepnpaddr(0x87);
+ // now go ahead and set up com1.
+ // set address
+ cx700_writepnpaddr(0x7);
+ cx700_writepnpdata(0x2);
+ // enable serial out
+ cx700_writepnpaddr(0x30);
+ cx700_writepnpdata(0x1);
+ // serial port 1 base address (FEh)
+ cx700_writepnpaddr(0x60);
+ cx700_writepnpdata(0xfe);
+ // serial port 1 IRQ (04h)
+ cx700_writepnpaddr(0x70);
+ cx700_writepnpdata(0x4);
+ // serial port 1 control
+ cx700_writepnpaddr(0xf0);
+ cx700_writepnpdata(0x2);
+ // turn of pnp
+ cx700_writepnpaddr(0xaa);
+
+ // XXX This part should be fully taken care of by
+ // src/pc80/serial.c:uart_init
+
+ // set up reg to set baud rate.
+ cx700_writesiobyte(0x3fb, 0x80);
+ // Set 115 kb
+ cx700_writesioword(0x3f8, 1);
+ // Set 9.6 kb
+ // cx700_writesioword(0x3f8, 12)
+ // now set no parity, one stop, 8 bits
+ cx700_writesiobyte(0x3fb, 3);
+ // now turn on RTS, DRT
+ cx700_writesiobyte(0x3fc, 3);
+ // Enable interrupts
+ cx700_writesiobyte(0x3f9, 0xf);
+ // should be done. Dump a char for fun.
+ cx700_writesiobyte(0x3f8, 48);
+
+ outb(7, 0x80);
+}
diff --git a/src/northbridge/via/cx700/cx700_early_smbus.c b/src/northbridge/via/cx700/cx700_early_smbus.c
new file mode 100644
index 0000000000..218ae0a7a1
--- /dev/null
+++ b/src/northbridge/via/cx700/cx700_early_smbus.c
@@ -0,0 +1,268 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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
+ */
+
+// other bioses use this, too:
+#define SMBUS_IO_BASE 0x0500
+
+#define SMBHSTSTAT SMBUS_IO_BASE + 0x0
+#define SMBSLVSTAT SMBUS_IO_BASE + 0x1
+#define SMBHSTCTL SMBUS_IO_BASE + 0x2
+#define SMBHSTCMD SMBUS_IO_BASE + 0x3
+#define SMBXMITADD SMBUS_IO_BASE + 0x4
+#define SMBHSTDAT0 SMBUS_IO_BASE + 0x5
+#define SMBHSTDAT1 SMBUS_IO_BASE + 0x6
+
+#define SMBBLKDAT SMBUS_IO_BASE + 0x7
+#define SMBSLVCTL SMBUS_IO_BASE + 0x8
+#define SMBTRNSADD SMBUS_IO_BASE + 0x9
+#define SMBSLVDATA SMBUS_IO_BASE + 0xa
+#define SMLINK_PIN_CTL SMBUS_IO_BASE + 0xe
+#define SMBUS_PIN_CTL SMBUS_IO_BASE + 0xf
+
+/* Define register settings */
+#define HOST_RESET 0xff
+#define DIMM_BASE 0xa0 // 1010000 is base for DIMM in SMBus
+#define READ_CMD 0x01 // 1 in the 0 bit of SMBHSTADD states to READ
+
+#define SMBUS_TIMEOUT (100*1000*10)
+
+#define I2C_TRANS_CMD 0x40
+#define CLOCK_SLAVE_ADDRESS 0x69
+
+#define SMBUS_DELAY() outb(0x80, 0x80)
+
+/* Debugging macros. */
+
+// #define DEBUG_SMBUS 1
+
+#ifdef DEBUG_SMBUS
+#define PRINT_DEBUG(x) print_debug(x)
+#define PRINT_DEBUG_HEX16(x) print_debug_hex16(x)
+#else
+#define PRINT_DEBUG(x)
+#define PRINT_DEBUG_HEX16(x)
+#endif
+
+/* Internal functions */
+static void smbus_print_error(unsigned char host_status_register, int loops)
+{
+ /* Check if there actually was an error */
+ if (host_status_register == 0x00 || host_status_register == 0x40 ||
+ host_status_register == 0x42)
+ return;
+ print_err("SMBus Error: ");
+ print_err_hex8(host_status_register);
+
+ print_err("\r\n");
+ if (loops >= SMBUS_TIMEOUT) {
+ print_err("SMBus Timout\r\n");
+ }
+ if (host_status_register & (1 << 4)) {
+ print_err("Interrup/SMI# was Failed Bus Transaction\r\n");
+ }
+ if (host_status_register & (1 << 3)) {
+ print_err("Bus Error\r\n");
+ }
+ if (host_status_register & (1 << 2)) {
+ print_err("Device Error\r\n");
+ }
+ if (host_status_register & (1 << 1)) {
+ /* This isn't a real error... */
+ print_debug("Interrupt/SMI# was Successful Completion\r\n");
+ }
+ if (host_status_register & (1 << 0)) {
+ print_err("Host Busy\r\n");
+ }
+}
+
+static void smbus_wait_until_ready(void)
+{
+ int loops;
+
+ loops = 0;
+
+ /* Yes, this is a mess, but it's the easiest way to do it */
+ while (((inb(SMBHSTSTAT) & 1) == 1) && (loops <= SMBUS_TIMEOUT)) {
+ SMBUS_DELAY();
+ ++loops;
+ }
+#ifdef DEBUG_SMBUS
+ /* Some systems seem to have a flakey SMBus. No need to spew a lot of
+ * errors on those, once we know that SMBus access is principally
+ * working.
+ */
+ smbus_print_error(inb(SMBHSTSTAT), loops);
+#endif
+}
+
+static void smbus_reset(void)
+{
+ outb(HOST_RESET, SMBHSTSTAT);
+}
+
+/* Public functions */
+static void set_ics_data(unsigned char dev, int data, char len)
+{
+ //int i;
+ smbus_reset();
+ /* clear host data port */
+ outb(0x00, SMBHSTDAT0);
+ SMBUS_DELAY();
+ smbus_wait_until_ready();
+
+ /* read to reset block transfer counter */
+ inb(SMBHSTCTL);
+
+ /* fill blocktransfer array */
+ if (dev = 0xd2) {
+ //char d2_data[] = {0x0d,0x00,0x3f,0xcd,0x7f,0xbf,0x1a,0x2a,0x01,0x0f,0x0b,0x00,0x8d,0x9b};
+ outb(0x0d, SMBBLKDAT);
+ outb(0x00, SMBBLKDAT);
+ outb(0x3f, SMBBLKDAT);
+ outb(0xcd, SMBBLKDAT);
+ outb(0x7f, SMBBLKDAT);
+ outb(0xbf, SMBBLKDAT);
+ outb(0x1a, SMBBLKDAT);
+ outb(0x2a, SMBBLKDAT);
+ outb(0x01, SMBBLKDAT);
+ outb(0x0f, SMBBLKDAT);
+ outb(0x0b, SMBBLKDAT);
+ outb(0x80, SMBBLKDAT);
+ outb(0x8d, SMBBLKDAT);
+ outb(0x9b, SMBBLKDAT);
+ } else {
+ //char d4_data[] = {0x08,0xff,0x3f,0x00,0x00,0xff,0xff,0xff,0xff};
+ outb(0x08, SMBBLKDAT);
+ outb(0xff, SMBBLKDAT);
+ outb(0x3f, SMBBLKDAT);
+ outb(0x00, SMBBLKDAT);
+ outb(0x00, SMBBLKDAT);
+ outb(0xff, SMBBLKDAT);
+ outb(0xff, SMBBLKDAT);
+ outb(0xff, SMBBLKDAT);
+ outb(0xff, SMBBLKDAT);
+ }
+
+ //for (i=0; i < len; i++)
+ // outb(data[i],SMBBLKDAT);
+
+ outb(dev, SMBXMITADD);
+ outb(0, SMBHSTCMD);
+ outb(len, SMBHSTDAT0);
+ outb(0x74, SMBHSTCTL);
+
+ SMBUS_DELAY();
+
+ smbus_wait_until_ready();
+
+ smbus_reset();
+
+}
+
+static unsigned int get_spd_data(const struct mem_controller *ctrl, unsigned int dimm,
+ unsigned int offset)
+{
+ unsigned int val, addr;
+
+ smbus_reset();
+
+ /* clear host data port */
+ outb(0x00, SMBHSTDAT0);
+ SMBUS_DELAY();
+ smbus_wait_until_ready();
+
+ /* Fetch the SMBus address of the SPD ROM from
+ * the ctrl struct in auto.c in case they are at
+ * non-standard positions.
+ * SMBus Address shifted by 1
+ */
+ addr = (ctrl->channel0[dimm]) << 1;
+
+ outb(addr | 0x1, SMBXMITADD);
+ outb(offset, SMBHSTCMD);
+ outb(0x48, SMBHSTCTL);
+
+ SMBUS_DELAY();
+
+ smbus_wait_until_ready();
+
+ val = inb(SMBHSTDAT0);
+ smbus_reset();
+ return val;
+}
+
+static void enable_smbus(void)
+{
+ device_t dev;
+
+ /* The CX700 ISA Bridge (0x1106, 0x8324) is hardcoded to this location,
+ * no need to probe.
+ */
+ dev = PCI_DEV(0, 17, 0);
+
+ /* SMBus Clock Select: Divider fof 14.318MHz */
+ pci_write_config8(dev, 0x94, 0x20);
+
+ /* SMBus I/O Base, enable SMBus */
+ pci_write_config16(dev, 0xd0, SMBUS_IO_BASE | 1);
+
+ /* SMBus Clock from 128K Source, Enable SMBus Host Controller */
+ pci_write_config8(dev, 0xd2, 0x05);
+
+ /* Enable I/O decoding */
+ pci_write_config16(dev, 0x04, 0x0003);
+
+ /* Setup clock chips */
+ set_ics_data(0xd2, 0, 14);
+ set_ics_data(0xd4, 0, 9);
+}
+
+/* Debugging Function */
+#ifdef DEBUG_SMBUS
+static void dump_spd_data(const struct mem_controller *ctrl)
+{
+ int dimm, offset, regs;
+ unsigned int val;
+
+ for (dimm = 0; dimm < DIMM_SOCKETS; dimm++) {
+ print_debug("SPD Data for DIMM ");
+ print_debug_hex8(dimm);
+ print_debug("\r\n");
+
+ val = get_spd_data(ctrl, dimm, 0);
+ if (val == 0xff) {
+ regs = 256;
+ } else if (val == 0x80) {
+ regs = 128;
+ } else {
+ print_debug("No DIMM present\r\n");
+ regs = 0;
+ }
+ for (offset = 0; offset < regs; offset++) {
+ print_debug(" Offset ");
+ print_debug_hex8(offset);
+ print_debug(" = 0x");
+ print_debug_hex8(get_spd_data(ctrl, dimm, offset));
+ print_debug("\r\n");
+ }
+ }
+}
+#else
+#define dump_spd_data(ctrl)
+#endif
diff --git a/src/northbridge/via/cx700/cx700_lpc.c b/src/northbridge/via/cx700/cx700_lpc.c
new file mode 100644
index 0000000000..65275baa81
--- /dev/null
+++ b/src/northbridge/via/cx700/cx700_lpc.c
@@ -0,0 +1,397 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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 <arch/io.h>
+#include <console/console.h>
+
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ops.h>
+#include <device/pci_ids.h>
+
+#include <pc80/mc146818rtc.h>
+#include <pc80/i8259.h>
+#include <pc80/keyboard.h>
+#include <pc80/isa-dma.h>
+
+#include <cpu/x86/lapic.h>
+#include <stdlib.h>
+
+#define ACPI_IO_BASE 0x400
+#define HPET_ADDR 0xfe800000UL
+#define IOAPIC_ADDR 0xfec00000ULL
+
+#ifdef CONFIG_IOAPIC
+struct ioapicreg {
+ unsigned int reg;
+ unsigned int value_low, value_high;
+};
+
+static struct ioapicreg ioapicregvalues[] = {
+#define ALL (0xff << 24)
+#define NONE (0)
+#define DISABLED (1 << 16)
+#define ENABLED (0 << 16)
+#define TRIGGER_EDGE (0 << 15)
+#define TRIGGER_LEVEL (1 << 15)
+#define POLARITY_HIGH (0 << 13)
+#define POLARITY_LOW (1 << 13)
+#define PHYSICAL_DEST (0 << 11)
+#define LOGICAL_DEST (1 << 11)
+#define ExtINT (7 << 8)
+#define NMI (4 << 8)
+#define SMI (2 << 8)
+#define INT (1 << 8)
+ /* IO-APIC virtual wire mode configuration */
+ /* mask, trigger, polarity, destination, delivery, vector */
+ { 0, ENABLED | TRIGGER_EDGE | POLARITY_HIGH | PHYSICAL_DEST | ExtINT, NONE},
+ { 1, DISABLED, NONE},
+ { 2, DISABLED, NONE},
+ { 3, DISABLED, NONE},
+ { 4, DISABLED, NONE},
+ { 5, DISABLED, NONE},
+ { 6, DISABLED, NONE},
+ { 7, DISABLED, NONE},
+ { 8, DISABLED, NONE},
+ { 9, DISABLED, NONE},
+ {10, DISABLED, NONE},
+ {11, DISABLED, NONE},
+ {12, DISABLED, NONE},
+ {13, DISABLED, NONE},
+ {14, DISABLED, NONE},
+ {15, DISABLED, NONE},
+ {16, DISABLED, NONE},
+ {17, DISABLED, NONE},
+ {18, DISABLED, NONE},
+ {19, DISABLED, NONE},
+ {20, DISABLED, NONE},
+ {21, DISABLED, NONE},
+ {22, DISABLED, NONE},
+ {23, DISABLED, NONE},
+};
+
+static void setup_ioapic(void)
+{
+ int i;
+ unsigned long value_low, value_high, val;
+ unsigned long ioapic_base = IOAPIC_ADDR;
+ volatile unsigned long *l;
+ struct ioapicreg *a = ioapicregvalues;
+ unsigned long bsp_lapicid = lapicid();
+
+ l = (unsigned long *)ioapic_base;
+
+ /* Set APIC ADDR */
+ l[0] = 0;
+ val = l[4];
+ l[4] = (val & 0xF0FFFF) | (2 << 24); // 2 == ID as programmed elsewhere. should be a define? XXX
+
+ /* Set APIC to FSB message bus. */
+ l[0] = 0x3;
+ val = l[4];
+ l[4] = (val & 0xFFFFFE) | 1;
+
+ ioapicregvalues[0].value_high = bsp_lapicid << (56 - 32);
+
+ printk_debug("IOAPIC: Bootstrap Processor Local APIC ID = %02x\n", bsp_lapicid);
+
+ for (i = 0; i < ARRAY_SIZE(ioapicregvalues); i++, a++) {
+ l[0] = (a->reg * 2) + 0x10;
+ l[4] = a->value_low;
+ value_low = l[4];
+ l[0] = (a->reg * 2) + 0x11;
+ l[4] = a->value_high;
+ value_high = l[4];
+ if ((i == 0) && (value_low == 0xffffffff)) {
+ printk_warning("IOAPIC is not responding.\n");
+ return;
+ }
+ printk_debug("IOAPIC: IRQ reg 0x%08x value 0x%08x 0x%08x\n",
+ a->reg, a->value_low, a->value_high);
+ }
+}
+#endif
+
+static const unsigned char pci_irqs[4] = { 11, 11, 10, 10 };
+
+static const unsigned char usb_pins[4] = { 'A', 'B', 'C', 'D' };
+static const unsigned char vga_pins[4] = { 'A', 'B', 'C', 'D' };
+static const unsigned char slot_pins[4] = { 'B', 'C', 'D', 'A' };
+static const unsigned char ac97_pins[4] = { 'B', 'C', 'D', 'A' };
+
+static unsigned char *pin_to_irq(const unsigned char *pin)
+{
+ static unsigned char irqs[4];
+ int i;
+ for (i = 0; i < 4; i++)
+ irqs[i] = pci_irqs[pin[i] - 'A'];
+
+ return irqs;
+}
+
+static void pci_routing_fixup(struct device *dev)
+{
+ printk_debug("%s: device is %p\n", __FUNCTION__, dev);
+
+ /* set up PCI IRQ routing */
+ pci_write_config8(dev, 0x55, pci_irqs[0] << 4);
+ pci_write_config8(dev, 0x56, pci_irqs[1] | (pci_irqs[2] << 4));
+ pci_write_config8(dev, 0x57, pci_irqs[3] << 4);
+
+ /* Assigning IRQs */
+ printk_debug("Setting up USB interrupts.\n");
+ pci_assign_irqs(0, 0x10, pin_to_irq(usb_pins));
+
+ printk_debug("Setting up VGA interrupts.\n");
+ pci_assign_irqs(1, 0x00, pin_to_irq(vga_pins));
+
+ printk_debug("Setting up PCI slot interrupts.\n");
+ pci_assign_irqs(2, 0x04, pin_to_irq(slot_pins));
+ // more?
+
+ printk_debug("Setting up AC97 interrupts.\n");
+ pci_assign_irqs(0x80, 0x1, pin_to_irq(ac97_pins));
+}
+
+/*
+ * Set up the power management capabilities directly into ACPI mode. This
+ * avoids having to handle any System Management Interrupts (SMI's) which I
+ * can't figure out how to do !!!!
+ */
+
+void setup_pm(device_t dev)
+{
+ /* Debounce LID and PWRBTN# Inputs for 16ms. */
+ pci_write_config8(dev, 0x80, 0x20);
+
+ /* Set ACPI base address to IO ACPI_IO_BASE */
+ pci_write_config16(dev, 0x88, ACPI_IO_BASE | 1);
+
+ /* set ACPI irq to 9 */
+ pci_write_config8(dev, 0x82, 0x49);
+
+ /* Primary interupt channel, define wake events 0=IRQ0 15=IRQ15 1=en. */
+ pci_write_config16(dev, 0x84, 0x609a);
+
+ /* SMI output level to low, 7.5us throttle clock */
+ pci_write_config8(dev, 0x8d, 0x18);
+
+ /* GP Timer Control 1s */
+ pci_write_config8(dev, 0x93, 0x88);
+
+ /* Power Well */
+ pci_write_config8(dev, 0x94, 0x20); // 0x20??
+
+ /* 7 = stp to sust delay 1msec
+ * 6 = SUSST# Deasserted Before PWRGD for STD
+ */
+ pci_write_config8(dev, 0x95, 0xc0); // 0xc1??
+
+ /* Disable GP2 & GP3 Timer */
+ pci_write_config8(dev, 0x98, 0);
+
+ /* GP2 Timer Counter */
+ pci_write_config8(dev, 0x99, 0xfb);
+ /* GP3 Timer Counter */
+ //pci_write_config8(dev, 0x9a, 0x20);
+
+ /* Multi Function Select 1 */
+ pci_write_config8(dev, 0xe4, 0x00);
+
+ /* Multi Function Select 2 */
+ pci_write_config8(dev, 0xe5, 0x41); //??
+
+ /* Enable ACPI access (and setup like award) */
+ pci_write_config8(dev, 0x81, 0x84);
+
+ /* Clear status events. */
+ outw(0xffff, ACPI_IO_BASE + 0x00);
+ outw(0xffff, ACPI_IO_BASE + 0x20);
+ outw(0xffff, ACPI_IO_BASE + 0x28);
+ outl(0xffffffff, ACPI_IO_BASE + 0x30);
+
+ /* Disable SCI on GPIO. */
+ outw(0x0, ACPI_IO_BASE + 0x22);
+
+ /* Disable SMI on GPIO. */
+ outw(0x0, ACPI_IO_BASE + 0x24);
+
+ /* Disable all global enable SMIs. */
+ outw(0x0, ACPI_IO_BASE + 0x2a);
+
+ /* All SMI off, both IDE buses ON, PSON rising edge. */
+ outw(0x0, ACPI_IO_BASE + 0x2c);
+
+ /* Primary activity SMI disable. */
+ outl(0x0, ACPI_IO_BASE + 0x34);
+
+ /* GP timer reload on none. */
+ outl(0x0, ACPI_IO_BASE + 0x38);
+
+ /* Disable extended IO traps. */
+ outb(0x0, ACPI_IO_BASE + 0x42);
+
+ /* SCI is generated for RTC/pwrBtn/slpBtn. */
+ outw(0x0001, ACPI_IO_BASE + 0x04);
+
+ /* Allow SLP# signal to assert LDTSTOP_L.
+ * Will work for C3 and for FID/VID change.
+ */
+ outb(0x1, ACPI_IO_BASE + 0x11);
+}
+
+static void cx700_set_lpc_registers(struct device *dev)
+{
+ unsigned char enables;
+
+ printk_debug("VIA CX700 LPC bridge init\n");
+
+ // enable the internal I/O decode
+ enables = pci_read_config8(dev, 0x6C);
+ enables |= 0x80;
+ pci_write_config8(dev, 0x6C, enables);
+
+ // Map 4MB of FLASH into the address space
+// pci_write_config8(dev, 0x41, 0x7f);
+
+ // Set bit 6 of 0x40, because Award does it (IO recovery time)
+ // IMPORTANT FIX - EISA 0x4d0 decoding must be on so that PCI
+ // interrupts can be properly marked as level triggered.
+ enables = pci_read_config8(dev, 0x40);
+ enables |= 0x44;
+ pci_write_config8(dev, 0x40, enables);
+
+ /* DMA Line buffer control */
+ enables = pci_read_config8(dev, 0x42);
+ enables |= 0xf0;
+ pci_write_config8(dev, 0x42, enables);
+
+ /* I/O recovery time */
+ pci_write_config8(dev, 0x4c, 0x44);
+
+ /* ROM memory cycles go to LPC. */
+ pci_write_config8(dev, 0x59, 0x80);
+
+ /* Enable SM dynamic clock gating */
+ pci_write_config8(dev, 0x5b, 0x01);
+
+ /* Set Read Pass Write Control Enable */
+ pci_write_config8(dev, 0x48, 0x0c);
+
+ /* Set SM Misc Control: Enable Internal APIC . */
+ enables = pci_read_config8(dev, 0x58);
+ enables |= 1 << 6;
+ pci_write_config8(dev, 0x58, enables);
+ enables = pci_read_config8(dev, 0x4d);
+ enables |= 1 << 3;
+ pci_write_config8(dev, 0x4d, enables);
+
+ /* Set bit 3 of 0x4f to match award (use INIT# as cpu reset) */
+ enables = pci_read_config8(dev, 0x4f);
+ enables |= 0x08;
+ pci_write_config8(dev, 0x4f, enables);
+
+ /* enable KBC configuration */
+ pci_write_config8(dev, 0x51, 0x1f);
+
+ /* enable serial irq */
+ pci_write_config8(dev, 0x52, 0x9);
+
+ /* dma */
+ pci_write_config8(dev, 0x53, 0x00);
+
+ // Power management setup
+ setup_pm(dev);
+
+ /* set up isa bus -- i/o recovery time, rom write enable, extend-ale */
+ pci_write_config8(dev, 0x40, 0x54);
+
+ /* Enable HPET timer */
+ pci_write_config32(dev, 0x68, (1 << 31) | (HPET_ADDR >> 8));
+
+}
+
+void cx700_read_resources(device_t dev)
+{
+ struct resource *resource;
+
+ /* Make sure we call our childrens set/enable functions - these
+ * are not called unless this device has a resource to set.
+ */
+
+ pci_dev_read_resources(dev);
+
+ resource = new_resource(dev, 1);
+ resource->flags |=
+ IORESOURCE_FIXED | IORESOURCE_ASSIGNED | IORESOURCE_IO | IORESOURCE_STORED;
+ resource->size = 2;
+ resource->base = 0x2e;
+}
+
+void cx700_set_resources(device_t dev)
+{
+ struct resource *resource;
+ resource = find_resource(dev, 1);
+ resource->flags |= IORESOURCE_STORED;
+ pci_dev_set_resources(dev);
+}
+
+void cx700_enable_resources(device_t dev)
+{
+ /* Enable SuperIO decoding */
+ pci_dev_enable_resources(dev);
+ enable_childrens_resources(dev);
+}
+
+static void cx700_lpc_init(struct device *dev)
+{
+ cx700_set_lpc_registers(dev);
+
+#ifdef CONFIG_IOAPIC
+ setup_ioapic();
+#endif
+
+ /* Initialize interrupts */
+ pci_routing_fixup(dev);
+ /* make sure interupt controller is configured before keyboard init */
+ setup_i8259();
+
+ /* Start the Real Time Clock */
+ rtc_init(0);
+
+ /* Initialize isa dma */
+ isa_dma_init();
+
+ /* Initialize keyboard controller */
+ init_pc_keyboard(0x60, 0x64, 0);
+}
+
+static struct device_operations cx700_lpc_ops = {
+ .read_resources = cx700_read_resources,
+ .set_resources = cx700_set_resources,
+ .enable_resources = cx700_enable_resources,
+ .init = &cx700_lpc_init,
+ .scan_bus = scan_static_bus,
+};
+
+static const struct pci_driver lpc_driver __pci_driver = {
+ .ops = &cx700_lpc_ops,
+ .vendor = PCI_VENDOR_ID_VIA,
+ .device = 0x8324,
+};
diff --git a/src/northbridge/via/cx700/cx700_registers.h b/src/northbridge/via/cx700/cx700_registers.h
new file mode 100644
index 0000000000..996c00f015
--- /dev/null
+++ b/src/northbridge/via/cx700/cx700_registers.h
@@ -0,0 +1,272 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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
+ */
+
+/* CX700 has 48 bytes of scratch registers in D0F4 starting at Reg. 0xd0 */
+#define SCRATCH_REG_BASE 0xd0
+#define SCRATCH_RANK_0 0xd0
+#define SCRATCH_RANK_1 0xd1
+#define SCRATCH_RANK_2 0xd2
+#define SCRATCH_RANK_3 0xd3
+#define SCRATCH_DIMM_NUM 0xd4
+#define SCRATCH_RANK_NUM 0xd5
+#define SCRATCH_RANK_MAP 0xd6
+#define SCRATCH_DRAM_FREQ 0xd7
+#define SCRATCH_DRAM_NB_ODT 0xd8
+#define SCRATCH_RANK0_SIZE_REG 0xe0 /* RxE0~RxE3 */
+#define SCRATCH_RANK0_MA_REG 0xe4 /* RxE4~RxE7 */
+#define SCRATCH_CHA_DQSI_LOW_REG 0xe8
+#define SCRATCH_CHA_DQSI_HIGH_REG 0xe9
+#define SCRATCH_ChA_DQSI_REG 0xea
+#define SCRATCH_DRAM_256M_BIT 0xee
+#define SCRATCH_FLAGS 0xef
+
+static const u8 Reg_Val[] = {
+/* REG, VALUE */
+ 0x70, 0x33,
+ 0x71, 0x11,
+ 0x72, 0x33,
+ 0x73, 0x11,
+ 0x74, 0x20,
+ 0x75, 0x2e,
+ 0x76, 0x64,
+ 0x77, 0x00,
+ 0x78, 0x44,
+ 0x79, 0xaa,
+ 0x7a, 0x33,
+ 0x7b, 0xaa,
+ 0x7c, 0x00,
+ 0x7e, 0x33,
+ 0x7f, 0x33,
+ 0x80, 0x44,
+ 0x81, 0x44,
+ 0x82, 0x44,
+ 0x83, 0x02,
+ 0x50, 0x88,
+ 0x51, 0x7b,
+ 0x52, 0x6f,
+ 0x53, 0x88,
+ 0x54, 0x0e,
+ 0x55, 0x00,
+ 0x56, 0x00,
+ 0x59, 0x00,
+ 0x5d, 0x72,
+ 0x5e, 0x88,
+ 0x5f, 0xc7,
+ 0x68, 0x01,
+};
+
+/* Host registers initial value */
+static const u8 Host_Reg_Val[] = {
+/* REG, VALUE */
+ 0x60, 0xff,
+ 0x61, 0xff,
+ 0x62, 0x0f,
+ 0x63, 0xff,
+ 0x64, 0xff,
+ 0x65, 0x0f,
+ 0x66, 0xff,
+ 0x67, 0x30,
+};
+
+static const u8 Mem_Reg_Init[] = {
+/* REG, AND, OR */
+ 0x50, 0x11, 0x66,
+ 0x51, 0x11, 0x66,
+ 0x52, 0x00, 0x11,
+ 0x53, 0x00, 0x0f,
+ 0x54, 0x00, 0x00,
+ 0x55, 0x00, 0x00,
+ 0x56, 0x00, 0x00,
+ 0x57, 0x00, 0x00,
+ 0x60, 0x00, 0x00,
+ 0x62, 0xf7, 0x08,
+ 0x65, 0x00, 0xd9,
+ 0x66, 0x00, 0x80,
+ 0x67, 0x00, 0x50, /* OR 0x00 ?? */
+ 0x69, 0xf0, 0x00,
+ 0x6a, 0x00, 0x00,
+ 0x6d, 0xcf, 0xc0,
+ 0x6e, 0xff, 0x80,
+ 0x75, 0x0f, 0x40,
+ 0x77, 0x00, 0x00,
+ 0x80, 0x00, 0x00,
+ 0x81, 0x00, 0x00,
+ 0x82, 0x00, 0x00,
+ 0x83, 0x00, 0x00,
+ 0x84, 0x00, 0x00,
+ 0x85, 0x00, 0x00,
+ 0x86, 0xff, 0x2c, /* OR 0x28 if we don't want enable top 1M SM memory */
+ 0x40, 0x00, 0x00,
+ 0x7c, 0x00, 0x00,
+ 0x7e, 0x00, 0x00,
+ 0xa4, 0xfe, 0x00,
+ 0xb0, 0x7f, 0x80,
+ 0xb1, 0x00, 0xaa,
+ 0xb4, 0xfd, 0x02,
+ 0xb8, 0xfe, 0x00,
+};
+
+static const u8 Dram_Driving_ODT_CTRL[] = {
+/* REG, VALUE */
+ 0xd6, 0xa8,
+ 0xd4, 0x80,
+ 0xd0, 0x88,
+ 0xd3, 0x01,
+ 0xd8, 0x00,
+ 0xda, 0x80,
+};
+
+#define Rank0_ODT 0x00
+#define Rank1_ODT 0x01
+#define Rank2_ODT 0x02
+#define Rank3_ODT 0x03
+#define NA_ODT 0x00
+#define NB_ODT_75ohm 0x00
+#define NB_ODT_150ohm 0x01
+#define DDR2_ODT_75ohm 0x20
+#define DDR2_ODT_150ohm 0x40
+
+static const u8 ODT_TBL[] = {
+/* RankMap, ODT Control Bits, DRAM & NB ODT setting */
+ 0x01, ((NA_ODT << 6) | (NA_ODT << 4) | (NA_ODT << 2) | Rank0_ODT), (DDR2_ODT_150ohm | NB_ODT_75ohm),
+ 0x03, ((NA_ODT << 6) | (NA_ODT << 4) | (Rank0_ODT << 2) | Rank1_ODT), (DDR2_ODT_150ohm | NB_ODT_75ohm),
+ 0x04, ((NA_ODT << 6) | (Rank2_ODT << 4) | (NA_ODT << 2) | NA_ODT), (DDR2_ODT_150ohm | NB_ODT_75ohm),
+ 0x05, ((NA_ODT << 6) | (Rank0_ODT << 4) | (NA_ODT << 2) | Rank2_ODT), (DDR2_ODT_75ohm | NB_ODT_150ohm),
+ 0x07, ((NA_ODT << 6) | (Rank0_ODT << 4) | (Rank2_ODT << 2) | Rank2_ODT), (DDR2_ODT_75ohm | NB_ODT_150ohm),
+ 0x0c, ((Rank2_ODT << 6) | (Rank3_ODT << 4) | (NA_ODT << 2) | NA_ODT), (DDR2_ODT_150ohm | NB_ODT_75ohm),
+ 0x0d, ((Rank0_ODT << 6) | (Rank0_ODT << 4) | (NA_ODT << 2) | Rank2_ODT), (DDR2_ODT_75ohm | NB_ODT_150ohm),
+ 0x0f, ((Rank0_ODT << 6) | (Rank0_ODT << 4) | (Rank2_ODT << 2) | Rank2_ODT), (DDR2_ODT_75ohm | NB_ODT_150ohm),
+};
+
+static const u8 DQS_DQ_TBL[] = {
+/* RxE0: DRAM Timing DQS */
+/* RxE2: DRAM Timing DQ */
+/* RxE0, RxE2 */
+ 0xee, 0xba,
+ 0xee, 0xba,
+ 0xcc, 0xba,
+ 0xcc, 0xba,
+};
+
+static const u8 Duty_Control_DDR2[] = {
+/* RxEC, RxED, RxEE, RXEF */
+ /* DDRII533 1~2 rank, DDRII400 */
+ 0x84, 0x10, 0x00, 0x10,
+ /* DDRII533 3~4 rank */
+ 0x44, 0x10, 0x00, 0x10,
+};
+
+static const u8 ChA_Clk_Phase_DDR2_Table[] = {
+/* Rx91, Rx92, Rx93 */
+ /* DDRII533 1 rank */
+ 0x04, 0x05, 0x06,
+ /* DDRII533 2~4 rank */
+ 0x04, 0x05, 0x05,
+ /* DDRII400 */
+ 0x02, 0x04, 0x04,
+};
+
+static const u8 DQ_DQS_Table[] = {
+/* REG, VALUE */
+/* DRAM DQ/DQS Output Delay Control */
+ 0xdc, 0x65,
+ 0xdd, 0x01,
+ 0xde, 0xc0,
+/* DRAM DQ/DQS input Capture Control */
+ 0x78, 0x83,
+ 0x79, 0x83,
+ 0x7a, 0x00,
+};
+
+static const u8 DQSOChA_DDR2_Driving_Table[] = {
+/* Rx70, Rx71 */
+ /* DDRII533 1~2 rank */
+ 0x00, 0x01,
+ /* DDRII533 3~4 rank */
+ 0x03, 0x00,
+ /* DDRII400 1~2 rank */
+ 0x00, 0x04,
+ /* DDRII400 3~4 rank */
+ 0x00, 0x01,
+};
+
+/************************************************************************/
+/* Chipset Performance UP and other setting after DRAM Sizing Registers */
+/************************************************************************/
+static const u8 Dram_Table[] = {
+/* REG, AND, OR */
+ 0x60, 0xff, 0x03,
+ 0x66, 0xcf, 0x80,
+ 0x68, 0x00, 0x00,
+ 0x69, 0xfd, 0x03,
+ 0x6e, 0xff, 0x01,
+ 0x95, 0xff, 0x40,
+};
+
+static const u8 Host_Table[] = {
+/* REG, AND, OR */
+ 0x51, 0x81, 0x7a,
+ 0x55, 0xff, 0x06,
+ 0x5e, 0x00, 0x88,
+ 0x5d, 0xff, 0xb2,
+};
+
+static const u8 Init_Rank_Reg_Table[] = {
+ /* Rank Ending Address Registers */
+ 0x40, 0x41, 0x42, 0x43,
+ /* Rank Beginning Address Registers */
+ 0x48, 0x49, 0x4a, 0x4b,
+ /* Physical-to-Virtual Rank Mapping Registers */
+ 0x54, 0x55,
+};
+
+static const u16 DDR2_MRS_table[] = {
+/* CL: 2, 3, 4, 5 */
+ 0x150, 0x1d0, 0x250, 0x2d0, /* BL=4 ;Use 1X-bandwidth MA table to init DRAM */
+ 0x158, 0x1d8, 0x258, 0x2d8, /* BL=8 ;Use 1X-bandwidth MA table to init DRAM */
+};
+
+#define MRS_DDR2_TWR2 ((0 << 15) | (0 << 20) | (1 << 12))
+#define MRS_DDR2_TWR3 ((0 << 15) | (1 << 20) | (0 << 12))
+#define MRS_DDR2_TWR4 ((0 << 15) | (1 << 20) | (1 << 12))
+#define MRS_DDR2_TWR5 ((1 << 15) | (0 << 20) | (0 << 12))
+static const u32 DDR2_Twr_table[] = {
+ MRS_DDR2_TWR2,
+ MRS_DDR2_TWR3,
+ MRS_DDR2_TWR4,
+ MRS_DDR2_TWR5,
+};
+
+static const u8 DQSI_Rate_Table[] = {
+ 8, /* DDRII 200 */
+ 8, /* DDRII 266 */
+ 8, /* DDRII 333 */
+ 7, /* DDRII 400 */
+ 8, /* DDRII 533 */
+ 8, /* DDRII 666 */
+};
+
+static const u8 REFC_Table[] = {
+ 0x65, 0x32, /* DDRII 100 */
+ 0x86, 0x43, /* DDRII 266 */
+ 0xa8, 0x54, /* DDRII 333 */
+ 0xca, 0x65, /* DDRII 400 */
+ 0xca, 0x86, /* DDRII 533 */
+ 0xca, 0xa8, /* DDRII 666 */
+};
diff --git a/src/northbridge/via/cx700/cx700_reset.c b/src/northbridge/via/cx700/cx700_reset.c
new file mode 100644
index 0000000000..80e09d7fab
--- /dev/null
+++ b/src/northbridge/via/cx700/cx700_reset.c
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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 <arch/io.h>
+
+void hard_reset(void)
+{
+ outb((1 << 2) | (1 << 1), 0xcf9);
+}
diff --git a/src/northbridge/via/cx700/cx700_sata.c b/src/northbridge/via/cx700/cx700_sata.c
new file mode 100644
index 0000000000..893126606e
--- /dev/null
+++ b/src/northbridge/via/cx700/cx700_sata.c
@@ -0,0 +1,160 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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 <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+/* IDE specific bits */
+#define IDE_MODE_REG 0x09
+#define IDE0_NATIVE_MODE (1 << 0)
+#define IDE1_NATIVE_MODE (1 << 2)
+
+/* These are default addresses */
+#define IDE0_DATA_ADDR 0x1f0
+#define IDE0_CONTROL_ADDR 0x3f4
+#define IDE1_DATA_ADDR 0x170
+#define IDE1_CONTROL_ADDR 0x370
+
+#define BUS_MASTER_ADDR 0xfc00
+
+#define CHANNEL_ENABLE_REG 0x40
+#define ENABLE_IDE0 (1 << 0)
+#define ENABLE_IDE1 (1 << 1)
+
+/* TODO: better user configuration */
+#define DISABLE_SATA 0
+
+static void sata_init(struct device *dev)
+{
+ u8 reg8;
+
+ printk_debug("Configuring VIA SATA & EIDE Controller\n");
+
+ /* Class IDE Disk, instead of RAID controller */
+ reg8 = pci_read_config8(dev, 0x45);
+ reg8 &= 0x7f; /* Sub Class Write Protect off */
+ pci_write_config8(dev, 0x45, reg8);
+ pci_write_config8(dev, 0x0a, 0x01);
+ reg8 |= 0x80; /* Sub Class Write Protect on */
+ pci_write_config8(dev, 0x45, reg8);
+
+#if defined(DISABLE_SATA) && (DISABLE_SATA == 1)
+ printk_info("Disabling SATA (Primary Channel)\n");
+ /* Disable SATA channels */
+ pci_write_config8(dev, 0x40, 0x00);
+#else
+ pci_write_config8(dev, 0x40, 0x43);
+#endif
+
+ reg8 = pci_read_config8(dev, 0x6a);
+ reg8 |= 0x8; /* Mode Select set to Manual Mode */
+ reg8 &= ~7;
+ reg8 |= 0x2; /* Manual setting to 50 ohm */
+
+ pci_write_config8(dev, 0x6a, reg8);
+
+ reg8 = pci_read_config8(dev, 0x6b);
+ reg8 &= ~7;
+ reg8 |= 0x01; /* Autocomp of Termination */
+ pci_write_config8(dev, 0x6b, reg8);
+
+ /* Enable EIDE (secondary channel) even if SATA disabled */
+ reg8 = pci_read_config8(dev, 0xc0);
+ reg8 |= 0x1;
+ pci_write_config8(dev, 0xc0, reg8);
+
+ // Enable bus mastering, memory space acces, io space access
+ pci_write_config16(dev, 0x04, 0x0007);
+
+ /* Set SATA base ports. */
+ pci_write_config32(dev, 0x10, 0x01f1);
+ pci_write_config32(dev, 0x14, 0x03f5);
+ /* Set EIDE base ports. */
+ pci_write_config32(dev, 0x18, 0x0171);
+ pci_write_config32(dev, 0x1c, 0x0375);
+
+ /* SATA/EIDE Bus Master mode base address */
+ pci_write_config32(dev, 0x20, BUS_MASTER_ADDR | 1);
+
+ /* Enable read/write prefetch buffers */
+ reg8 = pci_read_config8(dev, 0xc1);
+ reg8 |= 0x30;
+ pci_write_config8(dev, 0xc1, reg8);
+
+ /* Set FIFO thresholds like */
+ pci_write_config8(dev, 0xc3, 0x1); /* FIFO flushed when 1/2 full */
+
+ /* EIDE Sector Size */
+ pci_write_config16(dev, 0xe8, 0x200);
+
+ /* Some Miscellaneous Control */
+ pci_write_config8(dev, 0x44, 0x7);
+ pci_write_config8(dev, 0x45, 0xaf);
+ pci_write_config8(dev, 0x46, 0x8);
+
+ /* EIDE Configuration */
+ reg8 = pci_read_config8(dev, 0xc4);
+ reg8 |= 0x10;
+ pci_write_config8(dev, 0xc4, reg8);
+
+ pci_write_config8(dev, 0xc5, 0xc);
+
+ /* Interrupt Line */
+ reg8 = pci_read_config8(dev, 0x45);
+ reg8 &= ~(1 << 4); /* Interrupt Line Write Protect off */
+ pci_write_config8(dev, 0x45, reg8);
+
+ pci_write_config8(dev, 0x3c, 0x0e); /* Interrupt */
+
+ /* Set the drive timing control */
+ pci_write_config16(dev, 0x48, 0x5d5d);
+
+ /* Enable only compatibility mode. */
+ reg8 = pci_read_config8(dev, 0x42);
+ reg8 &= ~0xa0;
+ pci_write_config8(dev, 0x42, reg8);
+ reg8 = pci_read_config8(dev, 0x42);
+ printk_debug("Reg 0x42 read back as 0x%x\n", reg8);
+
+ /* Support Staggered Spin-Up */
+ reg8 = pci_read_config8(dev, 0xb9);
+ if ((reg8 & 0x8) == 0) {
+ printk_debug("start OOB sequence on both drives\n");
+ reg8 |= 0x30;
+ pci_write_config8(dev, 0xb9, reg8);
+ }
+}
+
+static struct device_operations sata_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = sata_init,
+ .enable = 0,
+ .ops_pci = 0,
+};
+
+/* When the SATA controller is in IDE mode, the Device ID is 0x5324 */
+static const struct pci_driver northbridge_driver __pci_driver = {
+ .ops = &sata_ops,
+ .vendor = PCI_VENDOR_ID_VIA,
+ .device = 0x5324,
+};
diff --git a/src/northbridge/via/cx700/cx700_usb.c b/src/northbridge/via/cx700/cx700_usb.c
new file mode 100644
index 0000000000..b2dc482df3
--- /dev/null
+++ b/src/northbridge/via/cx700/cx700_usb.c
@@ -0,0 +1,56 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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 <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+
+static void usb_init(struct device *dev)
+{
+ u32 reg32;
+ u8 reg8;
+
+ /* USB Specification says the device must be Bus Master */
+ printk_debug("UHCI: Setting up controller.. ");
+
+ reg32 = pci_read_config32(dev, PCI_COMMAND);
+ pci_write_config32(dev, PCI_COMMAND, reg32 | PCI_COMMAND_MASTER);
+
+ reg8 = pci_read_config8(dev, 0xca);
+ reg8 |= (1 << 0);
+ pci_write_config8(dev, 0xca, reg8);
+
+ printk_debug("done.\n");
+}
+
+static struct device_operations usb_ops = {
+ .read_resources = pci_dev_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = usb_init,
+ .enable = 0,
+ .ops_pci = 0,
+};
+
+static const struct pci_driver via_usb_driver __pci_driver = {
+ .ops = &usb_ops,
+ .vendor = PCI_VENDOR_ID_VIA,
+ .device = 0x3038,
+};
diff --git a/src/northbridge/via/cx700/cx700_vga.c b/src/northbridge/via/cx700/cx700_vga.c
new file mode 100644
index 0000000000..96bb769e20
--- /dev/null
+++ b/src/northbridge/via/cx700/cx700_vga.c
@@ -0,0 +1,119 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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 <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/cpu.h>
+#include <cpu/x86/mtrr.h>
+#include <cpu/x86/msr.h>
+#include "chip.h"
+#include "northbridge.h"
+
+/* PCI Domain 1 Device 0 Function 0 */
+
+#define SR_INDEX 0x3c4
+#define SR_DATA 0x3c5
+#define CRTM_INDEX 0x3b4
+#define CRTM_DATA 0x3b5
+#define CRTC_INDEX 0x3d4
+#define CRTC_DATA 0x3d5
+
+void setup_realmode_idt(void);
+void do_vgabios(void);
+void vga_enable_console(void);
+
+void write_protect_vgabios(void)
+{
+ device_t dev;
+
+ printk_debug("write_protect_vgabios\n");
+
+ dev = dev_find_device(PCI_VENDOR_ID_VIA, 0x3324, 0);
+ if (dev)
+ pci_write_config8(dev, 0x80, 0xff);
+
+ dev = dev_find_device(PCI_VENDOR_ID_VIA, 0x7324, 0);
+ if (dev)
+ pci_write_config8(dev, 0x61, 0xff);
+}
+
+static void vga_init(device_t dev)
+{
+ u8 reg8;
+
+ printk_debug("Initializing VGA...\n");
+
+ //*
+ pci_write_config8(dev, 0x04, 0x07);
+ pci_write_config8(dev, 0x3e, 0x02);
+ pci_write_config8(dev, 0x0d, 0x40);
+ pci_write_config32(dev, 0x10, 0xa0000008);
+ pci_write_config32(dev, 0x14, 0xdd000000);
+ pci_write_config8(dev, 0x3c, 0x0b);
+ //*/
+
+ printk_debug("Executing VGA option rom in real mode\n");
+ setup_realmode_idt();
+ do_vgabios();
+ printk_debug("Enable VGA console\n");
+ vga_enable_console();
+
+ /* It's not clear if these need to be programmed before or after
+ * the VGA bios runs. Try both, clean up later */
+ /* Set memory rate to 200MHz */
+ outb(0x3d, CRTM_INDEX);
+ reg8 = inb(CRTM_DATA);
+ reg8 &= 0x0f;
+ reg8 |= (0x3 << 4);
+ outb(0x3d, CRTM_INDEX);
+ outb(reg8, CRTM_DATA);
+
+ /* Set framebuffer size to 32mb */
+ reg8 = (32 / 4);
+ outb(0x39, SR_INDEX);
+ outb(reg8, SR_DATA);
+}
+
+static void vga_read_resources(device_t dev)
+{
+ dev->rom_address = 0xfff80000;
+ dev->on_mainboard = 1;
+ pci_dev_read_resources(dev);
+}
+
+static struct device_operations vga_operations = {
+ .read_resources = vga_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_dev_enable_resources,
+ .init = vga_init,
+ .ops_pci = 0,
+};
+
+static const struct pci_driver vga_driver __pci_driver = {
+ .ops = &vga_operations,
+ .vendor = PCI_VENDOR_ID_VIA,
+ .device = 0x3157,
+};
diff --git a/src/northbridge/via/cx700/northbridge.c b/src/northbridge/via/cx700/northbridge.c
new file mode 100644
index 0000000000..dc0c667d10
--- /dev/null
+++ b/src/northbridge/via/cx700/northbridge.c
@@ -0,0 +1,182 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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 <console/console.h>
+#include <arch/io.h>
+#include <stdint.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/hypertransport.h>
+#include <device/pci_ids.h>
+#include <stdlib.h>
+#include <string.h>
+#include <bitops.h>
+#include <cpu/cpu.h>
+#include <cpu/x86/mtrr.h>
+#include "chip.h"
+#include "northbridge.h"
+
+static void pci_domain_read_resources(device_t dev)
+{
+ struct resource *resource;
+
+ /* Initialize the system wide io space constraints */
+ resource = new_resource(dev, IOINDEX_SUBTRACTIVE(0, 0));
+ resource->limit = 0xffffUL;
+ resource->flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
+
+ /* Initialize the system wide memory resources constraints */
+ resource = new_resource(dev, IOINDEX_SUBTRACTIVE(1, 0));
+ resource->limit = 0xffffffffULL;
+ resource->flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
+}
+
+static void ram_resource(device_t dev, unsigned long index,
+ unsigned long basek, unsigned long sizek)
+{
+ struct resource *resource;
+
+ if (!sizek) {
+ return;
+ }
+ resource = new_resource(dev, index);
+ resource->base = ((resource_t) basek) << 10;
+ resource->size = ((resource_t) sizek) << 10;
+ resource->flags = IORESOURCE_MEM | IORESOURCE_CACHEABLE |
+ IORESOURCE_FIXED | IORESOURCE_STORED | IORESOURCE_ASSIGNED;
+}
+
+static void tolm_test(void *gp, struct device *dev, struct resource *new)
+{
+ struct resource **best_p = gp;
+ struct resource *best;
+ best = *best_p;
+ if (!best || (best->base > new->base)) {
+ best = new;
+ }
+ *best_p = best;
+}
+
+static u32 find_pci_tolm(struct bus *bus)
+{
+ struct resource *min = NULL;
+ u32 tolm;
+
+ search_bus_resources(bus, IORESOURCE_MEM, IORESOURCE_MEM, tolm_test, &min);
+ tolm = 0xffffffffUL;
+ if (min && tolm > min->base) {
+ tolm = min->base;
+ }
+
+ return tolm;
+}
+
+static void pci_domain_set_resources(device_t dev)
+{
+ device_t mc_dev;
+ u32 pci_tolm;
+ unsigned char reg;
+ unsigned long tomk, tolmk;
+ unsigned char rambits;
+ int idx;
+
+ pci_tolm = find_pci_tolm(&dev->link[0]);
+ mc_dev = dev_find_device(PCI_VENDOR_ID_VIA, 0x3324, 0);
+
+ rambits = pci_read_config8(mc_dev, 0x88);
+ rambits >>= 2;
+
+ /* Get memory size and frame buffer from northbridge's registers.
+ *
+ * If register contains an invalid value we set frame buffer size to a
+ * default of 32M, but that probably won't happen.
+ */
+ reg = pci_read_config8(mc_dev, 0xa1);
+ reg &= 0x70;
+ reg = reg >> 4;
+
+ /* TOP 1M SMM Memory */
+ if (reg == 0x0 || reg == 0x6 || reg == 0x7)
+ tomk = (((rambits << 6) - 32 - 1) * 1024); // Set frame buffer 32M for default
+ else
+ tomk = (((rambits << 6) - (4 << reg) - 1) * 1024);
+
+ /* Compute the top of Low memory */
+ tolmk = pci_tolm >> 10;
+ if (tolmk >= tomk) {
+ /* The PCI hole does does not overlap the memory. */
+ tolmk = tomk;
+ tolmk -= 1024; // TOP 1M SM Memory
+ }
+
+ /* Report the memory regions */
+ idx = 10;
+
+ /* TODO: Hole needed? Should this go elsewhere? */
+ ram_resource(dev, idx++, 0, 640); /* first 640k */
+ ram_resource(dev, idx++, 768, (tolmk - 768)); /* leave a hole for vga */
+ assign_resources(&dev->link[0]);
+}
+
+static unsigned int pci_domain_scan_bus(device_t dev, unsigned int max)
+{
+ max = pci_scan_bus(&dev->link[0], PCI_DEVFN(0, 0), 0xff, max);
+ return max;
+}
+
+static struct device_operations pci_domain_ops = {
+ .read_resources = pci_domain_read_resources,
+ .set_resources = pci_domain_set_resources,
+ .enable_resources = enable_childrens_resources,
+ .init = 0,
+ .scan_bus = pci_domain_scan_bus,
+};
+
+static void cpu_bus_init(device_t dev)
+{
+ initialize_cpus(&dev->link[0]);
+}
+
+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)
+{
+ /* Our wonderful device model */
+ 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_via_cx700_ops = {
+ CHIP_NAME("VIA CX700 Northbridge")
+ .enable_dev = enable_dev
+};
diff --git a/src/northbridge/via/cx700/northbridge.h b/src/northbridge/via/cx700/northbridge.h
new file mode 100644
index 0000000000..1048a96643
--- /dev/null
+++ b/src/northbridge/via/cx700/northbridge.h
@@ -0,0 +1,25 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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
+ */
+
+#ifndef NORTHBRIDGE_VIA_CX700_H
+#define NORTHBRIDGE_VIA_CX700_H
+
+extern unsigned int cx700_scan_root_bus(device_t root, unsigned int max);
+
+#endif /* NORTHBRIDGE_VIA_CX700_H */
diff --git a/src/northbridge/via/cx700/raminit.c b/src/northbridge/via/cx700/raminit.c
new file mode 100644
index 0000000000..ff21e537ca
--- /dev/null
+++ b/src/northbridge/via/cx700/raminit.c
@@ -0,0 +1,1480 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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 <types.h>
+#include <spd.h>
+#include <spd_ddr2.h>
+#include <sdram_mode.h>
+#include <delay.h>
+#include "cx700_registers.h"
+
+// #define DEBUG_RAM_SETUP 1
+
+/* Debugging macros. */
+#if defined(DEBUG_RAM_SETUP)
+#define PRINTK_DEBUG(x...) printk_debug(x)
+#else
+#define PRINTK_DEBUG(x...)
+#endif
+
+#define RAM_COMMAND_NORMAL 0x0
+#define RAM_COMMAND_NOP 0x1
+#define RAM_COMMAND_PRECHARGE 0x2
+#define RAM_COMMAND_MRS 0x3
+#define RAM_COMMAND_CBR 0x4
+
+#define HOSTCTRL PCI_DEV(0, 0, 2)
+#define MEMCTRL PCI_DEV(0, 0, 3)
+
+#define DDRII_666 0x5
+#define DDRII_533 0x4
+#define DDRII_400 0x3
+#define DDRII_333 0x2
+#define DDRII_266 0x1
+#define DDRII_200 0x0
+
+#define OHM_150 1
+
+#ifdef MEM_WIDTH_32BIT_MODE
+#define SDRAM1X_RA_14 30
+#define SDRAM1X_RA_13 29
+#define SDRAM1X_RA_12 28
+#define SDRAM1X_RA_12_8bk 26
+#define SDRAM1X_CA_12 15
+#define SDRAM1X_CA_11 14
+#define SDRAM1X_CA_09 11
+#define SDRAM1X_CA_09_8bk 11
+#define SDRAM1X_BA1 13
+#define SDRAM1X_BA2_8bk 14
+#define SDRAM1X_BA1_8bk 13
+#else
+#define SDRAM1X_RA_14 31
+#define SDRAM1X_RA_13 30
+#define SDRAM1X_RA_12 29
+#define SDRAM1X_RA_12_8bk 27
+#define SDRAM1X_CA_12 16
+#define SDRAM1X_CA_11 15
+#define SDRAM1X_CA_09 12
+#define SDRAM1X_CA_09_8bk 12
+#define SDRAM1X_BA1 14
+#define SDRAM1X_BA2_8bk 15
+#define SDRAM1X_BA1_8bk 14
+#endif
+
+#define MA_Column 0x06
+#define MA_Bank 0x08
+#define MA_Row 0x30
+#define MA_4_Bank 0x00
+#define MA_8_Bank 0x08
+#define MA_12_Row 0x00
+#define MA_13_Row 0x10
+#define MA_14_Row 0x20
+#define MA_15_Row 0x30
+#define MA_9_Column 0x00
+#define MA_10_Column 0x02
+#define MA_11_Column 0x04
+#define MA_12_Column 0x06
+
+#define GET_SPD(i, val, tmp, reg) \
+ do{ \
+ val = 0; \
+ tmp = 0; \
+ for(i = 0; i < 2; i++) { \
+ if(pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_REG_BASE + (i << 1)))) { \
+ tmp = get_spd_data(ctrl, i, reg); \
+ if(tmp > val) \
+ val = tmp; \
+ } \
+ } \
+ } while ( 0 )
+
+#define REGISTERPRESET(bus,dev,fun,bdfspec) \
+ { u8 i, reg; \
+ for (i=0; i<(sizeof((bdfspec))/sizeof(struct regmask)); i++) { \
+ printk_debug("Writing bus " #bus " dev " #dev " fun " #fun " register "); \
+ printk_debug("%02x", (bdfspec)[i].reg); \
+ printk_debug("\n"); \
+ reg = pci_read_config8(PCI_DEV((bus), (dev), (fun)), (bdfspec)[i].reg); \
+ reg &= (bdfspec)[i].mask; \
+ reg |= (bdfspec)[i].val; \
+ pci_write_config8(PCI_DEV((bus), (dev), (fun)), (bdfspec)[i].reg, reg); \
+ } \
+ }
+
+
+static void do_ram_command(const struct mem_controller *ctrl, u8 command)
+{
+ u8 reg;
+
+ reg = pci_read_config8(MEMCTRL, 0x6b);
+ reg &= 0xf8; /* Clear bits 2-0. */
+ reg |= command;
+ pci_write_config8(MEMCTRL, 0x6b, reg);
+
+ PRINTK_DEBUG(" Sending RAM command 0x%02x\n", reg);
+}
+
+// TODO factor out to another file
+static void c7_cpu_setup(const struct mem_controller *ctrl)
+{
+ u8 size, i;
+ size = sizeof(Reg_Val) / sizeof(Reg_Val[0]);
+ for (i = 0; i < size; i += 2)
+ pci_write_config8(HOSTCTRL, Reg_Val[i], Reg_Val[i + 1]);
+}
+
+static void ddr_detect(const struct mem_controller *ctrl)
+{
+ /* FIXME: Only supports 2 ranks per DIMM */
+ u8 val, rsize, dimm;
+ u8 nrank = 0;
+ u8 ndimm = 0;
+ u8 rmap = 0;
+ for (dimm = 0; dimm < DIMM_SOCKETS; dimm++) {
+ val = get_spd_data(ctrl, dimm, 0);
+ if ((val == 0x80) || (val == 0xff)) {
+ ndimm++;
+ rsize = get_spd_data(ctrl, dimm, SPD_RANK_SIZE);
+ /* unit is 128M */
+ rsize = (rsize << 3) | (rsize >> 5);
+ val =
+ get_spd_data(ctrl, dimm,
+ SPD_MOD_ATTRIB_RANK) & SPD_MOD_ATTRIB_RANK_NUM_MASK;
+ switch (val) {
+ case 1:
+ pci_write_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK_1 + (dimm << 1)),
+ rsize);
+ rmap |= (1 << ((dimm << 1) + 1));
+ nrank++;
+ case 0:
+ pci_write_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK_0 + (dimm << 1)),
+ rsize);
+ rmap |= (1 << (dimm << 1));
+ nrank++;
+ }
+ }
+ }
+ pci_write_config8(PCI_DEV(0, 0, 4), SCRATCH_DIMM_NUM, ndimm);
+ pci_write_config8(PCI_DEV(0, 0, 4), SCRATCH_RANK_NUM, nrank);
+ pci_write_config8(PCI_DEV(0, 0, 4), SCRATCH_RANK_MAP, rmap);
+}
+
+static void sdram_set_safe_values(const struct mem_controller *ctrl)
+{
+ /* The purpose of this function is to set initial values for the dram
+ * size and timings. It will be replaced with the SPD based function
+ * once the RAM commands are working with these values.
+ */
+ u8 regs, val, t, dimm;
+ u32 spds, tmp;
+
+ regs = pci_read_config8(MEMCTRL, 0x6c);
+ if (regs & (1 << 6))
+ printk_debug("DDR2 Detected.\n");
+ else
+ die("ERROR: DDR1 memory detected but not supported by coreboot.\n");
+
+ /* Enable DDR2 */
+ regs |= (1 << 7);
+ pci_write_config8(MEMCTRL, 0x6c, regs);
+
+ /* SPD 5 # of ranks */
+ pci_write_config8(MEMCTRL, 0x6d, 0xc0);
+
+ /**********************************************/
+ /* Set DRAM Freq (DDR2 533) */
+ /**********************************************/
+ /* SPD 9 SDRAM Cycle Time */
+ GET_SPD(dimm, spds, regs, 9);
+
+ printk_debug("\nDDRII ");
+ if (spds <= 0x3d) {
+ printk_debug("533");
+ val = DDRII_533;
+ t = 38;
+ } else if (spds <= 0x50) {
+ printk_debug("400");
+ val = DDRII_400;
+ t = 50;
+ } else if (spds <= 0x60) {
+ printk_debug("333");
+ val = DDRII_333;
+ t = 60;
+ } else if (spds <= 0x75) {
+ printk_debug("266");
+ val = DDRII_266;
+ t = 75;
+ } else {
+ printk_debug("200");
+ val = DDRII_200;
+ t = 100;
+ }
+ /* To store DDRII frequence */
+ pci_write_config8(PCI_DEV(0, 0, 4), SCRATCH_DRAM_FREQ, val);
+
+ /* Manual reset and adjust DLL when DRAM change frequency
+ * This is a necessary sequence.
+ */
+ udelay(2000);
+ regs = pci_read_config8(MEMCTRL, 0x90);
+ regs |= 0x7;
+ pci_write_config8(MEMCTRL, 0x90, regs);
+ udelay(2000);
+ regs = pci_read_config8(MEMCTRL, 0x90);
+ regs &= ~0x7;
+ regs |= val;
+ pci_write_config8(MEMCTRL, 0x90, regs);
+ udelay(2000);
+ regs = pci_read_config8(MEMCTRL, 0x6b);
+ regs |= 0xc0;
+ regs &= ~0x10;
+ pci_write_config8(MEMCTRL, 0x6b, regs);
+ udelay(1);
+ regs |= 0x10;
+ pci_write_config8(MEMCTRL, 0x6b, regs);
+ udelay(1);
+ regs &= ~0xc0;
+ pci_write_config8(MEMCTRL, 0x6b, regs);
+ regs = pci_read_config8(MEMCTRL, 0x6f);
+ regs |= 0x1;
+ pci_write_config8(MEMCTRL, 0x6f, regs);
+
+ /**********************************************/
+ /* Set DRAM Timing Setting (DDR2 533) */
+ /**********************************************/
+ /* SPD 9 18 23 25 CAS Latency NB3DRAM_REG62[2:0] */
+ /* Read SPD byte 18 CAS Latency */
+ GET_SPD(dimm, spds, regs, SPD_CAS_LAT);
+ printk_debug("\nCAS Supported ");
+ if (spds & SPD_CAS_LAT_2)
+ printk_debug("2 ");
+ if (spds & SPD_CAS_LAT_3)
+ printk_debug("3 ");
+ if (spds & SPD_CAS_LAT_4)
+ printk_debug("4 ");
+ if (spds & SPD_CAS_LAT_5)
+ printk_debug("5 ");
+ if (spds & SPD_CAS_LAT_6)
+ printk_debug("6");
+
+ /* We don't consider CAS = 6, because CX700 doesn't support it */
+ printk_debug("\n CAS:");
+ if (spds & SPD_CAS_LAT_5) {
+ printk_debug("Starting at CL5");
+ val = 0x3;
+ /* See whether we can improve it */
+ GET_SPD(dimm, tmp, regs, SPD_CAS_LAT_MIN_X_1);
+ if ((spds & SPD_CAS_LAT_4) && (tmp < 0x50)) {
+ printk_debug("\n... going to CL4");
+ val = 0x2;
+ }
+ GET_SPD(dimm, tmp, regs, SPD_CAS_LAT_MIN_X_2);
+ if ((spds & SPD_CAS_LAT_3) && (tmp < 0x50)) {
+ printk_debug("\n... going to CL3");
+ val = 0x1;
+ }
+ } else {
+ printk_debug("Starting at CL4");
+ val = 0x2;
+ GET_SPD(dimm, tmp, regs, SPD_CAS_LAT_MIN_X_1);
+ if ((spds & SPD_CAS_LAT_3) && (tmp < 0x50)) {
+ printk_debug("\n... going to CL3");
+ val = 0x1;
+ }
+ GET_SPD(dimm, tmp, regs, SPD_CAS_LAT_MIN_X_2);
+ if ((spds & SPD_CAS_LAT_2) && (tmp < 0x50)) {
+ printk_debug("\n... going to CL2");
+ val = 0x0;
+ }
+ }
+ regs = pci_read_config8(MEMCTRL, 0x62);
+ regs &= ~0x7;
+ regs |= val;
+ pci_write_config8(MEMCTRL, 0x62, regs);
+
+ /* SPD 27 Trp NB3DRAM_REG64[3:2] */
+ GET_SPD(dimm, spds, regs, SPD_TRP);
+ printk_debug("\nTrp %d", spds);
+ spds >>= 2;
+ for (val = 2; val <= 5; val++) {
+ if (spds <= (val * t / 10)) {
+ val = val - 2;
+ break;
+ }
+ }
+ val <<= 2;
+ regs = pci_read_config8(MEMCTRL, 0x64);
+ regs &= ~0xc;
+ regs |= val;
+ pci_write_config8(MEMCTRL, 0x64, regs);
+
+ /* SPD 29 Trcd NB3DRAM_REG64[7:6] */
+ GET_SPD(dimm, spds, regs, SPD_TRCD);
+ printk_debug("\nTrcd %d", spds);
+ spds >>= 2;
+ for (val = 2; val <= 5; val++) {
+ if (spds <= (val * t / 10)) {
+ val = val - 2;
+ break;
+ }
+ }
+ val <<= 6;
+ regs = pci_read_config8(MEMCTRL, 0x64);
+ regs &= ~0xc0;
+ regs |= val;
+ pci_write_config8(MEMCTRL, 0x64, regs);
+
+ /* SPD 30 Tras NB3DRAM_REG62[7:4] */
+ GET_SPD(dimm, spds, regs, SPD_TRAS);
+ printk_debug("\nTras %d", spds);
+ for (val = 5; val <= 20; val++) {
+ if (spds <= (val * t / 10)) {
+ val = val - 5;
+ break;
+ }
+ }
+ val <<= 4;
+ regs = pci_read_config8(MEMCTRL, 0x62);
+ regs &= ~0xf0;
+ regs |= val;
+ pci_write_config8(MEMCTRL, 0x62, regs);
+
+ /* SPD 42 SPD 40 Trfc NB3DRAM_REG61[5:0] */
+ GET_SPD(dimm, spds, regs, SPD_TRFC);
+ printk_debug("\nTrfc %d", spds);
+ tmp = spds;
+ GET_SPD(dimm, spds, regs, SPD_EX_TRC_TRFC);
+ if (spds & 0x1)
+ tmp += 256;
+ if (spds & 0xe)
+ tmp++;
+ for (val = 8; val <= 71; val++) {
+ if (tmp <= (val * t / 10)) {
+ val = val - 8;
+ break;
+ }
+ }
+ regs = pci_read_config8(MEMCTRL, 0x61);
+ regs &= ~0x3f;
+ regs |= val;
+ pci_write_config8(MEMCTRL, 0x61, regs);
+
+ /* SPD 28 Trrd NB3DRAM_REG63[7:6] */
+ GET_SPD(dimm, spds, regs, SPD_TRRD);
+ for (val = 2; val <= 5; val++) {
+ if (spds <= (val * t / 10)) {
+ val = val - 2;
+ break;
+ }
+ }
+ val <<= 6;
+ printk_debug("\nTrrd val = 0x%x", val);
+ regs = pci_read_config8(MEMCTRL, 0x63);
+ regs &= ~0xc0;
+ regs |= val;
+ pci_write_config8(MEMCTRL, 0x63, regs);
+
+ /* SPD 36 Twr NB3DRAM_REG61[7:6] */
+ GET_SPD(dimm, spds, regs, SPD_TWR);
+ for (val = 2; val <= 5; val++) {
+ if (spds <= (val * t / 10)) {
+ val = val - 2;
+ break;
+ }
+ }
+ val <<= 6;
+ printk_debug("\nTwr val = 0x%x", val);
+
+ regs = pci_read_config8(MEMCTRL, 0x61);
+ regs &= ~0xc0;
+ regs |= val;
+ pci_write_config8(MEMCTRL, 0x61, regs);
+
+ /* SPD 37 Twtr NB3DRAM_REG63[1] */
+ GET_SPD(dimm, spds, regs, SPD_TWTR);
+ spds >>= 2;
+ printk_debug("\nTwtr 0x%x", spds);
+ if (spds <= (t * 2 / 10))
+ val = 0;
+ else
+ val = 1;
+ val <<= 1;
+ printk_debug("\nTwtr val = 0x%x", val);
+
+ regs = pci_read_config8(MEMCTRL, 0x63);
+ regs &= ~0x2;
+ regs |= val;
+ pci_write_config8(MEMCTRL, 0x63, regs);
+
+ /* SPD 38 Trtp NB3DRAM_REG63[3] */
+ GET_SPD(dimm, spds, regs, SPD_TRTP);
+ spds >>= 2;
+ printk_debug("\nTrtp 0x%x", spds);
+ if (spds <= (t * 2 / 10))
+ val = 0;
+ else
+ val = 1;
+ val <<= 3;
+ printk_debug("\nTrtp val = 0x%x", val);
+
+ regs = pci_read_config8(MEMCTRL, 0x63);
+ regs &= ~0x8;
+ regs |= val;
+ pci_write_config8(MEMCTRL, 0x63, regs);
+
+ /**********************************************/
+ /* Set DRAM DRDY Setting */
+ /**********************************************/
+ /* Write slowest value to register */
+ tmp = sizeof(Host_Reg_Val) / sizeof(Host_Reg_Val[0]);
+ for (val = 0; val < tmp; val += 2)
+ pci_write_config8(HOSTCTRL, Host_Reg_Val[val], Host_Reg_Val[val + 1]);
+
+ /* F2_RX51[7]=0, disable DRDY timing */
+ regs = pci_read_config8(HOSTCTRL, 0x51);
+ regs &= ~0x80;
+ pci_write_config8(HOSTCTRL, 0x51, regs);
+
+ /**********************************************/
+ /* Set DRAM BurstLength */
+ /**********************************************/
+ regs = pci_read_config8(MEMCTRL, 0x6c);
+ for (dimm = 0; dimm < DIMM_SOCKETS; dimm++) {
+ if (pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_REG_BASE + (dimm << 1)))) {
+ spds = get_spd_data(ctrl, dimm, 16);
+ if (!(spds & 0x8))
+ break;
+ }
+ }
+ if (dimm == 2)
+ regs |= 0x8;
+ pci_write_config8(MEMCTRL, 0x6c, regs);
+ val = pci_read_config8(HOSTCTRL, 0x54);
+ val &= ~0x10;
+ if (dimm == 2)
+ val |= 0x10;
+ pci_write_config8(HOSTCTRL, 0x54, val);
+
+ /**********************************************/
+ /* Set DRAM Driving Setting */
+ /**********************************************/
+ /* DRAM Timing ODT */
+ tmp = sizeof(Dram_Driving_ODT_CTRL) / sizeof(Dram_Driving_ODT_CTRL[0]);
+ for (val = 0; val < tmp; val += 2)
+ pci_write_config8(MEMCTRL, Dram_Driving_ODT_CTRL[val],
+ Dram_Driving_ODT_CTRL[val + 1]);
+
+ regs = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_RANK_NUM);
+ val = pci_read_config8(MEMCTRL, 0xd5);
+ val &= ~0xaa;
+ switch (regs) {
+ case 3:
+ case 2:
+ val |= 0xa0;
+ break;
+ default:
+ val |= 0x80;
+ }
+ regs = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_DIMM_NUM);
+ if (regs == 1)
+ val |= 0xa;
+ pci_write_config8(MEMCTRL, 0xd5, val);
+
+ regs = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_DIMM_NUM);
+ val = pci_read_config8(MEMCTRL, 0xd6);
+ val &= ~0x2;
+ if (regs == 1)
+ val |= 0x2;
+ pci_write_config8(MEMCTRL, 0xd6, val);
+
+ regs = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_RANK_MAP);
+ tmp = sizeof(ODT_TBL) / sizeof(ODT_TBL[0]);
+ for (val = 0; val < tmp; val += 3) {
+ if (regs == ODT_TBL[val]) {
+ pci_write_config8(MEMCTRL, 0xd8, ODT_TBL[val + 1]);
+ /* Store DRAM & NB ODT setting in d0f4_Rxd8 */
+ pci_write_config8(PCI_DEV(0, 0, 4), SCRATCH_DRAM_NB_ODT, ODT_TBL[val + 2]);
+ break;
+ }
+ }
+
+ pci_write_config8(MEMCTRL, 0xd9, 0x0a);
+ regs = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_RANK_NUM);
+ regs--;
+ regs = regs << 1;
+ pci_write_config8(MEMCTRL, 0xe0, DQS_DQ_TBL[regs++]);
+ pci_write_config8(MEMCTRL, 0xe2, DQS_DQ_TBL[regs]);
+
+ /* DRAM Timing CS */
+ pci_write_config8(MEMCTRL, 0xe4, 0x66);
+
+ /* DRAM Timing MAA */
+ val = 0;
+ for (dimm = 0; dimm < DIMM_SOCKETS; dimm++) {
+ if (pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_REG_BASE + (dimm << 1)))) {
+ spds = get_spd_data(ctrl, dimm, SPD_PRI_WIDTH);
+ spds = 64 / spds;
+ if (pci_read_config8
+ (PCI_DEV(0, 0, 4), (SCRATCH_REG_BASE + (dimm << 1) + 1)))
+ spds = spds << 1;
+ val += spds;
+ }
+ }
+ printk_debug("\nchip #%d", val);
+ if (val > 18)
+ regs = 0xdb;
+ else
+ regs = 0x86;
+ pci_write_config8(MEMCTRL, 0xe8, regs);
+
+ /* DRAM Timing MAB */
+ pci_write_config8(MEMCTRL, 0xe9, 0x0);
+
+ /* DRAM Timing DCLK VT8454C always 0x66 */
+ pci_write_config8(MEMCTRL, 0xe6, 0xaa);
+
+ /**********************************************/
+ /* Set DRAM Duty Control */
+ /**********************************************/
+ regs = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_RANK_NUM);
+ switch (regs) {
+ case 1:
+ case 2: /* 1~2 rank */
+ val = 0;
+ break;
+ case 3:
+ case 4: /* 3~4 rank */
+ regs = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_DRAM_FREQ);
+ if (regs == DDRII_533)
+ val = 4;
+ else /* DDRII-400 */
+ val = 0;
+ break;
+ }
+ regs = 0xec;
+ for (t = 0; t < 4; t++) {
+ pci_write_config8(MEMCTRL, regs, Duty_Control_DDR2[val]);
+ regs++;
+ val++;
+ }
+
+ /**********************************************/
+ /* Set DRAM Clock Control */
+ /**********************************************/
+ /* Write Data Phase */
+ val = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_DRAM_FREQ);
+ regs = pci_read_config8(MEMCTRL, 0x75);
+ regs &= 0xf0;
+ switch (val) {
+ case DDRII_533:
+ pci_write_config8(MEMCTRL, 0x74, 0x07);
+ regs |= 0x7;
+ break;
+ case DDRII_400:
+ default:
+ pci_write_config8(MEMCTRL, 0x74, 0x05);
+ regs |= 0x5;
+ break;
+ }
+ pci_write_config8(MEMCTRL, 0x75, regs);
+ pci_write_config8(MEMCTRL, 0x76, 0x80);
+
+ /* Clock Phase Control for FeedBack Mode */
+ regs = pci_read_config8(MEMCTRL, 0x90);
+// regs |= 0x80;
+ pci_write_config8(MEMCTRL, 0x90, regs);
+
+ regs = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_DRAM_FREQ);
+ switch (regs) {
+ case DDRII_533:
+ regs = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_RANK_NUM);
+ if (regs == 1)
+ val = 0;
+ else
+ val = 3;
+ break;
+ case DDRII_400:
+ default:
+ val = 6;
+ break;
+ }
+ regs = pci_read_config8(MEMCTRL, 0x91);
+ regs &= ~0xc0;
+ regs |= 0x80;
+ pci_write_config8(MEMCTRL, 0x91, regs);
+ regs = 0x91;
+ for (t = 0; t < 3; t++) {
+ dimm = pci_read_config8(MEMCTRL, regs);
+ dimm &= ~0x7;
+ dimm |= ChA_Clk_Phase_DDR2_Table[val];
+ pci_write_config8(MEMCTRL, regs, dimm);
+ regs++;
+ val++;
+ }
+
+ pci_write_config8(MEMCTRL, 0x97, 0x12);
+ pci_write_config8(MEMCTRL, 0x98, 0x33);
+
+ regs = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_RANK_0);
+ val = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_RANK_2);
+ if (regs && val)
+ pci_write_config8(MEMCTRL, 0x9d, 0x00);
+ else
+ pci_write_config8(MEMCTRL, 0x9d, 0x0f);
+
+ tmp = sizeof(DQ_DQS_Table) / sizeof(DQ_DQS_Table[0]);
+ for (val = 0; val < tmp; val += 2)
+ pci_write_config8(MEMCTRL, DQ_DQS_Table[val], DQ_DQS_Table[val + 1]);
+ regs = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_DRAM_FREQ);
+ if (regs == DDRII_533)
+ pci_write_config8(MEMCTRL, 0x7b, 0xa0);
+ else
+ pci_write_config8(MEMCTRL, 0x7b, 0x10);
+
+ /***************************************************/
+ /* Set necessary register before DRAM initialize */
+ /***************************************************/
+ tmp = sizeof(Mem_Reg_Init) / sizeof(Mem_Reg_Init[0]);
+ for (val = 0; val < tmp; val += 3) {
+ regs = pci_read_config8(MEMCTRL, Mem_Reg_Init[val]);
+ regs &= Mem_Reg_Init[val + 1];
+ regs |= Mem_Reg_Init[val + 2];
+ pci_write_config8(MEMCTRL, Mem_Reg_Init[val], regs);
+ }
+ regs = pci_read_config8(HOSTCTRL, 0x51);
+ regs &= 0xbf; // Clear bit 6 Disable Read Around Write
+ pci_write_config8(HOSTCTRL, 0x51, regs);
+
+ regs = pci_read_config8(HOSTCTRL, 0x54);
+ t = regs >> 5;
+ val = pci_read_config8(HOSTCTRL, 0x57);
+ dimm = val >> 5;
+ if (t == dimm)
+ t = 0x0;
+ else
+ t = 0x1;
+ regs &= ~0x1;
+ regs |= t;
+ val &= ~0x1;
+ val |= t;
+ pci_write_config8(HOSTCTRL, 0x57, val);
+
+ regs = pci_read_config8(HOSTCTRL, 0x51);
+ regs |= t;
+ pci_write_config8(HOSTCTRL, 0x51, regs);
+
+ regs = pci_read_config8(MEMCTRL, 0x90);
+ regs &= 0x7;
+ val = 0;
+ if (regs < 0x2)
+ val = 0x80;
+ regs = pci_read_config8(MEMCTRL, 0x76);
+ regs &= 0x80;
+ regs |= val;
+ pci_write_config8(MEMCTRL, 0x76, regs);
+
+ regs = pci_read_config8(MEMCTRL, 0x6f);
+ regs |= 0x10;
+ pci_write_config8(MEMCTRL, 0x6f, regs);
+
+ /***************************************************/
+ /* Find suitable DQS value for ChA and ChB */
+ /***************************************************/
+ // Set DQS output delay for Channel A
+ regs = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_DRAM_FREQ);
+ val = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_RANK_NUM);
+ switch (regs) {
+ case DDRII_533:
+ if (val < 2)
+ val = 0;
+ else
+ val = 2;
+ break;
+ case DDRII_400:
+ default:
+ if (val < 2)
+ val = 4;
+ else
+ val = 6;
+ break;
+ }
+ for (t = 0; t < 2; t++)
+ pci_write_config8(MEMCTRL, (0x70 + t), DQSOChA_DDR2_Driving_Table[val + t]);
+ // Set DQS output delay for Channel B
+ pci_write_config8(MEMCTRL, 0x72, 0x0);
+
+ regs = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_RANK_0);
+ val = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_RANK_2);
+ if (regs && val)
+ pci_write_config8(MEMCTRL, 0x73, 0xfd);
+ else
+ pci_write_config8(MEMCTRL, 0x73, 0x01);
+}
+
+static void sdram_set_registers(const struct mem_controller *ctrl)
+{
+ c7_cpu_setup(ctrl);
+ ddr_detect(ctrl);
+ sdram_set_safe_values(ctrl);
+}
+
+static void step_20_21(const struct mem_controller *ctrl)
+{
+ u8 val;
+
+ // Step 20
+ udelay(200);
+
+ val = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_DRAM_NB_ODT);
+ if (val & DDR2_ODT_150ohm)
+ read32(0x102200);
+ else
+ read32(0x102020);
+
+ /* Step 21. Normal operation */
+ print_spew("RAM Enable 5: Normal operation\n");
+ do_ram_command(ctrl, RAM_COMMAND_NORMAL);
+ udelay(3);
+}
+
+static void step_2_19(const struct mem_controller *ctrl)
+{
+ u32 i;
+ u8 val;
+
+ // Step 2
+ val = pci_read_config8(MEMCTRL, 0x69);
+ val &= ~0x03;
+ pci_write_config8(MEMCTRL, 0x69, val);
+
+ /* Step 3 Apply NOP. */
+ print_spew("RAM Enable 1: Apply NOP\n");
+ do_ram_command(ctrl, RAM_COMMAND_NOP);
+
+ udelay(15);
+
+ // Step 4
+ print_spew("SEND: ");
+ read32(0);
+ print_spew("OK\n");
+
+ // Step 5
+ udelay(400);
+
+ /* 6. Precharge all. Wait tRP. */
+ print_spew("RAM Enable 2: Precharge all\n");
+ do_ram_command(ctrl, RAM_COMMAND_PRECHARGE);
+
+ // Step 7
+ print_spew("SEND: ");
+ read32(0);
+ print_spew("OK\n");
+
+ /* Step 8. Mode register set. */
+ print_spew("RAM Enable 4: Mode register set\n");
+ do_ram_command(ctrl, RAM_COMMAND_MRS); //enable dll
+
+ // Step 9
+ print_spew("SEND: ");
+
+ val = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_DRAM_NB_ODT);
+ if (val & DDR2_ODT_150ohm)
+ read32(0x102200); //DDR2_ODT_150ohm
+ else
+ read32(0x102020);
+ print_spew("OK\n");
+
+ // Step 10
+ print_spew("SEND: ");
+ read32(0x800);
+ print_spew("OK\n");
+
+ /* Step 11. Precharge all. Wait tRP. */
+ print_spew("RAM Enable 2: Precharge all\n");
+ do_ram_command(ctrl, RAM_COMMAND_PRECHARGE);
+
+ // Step 12
+ print_spew("SEND: ");
+ read32(0x0);
+ print_spew("OK\n");
+
+ /* Step 13. Perform 8 refresh cycles. Wait tRC each time. */
+ print_spew("RAM Enable 3: CBR\n");
+ do_ram_command(ctrl, RAM_COMMAND_CBR);
+
+ /* JEDEC says only twice, do 8 times for posterity */
+ // Step 16: Repeat Step 14 and 15 another 7 times
+ for (i = 0; i < 8; i++) {
+ // Step 14
+ read32(0);
+ print_spew(".");
+
+ // Step 15
+ udelay(100);
+ }
+
+ /* Step 17. Mode register set. Wait 200us. */
+ print_spew("\nRAM Enable 4: Mode register set\n");
+
+ //safe value for now, BL=8, WR=4, CAS=4
+ do_ram_command(ctrl, RAM_COMMAND_MRS);
+ udelay(200);
+
+ /* Use Single Chanel temporarily */
+ val = pci_read_config8(MEMCTRL, 0x6c);
+ if (val & 0x8) { /* Burst Length = 8 */
+ val = pci_read_config8(MEMCTRL, 0x62);
+ val &= 0x7;
+ i = DDR2_MRS_table[4 + val];
+ } else {
+ val = pci_read_config8(MEMCTRL, 0x62);
+ val &= 0x7;
+ i = DDR2_MRS_table[val];
+ }
+
+ // Step 18
+ val = pci_read_config8(MEMCTRL, 0x61);
+ val = val >> 6;
+ i |= DDR2_Twr_table[val];
+ read32(i);
+
+ printk_debug("MRS = %08x\n", i);
+
+ udelay(15);
+
+ // Step 19
+ val = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_DRAM_NB_ODT);
+ if (val & DDR2_ODT_150ohm)
+ read32(0x103e00); //EMRS OCD Default
+ else
+ read32(0x103c20);
+}
+
+static void sdram_set_vr(const struct mem_controller *ctrl, u8 num)
+{
+ u8 reg, val;
+ val = 0x54 + (num >> 1);
+ reg = pci_read_config8(MEMCTRL, val);
+ reg &= (0xf << (4 * (num & 0x1)));
+ reg |= (((0x8 | num) << 4) >> (4 * (num & 0x1)));
+ pci_write_config8(MEMCTRL, val, reg);
+}
+static void sdram_ending_addr(const struct mem_controller *ctrl, u8 num)
+{
+ u8 reg, val;
+ /* Set Ending Address */
+ val = 0x40 + num;
+ reg = pci_read_config8(MEMCTRL, val);
+ reg += 0x10;
+ pci_write_config8(MEMCTRL, val, reg);
+ /* Set Beginning Address */
+ val = 0x48 + num;
+ pci_write_config8(MEMCTRL, val, 0x0);
+}
+
+static void sdram_clear_vr_addr(const struct mem_controller *ctrl, u8 num)
+{
+ u8 reg, val;
+ val = 0x54 + (num >> 1);
+ reg = pci_read_config8(MEMCTRL, val);
+ reg = ~(0x80 >> (4 * (num & 0x1)));
+ pci_write_config8(MEMCTRL, val, reg);
+ val = 0x40 + num;
+ reg = pci_read_config8(MEMCTRL, val);
+ reg -= 0x10;
+ pci_write_config8(MEMCTRL, val, reg);
+ val = 0x48 + num;
+ pci_write_config8(MEMCTRL, val, 0x0);
+}
+
+/* Perform sizing DRAM by dynamic method */
+static void sdram_calc_size(const struct mem_controller *ctrl, u8 num)
+{
+ u8 ca, ra, ba, reg;
+ ba = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_FLAGS);
+ if (ba == 8) {
+ write8(0, 0x0d);
+ ra = read8(0);
+ write8((1 << SDRAM1X_RA_12_8bk), 0x0c);
+ ra = read8(0);
+
+ write8(0, 0x0a);
+ ca = read8(0);
+ write8((1 << SDRAM1X_CA_09_8bk), 0x0c);
+ ca = read8(0);
+
+ write8(0, 0x03);
+ ba = read8(0);
+ write8((1 << SDRAM1X_BA2_8bk), 0x02);
+ ba = read8(0);
+ write8((1 << SDRAM1X_BA1_8bk), 0x01);
+ ba = read8(0);
+ } else {
+ write8(0, 0x0f);
+ ra = read8(0);
+ write8((1 << SDRAM1X_RA_14), 0x0e);
+ ra = read8(0);
+ write8((1 << SDRAM1X_RA_13), 0x0d);
+ ra = read8(0);
+ write8((1 << SDRAM1X_RA_12), 0x0c);
+ ra = read8(0);
+
+ write8(0, 0x0c);
+ ca = read8(0);
+ write8((1 << SDRAM1X_CA_12), 0x0b);
+ ca = read8(0);
+ write8((1 << SDRAM1X_CA_11), 0x0a);
+ ca = read8(0);
+ write8((1 << SDRAM1X_CA_09), 0x09);
+ ca = read8(0);
+
+ write8(0, 0x02);
+ ba = read8(0);
+ write8((1 << SDRAM1X_BA1), 0x01);
+ ba = read8(0);
+ }
+
+ if (ra < 10 || ra > 15)
+ die("bad RA");
+ if (ca < 8 || ca > 12)
+ die("bad CA");
+ if (ba < 1 || ba > 3)
+ die("bad BA");
+
+ /* Calculate MA type save to scratch register */
+ reg = 0;
+
+ switch (ra) {
+ case 12:
+ reg |= MA_12_Row;
+ break;
+ case 13:
+ reg |= MA_13_Row;
+ break;
+ case 14:
+ reg |= MA_14_Row;
+ break;
+ default:
+ reg |= MA_15_Row;
+ }
+
+ switch (ca) {
+ case 9:
+ reg |= MA_9_Column;
+ break;
+ case 10:
+ reg |= MA_10_Column;
+ break;
+ case 11:
+ reg |= MA_11_Column;
+ break;
+ default:
+ reg |= MA_12_Column;
+ }
+
+ switch (ba) {
+ case 3:
+ reg |= MA_8_Bank;
+ break;
+ default:
+ reg |= MA_4_Bank;
+ }
+
+ pci_write_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK0_MA_REG + num), reg);
+
+ if (ra >= 13)
+ pci_write_config8(PCI_DEV(0, 0, 4), SCRATCH_DRAM_256M_BIT, 1);
+
+ /* Calculate rank size save to scratch register */
+ ra = ra + ca + ba + 3 - 26; /* 1 unit = 64M */
+ ra = 1 << ra;
+ pci_write_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK0_SIZE_REG + num), ra);
+}
+
+static void sdram_enable(const struct mem_controller *ctrl)
+{
+ u8 reg8;
+ u8 val, i;
+ device_t dev;
+ u8 dl, dh;
+ u32 quot;
+
+ /* Init Present Bank */
+ val = sizeof(Init_Rank_Reg_Table) / sizeof(Init_Rank_Reg_Table[0]);
+ for (i = 0; i < val; i++)
+ pci_write_config8(MEMCTRL, Init_Rank_Reg_Table[i], 0x0);
+
+ /* Init other banks */
+ for (i = 0; i < 4; i++) {
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK_0 + i));
+ if (reg8) {
+ sdram_set_vr(ctrl, i);
+ sdram_ending_addr(ctrl, i);
+ step_2_19(ctrl);
+ step_20_21(ctrl);
+ sdram_clear_vr_addr(ctrl, i);
+ }
+ }
+
+#ifdef MEM_WIDTH_32BIT_MODE
+ /****************************************************************/
+ /* Set Dram 32bit Mode */
+ /****************************************************************/
+ reg8 = pci_read_config8(MEMCTRL, 0x6c);
+ reg8 |= 0x20;
+ pci_write_config(MEMCTRL, 0x6c, reg8);
+#endif
+
+ /****************************************************************/
+ /* Find the DQSI Low/High bound and save it to Scratch register */
+ /****************************************************************/
+ for (dl = 0; dl < 0x3f; dl += 2) {
+ reg8 = dl & 0x3f;
+ reg8 |= 0x80; /* Set Manual Mode */
+ pci_write_config8(MEMCTRL, 0x77, reg8);
+ for (i = 0; i < 4; i++) {
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK_0 + i));
+ if (reg8) {
+ sdram_set_vr(ctrl, i);
+ sdram_ending_addr(ctrl, i);
+ write32(0, 0x55555555);
+ write32(4, 0x55555555);
+ udelay(15);
+ if (read32(0) != 0x55555555)
+ break;
+ if (read32(4) != 0x55555555)
+ break;
+ write32(0, 0xaaaaaaaa);
+ write32(4, 0xaaaaaaaa);
+ udelay(15);
+ if (read32(0) != 0xaaaaaaaa)
+ break;
+ if (read32(4) != 0xaaaaaaaa)
+ break;
+ sdram_clear_vr_addr(ctrl, i);
+ }
+ }
+ if (i == 4)
+ break;
+ else
+ sdram_clear_vr_addr(ctrl, i);
+ }
+ printk_debug("\nDQSI Low %08x", dl);
+ for (dh = dl; dh < 0x3f; dh += 2) {
+ reg8 = dh & 0x3f;
+ reg8 |= 0x80; /* Set Manual Mode */
+ pci_write_config8(MEMCTRL, 0x77, reg8);
+ for (i = 0; i < 4; i++) {
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK_0 + i));
+ if (reg8) {
+ sdram_set_vr(ctrl, i);
+ sdram_ending_addr(ctrl, i);
+
+ write32(0, 0x55555555);
+ write32(4, 0x55555555);
+ udelay(15);
+ if (read32(0) != 0x55555555)
+ break;
+ if (read32(4) != 0x55555555)
+ break;
+ write32(0, 0xaaaaaaaa);
+ write32(4, 0xaaaaaaaa);
+ udelay(15);
+ if (read32(0) != 0xaaaaaaaa)
+ break;
+ if (read32(4) != 0xaaaaaaaa)
+ break;
+ sdram_clear_vr_addr(ctrl, i);
+ }
+ }
+ if (i != 4) {
+ sdram_clear_vr_addr(ctrl, i);
+ break;
+ }
+ }
+ printk_debug("\nDQSI High %02x", dh);
+ pci_write_config8(PCI_DEV(0, 0, 4), SCRATCH_CHA_DQSI_LOW_REG, dl);
+ pci_write_config8(PCI_DEV(0, 0, 4), SCRATCH_CHA_DQSI_HIGH_REG, dh);
+ reg8 = pci_read_config8(MEMCTRL, 0X90) & 0X7;
+ val = DQSI_Rate_Table[reg8];
+ quot = dh - dl;
+ quot = quot * val;
+ quot >>= 4;
+ val = quot + dl;
+ pci_write_config8(PCI_DEV(0, 0, 4), SCRATCH_ChA_DQSI_REG, val);
+ reg8 = val & 0x3f;
+ reg8 |= 0x80;
+ pci_write_config8(MEMCTRL, 0x77, reg8);
+
+ /****************************************************************/
+ /* Find out the lowest Bank Interleave and Set Register */
+ /****************************************************************/
+#if 0
+ //TODO
+ reg8 = pci_read_config8(MEMCTRL, 0x69);
+ reg8 &= ~0xc0;
+ reg8 |= 0x80; //8 banks
+ pci_write_config8(MEMCTRL, 0x69, reg8);
+#endif
+ dl = 2;
+ for (i = 0; i < 4; i++) {
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK_0 + i));
+ if (reg8) {
+ reg8 = get_spd_data(ctrl, (i >> 1), 17);
+ sdram_set_vr(ctrl, i);
+ sdram_ending_addr(ctrl, i);
+ if (reg8 == 4) {
+ write8(0, 0x02);
+ val = read8(0);
+ write8((1 << SDRAM1X_BA1), 0x01);
+ val = read8(0);
+ } else {
+ write8(0, 0x03);
+ val = read8(0);
+ write8((1 << SDRAM1X_BA2_8bk), 0x02);
+ val = read8(0);
+ write8((1 << SDRAM1X_BA1_8bk), 0x01);
+ val = read8(0);
+ }
+ if (val < dl)
+ dl = val;
+ sdram_clear_vr_addr(ctrl, i);
+ }
+ }
+ dl <<= 6;
+ reg8 = pci_read_config8(MEMCTRL, 0x69);
+ reg8 &= ~0xc0;
+ reg8 |= dl;
+ pci_write_config8(MEMCTRL, 0x69, reg8);
+
+ /****************************************************************/
+ /* DRAM Sizing and Fill MA type */
+ /****************************************************************/
+ for (i = 0; i < 4; i++) {
+ val = pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK_0 + i));
+ if (val) {
+ reg8 = get_spd_data(ctrl, (i >> 1), 17);
+ pci_write_config8(PCI_DEV(0, 0, 4), SCRATCH_FLAGS, reg8);
+ if (reg8 == 4) {
+ /* Use MA Type 3 for DRAM sizing */
+ reg8 = pci_read_config8(MEMCTRL, 0x50);
+ reg8 &= 0x11;
+ reg8 |= 0x66;
+ pci_write_config8(MEMCTRL, 0x50, reg8);
+ pci_write_config8(MEMCTRL, 0x51, reg8);
+ } else {
+ /* Use MA Type 5 for DRAM sizing */
+ reg8 = pci_read_config8(MEMCTRL, 0x50);
+ reg8 &= 0x11;
+ reg8 |= 0xaa;
+ pci_write_config8(MEMCTRL, 0x50, reg8);
+ pci_write_config8(MEMCTRL, 0x51, reg8);
+ reg8 = pci_read_config8(MEMCTRL, 0x53);
+ reg8 &= 0x0f;
+ reg8 |= 0x90;
+ pci_write_config8(MEMCTRL, 0x53, reg8);
+ }
+ sdram_set_vr(ctrl, i);
+ val = 0x40 + i;
+ reg8 = pci_read_config8(MEMCTRL, val);
+ /* max size 3G for new MA table */
+ reg8 += 0x30;
+ pci_write_config8(MEMCTRL, val, reg8);
+ /* Set Beginning Address */
+ val = 0x48 + i;
+ pci_write_config8(MEMCTRL, val, 0x0);
+
+ sdram_calc_size(ctrl, i);
+
+ /* Clear */
+ val = 0x54 + (i >> 1);
+ reg8 = pci_read_config8(MEMCTRL, val);
+ reg8 = ~(0x80 >> (4 * (i & 0x1)));
+ pci_write_config8(MEMCTRL, val, reg8);
+ val = 0x40 + i;
+ reg8 = pci_read_config8(MEMCTRL, val);
+ reg8 -= 0x30;
+ pci_write_config8(MEMCTRL, val, reg8);
+ val = 0x48 + i;
+ pci_write_config8(MEMCTRL, val, 0x0);
+
+ }
+ }
+ /* Clear MA Type */
+ reg8 = pci_read_config8(MEMCTRL, 0x50);
+ reg8 &= 0x11;
+ pci_write_config8(MEMCTRL, 0x50, reg8);
+ pci_write_config8(MEMCTRL, 0x51, reg8);
+ reg8 = pci_read_config8(MEMCTRL, 0x6b);
+ reg8 &= ~0x08;
+ pci_write_config8(MEMCTRL, 0x6b, reg8);
+
+ /****************************************************************/
+ /* DRAM re-initialize for burst length */
+ /****************************************************************/
+ for (i = 0; i < 4; i++) {
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK_0 + i));
+ if (reg8) {
+ sdram_set_vr(ctrl, i);
+ sdram_ending_addr(ctrl, i);
+ step_2_19(ctrl);
+ step_20_21(ctrl);
+ sdram_clear_vr_addr(ctrl, i);
+ }
+ }
+
+ /****************************************************************/
+ /* Set the MA Type */
+ /****************************************************************/
+ reg8 = pci_read_config8(MEMCTRL, 0x50);
+ reg8 &= 0x11;
+ pci_write_config8(MEMCTRL, 0x50, reg8);
+
+ reg8 = pci_read_config8(MEMCTRL, 0x51);
+ reg8 &= 0x11;
+ pci_write_config8(MEMCTRL, 0x51, reg8);
+
+ reg8 = pci_read_config8(MEMCTRL, 0x6b);
+ reg8 &= ~0x08;
+ pci_write_config8(MEMCTRL, 0x6b, reg8);
+
+ for (i = 0; i < 4; i += 2) {
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK_0 + i));
+ if (reg8) {
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK0_MA_REG + i));
+ reg8 &= (MA_Bank + MA_Column);
+ val = pci_read_config8(MEMCTRL, 0x50);
+ if (i == 0) {
+ reg8 <<= 4;
+ val &= 0x1f;
+ } else
+ val &= 0xf1;
+ val |= reg8;
+ pci_write_config8(MEMCTRL, 0x50, val);
+ }
+ }
+
+ /****************************************************************/
+ /* Set Start and Ending Address */
+ /****************************************************************/
+ dl = 0; /* Begin Address */
+ dh = 0; /* Ending Address */
+ for (i = 0; i < 4; i++) {
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK_0 + i));
+ if (reg8) {
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK0_SIZE_REG + i));
+ if (reg8 == 0)
+ continue;
+ dh += reg8;
+ pci_write_config8(MEMCTRL, (0x40 + i), dh);
+ pci_write_config8(MEMCTRL, (0x48 + i), dl);
+ dl = dh;
+ }
+ }
+ dh <<= 2;
+ // F7_Rx57 Ending address mirror register
+ pci_write_config8(PCI_DEV(0, 0, 7), 0x57, dh);
+ dev = pci_locate_device(PCI_ID(0x1106, 0x324e), 0);
+ pci_write_config8(dev, 0x57, dh);
+ // LOW TOP Address
+ pci_write_config8(MEMCTRL, 0x88, dh);
+ pci_write_config8(MEMCTRL, 0x85, dh);
+ // also program vlink mirror
+ pci_write_config8(PCI_DEV(0, 0, 7), 0xe5, dh);
+
+ /****************************************************************/
+ /* Set Physical to Virtual Rank mapping */
+ /****************************************************************/
+ pci_write_config32(MEMCTRL, 0x54, 0x0);
+ for (i = 0; i < 4; i++) {
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK_0 + i));
+ if (reg8) {
+ reg8 = pci_read_config8(MEMCTRL, (0x54 + (i >> 1)));
+ if (i & 0x1) { /* Odd Rank */
+ reg8 &= 0xf0;
+ reg8 |= (0x8 | i);
+ } else { /* Even Rank */
+
+ reg8 &= 0x0f;
+ reg8 |= ((0x8 | i) << 4);
+ }
+ pci_write_config8(MEMCTRL, (0x54 + (i >> 1)), reg8);
+ }
+ }
+
+ /****************************************************************/
+ /* Set DRAM Refresh Counter */
+ /****************************************************************/
+ val = pci_read_config8(MEMCTRL, 0X90) & 0X7;
+ val <<= 1;
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 4), SCRATCH_DRAM_256M_BIT);
+ if (reg8)
+ val++;
+ pci_write_config8(MEMCTRL, 0x6a, REFC_Table[val]);
+
+ /****************************************************************/
+ /* Chipset Performance UP and other setting after DRAM Sizing */
+ /****************************************************************/
+ /* Dram Registers */
+ val = sizeof(Dram_Table) / sizeof(Dram_Table[0]);
+ for (i = 0; i < val; i += 3) {
+ reg8 = pci_read_config8(MEMCTRL, Dram_Table[i]);
+ reg8 &= Dram_Table[i + 1];
+ reg8 |= Dram_Table[i + 2];
+ pci_write_config8(MEMCTRL, Dram_Table[i], reg8);
+ }
+
+ /* Host Registers */
+ val = sizeof(Host_Table) / sizeof(Host_Table[0]);
+ for (i = 0; i < val; i += 3) {
+ reg8 = pci_read_config8(HOSTCTRL, Host_Table[i]);
+ reg8 &= Host_Table[i + 1];
+ reg8 |= Host_Table[i + 2];
+ pci_write_config8(HOSTCTRL, Host_Table[i], reg8);
+ }
+
+ /* PM Registers */
+#ifdef SETUP_PM_REGISTERS
+ val = sizeof(PM_Table) / sizeof(PM_Table[0]);
+ for (i = 0; i < val; i += 3) {
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 4), PM_Table[i]);
+ reg8 &= PM_Table[i + 1];
+ reg8 |= PM_Table[i + 2];
+ pci_write_config8(PCI_DEV(0, 0, 4), PM_Table[i], reg8);
+ }
+#endif
+ pci_write_config8(HOSTCTRL, 0x5d, 0xb2);
+
+ /****************************************************************/
+ /* UMA registers for N-series projects */
+ /****************************************************************/
+
+ /* Manual setting frame buffer bank */
+ for (i = 0; i < 4; i++) {
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 4), (SCRATCH_RANK_0 + i));
+ if (reg8)
+ val = i;
+ }
+ pci_write_config8(MEMCTRL, 0xb0, val);
+ reg8 = 0x40; // Frame buffer size 64M
+ reg8 |= 0x80; // VGA Enable
+ reg8 |= 0x0a; // A[31:28] = 1010b
+ pci_write_config8(MEMCTRL, 0xa1, reg8);
+
+#ifdef ECC
+ // Clear Ecc
+ outl(0x80000180, 0xcf8);
+ outb(0xff, 0xcfc);
+ // Enable Ecc
+ outl(0x80000188, 0xcf8);
+ outb(0xcf, 0xcfc);
+
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 0), 0xa5);
+ reg8 |= 0x10;
+ pci_write_config8(PCI_DEV(0, 0, 0), 0xa5, reg8);
+
+ reg8 = pci_read_config8(PCI_DEV(0, 0, 0), 0x91);
+ reg8 |= 0x20;
+ pci_write_config8(PCI_DEV(0, 0, 0), 0x91, reg8);
+#endif
+
+ static const struct regmask {
+ u8 reg;
+ u8 mask;
+ u8 val;
+ } b0d1f0[] = {
+ { 0x40, 0x00, 0x8b},
+ { 0x41, 0x80, 0x43},
+ { 0x42, 0x00, 0x62},
+ { 0x43, 0x00, 0x44},
+ { 0x44, 0x00, 0x34},
+ { 0x45, 0x00, 0x72}
+ }, b0d0f3[] = {
+ { 0x53, 0xf0, 0x0f},
+ { 0x60, 0x00, 0x03},
+ { 0x65, 0x00, 0xd9},
+ { 0x66, 0x00, 0x80},
+ { 0x67, 0x00, 0x00},
+ { 0x68, 0x00, 0x01},
+ { 0x69, 0xe0, 0x03},
+ { 0x6b, 0x00, 0x10},
+ { 0x6c, 0xc1, 0x08},
+ { 0x6e, 0x00, 0x89},
+ { 0x6f, 0x00, 0x51},
+ { 0x75, ~0x40, 0x40},
+ { 0x76, 0x8f, 0x00},
+ { 0x7b, 0x00, 0xa0},
+ { 0x86, 0x01, 0x24},
+ { 0x86, 0x04, 0x29},
+ { 0x8c, 0x00, 0x00},
+ { 0x8d, 0x00, 0x00},
+ { 0x95, ~0x40, 0x00},
+ { 0xa2, 0x00, 0x44},
+ { 0xb1, 0x00, 0xaa}
+ }, b0d0f0[] = {
+ { 0x4d, 0x00, 0x24},
+ { 0x4f, 0x00, 0x01},
+ { 0xbc, 0x00, 0x21},
+ { 0xbe, 0x00, 0x00},
+ { 0xbf, 0x7f, 0x80}
+ }, b0d17f0[] = {
+ { 0x40, ~0x01, 0x01}, // enable timer/counter shadow registers
+ { 0x67, ~0x03, 0x01},
+ { 0x5b, ~0x01, 0x00},
+ { 0x8d, ~0x02, 0x02},
+ { 0x97, ~0x80, 0x00},
+ { 0xd2, ~0x18, 0x00},
+ { 0xe2, ~0x36, 0x06},
+ { 0xe4, ~0x80, 0x00},
+ { 0xe5, 0x00, 0x40},
+ { 0xe6, 0x00, 0x20},
+ { 0xe7, ~0xd0, 0xc0},
+ { 0xec, ~0x08, 0x00}
+ }, b0d17f7[] = {
+ { 0x4e, ~0x80, 0x80},
+ { 0x4f, ~(1 << 6), 1 << 6 }, /* PG_CX700: 14.1.1 enable P2P Bridge Header for External PCI Bus */
+ { 0x74, ~0x00, 0x04}, /* PG_CX700: 14.1.2 APIC FSB directly up to snmic, not on pci */
+ { 0x7c, ~0x00, 0x02}, /* PG_CX700: 14.1.1 APIC FSB directly up to snmic, not on pci */
+ { 0xe6, 0x0, 0x04} // MSI post
+ }, b0d19f0[] = { /* P2PE */
+ { 0x42, ~0x08, 0x08}, // Disable HD Audio,
+ { 0x40, ~0xc0, 0x80} // 14.1.3.1.1 of the PG: extended cfg mode for pcie. enable capability, but don't activate
+ }, b0d0f2[] = {
+ { 0x50, ~0x40, 0x88},
+ { 0x51, 0x80, 0x7b},
+ { 0x52, 0x90, 0x6f},
+ { 0x53, 0x00, 0x88},
+ { 0x54, 0xe4, 0x16},
+ { 0x55, 0xf2, 0x04},
+ { 0x56, 0x0f, 0x00},
+ { 0x57, ~0x04, 0x00},
+ { 0x5d, 0x00, 0xb2},
+ { 0x5e, 0x00, 0x88},
+ { 0x5f, 0x00, 0xc7},
+ { 0x5c, 0x00, 0x01}
+ };
+
+ REGISTERPRESET(0, 0, 0, b0d0f0);
+ REGISTERPRESET(0, 0, 2, b0d0f2);
+ REGISTERPRESET(0, 0, 3, b0d0f3);
+ REGISTERPRESET(0, 1, 0, b0d1f0);
+ REGISTERPRESET(0, 17, 0, b0d17f0);
+ REGISTERPRESET(0, 17, 7, b0d17f7);
+ REGISTERPRESET(0, 19, 0, b0d19f0);
+}
diff --git a/src/northbridge/via/cx700/raminit.h b/src/northbridge/via/cx700/raminit.h
new file mode 100644
index 0000000000..482902e59b
--- /dev/null
+++ b/src/northbridge/via/cx700/raminit.h
@@ -0,0 +1,28 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * Copyright (C) 2007-2009 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; 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
+ */
+
+#ifndef RAMINIT_H
+#define RAMINIT_H
+
+#define DIMM_SOCKETS 2
+
+struct mem_controller {
+ u16 channel0[DIMM_SOCKETS];
+};
+#endif
diff --git a/src/northbridge/via/cx700/vgabios.c b/src/northbridge/via/cx700/vgabios.c
new file mode 100644
index 0000000000..e7ba33ab3b
--- /dev/null
+++ b/src/northbridge/via/cx700/vgabios.c
@@ -0,0 +1,783 @@
+/*
+ * This file is part of the coreboot project.
+ *
+ * (C) 2007-2009 coresystems GmbH
+ * (See further copyright notices below)
+ *
+ * NOTE: This file is supposed to go away once the generic vm86 handler
+ * in util/x86emu is able to handle intXX hooks like yabel does.
+ *
+ * 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 <console/console.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#undef __KERNEL__
+#include <arch/io.h>
+#include <string.h>
+
+void write_protect_vgabios(void);
+
+/* vgabios.c. Derived from: */
+
+/*------------------------------------------------------------ -*- C -*-
+ * 2 Kernel Monte a.k.a. Linux loading Linux on x86
+ *
+ * Erik Arjan Hendriks <hendriks@lanl.gov>
+ *
+ * This version is a derivative of the original two kernel monte
+ * which is (C) 2000 Scyld.
+ *
+ * Copyright (C) 2000 Scyld Computing Corporation
+ *
+ * Portions related to the alpha architecture are:
+ *
+ * Copyright(C) 2001 University of California. LA-CC Number 01-67.
+ * This software has been authored by an employee or employees of the
+ * University of California, operator of the Los Alamos National
+ * Laboratory under Contract No. W-7405-ENG-36 with the U.S.
+ * Department of Energy. The U.S. Government has rights to use,
+ * reproduce, and distribute this software. If the software is
+ * modified to produce derivative works, such modified software should
+ * be clearly marked, so as not to confuse it with the version
+ * available from LANL.
+ *
+ * This software may be used and distributed according to the terms
+ * of the GNU General Public License, incorporated herein by
+ * reference to http://www.gnu.org/licenses/gpl.html.
+ *
+ * This software is provided by the author(s) "as is" and any express
+ * or implied warranties, including, but not limited to, the implied
+ * warranties of merchantability and fitness for a particular purpose
+ * are disclaimed. In no event shall the author(s) be liable for any
+ * direct, indirect, incidental, special, exemplary, or consequential
+ * damages (including, but not limited to, procurement of substitute
+ * goods or services; loss of use, data, or profits; or business
+ * interruption) however caused and on any theory of liability,
+ * whether in contract, strict liability, or tort (including
+ * negligence or otherwise) arising in any way out of the use of this
+ * software, even if advised of the possibility of such damage.
+ *
+ *--------------------------------------------------------------------*/
+
+/* Modified to be a self sufficient plug in so that it can be used
+ without reliance on other parts of core Linuxbios
+ (C) 2005 Nick.Barker9@btinternet.com
+
+ Used initially for epia-m where there are problems getting the bios
+ emulator to successfully run this bios.
+*/
+
+/* Declare a temporary global descriptor table - necessary because the
+ Core part of the bios no longer sets up any 16 bit segments */
+__asm__(
+ /* pointer to original gdt */
+ "gdtarg: \n"
+ " .word gdt_limit \n"
+ " .long gdt \n"
+ /* compute the table limit */
+ "__mygdt_limit = __mygdt_end - __mygdt - 1 \n"
+ "__mygdtaddr: \n"
+ " .word __mygdt_limit \n"
+ " .long __mygdt \n"
+ "__mygdt: \n"
+ /* selgdt 0, unused */
+ " .word 0x0000, 0x0000 \n"
+ " .byte 0x00, 0x00, 0x00, 0x00 \n"
+ /* selgdt 8, unused */
+ " .word 0x0000, 0x0000 \n"
+ " .byte 0x00, 0x00, 0x00, 0x00 \n"
+ /* selgdt 0x10, flat code segment */
+ " .word 0xffff, 0x0000 \n"
+ " .byte 0x00, 0x9b, 0xcf, 0x00 \n"
+ /* selgdt 0x18, flat data segment */
+ " .word 0xffff, 0x0000 \n"
+ " .byte 0x00, 0x93, 0xcf, 0x00 \n"
+ /* selgdt 0x20, unused */
+ " .word 0x0000, 0x0000 \n"
+ " .byte 0x00, 0x00, 0x00, 0x00 \n"
+ /* selgdt 0x28 16-bit 64k code at 0x00000000 */
+ " .word 0xffff, 0x0000 \n"
+ " .byte 0, 0x9a, 0, 0 \n"
+ /* selgdt 0x30 16-bit 64k data at 0x00000000 */
+ " .word 0xffff, 0x0000 \n"
+ " .byte 0, 0x92, 0, 0 \n"
+ "__mygdt_end: \n");
+
+/* Declare a pointer to where our idt is going to be i.e. at mem zero */
+__asm__("__myidt: \n"
+ /* 16-bit limit */
+ " .word 1023 \n"
+ /* 24-bit base */
+ " .long 0 \n" " .word 0 \n");
+
+/* The address arguments to this function are PHYSICAL ADDRESSES */
+static void real_mode_switch_call_vga(unsigned long devfn)
+{
+ __asm__ __volatile__(
+ // paranoia -- does ecx get saved? not sure. This is
+ // the easiest safe thing to do.
+ " pushal \n"
+ /* save the stack */
+ " mov %esp, __stack \n"
+ " jmp 1f \n"
+ "__stack: .long 0 \n" "1:\n"
+ /* get devfn into %ecx */
+ " movl %esp, %ebp \n"
+ " movl 8(%ebp), %ecx \n"
+ /* load 'our' gdt */
+ " lgdt %cs:__mygdtaddr \n"
+ /* This configures CS properly for real mode. */
+ " ljmp $0x28, $__rms_16bit\n"
+ "__rms_16bit: \n"
+ " .code16 \n"
+ /* 16 bit code from here on... */
+ /* Load the segment registers w/ properly configured segment
+ * descriptors. They will retain these configurations (limits,
+ * writability, etc.) once protected mode is turned off. */
+ " mov $0x30, %ax \n"
+ " mov %ax, %ds \n"
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov %ax, %ss \n"
+ /* Turn off protection (bit 0 in CR0) */
+ " movl %cr0, %eax \n"
+ " andl $0xFFFFFFFE, %eax \n"
+ " movl %eax, %cr0 \n"
+ /* Now really going into real mode */
+ " ljmp $0, $__rms_real\n"
+ "__rms_real: \n"
+ /* put the stack at the end of page zero.
+ * that way we can easily share it between real and protected,
+ * since the 16-bit ESP at segment 0 will work for any case.
+ */
+ /* Setup a stack */
+ " mov $0x0, %ax \n"
+ " mov %ax, %ss \n"
+ " movl $0x1000, %eax \n"
+ " movl %eax, %esp \n"
+ /* Load our 16 it idt */
+ " xor %ax, %ax \n"
+ " mov %ax, %ds \n"
+ " lidt __myidt \n"
+ /* Dump zeros in the other segregs */
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov $0x40, %ax \n"
+ " mov %ax, %ds \n"
+ " mov %cx, %ax \n"
+ /* run VGA BIOS at 0xc000:0003 */
+ " lcall $0xc000, $0x0003\n"
+ /* if we got here, just about done.
+ * Need to get back to protected mode */
+ " movl %cr0, %eax \n" " orl $0x0000001, %eax\n" /* PE = 1 */
+ " movl %eax, %cr0 \n"
+ /* Now that we are in protected mode jump to a 32 bit code segment. */
+ " data32 ljmp $0x10, $vgarestart\n"
+ "vgarestart:\n"
+ " .code32\n"
+ " movw $0x18, %ax \n"
+ " mov %ax, %ds \n"
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov %ax, %ss \n"
+ /* restore proper gdt and idt */
+ " lgdt %cs:gdtarg \n"
+ " lidt idtarg \n"
+ ".globl vga_exit \n"
+ "vga_exit: \n"
+ " mov __stack, %esp \n"
+ " popal \n");
+}
+
+__asm__(".text\n" "real_mode_switch_end:\n");
+extern char real_mode_switch_end[];
+
+/* call vga bios int 10 function 0x4f14 to enable main console
+ epia-m does not always autosence the main console so forcing it on is good !! */
+void vga_enable_console(void)
+{
+ __asm__ __volatile__(
+ /* paranoia -- does ecx get saved? not sure. This is
+ * the easiest safe thing to do. */
+ " pushal \n"
+ /* save the stack */
+ " mov %esp, __stack \n"
+ /* load 'our' gdt */
+ " lgdt %cs:__mygdtaddr \n"
+ /* This configures CS properly for real mode. */
+ " ljmp $0x28, $__vga_ec_16bit\n"
+ "__vga_ec_16bit: \n"
+ " .code16 \n"
+ /* 16 bit code from here on... */
+ /* Load the segment registers w/ properly configured segment
+ * descriptors. They will retain these configurations (limits,
+ * writability, etc.) once protected mode is turned off. */
+ " mov $0x30, %ax \n"
+ " mov %ax, %ds \n"
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov %ax, %ss \n"
+ /* Turn off protection (bit 0 in CR0) */
+ " movl %cr0, %eax \n"
+ " andl $0xFFFFFFFE, %eax\n"
+ " movl %eax, %cr0 \n"
+ /* Now really going into real mode */
+ " ljmp $0, $__vga_ec_real \n"
+ "__vga_ec_real: \n"
+ /* put the stack at the end of page zero.
+ * that way we can easily share it between real and protected,
+ * since the 16-bit ESP at segment 0 will work for any case.
+ */
+ /* Setup a stack */
+ " mov $0x0, %ax \n"
+ " mov %ax, %ss \n"
+ " movl $0x1000, %eax \n"
+ " movl %eax, %esp \n"
+ /* debugging for RGM */
+ " mov $0x11, %al \n"
+ " outb %al, $0x80 \n"
+ /* Load our 16 it idt */
+ " xor %ax, %ax \n"
+ " mov %ax, %ds \n"
+ " lidt __myidt \n"
+ /* Dump zeros in the other segregs */
+ " mov %ax, %ds \n"
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ /* ask bios to enable main console */
+ /* set up for int 10 call - values found from X server
+ * bios call routines */
+ " movw $0x4f14,%ax \n"
+ " movw $0x8003,%bx \n"
+ " movw $1, %cx \n"
+ " movw $0, %dx \n"
+ " movw $0, %di \n"
+ " int $0x10 \n"
+ " movb $0x55, %al \n"
+ " outb %al, $0x80 \n"
+ /* if we got here, just about done.
+ * Need to get back to protected mode */
+ " movl %cr0, %eax \n" " orl $0x0000001, %eax\n" /* PE = 1 */
+ " movl %eax, %cr0 \n"
+ /* Now that we are in protected mode jump to a 32 bit code segment. */
+ " data32 ljmp $0x10, $vga_ec_restart\n"
+ "vga_ec_restart:\n"
+ " .code32\n"
+ " movw $0x18, %ax \n"
+ " mov %ax, %ds \n"
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov %ax, %ss \n"
+ /* restore proper gdt and idt */
+ " lgdt %cs:gdtarg \n"
+ " lidt idtarg \n"
+ " .globl vga__ec_exit \n"
+ "vga_ec_exit:\n"
+ " mov __stack, %esp \n"
+ " popal\n");
+}
+
+void do_vgabios(void)
+{
+ device_t dev;
+ unsigned long busdevfn;
+ unsigned int rom = 0;
+ unsigned char *buf;
+ unsigned int size = 64 * 1024;
+ int i;
+
+ /* clear vga bios data area */
+ for (i = 0x400; i < 0x500; i++) {
+ *(unsigned char *)i = 0;
+ }
+
+ dev = dev_find_class(PCI_CLASS_DISPLAY_VGA << 8, 0);
+
+ if (!dev) {
+ printk_debug("NO VGA FOUND\n");
+ return;
+ }
+ printk_debug("found VGA: vid=%x, did=%x\n", dev->vendor, dev->device);
+
+ /* declare rom address here - keep any config data out of the way
+ * of core LXB stuff */
+
+#warning ROM address hardcoded to 512K
+ rom = 0xfff80000;
+ pci_write_config32(dev, PCI_ROM_ADDRESS, rom | 1);
+ printk_debug("rom base, size: %x\n", rom);
+
+ buf = (unsigned char *)rom;
+ if ((buf[0] == 0x55) && (buf[1] == 0xaa)) {
+ memcpy((void *)0xc0000, buf, size);
+
+ write_protect_vgabios(); // in northbridge
+
+ // check signature again
+ buf = (unsigned char *)0xc0000;
+ if (buf[0] == 0x55 && buf[1] == 0xAA) {
+ busdevfn =
+ (dev->bus->secondary << 8) | dev->path.pci.devfn;
+ printk_debug("bus/devfn = %#x\n", busdevfn);
+
+ real_mode_switch_call_vga(busdevfn);
+ } else
+ printk_debug("Failed to copy VGA BIOS to 0xc0000\n");
+ } else
+ printk_debug("BAD SIGNATURE 0x%x 0x%x\n", buf[0], buf[1]);
+
+ pci_write_config32(dev, PCI_ROM_ADDRESS, 0);
+}
+
+// we had hoped to avoid this.
+// this is a stub IDT only. It's main purpose is to ignore calls
+// to the BIOS.
+// no longer. Dammit. We have to respond to these.
+struct realidt {
+ unsigned short offset, cs;
+};
+
+// from a handy writeup that andrey found.
+
+// handler.
+// There are some assumptions we can make here.
+// First, the Top Of Stack (TOS) is located on the top of page zero.
+// we can share this stack between real and protected mode.
+// that simplifies a lot of things ...
+// we'll just push all the registers on the stack as longwords,
+// and pop to protected mode.
+// second, since this only ever runs as part of linuxbios,
+// we know all the segment register values -- so we don't save any.
+// keep the handler that calls things small. It can do a call to
+// more complex code in linuxbios itself. This helps a lot as we don't
+// have to do address fixup in this little stub, and calls are absolute
+// so the handler is relocatable.
+void handler(void)
+{
+ __asm__ __volatile__(" .code16 \n"
+ "idthandle: \n"
+ " pushal \n"
+ " movb $0, %al \n"
+ " ljmp $0, $callbiosint16\n"
+ "end_idthandle: \n"
+ " .code32 \n");
+}
+
+void debughandler(void)
+{
+ __asm__ __volatile__(" .code16 \n"
+ "debughandle: \n"
+ " pushw %cx \n"
+ " movw $250, %cx \n"
+ "dbh1: \n"
+ " loop dbh1 \n"
+ " popw %cx \n"
+ " iret \n"
+ "end_debughandle: \n" ".code32 \n");
+}
+
+// Calling conventions. The first C function is called with this stuff
+// on the stack. They look like value parameters, but note that if you
+// modify them they will go back to the INTx function modified.
+// the C function will call the biosint function with these as
+// REFERENCE parameters. In this way, we can easily get
+// returns back to the INTx caller (i.e. vgabios)
+void callbiosint(void)
+{
+ __asm__ __volatile__(" .code16 \n"
+ "callbiosint16: \n"
+ " push %ds \n"
+ " push %es \n"
+ " push %fs \n" " push %gs \n"
+ // clean up the int #. To save space we put it in the lower
+ // byte. But the top 24 bits are junk.
+ " andl $0xff, %eax\n"
+ // this push does two things:
+ // - put the INT # on the stack as a parameter
+ // - provides us with a temp for the %cr0 mods.
+ " pushl %eax \n" " movl %cr0, %eax\n" " orl $0x00000001, %eax\n" /* PE = 1 */
+ " movl %eax, %cr0\n"
+ /* Now that we are in protected mode jump to a 32 bit code segment. */
+ " data32 ljmp $0x10, $biosprotect\n"
+ "biosprotect: \n"
+ " .code32 \n"
+ " movw $0x18, %ax \n"
+ " mov %ax, %ds \n"
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov %ax, %ss \n"
+ " lidt idtarg \n"
+ " call biosint \n"
+ // back to real mode ...
+ " ljmp $0x28, $__rms_16bit2\n"
+ "__rms_16bit2: \n"
+ " .code16 \n"
+ /* 16 bit code from here on... */
+ /* Load the segment registers w/ properly configured segment
+ * descriptors. They will retain these configurations (limits,
+ * writability, etc.) once protected mode is turned off. */
+ " mov $0x30, %ax \n"
+ " mov %ax, %ds \n"
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov %ax, %ss \n"
+ /* Turn off protection (bit 0 in CR0) */
+ " movl %cr0, %eax \n"
+ " andl $0xFFFFFFFE, %eax \n"
+ " movl %eax, %cr0 \n"
+ /* Now really going into real mode */
+ " ljmp $0, $__rms_real2 \n"
+ "__rms_real2: \n"
+ /* Setup a stack
+ * FixME: where is esp? */
+ " mov $0x0, %ax \n"
+ " mov %ax, %ss \n"
+ /* ebugging for RGM */
+ " mov $0x11, %al \n"
+ " outb %al, $0x80 \n"
+ /* Load our 16 it idt */
+ " xor %ax, %ax \n"
+ " mov %ax, %ds \n"
+ " lidt __myidt \n"
+ /* Dump zeros in the other segregs */
+ " mov %ax, %es \n"
+ " mov %ax, %fs \n"
+ " mov %ax, %gs \n"
+ " mov $0x40, %ax \n"
+ " mov %ax, %ds \n"
+ /* pop the INT # that you pushed earlier */
+ " popl %eax \n"
+ " pop %gs \n"
+ " pop %fs \n"
+ " pop %es \n"
+ " pop %ds \n"
+ " popal \n"
+ " iret \n"
+ " .code32 \n");
+}
+
+enum {
+ PCIBIOS = 0x1a,
+ MEMSIZE = 0x12
+};
+
+int pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp,
+ unsigned long *pesp, unsigned long *pebx, unsigned long *pedx,
+ unsigned long *pecx, unsigned long *peax, unsigned long *pflags);
+
+int handleint21(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp,
+ unsigned long *pesp, unsigned long *pebx, unsigned long *pedx,
+ unsigned long *pecx, unsigned long *peax,
+ unsigned long *pflags);
+
+extern void vga_exit(void);
+
+int biosint(unsigned long intnumber,
+ unsigned long gsfs, unsigned long dses,
+ unsigned long edi, unsigned long esi,
+ unsigned long ebp, unsigned long esp,
+ unsigned long ebx, unsigned long edx,
+ unsigned long ecx, unsigned long eax,
+ unsigned long cs_ip, unsigned short stackflags)
+{
+ unsigned long ip;
+ unsigned long cs;
+ unsigned long flags;
+ int ret = -1;
+
+ ip = cs_ip & 0xffff;
+ cs = cs_ip >> 16;
+ flags = stackflags;
+
+ printk_debug("biosint: INT# 0x%lx\n", intnumber);
+ printk_debug("biosint: eax 0x%lx ebx 0x%lx ecx 0x%lx edx 0x%lx\n",
+ eax, ebx, ecx, edx);
+ printk_debug("biosint: ebp 0x%lx esp 0x%lx edi 0x%lx esi 0x%lx\n",
+ ebp, esp, edi, esi);
+ printk_debug("biosint: ip 0x%x cs 0x%x flags 0x%x\n",
+ ip, cs, flags);
+
+ // cases in a good compiler are just as good as your own tables.
+ switch (intnumber) {
+ case 0 ... 15:
+ // These are not BIOS service, but the CPU-generated exceptions
+ printk_info("biosint: Oops, exception %u\n", intnumber);
+ if (esp < 0x1000) {
+ printk_debug("Stack contents: ");
+ while (esp < 0x1000) {
+ printk_debug("0x%04x ", *(unsigned short *)esp);
+ esp += 2;
+ }
+ printk_debug("\n");
+ }
+ printk_debug("biosint: Bailing out\n");
+ // "longjmp"
+ vga_exit();
+ break;
+
+ case PCIBIOS:
+ ret = pcibios(&edi, &esi, &ebp, &esp,
+ &ebx, &edx, &ecx, &eax, &flags);
+ break;
+ case MEMSIZE:
+ // who cares.
+ eax = 64 * 1024;
+ ret = 0;
+ break;
+ case 0x15:
+ ret = handleint21(&edi, &esi, &ebp, &esp,
+ &ebx, &edx, &ecx, &eax, &flags);
+ break;
+ default:
+ printk_info("BIOSINT: Unsupport int #0x%x\n", intnumber);
+ break;
+ }
+ if (ret)
+ flags |= 1; // carry flags
+ else
+ flags &= ~1;
+ stackflags = flags;
+ return ret;
+}
+
+void setup_realmode_idt(void)
+{
+ extern unsigned char idthandle, end_idthandle;
+ extern unsigned char debughandle, end_debughandle;
+
+ int i;
+ struct realidt *idts = (struct realidt *)0;
+ int codesize = &end_idthandle - &idthandle;
+ unsigned char *intbyte, *codeptr;
+
+ // for each int, we create a customized little handler
+ // that just pushes %ax, puts the int # in %al,
+ // then calls the common interrupt handler.
+ // this necessitated because intel didn't know much about
+ // architecture when they did the 8086 (it shows)
+ // (hmm do they know anymore even now :-)
+ // obviously you can see I don't really care about memory
+ // efficiency. If I did I would probe back through the stack
+ // and get it that way. But that's really disgusting.
+ for (i = 0; i < 256; i++) {
+ idts[i].cs = 0;
+ codeptr = (unsigned char *)4096 + i * codesize;
+ idts[i].offset = (unsigned)codeptr;
+ memcpy(codeptr, &idthandle, codesize);
+ intbyte = codeptr + 3;
+ *intbyte = i;
+ }
+
+ // fixed entry points
+
+ // VGA BIOSes tend to hardcode f000:f065 as the previous handler of
+ // int10.
+ // calling convention here is the same as INTs, we can reuse
+ // the int entry code.
+ codeptr = (unsigned char *)0xff065;
+ memcpy(codeptr, &idthandle, codesize);
+ intbyte = codeptr + 3;
+ *intbyte = 0x42; /* int42 is the relocated int10 */
+
+ // VIA's VBIOS will call f000:f859 instead of sending int15.
+ codeptr = (unsigned char *)0xff859;
+ memcpy(codeptr, &idthandle, codesize);
+ intbyte = codeptr + 3;
+ *intbyte = 0x15;
+
+ /* debug handler - useful to set a programmable delay between instructions if the
+ TF bit is set upon call to real mode */
+ idts[1].cs = 0;
+ idts[1].offset = 16384;
+ memcpy((void *)16384UL, &debughandle, &end_debughandle - &debughandle);
+}
+
+enum {
+ CHECK = 0xb001,
+ FINDDEV = 0xb102,
+ READCONFBYTE = 0xb108,
+ READCONFWORD = 0xb109,
+ READCONFDWORD = 0xb10a,
+ WRITECONFBYTE = 0xb10b,
+ WRITECONFWORD = 0xb10c,
+ WRITECONFDWORD = 0xb10d
+};
+
+// errors go in AH. Just set these up so that word assigns
+// will work. KISS.
+enum {
+ PCIBIOS_NODEV = 0x8600,
+ PCIBIOS_BADREG = 0x8700
+};
+
+int
+pcibios(unsigned long *pedi, unsigned long *pesi, unsigned long *pebp,
+ unsigned long *pesp, unsigned long *pebx, unsigned long *pedx,
+ unsigned long *pecx, unsigned long *peax, unsigned long *pflags)
+{
+ unsigned short func = (unsigned short)(*peax);
+ int retval = 0;
+ unsigned short devid, vendorid, devfn;
+ short devindex; /* Use short to get rid of garbage in upper half of 32-bit register */
+ unsigned char bus;
+ device_t dev;
+
+ switch (func) {
+ case CHECK:
+ *pedx = 0x4350;
+ *pecx = 0x2049;
+ retval = 0;
+ break;
+ case FINDDEV:
+ {
+ devid = *pecx;
+ vendorid = *pedx;
+ devindex = *pesi;
+ dev = 0;
+ while ((dev = dev_find_device(vendorid, devid, dev))) {
+ if (devindex <= 0)
+ break;
+ devindex--;
+ }
+ if (dev) {
+ unsigned short busdevfn;
+ *peax = 0;
+ // busnum is an unsigned char;
+ // devfn is an int, so we mask it off.
+ busdevfn = (dev->bus->secondary << 8)
+ | (dev->path.pci.devfn & 0xff);
+ printk_debug("0x%x: return 0x%x\n", func,
+ busdevfn);
+ *pebx = busdevfn;
+ retval = 0;
+ } else {
+ *peax = PCIBIOS_NODEV;
+ retval = -1;
+ }
+ }
+ break;
+ case READCONFDWORD:
+ case READCONFWORD:
+ case READCONFBYTE:
+ case WRITECONFDWORD:
+ case WRITECONFWORD:
+ case WRITECONFBYTE:
+ {
+ unsigned long dword;
+ unsigned short word;
+ unsigned char byte;
+ unsigned char reg;
+
+ devfn = *pebx & 0xff;
+ bus = *pebx >> 8;
+ reg = *pedi;
+ dev = dev_find_slot(bus, devfn);
+ if (!dev) {
+ printk_debug
+ ("0x%x: BAD DEVICE bus %d devfn 0x%x\n",
+ func, bus, devfn);
+ // idiots. the pcibios guys assumed you'd never pass a bad bus/devfn!
+ *peax = PCIBIOS_BADREG;
+ retval = -1;
+ }
+ switch (func) {
+ case READCONFBYTE:
+ byte = pci_read_config8(dev, reg);
+ *pecx = byte;
+ break;
+ case READCONFWORD:
+ word = pci_read_config16(dev, reg);
+ *pecx = word;
+ break;
+ case READCONFDWORD:
+ dword = pci_read_config32(dev, reg);
+ *pecx = dword;
+ break;
+ case WRITECONFBYTE:
+ byte = *pecx;
+ pci_write_config8(dev, reg, byte);
+ break;
+ case WRITECONFWORD:
+ word = *pecx;
+ pci_write_config16(dev, reg, word);
+ break;
+ case WRITECONFDWORD:
+ dword = *pecx;
+ pci_write_config32(dev, reg, dword);
+ break;
+ }
+
+ if (retval)
+ retval = PCIBIOS_BADREG;
+ printk_debug
+ ("0x%x: bus %d devfn 0x%x reg 0x%x val 0x%lx\n",
+ func, bus, devfn, reg, *pecx);
+ *peax = 0;
+ retval = 0;
+ }
+ break;
+ default:
+ printk_err("UNSUPPORTED PCIBIOS FUNCTION 0x%x\n", func);
+ break;
+ }
+
+ return retval;
+}
+
+int handleint21(unsigned long *edi, unsigned long *esi, unsigned long *ebp,
+ unsigned long *esp, unsigned long *ebx, unsigned long *edx,
+ unsigned long *ecx, unsigned long *eax, unsigned long *flags)
+{
+ int res = -1;
+ switch (*eax & 0xffff) {
+ case 0x5f19:
+ break;
+ case 0x5f18:
+ *eax = 0x5f;
+ *ebx = 0x545; // MCLK = 133, 32M frame buffer, 256 M main memory
+ *ecx = 0x060;
+ res = 0;
+ break;
+ case 0x5f00:
+ *eax = 0x8600;
+ break;
+ case 0x5f01:
+ *eax = 0x5f;
+ *ecx = (*ecx & 0xffffff00) | 2; // panel type = 2 = 1024 * 768
+ res = 0;
+ break;
+ case 0x5f02:
+ *eax = 0x5f;
+ *ebx = (*ebx & 0xffff0000) | 2;
+ *ecx = (*ecx & 0xffff0000) | 0x401; // PAL + crt only
+ *edx = (*edx & 0xffff0000) | 0; // TV Layout - default
+ res = 0;
+ break;
+ case 0x5f0f:
+ *eax = 0x860f;
+ break;
+ }
+ return res;
+}
diff --git a/src/pc80/udelay_io.c b/src/pc80/udelay_io.c
index a67b5a1986..7a5320e370 100644
--- a/src/pc80/udelay_io.c
+++ b/src/pc80/udelay_io.c
@@ -1,6 +1,6 @@
#include <arch/io.h>
-void udelay(int usecs)
+void udelay(unsigned usecs)
{
int i;
for(i = 0; i < usecs; i++)
diff --git a/targets/via/vt8454c/Config-abuild.lb b/targets/via/vt8454c/Config-abuild.lb
new file mode 100644
index 0000000000..7103b75c46
--- /dev/null
+++ b/targets/via/vt8454c/Config-abuild.lb
@@ -0,0 +1,44 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2007-2009 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; version 2 of the License.
+##
+## This program is distributed in the hope that it will be useful,
+## but WITHOUT ANY WARRANTY; without even the implied warranty of
+## MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+## GNU General Public License for more details.
+##
+## You should have received a copy of the GNU General Public License
+## along with this program; if not, write to the Free Software
+## Foundation, Inc., 51 Franklin St, Fifth Floor, Boston, MA 02110-1301 USA
+##
+
+
+# This will make a target directory of ./VENDOR_MAINBOARD
+# build a single image coreboot. Only Fallback, no normal.
+
+target VENDOR_MAINBOARD
+mainboard VENDOR/MAINBOARD
+
+option CC="CROSSCC"
+option CROSS_COMPILE="CROSS_PREFIX"
+option HOSTCC="CROSS_HOSTCC"
+
+option ROM_SIZE=(512-64)*1024
+option FALLBACK_SIZE=(512-64)*1024
+
+__COMPRESSION__
+
+romimage "fallback"
+ option USE_FALLBACK_IMAGE=1
+ option ROM_IMAGE_SIZE=0x15000
+ option COREBOOT_EXTRA_VERSION=".0-fallback"
+ payload __PAYLOAD__
+end
+
+buildrom ./coreboot.rom ROM_SIZE "fallback"
+
diff --git a/targets/via/vt8454c/Config.lb b/targets/via/vt8454c/Config.lb
new file mode 100644
index 0000000000..a75c1e3b0a
--- /dev/null
+++ b/targets/via/vt8454c/Config.lb
@@ -0,0 +1,45 @@
+##
+## This file is part of the coreboot project.
+##
+## Copyright (C) 2007-2009 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; 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
+##
+
+# Config file for VIA VT8454c mainboard
+#
+
+target via_vt8454c
+mainboard via/vt8454c
+
+option MAXIMUM_CONSOLE_LOGLEVEL=5
+option DEFAULT_CONSOLE_LOGLEVEL=5
+
+option ROM_SIZE=(512-64)*1024
+
+romimage "normal"
+ option USE_FALLBACK_IMAGE=0
+ option ROM_IMAGE_SIZE=0x14000
+ option COREBOOT_EXTRA_VERSION=".0-normal"
+ payload $(HOME)/payload.elf
+end
+
+romimage "fallback"
+ option USE_FALLBACK_IMAGE=1
+ option ROM_IMAGE_SIZE=0x14000
+ option COREBOOT_EXTRA_VERSION=".0-fallback"
+ payload $(HOME)/payload.elf
+end
+
+buildrom ./coreboot.rom ROM_SIZE "normal" "fallback"