aboutsummaryrefslogtreecommitdiff
path: root/src
diff options
context:
space:
mode:
Diffstat (limited to 'src')
-rw-r--r--src/arch/i386/include/arch/hlt.h20
-rw-r--r--src/arch/i386/include/arch/romcc_io.h57
-rw-r--r--src/arch/i386/include/arch/smp/lapic.h55
-rw-r--r--src/arch/i386/lib/cpu.c4
-rw-r--r--src/arch/i386/smp/start_stop.c9
-rw-r--r--src/arch/ppc/boot/linuxbios_table.c3
-rw-r--r--src/config/Config.lb15
-rw-r--r--src/config/Options.lb41
-rw-r--r--src/cpu/i386/bist32.inc4
-rw-r--r--src/cpu/i386/bist32_fail.inc44
-rw-r--r--src/cpu/i386/entry16.inc5
-rw-r--r--src/cpu/i386/entry32.inc6
-rw-r--r--src/cpu/k8/cpufixup.c287
-rw-r--r--src/cpu/k8/earlymtrr.c26
-rw-r--r--src/cpu/k8/earlymtrr.inc22
-rw-r--r--src/cpu/k8/enable_mmx_sse.inc6
-rw-r--r--src/cpu/p6/Config.lb1
-rw-r--r--src/cpu/p6/boot_cpu.c2
-rw-r--r--src/cpu/p6/earlymtrr.c10
-rw-r--r--src/cpu/p6/mtrr.c37
-rw-r--r--src/cpu/p6/pgtbl.c91
-rw-r--r--src/devices/Config.lb1
-rw-r--r--src/devices/chip.c11
-rw-r--r--src/devices/device.c20
-rw-r--r--src/devices/device_util.c73
-rw-r--r--src/devices/hypertransport.c51
-rw-r--r--src/devices/pci_device.c124
-rw-r--r--src/devices/pnp_device.c217
-rw-r--r--src/include/cpu/k8/mtrr.h3
-rw-r--r--src/include/cpu/p6/mtrr.h2
-rw-r--r--src/include/cpu/p6/pgtbl.h7
-rw-r--r--src/include/device/chip.h23
-rw-r--r--src/include/device/device.h16
-rw-r--r--src/include/device/hypertransport.h2
-rw-r--r--src/include/device/hypertransport_def.h16
-rw-r--r--src/include/device/pci_def.h4
-rw-r--r--src/include/device/pnp.h97
-rw-r--r--src/include/device/pnp_def.h12
-rw-r--r--src/include/device/resource.h6
-rw-r--r--src/include/pc80/keyboard.h10
-rw-r--r--src/include/pc80/mc146818rtc.h22
-rw-r--r--src/include/string.h1
-rw-r--r--src/include/uart8250.h6
-rw-r--r--src/lib/Config.lb3
-rw-r--r--src/lib/memcpy.c11
-rw-r--r--src/lib/memmove.c20
-rw-r--r--src/lib/uart8250.c16
-rw-r--r--src/mainboard/amd/quartet/Config.lb36
-rw-r--r--src/mainboard/amd/solo/Config.lb81
-rw-r--r--src/mainboard/amd/solo/auto.c104
-rw-r--r--src/mainboard/amd/solo/cmos.layout26
-rw-r--r--src/mainboard/amd/solo/failover.c72
-rw-r--r--src/mainboard/amd/solo/mptable.c1
-rw-r--r--src/mainboard/arima/hdama/Config.lb61
-rw-r--r--src/mainboard/arima/hdama/auto.c134
-rw-r--r--src/mainboard/arima/hdama/cmos.layout26
-rw-r--r--src/mainboard/arima/hdama/failover.c72
-rw-r--r--src/mainboard/arima/hdama/irq_tables.c36
-rw-r--r--src/mainboard/arima/hdama/mainboard.c247
-rw-r--r--src/mainboard/newisys/khepri/Config.lb36
-rw-r--r--src/mainboard/newisys/khepri/auto.c127
-rw-r--r--src/northbridge/amd/amdk8/Config.lb7
-rw-r--r--src/northbridge/amd/amdk8/amdk8.h12
-rw-r--r--src/northbridge/amd/amdk8/coherent_ht.c469
-rw-r--r--src/northbridge/amd/amdk8/cpu_rev.c7
-rw-r--r--src/northbridge/amd/amdk8/early_ht.c3
-rw-r--r--src/northbridge/amd/amdk8/incoherent_ht.c244
-rw-r--r--src/northbridge/amd/amdk8/misc_control.c198
-rw-r--r--src/northbridge/amd/amdk8/northbridge.c86
-rw-r--r--src/northbridge/amd/amdk8/raminit.c907
-rw-r--r--src/northbridge/amd/amdk8/raminit.h5
-rw-r--r--src/northbridge/amd/amdk8/raminit_test.c442
-rw-r--r--src/northbridge/amd/amdk8/reset_test.c11
-rw-r--r--src/pc80/Config.lb7
-rw-r--r--src/pc80/isa-dma.c43
-rw-r--r--src/pc80/keyboard.c11
-rw-r--r--src/pc80/mc146818rtc_early.c11
-rw-r--r--src/pc80/serial.c3
-rw-r--r--src/pc80/serial.inc7
-rw-r--r--src/southbridge/amd/amd8111/Config.lb5
-rw-r--r--src/southbridge/amd/amd8111/amd8111.c21
-rw-r--r--src/southbridge/amd/amd8111/amd8111_acpi.c41
-rw-r--r--src/southbridge/amd/amd8111/amd8111_early_smbus.c3
-rw-r--r--src/southbridge/amd/amd8111/amd8111_ide.c3
-rw-r--r--src/southbridge/amd/amd8111/amd8111_lpc.c35
-rw-r--r--src/southbridge/amd/amd8111/amd8111_pci.c61
-rw-r--r--src/southbridge/amd/amd8111/amd8111_usb.c2
-rw-r--r--src/southbridge/amd/amd8111/amd8111_usb2.c3
-rw-r--r--src/southbridge/amd/amd8131/amd8131_bridge.c43
-rw-r--r--src/superio/NSC/pc87360/chip.h14
-rw-r--r--src/superio/NSC/pc87360/pc87360.h11
-rw-r--r--src/superio/NSC/pc87360/pc87360_early_serial.c11
-rw-r--r--src/superio/NSC/pc87360/superio.c339
93 files changed, 3806 insertions, 1837 deletions
diff --git a/src/arch/i386/include/arch/hlt.h b/src/arch/i386/include/arch/hlt.h
new file mode 100644
index 0000000000..86ed7c8f41
--- /dev/null
+++ b/src/arch/i386/include/arch/hlt.h
@@ -0,0 +1,20 @@
+#ifndef ARCH_HLT_H
+#define ARCH_HLT_H
+
+#ifdef __ROMCC__
+static void hlt(void)
+{
+ __builtin_hlt();
+}
+
+#endif
+
+#ifdef __GNUC__
+static inline void hlt(void)
+{
+ asm("hlt");
+ return;
+}
+#endif
+
+#endif /* ARCH_HLT_H */
diff --git a/src/arch/i386/include/arch/romcc_io.h b/src/arch/i386/include/arch/romcc_io.h
index 1a646359a7..c3a0ff76fa 100644
--- a/src/arch/i386/include/arch/romcc_io.h
+++ b/src/arch/i386/include/arch/romcc_io.h
@@ -1,11 +1,7 @@
#ifndef ARCH_ROMCC_IO_H
#define ARCH_ROMCC_IO_H 1
-
-static void hlt(void)
-{
- __builtin_hlt();
-}
+#include <stdint.h>
typedef __builtin_div_t div_t;
typedef __builtin_ldiv_t ldiv_t;
@@ -59,6 +55,9 @@ int log2(int value)
#define PCI_ID(VENDOR_ID, DEVICE_ID) \
((((DEVICE_ID) & 0xFFFF) << 16) | ((VENDOR_ID) & 0xFFFF))
+
+#define PNP_DEV(PORT, FUNC) (((PORT) << 8) | (FUNC))
+
typedef unsigned device_t;
static unsigned char pci_read_config8(device_t dev, unsigned where)
@@ -122,4 +121,52 @@ static device_t pci_locate_device(unsigned pci_id, device_t dev)
return PCI_DEV_INVALID;
}
+
+/* Generic functions for pnp devices */
+static inline void pnp_write_config(device_t dev, uint8_t reg, uint8_t value)
+{
+ unsigned port = dev >> 8;
+ outb(reg, port );
+ outb(value, port +1);
+}
+
+static inline uint8_t pnp_read_config(device_t dev, uint8_t reg)
+{
+ unsigned port = dev >> 8;
+ outb(reg, port);
+ return inb(port +1);
+}
+
+static inline void pnp_set_logical_device(device_t dev)
+{
+ unsigned device = dev & 0xff;
+ pnp_write_config(dev, 0x07, device);
+}
+
+static inline void pnp_set_enable(device_t dev, int enable)
+{
+ pnp_write_config(dev, 0x30, enable?0x1:0x0);
+}
+
+static inline int pnp_read_enable(device_t dev)
+{
+ return !!pnp_read_config(dev, 0x30);
+}
+
+static inline void pnp_set_iobase(device_t dev, unsigned index, unsigned iobase)
+{
+ pnp_write_config(dev, index + 0, (iobase >> 8) & 0xff);
+ pnp_write_config(dev, index + 1, iobase & 0xff);
+}
+
+static inline void pnp_set_irq(device_t dev, unsigned index, unsigned irq)
+{
+ pnp_write_config(dev, index, irq);
+}
+
+static inline void pnp_set_drq(device_t dev, unsigned index, unsigned drq)
+{
+ pnp_write_config(dev, index, drq & 0xff);
+}
+
#endif /* ARCH_ROMCC_IO_H */
diff --git a/src/arch/i386/include/arch/smp/lapic.h b/src/arch/i386/include/arch/smp/lapic.h
new file mode 100644
index 0000000000..0ac87aa2d3
--- /dev/null
+++ b/src/arch/i386/include/arch/smp/lapic.h
@@ -0,0 +1,55 @@
+#ifndef ARCH_SMP_LAPIC_H
+#define ARCH_SMP_LAPIC_H
+
+#include <cpu/p6/msr.h>
+#include <cpu/p6/apic.h>
+#include <arch/hlt.h>
+
+static void enable_lapic(void)
+{
+
+ msr_t msr;
+ msr = rdmsr(0x1b);
+ msr.hi &= 0xffffff00;
+ msr.lo &= 0x000007ff;
+ msr.lo |= APIC_DEFAULT_BASE | (1 << 11);
+ wrmsr(0x1b, msr);
+}
+
+static void disable_lapic(void)
+{
+ msr_t msr;
+ msr = rdmsr(0x1b);
+ msr.lo &= ~ (1 << 11);
+ wrmsr(0x1b, msr);
+}
+
+static inline unsigned long lapicid(void)
+{
+ return apic_read(APIC_ID) >> 24;
+}
+
+static void stop_this_cpu(void)
+{
+ unsigned apicid;
+ apicid = lapicid();
+
+ /* Send an APIC INIT to myself */
+ apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
+ apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT);
+ /* Wait for the ipi send to finish */
+ apic_wait_icr_idle();
+
+ /* Deassert the APIC INIT */
+ apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
+ apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
+ /* Wait for the ipi send to finish */
+ apic_wait_icr_idle();
+
+ /* If I haven't halted spin forever */
+ for(;;) {
+ hlt();
+ }
+}
+
+#endif /* ARCH_SMP_LAPIC_H */
diff --git a/src/arch/i386/lib/cpu.c b/src/arch/i386/lib/cpu.c
index ad982dbc6c..f459f3a853 100644
--- a/src/arch/i386/lib/cpu.c
+++ b/src/arch/i386/lib/cpu.c
@@ -10,6 +10,7 @@
#include <cpu/p6/msr.h>
#include <cpu/p6/apic.h>
#include <cpu/p5/cpuid.h>
+#include <arch/smp/lapic.h>
#if 0
#include <cpu/l2_cache.h>
#endif
@@ -97,8 +98,7 @@ static void interrupts_on()
APIC_DELIVERY_MODE_NMI)
);
- printk_debug(" apic_id: %d ",
- apic_read(APIC_ID));
+ printk_debug(" apic_id: %d ", lapicid());
#else /* APIC */
#if i686==1
diff --git a/src/arch/i386/smp/start_stop.c b/src/arch/i386/smp/start_stop.c
index b40452403c..bf26437984 100644
--- a/src/arch/i386/smp/start_stop.c
+++ b/src/arch/i386/smp/start_stop.c
@@ -4,16 +4,13 @@
#include <delay.h>
#include <string.h>
#include <console/console.h>
+#include <arch/smp/lapic.h>
+#include <arch/hlt.h>
-static inline void hlt(void)
-{
- asm("hlt");
- return;
-}
unsigned long this_processors_id(void)
{
- return apic_read(APIC_ID) >> 24;
+ return lapicid();
}
int processor_index(unsigned long apicid)
diff --git a/src/arch/ppc/boot/linuxbios_table.c b/src/arch/ppc/boot/linuxbios_table.c
index 20264c202c..f199615d5f 100644
--- a/src/arch/ppc/boot/linuxbios_table.c
+++ b/src/arch/ppc/boot/linuxbios_table.c
@@ -227,6 +227,9 @@ unsigned long write_linuxbios_table(
struct mem_range *ramp;
struct lb_header *head;
struct lb_memory *mem;
+#if HAVE_OPTION_TABLE == 1
+ struct lb_record *rec_dest, *rec_src;
+#endif
head = lb_table_init(low_table_end);
low_table_end = (unsigned long)head;
diff --git a/src/config/Config.lb b/src/config/Config.lb
index 4a99d07ffa..636e5537c6 100644
--- a/src/config/Config.lb
+++ b/src/config/Config.lb
@@ -7,7 +7,7 @@ makedefine LIBGCC_FILE_NAME := $(shell $(CC) -print-libgcc-file-name)
makedefine GCC_INC_DIR := $(shell $(CC) -print-search-dirs | sed -ne "s/install: \(.*\)/\1include/gp")
makedefine CPPFLAGS := -I$(TOP)/src/include -I$(TOP)/src/arch/$(ARCH)/include -I$(GCC_INC_DIR) $(CPUFLAGS)
-makedefine ROMCCPPFLAGS := -D__ROMCC__=0 -D__ROMCC_MINOR__=37
+makedefine ROMCCPPFLAGS := -D__ROMCC__=0 -D__ROMCC_MINOR__=38
makedefine CFLAGS := $(CPU_OPT) $(CPPFLAGS) -Os -nostdinc -nostdlib -fno-builtin -Wall
makedefine HOSTCFLAGS:= -Os -Wall
@@ -116,12 +116,12 @@ end
makerule ./romcc
depends "$(TOP)/util/romcc/romcc.c"
- action "$(HOSTCC) -g $(HOSTCFLAGS) -DVERSION='\"0.37\"' -DRELEASE_DATE='\"21 October 2003\"' $< -o $@"
+ action "$(HOSTCC) -g $(HOSTCFLAGS) -DVERSION='\"0.38\"' -DRELEASE_DATE='\"18 December 2003\"' $< -o $@"
end
makerule build_opt_tbl
- depends "$(TOP)/util/options/build_opt_tbl.c $(TOP)/src/include/pc80/mc146818rtc.h $(TOP)/src/include/boot/linuxbios_tables.h"
- action "$(HOSTCC) $(HOSTCFLAGS) $< -o $@"
+ depends "$(TOP)/util/options/build_opt_tbl.c $(TOP)/src/include/pc80/mc146818rtc.h $(TOP)/src/include/boot/linuxbios_tables.h Makefile.settings Makefile"
+ action "$(HOSTCC) $(HOSTCFLAGS) $(CPUFLAGS) $< -o $@"
end
#makerule /$(TARGET_DIR)/option_table.c
@@ -131,7 +131,12 @@ end
makerule option_table.c
depends "build_opt_tbl $(MAINBOARD)/cmos.layout"
- action "./build_opt_tbl -b --config $(MAINBOARD)/cmos.layout"
+ action "./build_opt_tbl -b --config $(MAINBOARD)/cmos.layout --header option_table.h"
+end
+
+makerule option_table.h
+ depends "build_opt_tbl $(MAINBOARD)/cmos.layout"
+ action "./build_opt_tbl -b --config $(MAINBOARD)/cmos.layout --header option_table.h"
end
if HAVE_OPTION_TABLE
diff --git a/src/config/Options.lb b/src/config/Options.lb
index 936f9c3727..a175f358e8 100644
--- a/src/config/Options.lb
+++ b/src/config/Options.lb
@@ -117,7 +117,7 @@ define OBJCOPY
comment "Objcopy command"
end
define LINUXBIOS_VERSION
- default "1.1.5"
+ default "1.1.6"
export always
comment "LinuxBIOS version"
end
@@ -318,6 +318,12 @@ define CONFIG_UNCOMPRESSED
export always
comment "Set for uncompressed image"
end
+define CONFIG_LB_MEM_TOPK
+ format "%d"
+ default 1024
+ export always
+ comment "Kilobytes of memory to initialized before executing code from RAM"
+end
define HAVE_OPTION_TABLE
default 0
export always
@@ -331,6 +337,29 @@ define USE_OPTION_TABLE
end
###############################################
+# CMOS variable options
+###############################################
+define LB_CKS_RANGE_START
+ default 49
+ format "%d"
+ export always
+ comment "First CMOS byte to use for LinuxBIOS options"
+end
+define LB_CKS_RANGE_END
+ default 125
+ format "%d"
+ export always
+ comment "Last CMOS byte to use for LinuxBIOS options"
+end
+define LB_CKS_LOC
+ default 126
+ format "%d"
+ export always
+ comment "Pair of bytes to use for CMOS checksum"
+end
+
+
+###############################################
# Build targets
###############################################
@@ -427,15 +456,15 @@ define MAINBOARD_VENDOR
export always
comment "Vendor of mainboard"
end
-define CONFIG_SYS_CLK_FREQ
+define MAINBOARD_POWER_ON_AFTER_POWER_FAIL
default none
export used
- comment "System clock frequency in MHz"
+ comment "Default power on after power fail setting"
end
-define CONFIG_KEYBOARD
- default 0
+define CONFIG_SYS_CLK_FREQ
+ default none
export used
- comment "Run PC keyboard enable code"
+ comment "System clock frequency in MHz"
end
define CONFIG_LEGACY_VGABIOS
default 0
diff --git a/src/cpu/i386/bist32.inc b/src/cpu/i386/bist32.inc
new file mode 100644
index 0000000000..d2fb98cdc3
--- /dev/null
+++ b/src/cpu/i386/bist32.inc
@@ -0,0 +1,4 @@
+
+ /* Carefully print the failure if the built in self test did not pass */
+ testl %eax, %eax
+ jnz bist32_fail
diff --git a/src/cpu/i386/bist32_fail.inc b/src/cpu/i386/bist32_fail.inc
new file mode 100644
index 0000000000..f467b065bc
--- /dev/null
+++ b/src/cpu/i386/bist32_fail.inc
@@ -0,0 +1,44 @@
+
+
+ jmp bist32_fail_0
+bist32_fail:
+ movl %eax, %ebp
+
+#if 1
+#define SIO_BASE 0x2e
+#define SIO_INDEX SIO_BASE
+#define SIO_DATA SIO_BASE+1
+#define SIO_WRITE_CONFIG(value, reg) \
+ movb reg, %al ; \
+ outb %al, $(SIO_INDEX) ; \
+ movb value, %al ; \
+ outb %al, $(SIO_DATA)
+
+#define SIO_READ_CONFIG(reg) \
+ movb reg, %al ; \
+ outb %al, $(SIO_INDEX) ; \
+ inb $(SIO_DATA), %al
+
+#define SIO_SET_LOGICAL_DEVICE(device) \
+ SIO_WRITE_CONFIG(device, $0x07)
+
+ /* Enable serial 1 */
+ SIO_SET_LOGICAL_DEVICE($3)
+ SIO_WRITE_CONFIG($1, $0x30)
+ SIO_WRITE_CONFIG($0x3, $0x60)
+ SIO_WRITE_CONFIG($0xf8, $0x61)
+
+#endif
+ CALLSP(serial_init)
+ CONSOLE_DEBUG_TX_STRING($str_bist_failed)
+ CONSOLE_DEBUG_TX_HEX32(%ebp)
+ CONSOLE_DEBUG_TX_STRING($str_bist_newline)
+ jmp .Lhlt
+
+bist32_fail_0:
+
+.section ".rom.data"
+str_bist_failed: .string "BIST failed: "
+str_bist_newline: .string "\r\n"
+.previous
+
diff --git a/src/cpu/i386/entry16.inc b/src/cpu/i386/entry16.inc
index 7ab3ff3bf0..f9e921f291 100644
--- a/src/cpu/i386/entry16.inc
+++ b/src/cpu/i386/entry16.inc
@@ -33,6 +33,8 @@ it with the version available from LANL.
_start:
cli
+ /* Save the BIST result */
+ movl %eax, %ebp
/* thanks to kmliu@sis.tw.com for this TBL fix ... */
/**/
@@ -93,6 +95,9 @@ _start:
orl $0x60000001, %eax /* CD, NW, PE = 1 */
movl %eax, %cr0
+ /* Restore BIST to %eax */
+ movl %ebp, %eax
+
/* Now that we are in protected mode jump to a 32 bit code segment. */
data32 ljmp $ROM_CODE_SEG, $__protected_start
diff --git a/src/cpu/i386/entry32.inc b/src/cpu/i386/entry32.inc
index 6f55f00203..3d30a3f85f 100644
--- a/src/cpu/i386/entry32.inc
+++ b/src/cpu/i386/entry32.inc
@@ -44,6 +44,9 @@ protected_start:
ljmp $ROM_CODE_SEG, $__protected_start
__protected_start:
+ /* Save the BIST value */
+ movl %eax, %ebp
+
intel_chip_post_macro(0x10) /* post 10 */
movw $ROM_DATA_SEG, %ax
@@ -53,3 +56,6 @@ __protected_start:
movw %ax, %fs
movw %ax, %gs
+ /* Restore the BIST value to %eax */
+ movl %ebp, %eax
+
diff --git a/src/cpu/k8/cpufixup.c b/src/cpu/k8/cpufixup.c
index 6aa6722579..2d347de829 100644
--- a/src/cpu/k8/cpufixup.c
+++ b/src/cpu/k8/cpufixup.c
@@ -4,8 +4,17 @@
#include <cpu/p6/msr.h>
#include <cpu/k8/mtrr.h>
#include <device/device.h>
-#include "../../northbridge/amd/amdk8/cpu_rev.c"
#include <device/chip.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <smp/start_stop.h>
+#include <string.h>
+#include <cpu/p6/msr.h>
+#include <cpu/p6/pgtbl.h>
+#include <pc80/mc146818rtc.h>
+#include <arch/smp/lapic.h>
+#include "../../northbridge/amd/amdk8/amdk8.h"
+#include "../../northbridge/amd/amdk8/cpu_rev.c"
#include "chip.h"
#define MCI_STATUS 0x401
@@ -14,7 +23,7 @@ static inline void disable_cache(void)
{
unsigned int tmp;
/* Disable cache */
- /* Write back the cache and flush TLB */
+ /* Write back the cache */
asm volatile (
"movl %%cr0, %0\n\t"
"orl $0x40000000, %0\n\t"
@@ -57,6 +66,232 @@ static inline void wrmsr_amd(unsigned index, msr_t msr)
);
}
+
+
+#define MTRR_COUNT 8
+#define ZERO_CHUNK_KB 0x800UL /* 2M */
+#define TOLM_KB 0x400000UL
+
+struct mtrr {
+ msr_t base;
+ msr_t mask;
+};
+struct mtrr_state {
+ struct mtrr mtrrs[MTRR_COUNT];
+ msr_t top_mem, top_mem2;
+ msr_t def_type;
+};
+
+static void save_mtrr_state(struct mtrr_state *state)
+{
+ int i;
+ for(i = 0; i < MTRR_COUNT; i++) {
+ state->mtrrs[i].base = rdmsr(MTRRphysBase_MSR(i));
+ state->mtrrs[i].mask = rdmsr(MTRRphysMask_MSR(i));
+ }
+ state->top_mem = rdmsr(TOP_MEM);
+ state->top_mem2 = rdmsr(TOP_MEM2);
+ state->def_type = rdmsr(MTRRdefType_MSR);
+}
+
+static void restore_mtrr_state(struct mtrr_state *state)
+{
+ int i;
+ disable_cache();
+
+ for(i = 0; i < MTRR_COUNT; i++) {
+ wrmsr(MTRRphysBase_MSR(i), state->mtrrs[i].base);
+ wrmsr(MTRRphysMask_MSR(i), state->mtrrs[i].mask);
+ }
+ wrmsr(TOP_MEM, state->top_mem);
+ wrmsr(TOP_MEM2, state->top_mem2);
+ wrmsr(MTRRdefType_MSR, state->def_type);
+
+ enable_cache();
+}
+
+
+#if 0
+static void print_mtrr_state(struct mtrr_state *state)
+{
+ int i;
+ for(i = 0; i < MTRR_COUNT; i++) {
+ printk_debug("var mtrr %d: %08x%08x mask: %08x%08x\n",
+ i,
+ state->mtrrs[i].base.hi, state->mtrrs[i].base.lo,
+ state->mtrrs[i].mask.hi, state->mtrrs[i].mask.lo);
+ }
+ printk_debug("top_mem: %08x%08x\n",
+ state->top_mem.hi, state->top_mem.lo);
+ printk_debug("top_mem2: %08x%08x\n",
+ state->top_mem2.hi, state->top_mem2.lo);
+ printk_debug("def_type: %08x%08x\n",
+ state->def_type.hi, state->def_type.lo);
+}
+#endif
+
+static void set_init_ecc_mtrrs(void)
+{
+ msr_t msr;
+ int i;
+ disable_cache();
+
+ /* First clear all of the msrs to be safe */
+ for(i = 0; i < MTRR_COUNT; i++) {
+ msr_t zero;
+ zero.lo = zero.hi = 0;
+ wrmsr(MTRRphysBase_MSR(i), zero);
+ wrmsr(MTRRphysMask_MSR(i), zero);
+ }
+
+ /* Write back cache the first 1MB */
+ msr.hi = 0x00000000;
+ msr.lo = 0x00000000 | MTRR_TYPE_WRBACK;
+ wrmsr(MTRRphysBase_MSR(0), msr);
+ msr.hi = 0x000000ff;
+ msr.lo = ~((CONFIG_LB_MEM_TOPK << 10) - 1) | 0x800;
+ wrmsr(MTRRphysMask_MSR(0), msr);
+
+ /* Set the default type to write combining */
+ msr.hi = 0x00000000;
+ msr.lo = 0xc00 | MTRR_TYPE_WRCOMB;
+ wrmsr(MTRRdefType_MSR, msr);
+
+ /* Set TOP_MEM to 4G */
+ msr.hi = 0x00000001;
+ msr.lo = 0x00000000;
+ wrmsr(TOP_MEM, msr);
+
+ enable_cache();
+}
+
+
+static void init_ecc_memory(void)
+{
+ unsigned long startk, begink, endk;
+ unsigned long basek;
+ struct mtrr_state mtrr_state;
+ device_t f1_dev, f2_dev, f3_dev;
+ int cpu_index, cpu_id, node_id;
+ int enable_scrubbing;
+ uint32_t dcl;
+ cpu_id = this_processors_id();
+ cpu_index = processor_index(cpu_id);
+ /* For now there is a 1-1 mapping between node_id and cpu_id */
+ node_id = cpu_id;
+
+ f1_dev = dev_find_slot(0, PCI_DEVFN(0x18 + node_id, 1));
+ if (!f1_dev) {
+ die("Cannot find cpu function 1\n");
+ }
+ f2_dev = dev_find_slot(0, PCI_DEVFN(0x18 + node_id, 2));
+ if (!f2_dev) {
+ die("Cannot find cpu function 2\n");
+ }
+ f3_dev = dev_find_slot(0, PCI_DEVFN(0x18 + node_id, 3));
+ if (!f3_dev) {
+ die("Cannot find cpu function 3\n");
+ }
+
+ /* See if we scrubbing should be enabled */
+ enable_scrubbing = 1;
+ get_option(&enable_scrubbing, "hw_scrubber");
+
+ /* Enable cache scrubbing at the lowest possible rate */
+ if (enable_scrubbing) {
+ pci_write_config32(f3_dev, SCRUB_CONTROL,
+ (SCRUB_84ms << 16) | (SCRUB_84ms << 8) | (SCRUB_NONE << 0));
+ } else {
+ pci_write_config32(f3_dev, SCRUB_CONTROL,
+ (SCRUB_NONE << 16) | (SCRUB_NONE << 8) | (SCRUB_NONE << 0));
+ printk_debug("Scrubbing Disabled\n");
+ }
+
+
+ /* If ecc support is not enabled don't touch memory */
+ dcl = pci_read_config32(f2_dev, DRAM_CONFIG_LOW);
+ if (!(dcl & DCL_DimmEccEn)) {
+ return;
+ }
+
+ startk = (pci_read_config32(f1_dev, 0x40 + (node_id*8)) & 0xffff0000) >> 2;
+ endk = ((pci_read_config32(f1_dev, 0x44 + (node_id*8)) & 0xffff0000) >> 2) + 0x4000;
+
+ /* Don't start too early */
+ begink = startk;
+ if (begink < CONFIG_LB_MEM_TOPK) {
+ begink = CONFIG_LB_MEM_TOPK;
+ }
+ printk_debug("Clearing memory %uK - %uK: ", startk, endk);
+
+ /* Save the normal state */
+ save_mtrr_state(&mtrr_state);
+
+ /* Switch to the init ecc state */
+ set_init_ecc_mtrrs();
+ disable_lapic();
+
+ /* Walk through 2M chunks and zero them */
+ for(basek = begink; basek < endk; basek = ((basek + ZERO_CHUNK_KB) & ~(ZERO_CHUNK_KB - 1))) {
+ unsigned long limitk;
+ unsigned long size;
+ void *addr;
+
+ /* Report every 64M */
+ if ((basek % (64*1024)) == 0) {
+ /* Restore the normal state */
+ map_2M_page(cpu_index, 0);
+ restore_mtrr_state(&mtrr_state);
+ enable_lapic();
+
+ /* Print a status message */
+ printk_debug("%c", (basek >= TOLM_KB)?'+':'-');
+
+ /* Return to the initialization state */
+ set_init_ecc_mtrrs();
+ disable_lapic();
+ }
+ limitk = (basek + ZERO_CHUNK_KB) & ~(ZERO_CHUNK_KB - 1);
+ if (limitk > endk) {
+ limitk = endk;
+ }
+ size = (limitk - basek) << 10;
+ addr = map_2M_page(cpu_index, basek >> 11);
+ addr = (void *)(((uint32_t)addr) | ((basek & 0x7ff) << 10));
+ if (addr == MAPPING_ERROR) {
+ continue;
+ }
+
+ /* clear memory 2M (limitk - basek) */
+ __asm__ volatile(
+ "1: \n\t"
+ "movl %0, (%1)\n\t"
+ "addl $4,%1\n\t"
+ "subl $4,%2\n\t"
+ "jnz 1b\n\t"
+ :
+ : "a" (0), "D" (addr), "c" (size)
+ );
+ }
+ /* Restore the normal state */
+ map_2M_page(cpu_index, 0);
+ restore_mtrr_state(&mtrr_state);
+ enable_lapic();
+
+ /* Set the scrub base address registers */
+ pci_write_config32(f3_dev, SCRUB_ADDR_LOW, startk << 10);
+ pci_write_config32(f3_dev, SCRUB_ADDR_HIGH, startk >> 22);
+
+ /* Enable the scrubber? */
+ if (enable_scrubbing) {
+ /* Enable scrubbing at the lowest possible rate */
+ pci_write_config32(f3_dev, SCRUB_CONTROL,
+ (SCRUB_84ms << 16) | (SCRUB_84ms << 8) | (SCRUB_84ms << 0));
+ }
+
+ printk_debug(" done\n");
+}
+
void k8_cpufixup(struct mem_range *mem)
{
unsigned long mmio_basek, tomk;
@@ -83,7 +318,11 @@ void k8_cpufixup(struct mem_range *mem)
if (mmio_basek > tomk) {
mmio_basek = tomk;
}
-
+ /* Round mmio_basek down to the nearst size that will fit in TOP_MEM */
+ mmio_basek = mmio_basek & ~TOP_MEM_MASK_KB;
+ /* Round tomk up to the next greater size that will fit in TOP_MEM */
+ tomk = (tomk + TOP_MEM_MASK_KB) & ~TOP_MEM_MASK_KB;
+
/* Setup TOP_MEM */
msr.hi = mmio_basek >> 22;
msr.lo = mmio_basek << 10;
@@ -101,7 +340,7 @@ void k8_cpufixup(struct mem_range *mem)
for(i = IORR_FIRST; i <= IORR_LAST; i++) {
wrmsr(i, msr);
}
-
+
msr = rdmsr(SYSCFG_MSR);
msr.lo |= SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_TOM2En;
wrmsr(SYSCFG_MSR, msr);
@@ -118,33 +357,34 @@ void k8_cpufixup(struct mem_range *mem)
msr = rdmsr(HWCR_MSR);
msr.lo |= (1 << 6);
wrmsr(HWCR_MSR, msr);
+
/* Erratum 69... */
-#if 1
msr = rdmsr_amd(BU_CFG_MSR);
msr.hi |= (1 << (45 - 32));
wrmsr_amd(BU_CFG_MSR, msr);
-#endif
+
/* Erratum 81... */
-#if 1
msr = rdmsr_amd(DC_CFG_MSR);
msr.lo |= (1 << 10);
wrmsr_amd(DC_CFG_MSR, msr);
-#endif
}
- /* Erratum 89 ... */
- msr = rdmsr(NB_CFG_MSR);
- msr.lo |= 1 << 3;
+ /* I can't touch this msr on early buggy cpus */
+ if (!is_cpu_pre_b3()) {
- if (!is_cpu_pre_c0()) {
- /* Erratum 86 Disable data masking on C0 and
- * later processor revs.
- * FIXME this is only needed if ECC is enabled.
- */
- msr.hi |= 1 << (36 - 32);
- }
- wrmsr(NB_CFG_MSR, msr);
-#if 1 /* The following erratum fixes reset the cpu ???? */
+ /* Erratum 89 ... */
+ msr = rdmsr(NB_CFG_MSR);
+ msr.lo |= 1 << 3;
+
+ if (!is_cpu_pre_c0()) {
+ /* Erratum 86 Disable data masking on C0 and
+ * later processor revs.
+ * FIXME this is only needed if ECC is enabled.
+ */
+ msr.hi |= 1 << (36 - 32);
+ }
+ wrmsr(NB_CFG_MSR, msr);
+ }
/* Erratum 97 ... */
if (!is_cpu_pre_c0()) {
@@ -158,11 +398,14 @@ void k8_cpufixup(struct mem_range *mem)
msr.lo |= 1 << 11;
wrmsr_amd(IC_CFG_MSR, msr);
-#endif
-
/* Erratum 91 prefetch miss is handled in the kernel */
enable_cache();
+
+ /* Is this a bad location? In particular can another node prefecth
+ * data from this node before we have initialized it?
+ */
+ init_ecc_memory();
}
static
diff --git a/src/cpu/k8/earlymtrr.c b/src/cpu/k8/earlymtrr.c
index 47ddd12340..5fb63d2e7d 100644
--- a/src/cpu/k8/earlymtrr.c
+++ b/src/cpu/k8/earlymtrr.c
@@ -6,7 +6,7 @@
static void early_mtrr_init(void)
{
- static unsigned long mtrr_msrs[] = {
+ static const unsigned long mtrr_msrs[] = {
/* fixed mtrr */
0x250, 0x258, 0x259,
0x268, 0x269, 0x26A
@@ -25,46 +25,46 @@ static void early_mtrr_init(void)
0
};
msr_t msr;
- unsigned long *msr_addr;
+ const unsigned long *msr_addr;
/* Inialize all of the relevant msrs to 0 */
msr.lo = 0;
msr.hi = 0;
- for(msr_addr = &mtrr_msrs; *msr_addr; msr_addr++) {
+ for(msr_addr = mtrr_msrs; *msr_addr; msr_addr++) {
wrmsr(*msr_addr, msr);
}
- /* Enable memory access for 0 - 8MB using top_mem */
+ /* Enable memory access for 0 - 1MB using top_mem */
msr.hi = 0;
- msr.lo = 0x08000000;
+ msr.lo = ((CONFIG_LB_MEM_TOPK << 10) + TOP_MEM_MASK) & ~TOP_MEM_MASK;
wrmsr(TOP_MEM, msr);
- /* Enable caching for 0 - 128MB using variable mtrr */
+ /* Enable caching for 0 - 1MB using variable mtrr */
msr = rdmsr(0x200);
msr.hi &= 0xfffffff0;
msr.hi |= 0x00000000;
msr.lo &= 0x00000f00;
- msr.lo |= 0x00000006;
+ msr.lo |= 0x00000000 | MTRR_TYPE_WRBACK;
wrmsr(0x200, msr);
msr = rdmsr(0x201);
msr.hi &= 0xfffffff0;
msr.hi |= 0x0000000f;
msr.lo &= 0x000007ff;
- msr.lo |= 0xf0000800;
+ msr.lo |= (~((CONFIG_LB_MEM_TOPK << 10) - 1)) | 0x800;
wrmsr(0x201, msr);
#if defined(XIP_ROM_SIZE) && defined(XIP_ROM_BASE)
- /* enable write back caching so we can do execute in place
+ /* enable write through caching so we can do execute in place
* on the flash rom.
*/
msr.hi = 0x00000000;
- msr.lo = XIP_ROM_BASE | 0x005;
- wrmsr(0x202);
+ msr.lo = XIP_ROM_BASE | MTRR_TYPE_WRTHROUGH;
+ wrmsr(0x202, msr);
#error "FIXME verify the type of MTRR I have setup"
msr.hi = 0x0000000f;
msr.lo = ~(XIP_ROM_SIZE - 1) | 0x800;
- wrmsr(0x203);
+ wrmsr(0x203, msr);
#endif
/* Set the default memory type and enable fixed and variable MTRRs
@@ -72,7 +72,7 @@ static void early_mtrr_init(void)
/* Enable Variable MTRRs */
msr.hi = 0x00000000;
msr.lo = 0x00000800;
- wrmsr(0x2ff, msr);
+ wrmsr(MTRRdefType_MSR, msr);
/* Enale the MTRRs in SYSCFG */
msr = rdmsr(SYSCFG_MSR);
diff --git a/src/cpu/k8/earlymtrr.inc b/src/cpu/k8/earlymtrr.inc
index d14afb1a31..acc917be7d 100644
--- a/src/cpu/k8/earlymtrr.inc
+++ b/src/cpu/k8/earlymtrr.inc
@@ -1,7 +1,11 @@
#include <cpu/k8/mtrr.h>
+
+ /* Save off the BIST value */
+ movl %eax, %ebp
+
/* The fixed and variable MTRRs are powered-up with random values, clear them to
- * MTRR_TYPE_UNCACHABLE for safty reason
+ * MTRR_TYPE_UNCACHEABLE for safty reason
*/
earlymtrr_start:
@@ -21,20 +25,20 @@ clear_fixed_var_mtrr:
jmp clear_fixed_var_mtrr
clear_fixed_var_mtrr_out:
-/* enable memory access for 0 - 8MB using top_mem */
+/* enable memory access for 0 - 1MB using top_mem */
movl $TOP_MEM, %ecx
xorl %edx, %edx
- movl $0x0800000, %eax
+ movl $(((CONFIG_LB_MEM_TOPK << 10) + TOP_MEM_MASK) & ~TOP_MEM_MASK) , %eax
wrmsr
set_var_mtrr:
- /* enable caching for 0 - 128MB using variable mtrr */
+ /* enable caching for 0 - 1MB using variable mtrr */
movl $0x200, %ecx
rdmsr
andl $0xfffffff0, %edx
orl $0x00000000, %edx
andl $0x00000f00, %eax
- orl $0x00000006, %eax
+ orl $(0x00000000 | MTRR_TYPE_WRBACK), %eax
wrmsr
movl $0x201, %ecx
@@ -42,7 +46,7 @@ set_var_mtrr:
andl $0xfffffff0, %edx
orl $0x0000000f, %edx
andl $0x000007ff, %eax
- orl $0xf0000800, %eax
+ orl $((~((CONFIG_LB_MEM_TOPK << 10) - 1)) | 0x800), %eax
wrmsr
#if defined(XIP_ROM_SIZE) && defined(XIP_ROM_BASE)
@@ -51,7 +55,7 @@ set_var_mtrr:
*/
movl $0x202, %ecx
xorl %edx, %edx
- movl $(XIP_ROM_BASE | 0x006), %eax
+ movl $(XIP_ROM_BASE | MTRR_TYPE_WRBACK), %eax
wrmsr
movl $0x203, %ecx
@@ -62,7 +66,7 @@ set_var_mtrr:
enable_mtrr:
/* Set the default memory type and enable fixed and variable MTRRs */
- movl $0x2ff, %ecx
+ movl $MTRRdefType_MSR, %ecx
xorl %edx, %edx
/* Enable Variable MTRRs */
movl $0x00000800, %eax
@@ -97,3 +101,5 @@ mem_top:
.long 0xC001001A, 0xC001001D
.long 0x000 /* NULL, end of table */
earlymtrr_end:
+ /* Restore the BIST value */
+ movl %ebp, %eax \ No newline at end of file
diff --git a/src/cpu/k8/enable_mmx_sse.inc b/src/cpu/k8/enable_mmx_sse.inc
index 5551525d68..907e817325 100644
--- a/src/cpu/k8/enable_mmx_sse.inc
+++ b/src/cpu/k8/enable_mmx_sse.inc
@@ -1,3 +1,6 @@
+ /* Save the BIST result */
+ movl %eax, %ebp
+
/*
* Enabling mmx registers is a noop
* Enable the use of the xmm registers
@@ -12,3 +15,6 @@
movl %cr4, %eax
orl $(1<<9), %eax
movl %eax, %cr4
+
+ /* Restore the BIST result */
+ movl %ebp, %eax
diff --git a/src/cpu/p6/Config.lb b/src/cpu/p6/Config.lb
index c9d483480a..f6e9777bcd 100644
--- a/src/cpu/p6/Config.lb
+++ b/src/cpu/p6/Config.lb
@@ -3,4 +3,5 @@ uses INTEL_PPRO_MTRR
dir /cpu/p5
object cpufixup.o
object mtrr.o
+object pgtbl.o
#object l2_cache.o
diff --git a/src/cpu/p6/boot_cpu.c b/src/cpu/p6/boot_cpu.c
index 803eecdd5d..77b060b219 100644
--- a/src/cpu/p6/boot_cpu.c
+++ b/src/cpu/p6/boot_cpu.c
@@ -2,8 +2,6 @@
int boot_cpu(void)
{
- volatile unsigned long *local_apic;
- unsigned long apic_id;
int bsp;
msr_t msr;
msr = rdmsr(0x1b);
diff --git a/src/cpu/p6/earlymtrr.c b/src/cpu/p6/earlymtrr.c
index f352f3d791..df74f905c8 100644
--- a/src/cpu/p6/earlymtrr.c
+++ b/src/cpu/p6/earlymtrr.c
@@ -51,7 +51,7 @@ static void early_mtrr_init(void)
/* Disable Variable MTRRs */
msr.hi = 0x00000000;
msr.lo = 0x00000000;
- wrmsr(0x2ff, msr);
+ wrmsr(MTRRdefType_MSR, msr);
/* Invalidate the cache again */
asm volatile ("invd");
@@ -65,19 +65,19 @@ static void early_mtrr_init(void)
wrmsr(*msr_addr, msr);
}
- /* Enable caching for 0 - 128MB using variable mtrr */
+ /* Enable caching for 0 - 1MB using variable mtrr */
msr = rdmsr(0x200);
msr.hi &= 0xfffffff0;
msr.hi |= 0x00000000;
msr.lo &= 0x00000f00;
- msr.lo |= 0x00000006;
+ msr.lo |= 0x00000000 | MTRR_TYPE_WRBACK;
wrmsr(0x200, msr);
msr = rdmsr(0x201);
msr.hi &= 0xfffffff0;
msr.hi |= 0x0000000f;
msr.lo &= 0x000007ff;
- msr.lo |= 0xf0000800;
+ msr.lo |= (~((CONFIG_LB_MEM_TOPK << 10) - 1)) | 0x800;
wrmsr(0x201, msr);
#if defined(XIP_ROM_SIZE) && defined(XIP_ROM_BASE)
@@ -98,7 +98,7 @@ static void early_mtrr_init(void)
/* Enable Variable MTRRs */
msr.hi = 0x00000000;
msr.lo = 0x00000800;
- wrmsr(0x2ff, msr);
+ wrmsr(MTRRdefType_MSR, msr);
/* Enable the cache */
cr0 = read_cr0();
diff --git a/src/cpu/p6/mtrr.c b/src/cpu/p6/mtrr.c
index ac6fd1db37..7e2eb06e95 100644
--- a/src/cpu/p6/mtrr.c
+++ b/src/cpu/p6/mtrr.c
@@ -104,7 +104,8 @@ static void intel_set_var_mtrr(unsigned int reg, unsigned long basek, unsigned l
if (sizek < 4*1024*1024) {
mask.hi = ADDRESS_MASK_HIGH;
mask.lo = ~((sizek << 10) -1);
- } else {
+ }
+ else {
mask.hi = ADDRESS_MASK_HIGH & (~((sizek >> 22) -1));
mask.lo = 0;
}
@@ -131,6 +132,36 @@ static void intel_set_var_mtrr(unsigned int reg, unsigned long basek, unsigned l
enable_cache();
}
+/* setting variable mtrr, comes from linux kernel source */
+void set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size, unsigned char type)
+{
+ if (reg >= 8)
+ return;
+
+ // it is recommended that we disable and enable cache when we
+ // do this.
+ disable_cache();
+ if (size == 0) {
+ /* The invalid bit is kept in the mask, so we simply clear the
+ relevant mask register to disable a range. */
+ msr_t zero;
+ zero.lo = zero.hi = 0;
+ wrmsr (MTRRphysMask_MSR(reg), zero);
+ } else {
+ /* Bit 32-35 of MTRRphysMask should be set to 1 */
+ msr_t basem, maskm;
+ basem.lo = base | type;
+ basem.hi = 0;
+ maskm.lo = ~(size - 1) | 0x800;
+ maskm.hi = 0x0F;
+ wrmsr (MTRRphysBase_MSR(reg), basem);
+ wrmsr (MTRRphysMask_MSR(reg), maskm);
+ }
+
+ // turn cache back on.
+ enable_cache();
+}
+
/* fms: find most sigificant bit set, stolen from Linux Kernel Source. */
static inline unsigned int fms(unsigned int x)
{
@@ -250,7 +281,7 @@ static unsigned int range_to_mtrr(unsigned int reg,
}
sizek = 1 << align;
printk_debug("Setting variable MTRR %d, base: %4dMB, range: %4dMB, type WB\n",
- reg, range_startk >>10, sizek >> 10);
+ reg, range_startk >>10, sizek >> 10);
intel_set_var_mtrr(reg++, range_startk, sizek, MTRR_TYPE_WRBACK);
range_startk += sizek;
range_sizek -= sizek;
@@ -274,7 +305,7 @@ void setup_mtrrs(struct mem_range *mem)
/* Initialized the fixed_mtrrs to uncached */
printk_debug("Setting fixed MTRRs(%d-%d) type: UC\n",
0, NUM_FIXED_RANGES);
- set_fixed_mtrrs(0, NUM_FIXED_RANGES, MTRR_TYPE_UNCACHABLE);
+ set_fixed_mtrrs(0, NUM_FIXED_RANGES, MTRR_TYPE_UNCACHEABLE);
/* Now see which of the fixed mtrrs cover ram.
*/
diff --git a/src/cpu/p6/pgtbl.c b/src/cpu/p6/pgtbl.c
new file mode 100644
index 0000000000..e996dd0e69
--- /dev/null
+++ b/src/cpu/p6/pgtbl.c
@@ -0,0 +1,91 @@
+#include <console/console.h>
+#include <smp/start_stop.h>
+#include <cpu/p6/pgtbl.h>
+
+static void paging_off(void)
+{
+ __asm__ __volatile__ (
+ /* Disable paging */
+ "movl %%cr0, %%eax\n\t"
+ "andl $0x7FFFFFFF, %%eax\n\t"
+ "movl %%eax, %%cr0\n\t"
+ /* Disable pae */
+ "movl %%cr4, %%eax\n\t"
+ "andl $0xFFFFFFDF, %%eax\n\t"
+ :
+ :
+ : "eax"
+ );
+}
+
+static void paging_on(void *pdp)
+{
+ __asm__ __volatile__(
+ /* Load the page table address */
+ "movl %0, %%cr3\n\t"
+ /* Enable pae */
+ "movl %%cr4, %%eax\n\t"
+ "orl $0x00000020, %%eax\n\t"
+ "movl %%eax, %%cr4\n\t"
+ /* Enable paging */
+ "movl %%cr0, %%eax\n\t"
+ "orl $0x80000000, %%eax\n\t"
+ "movl %%eax, %%cr0\n\t"
+ :
+ : "r" (pdp)
+ : "eax"
+ );
+}
+
+void *map_2M_page(int cpu_index, unsigned long page)
+{
+ struct pde {
+ uint32_t addr_lo;
+ uint32_t addr_hi;
+ } __attribute__ ((packed));
+ struct pg_table {
+ struct pde pd[2048];
+ struct pde pdp[512];
+ } __attribute__ ((packed));
+ static struct pg_table pgtbl[CONFIG_MAX_CPUS] __attribute__ ((aligned(4096)));
+ static unsigned long mapped_window[CONFIG_MAX_CPUS];
+ unsigned long window;
+ void *result;
+ int i;
+ if ((cpu_index < 0) || (cpu_index >= CONFIG_MAX_CPUS)) {
+ return MAPPING_ERROR;
+ }
+ window = page >> 10;
+ if (window != mapped_window[cpu_index]) {
+ paging_off();
+ if (window > 1) {
+ struct pde *pd, *pdp;
+ /* Point the page directory pointers at the page directories */
+ memset(&pgtbl[cpu_index].pdp, 0, sizeof(pgtbl[cpu_index].pdp));
+ pd = pgtbl[cpu_index].pd;
+ pdp = pgtbl[cpu_index].pdp;
+ pdp[0].addr_lo = ((uint32_t)&pd[512*0])|1;
+ pdp[1].addr_lo = ((uint32_t)&pd[512*1])|1;
+ pdp[2].addr_lo = ((uint32_t)&pd[512*2])|1;
+ pdp[3].addr_lo = ((uint32_t)&pd[512*3])|1;
+ /* The first half of the page table is identity mapped */
+ for(i = 0; i < 1024; i++) {
+ pd[i].addr_lo = ((i & 0x3ff) << 21)| 0xE3;
+ pd[i].addr_hi = 0;
+ }
+ /* The second half of the page table holds the mapped page */
+ for(i = 1024; i < 2048; i++) {
+ pd[i].addr_lo = ((window & 1) << 31) | ((i & 0x3ff) << 21) | 0xE3;
+ pd[i].addr_hi = (window >> 1);
+ }
+ paging_on(pdp);
+ }
+ mapped_window[cpu_index] = window;
+ }
+ if (window == 0) {
+ result = (void *)(page << 21);
+ } else {
+ result = (void *)(0x80000000 | ((page & 0x3ff) << 21));
+ }
+ return result;
+}
diff --git a/src/devices/Config.lb b/src/devices/Config.lb
index 6da04ee2e4..50d05579e5 100644
--- a/src/devices/Config.lb
+++ b/src/devices/Config.lb
@@ -2,5 +2,6 @@ object device.o
object root_device.o
object device_util.o
object pci_device.o
+object pnp_device.o
object hypertransport.o
object chip.o
diff --git a/src/devices/chip.c b/src/devices/chip.c
index c9e1ac5643..d8a59e3062 100644
--- a/src/devices/chip.c
+++ b/src/devices/chip.c
@@ -80,6 +80,7 @@ void chip_enumerate(struct chip *chip)
link += 1;
}
if (dev) {
+ struct chip_resource *res, *res_limit;
printk_spew("path (%p) %s %s", dev, dev_path(dev), identical_paths?"identical":"");
printk_spew(" parent: (%p) %s\n",dev->bus->dev, dev_path(dev->bus->dev));
dev->chip = chip;
@@ -90,6 +91,16 @@ void chip_enumerate(struct chip *chip)
child->bus = &dev->link[link];
}
}
+ res = &chip->path[i].resource[0];
+ res_limit = &chip->path[i].resource[MAX_RESOURCES];
+ for(; res < res_limit; res++) {
+ if (res->flags) {
+ struct resource *resource;
+ resource = get_resource(dev, res->index);
+ resource->flags = res->flags | IORESOURCE_FIXED | IORESOURCE_ASSIGNED;
+ resource->base = res->base;
+ }
+ }
}
if (dev && !chip->dev) {
chip->dev = dev;
diff --git a/src/devices/device.c b/src/devices/device.c
index 4f1cbb2c5d..b54e770294 100644
--- a/src/devices/device.c
+++ b/src/devices/device.c
@@ -23,9 +23,9 @@
#include <string.h>
/* Linked list of ALL devices */
-struct device *all_devices = 0;
+struct device *all_devices = &dev_root;
/* pointer to the last device */
-static struct device **last_dev_p = &all_devices;
+static struct device **last_dev_p = &dev_root.next;
#define DEVICE_MEM_HIGH 0xFEC00000UL /* Reserve 20M for the system */
#define DEVICE_IO_START 0x1000
@@ -323,7 +323,8 @@ void compute_allocate_resource(
/* base must be aligned to size */
base = round(base, 1UL << align);
resource->base = base;
- resource->flags |= IORESOURCE_SET;
+ resource->flags |= IORESOURCE_ASSIGNED;
+ resource->flags &= ~IORESOURCE_STORED;
base += size;
printk_spew(
@@ -459,19 +460,24 @@ void dev_configure(void)
* safe.
*/
root->resource[0].base = DEVICE_IO_START;
- root->resource[0].flags |= IORESOURCE_SET;
+ root->resource[0].flags |= IORESOURCE_ASSIGNED;
+ root->resource[0].flags &= ~IORESOURCE_STORED;
/* Now reallocate the pci resources memory with the
* highest addresses I can manage.
*/
root->resource[1].base =
round_down(DEVICE_MEM_HIGH - root->resource[1].size,
1UL << root->resource[1].align);
- root->resource[1].flags |= IORESOURCE_SET;
+ root->resource[1].flags |= IORESOURCE_ASSIGNED;
+ root->resource[1].flags &= ~IORESOURCE_STORED;
+
+ /* Allocate the VGA I/O resource..
+ */
+ allocate_vga_resource();
+
// now just set things into registers ... we hope ...
root->ops->set_resources(root);
- allocate_vga_resource();
-
printk_info("done.\n");
}
diff --git a/src/devices/device_util.c b/src/devices/device_util.c
index c806726853..013501474c 100644
--- a/src/devices/device_util.c
+++ b/src/devices/device_util.c
@@ -34,7 +34,8 @@ struct device *dev_find_slot(unsigned int bus, unsigned int devfn)
result = 0;
for (dev = all_devices; dev; dev = dev->next) {
- if ((dev->bus->secondary == bus) &&
+ if ((dev->path.type == DEVICE_PATH_PCI) &&
+ (dev->bus->secondary == bus) &&
(dev->path.u.pci.devfn == devfn)) {
result = dev;
break;
@@ -57,8 +58,9 @@ struct device *dev_find_device(unsigned int vendor, unsigned int device, struct
from = all_devices;
else
from = from->next;
- while (from && (from->vendor != vendor || from->device != device))
+ while (from && (from->vendor != vendor || from->device != device)) {
from = from->next;
+ }
return from;
}
@@ -142,3 +144,70 @@ int path_eq(struct device_path *path1, struct device_path *path2)
}
return equal;
}
+
+/**
+ * See if we have unused but allocated resource structures.
+ * If so remove the allocation.
+ * @param dev The device to find the resource on
+ */
+void compact_resources(device_t dev)
+{
+ struct resource *resource;
+ int i;
+ /* Move all of the free resources to the end */
+ for(i = 0; i < dev->resources;) {
+ resource = &dev->resource[i];
+ if (!resource->flags) {
+ memmove(resource, resource + 1, dev->resources - i);
+ dev->resources -= 1;
+ memset(&dev->resource[dev->resources], 0, sizeof(*resource));
+ } else {
+ i++;
+ }
+ }
+}
+
+/**
+ * See if a resource structure already exists for a given index and if
+ * not allocate one.
+ * @param dev The device to find the resource on
+ * @param index The index of the resource on the device.
+ */
+struct resource *get_resource(device_t dev, unsigned index)
+{
+ struct resource *resource;
+ int i;
+
+ /* First move all of the free resources to the end */
+ compact_resources(dev);
+
+ /* See if there is a resource with the appropriate index */
+ resource = 0;
+ for(i = 0; i < dev->resources; i++) {
+ if (dev->resource[i].index == index) {
+ resource = &dev->resource[i];
+ break;
+ }
+ }
+ if (!resource) {
+ if (dev->resources == MAX_RESOURCES) {
+ die("MAX_RESOURCES exceeded.");
+ }
+ resource = &dev->resource[dev->resources];
+ memset(resource, 0, sizeof(*resource));
+ dev->resources++;
+ }
+ /* Initialize the resource values */
+ if (!(resource->flags & IORESOURCE_FIXED)) {
+ resource->flags = 0;
+ resource->base = 0;
+ }
+ resource->size = 0;
+ resource->limit = 0;
+ resource->index = index;
+ resource->align = 0;
+ resource->gran = 0;
+
+ return resource;
+}
+
diff --git a/src/devices/hypertransport.c b/src/devices/hypertransport.c
index b65f518d3a..e50ebf6f20 100644
--- a/src/devices/hypertransport.c
+++ b/src/devices/hypertransport.c
@@ -3,6 +3,7 @@
#include <device/device.h>
#include <device/path.h>
#include <device/pci.h>
+#include <device/pci_ids.h>
#include <device/hypertransport.h>
#include <device/chip.h>
#include <part/hard_reset.h>
@@ -25,6 +26,30 @@ static device_t ht_scan_get_devs(device_t *old_devices)
return first;
}
+static unsigned ht_read_freq_cap(device_t dev, unsigned pos)
+{
+ /* Handle bugs in valid hypertransport frequency reporting */
+ unsigned freq_cap;
+
+ freq_cap = pci_read_config16(dev, pos);
+ freq_cap &= ~(1 << HT_FREQ_VENDOR); /* Ignore Vendor HT frequencies */
+
+ /* AMD 8131 Errata 48 */
+ if ((dev->vendor == PCI_VENDOR_ID_AMD) &&
+ (dev->device == PCI_DEVICE_ID_AMD_8131_PCIX)) {
+ freq_cap &= ~(1 << HT_FREQ_800Mhz);
+ }
+ /* AMD 8151 Errata 23 */
+ if ((dev->vendor == PCI_VENDOR_ID_AMD) &&
+ (dev->device == PCI_DEVICE_ID_AMD_8151_SYSCTRL)) {
+ freq_cap &= ~(1 << HT_FREQ_800Mhz);
+ }
+ /* AMD K8 Unsupported 1Ghz? */
+ if ((dev->vendor == PCI_VENDOR_ID_AMD) && (dev->device == 0x1100)) {
+ freq_cap &= ~(1 << HT_FREQ_1000Mhz);
+ }
+ return freq_cap;
+}
struct prev_link {
struct device *dev;
@@ -48,18 +73,13 @@ static int ht_setup_link(struct prev_link *prev, device_t dev, unsigned pos)
reset_needed = 0;
/* Read the capabilities */
- present_freq_cap = pci_read_config16(dev, pos + PCI_HT_CAP_SLAVE_FREQ_CAP0);
- upstream_freq_cap = pci_read_config16(prev->dev, prev->pos + prev->freq_cap_off);
+ present_freq_cap = ht_read_freq_cap(dev, pos + PCI_HT_CAP_SLAVE_FREQ_CAP0);
+ upstream_freq_cap = ht_read_freq_cap(prev->dev, prev->pos + prev->freq_cap_off);
present_width_cap = pci_read_config8(dev, pos + PCI_HT_CAP_SLAVE_WIDTH0);
upstream_width_cap = pci_read_config8(prev->dev, prev->pos + prev->config_off);
/* Calculate the highest useable frequency */
-#if 0
freq = log2(present_freq_cap & upstream_freq_cap);
-#else
- /* Errata for 8131 - freq 5 has hardware problems don't support it */
- freq = log2(present_freq_cap & upstream_freq_cap & 0x1f);
-#endif
/* Calculate the highest width */
ln_upstream_width_in = link_width_to_pow2[upstream_width_cap & 7];
@@ -144,9 +164,7 @@ static unsigned ht_lookup_slave_capability(struct device *dev)
break;
}
}
- if(pos) {
- pos = pci_read_config8(dev, pos + PCI_CAP_LIST_NEXT);
- }
+ pos = pci_read_config8(dev, pos + PCI_CAP_LIST_NEXT);
}
return pos;
}
@@ -244,9 +262,12 @@ unsigned int hypertransport_scan_chain(struct bus *bus, unsigned int max)
else {
/* Add this device to the pci bus chain */
*chain_last = dev;
- /* Run the magice enable/disable sequence for the device */
+ /* Run the magice enable sequence for the device */
if (dev->chip && dev->chip->control && dev->chip->control->enable_dev) {
+ int enable = dev->enable;
+ dev->enable = 1;
dev->chip->control->enable_dev(dev);
+ dev->enable = enable;
}
/* Now read the vendor and device id */
id = pci_read_config32(dev, PCI_VENDOR_ID);
@@ -320,9 +341,11 @@ unsigned int hypertransport_scan_chain(struct bus *bus, unsigned int max)
#if HAVE_HARD_RESET == 1
if(reset_needed) {
printk_info("HyperT reset needed\n");
-// By LYH hard_reset();
- } else
- printk_debug("HyperT reset not needed\n");
+ hard_reset();
+ }
+ else {
+ printk_debug("HyperT reset not needed\n");
+ }
#endif
if (next_unitid > 0x1f) {
next_unitid = 0x1f;
diff --git a/src/devices/pci_device.c b/src/devices/pci_device.c
index 734b982a6d..c3f1f6ac8c 100644
--- a/src/devices/pci_device.c
+++ b/src/devices/pci_device.c
@@ -27,19 +27,14 @@
* @param resource Pointer to the resource structure
* @param index Address of the pci configuration register
*/
-static void pci_get_resource(struct device *dev, struct resource *resource, unsigned long index)
+static struct resource *pci_get_resource(struct device *dev, unsigned long index)
{
+ struct resource *resource;
uint32_t addr, size, base;
unsigned long type;
/* Initialize the resources to nothing */
- resource->base = 0;
- resource->size = 0;
- resource->align = 0;
- resource->gran = 0;
- resource->limit = 0;
- resource->flags = 0;
- resource->index = index;
+ resource = get_resource(dev, index);
addr = pci_read_config32(dev, index);
@@ -87,7 +82,7 @@ static void pci_get_resource(struct device *dev, struct resource *resource, unsi
resource->size = (~((size | 0xffff0000) & PCI_BASE_ADDRESS_IO_MASK)) +1;
resource->align = log2(resource->size);
resource->gran = resource->align;
- resource->flags = IORESOURCE_IO;
+ resource->flags |= IORESOURCE_IO;
resource->limit = 0xffff;
}
else {
@@ -96,7 +91,7 @@ static void pci_get_resource(struct device *dev, struct resource *resource, unsi
resource->size = (~(size &PCI_BASE_ADDRESS_MEM_MASK)) +1;
resource->align = log2(resource->size);
resource->gran = resource->align;
- resource->flags = IORESOURCE_MEM;
+ resource->flags |= IORESOURCE_MEM;
if (type & PCI_BASE_ADDRESS_MEM_PREFETCH) {
resource->flags |= IORESOURCE_PREFETCH;
}
@@ -145,7 +140,7 @@ static void pci_get_resource(struct device *dev, struct resource *resource, unsi
}
}
/* dev->size holds the flags... */
- return;
+ return resource;
}
/** Read the base address registers for a given device.
@@ -154,75 +149,63 @@ static void pci_get_resource(struct device *dev, struct resource *resource, unsi
*/
static void pci_read_bases(struct device *dev, unsigned int howmany)
{
- unsigned int reg;
unsigned long index;
- reg = dev->resources;
- for(index = PCI_BASE_ADDRESS_0;
- (reg < MAX_RESOURCES) && (index < PCI_BASE_ADDRESS_0 + (howmany << 2)); ) {
+ for(index = PCI_BASE_ADDRESS_0; (index < PCI_BASE_ADDRESS_0 + (howmany << 2)); ) {
struct resource *resource;
- resource = &dev->resource[reg];
- pci_get_resource(dev, resource, index);
- reg += (resource->flags & (IORESOURCE_IO | IORESOURCE_MEM))? 1:0;
+ resource = pci_get_resource(dev, index);
index += (resource->flags & IORESOURCE_PCI64)?8:4;
}
- dev->resources = reg;
+ compact_resources(dev);
}
static void pci_bridge_read_bases(struct device *dev)
{
- unsigned int reg = dev->resources;
+ struct resource *resource;
/* FIXME handle bridges without some of the optional resources */
/* Initialize the io space constraints on the current bus */
- dev->resource[reg].base = 0;
- dev->resource[reg].size = 0;
- dev->resource[reg].align = log2(PCI_IO_BRIDGE_ALIGN);
- dev->resource[reg].gran = log2(PCI_IO_BRIDGE_ALIGN);
- dev->resource[reg].limit = 0xffffUL;
- dev->resource[reg].flags = IORESOURCE_IO | IORESOURCE_PCI_BRIDGE;
- dev->resource[reg].index = PCI_IO_BASE;
- compute_allocate_resource(&dev->link[0], &dev->resource[reg],
+ resource = get_resource(dev, PCI_IO_BASE);
+ resource->size = 0;
+ resource->align = log2(PCI_IO_BRIDGE_ALIGN);
+ resource->gran = log2(PCI_IO_BRIDGE_ALIGN);
+ resource->limit = 0xffffUL;
+ resource->flags |= IORESOURCE_IO | IORESOURCE_PCI_BRIDGE;
+ compute_allocate_resource(&dev->link[0], resource,
IORESOURCE_IO, IORESOURCE_IO);
- reg++;
/* Initiliaze the prefetchable memory constraints on the current bus */
- dev->resource[reg].base = 0;
- dev->resource[reg].size = 0;
- dev->resource[reg].align = log2(PCI_MEM_BRIDGE_ALIGN);
- dev->resource[reg].gran = log2(PCI_MEM_BRIDGE_ALIGN);
- dev->resource[reg].limit = 0xffffffffUL;
- dev->resource[reg].flags = IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_PCI_BRIDGE;
- dev->resource[reg].index = PCI_PREF_MEMORY_BASE;
- compute_allocate_resource(&dev->link[0], &dev->resource[reg],
+ resource = get_resource(dev, PCI_PREF_MEMORY_BASE);
+ resource->size = 0;
+ resource->align = log2(PCI_MEM_BRIDGE_ALIGN);
+ resource->gran = log2(PCI_MEM_BRIDGE_ALIGN);
+ resource->limit = 0xffffffffUL;
+ resource->flags = IORESOURCE_MEM | IORESOURCE_PREFETCH | IORESOURCE_PCI_BRIDGE;
+ resource->index = PCI_PREF_MEMORY_BASE;
+ compute_allocate_resource(&dev->link[0], resource,
IORESOURCE_MEM | IORESOURCE_PREFETCH,
IORESOURCE_MEM | IORESOURCE_PREFETCH);
- reg++;
/* Initialize the memory resources on the current bus */
- dev->resource[reg].base = 0;
- dev->resource[reg].size = 0;
- dev->resource[reg].align = log2(PCI_MEM_BRIDGE_ALIGN);
- dev->resource[reg].gran = log2(PCI_MEM_BRIDGE_ALIGN);
- dev->resource[reg].limit = 0xffffffffUL;
- dev->resource[reg].flags = IORESOURCE_MEM | IORESOURCE_PCI_BRIDGE;
- dev->resource[reg].index = PCI_MEMORY_BASE;
- compute_allocate_resource(&dev->link[0], &dev->resource[reg],
- IORESOURCE_MEM | IORESOURCE_PREFETCH,
+ resource = get_resource(dev, PCI_MEMORY_BASE);
+ resource->size = 0;
+ resource->align = log2(PCI_MEM_BRIDGE_ALIGN);
+ resource->gran = log2(PCI_MEM_BRIDGE_ALIGN);
+ resource->limit = 0xffffffffUL;
+ resource->flags = IORESOURCE_MEM | IORESOURCE_PCI_BRIDGE;
+ compute_allocate_resource(&dev->link[0], resource,
+ IORESOURCE_MEM | IORESOURCE_PREFETCH,
IORESOURCE_MEM);
- reg++;
- dev->resources = reg;
+ compact_resources(dev);
}
void pci_dev_read_resources(struct device *dev)
{
uint32_t addr;
- dev->resources = 0;
- memset(&dev->resource[0], 0, sizeof(dev->resource));
pci_read_bases(dev, 6);
addr = pci_read_config32(dev, PCI_ROM_ADDRESS);
dev->rom_address = (addr == 0xffffffff)? 0 : addr;
@@ -231,8 +214,6 @@ void pci_dev_read_resources(struct device *dev)
void pci_bus_read_resources(struct device *dev)
{
uint32_t addr;
- dev->resources = 0;
- memset(&dev->resource, 0, sizeof(dev->resource));
pci_bridge_read_bases(dev);
pci_read_bases(dev, 2);
@@ -246,10 +227,10 @@ static void pci_set_resource(struct device *dev, struct resource *resource)
{
unsigned long base, limit;
unsigned char buf[10];
- unsigned long align;
+ unsigned long gran;
/* Make certain the resource has actually been set */
- if (!(resource->flags & IORESOURCE_SET)) {
+ if (!(resource->flags & IORESOURCE_ASSIGNED)) {
#if 1
printk_err("ERROR: %s %02x not allocated\n",
dev_path(dev), resource->index);
@@ -257,6 +238,11 @@ static void pci_set_resource(struct device *dev, struct resource *resource)
return;
}
+ /* If I have already stored this resource don't worry about it */
+ if (resource->flags & IORESOURCE_STORED) {
+ return;
+ }
+
/* Only handle PCI memory and IO resources for now */
if (!(resource->flags & (IORESOURCE_MEM |IORESOURCE_IO)))
return;
@@ -272,12 +258,20 @@ static void pci_set_resource(struct device *dev, struct resource *resource)
}
/* Get the base address */
base = resource->base;
- /* Get the resource alignment */
- align = 1UL << resource->align;
+ /* Get the resource granularity */
+ gran = 1UL << resource->gran;
+
+ /* For a non bridge resource granularity and alignment are the same.
+ * For a bridge resource align is the largest needed alignment below
+ * the bridge. While the granularity is simply how many low bits of the
+ * address cannot be set.
+ */
/* Get the limit (rounded up) */
- limit = base + ((resource->size + align - 1UL) & ~(align - 1UL)) -1UL;
+ limit = base + ((resource->size + gran - 1UL) & ~(gran - 1UL)) -1UL;
+ /* Now store the resource */
+ resource->flags |= IORESOURCE_STORED;
if (!(resource->flags & IORESOURCE_PCI_BRIDGE)) {
/*
* some chipsets allow us to set/clear the IO bit.
@@ -326,6 +320,8 @@ static void pci_set_resource(struct device *dev, struct resource *resource)
pci_write_config32(dev, PCI_PREF_LIMIT_UPPER32, 0);
}
else {
+ /* Don't let me think I stored the resource */
+ resource->flags &= ~IORESOURCE_STORED;
printk_err("ERROR: invalid resource->index %x\n",
resource->index);
}
@@ -386,6 +382,7 @@ void pci_dev_enable_resources(struct device *dev)
uint16_t command;
command = pci_read_config16(dev, PCI_COMMAND);
command |= dev->command;
+ command |= (PCI_COMMAND_PARITY + PCI_COMMAND_SERR); /* error check */
printk_debug("%s cmd <- %02x\n", dev_path(dev), command);
pci_write_config16(dev, PCI_COMMAND, command);
@@ -397,6 +394,7 @@ void pci_bus_enable_resources(struct device *dev)
uint16_t ctrl;
ctrl = pci_read_config16(dev, PCI_BRIDGE_CONTROL);
ctrl |= dev->link[0].bridge_ctrl;
+ ctrl |= (PCI_BRIDGE_CTL_PARITY + PCI_BRIDGE_CTL_SERR); /* error check */
printk_debug("%s bridge ctrl <- %04x\n", dev_path(dev), ctrl);
pci_write_config16(dev, PCI_BRIDGE_CONTROL, ctrl);
@@ -560,9 +558,12 @@ unsigned int pci_scan_bus(struct bus *bus,
dev = alloc_dev(bus, &dummy.path);
}
else {
- /* Run the magic enable/disable sequence for the device */
+ /* Run the magic enable sequence for the device */
if (dev->chip && dev->chip->control && dev->chip->control->enable_dev) {
+ int enable = dev->enable;
+ dev->enable = 1;
dev->chip->control->enable_dev(dev);
+ dev->enable = enable;
}
/* Now read the vendor and device id */
id = pci_read_config32(dev, PCI_VENDOR_ID);
@@ -584,7 +585,7 @@ unsigned int pci_scan_bus(struct bus *bus,
*/
set_pci_ops(dev);
/* Error if we don't have some pci operations for it */
- if (dev->enable && !dev->ops) {
+ if (!dev->ops) {
printk_err("%s No device operations\n",
dev_path(dev));
continue;
@@ -594,6 +595,9 @@ unsigned int pci_scan_bus(struct bus *bus,
if (dev->ops && dev->ops->enable) {
dev->ops->enable(dev);
}
+ else if (dev->chip && dev->chip->control && dev->chip->control->enable_dev) {
+ dev->chip->control->enable_dev(dev);
+ }
printk_debug("%s [%04x/%04x] %s\n",
dev_path(dev),
diff --git a/src/devices/pnp_device.c b/src/devices/pnp_device.c
new file mode 100644
index 0000000000..0bccd7d151
--- /dev/null
+++ b/src/devices/pnp_device.c
@@ -0,0 +1,217 @@
+/* Copyright 2004 Linux Networx */
+/* This code is distrubted wihtout warrant under the GPL v2 (see COPYING) */
+
+#include <console/console.h>
+#include <stdlib.h>
+#include <stdint.h>
+#include <bitops.h>
+#include <string.h>
+#include <arch/io.h>
+#include <device/device.h>
+#include <device/pnp.h>
+
+
+/* PNP fundamental operations */
+
+void pnp_write_config(device_t dev, uint8_t reg, uint8_t value)
+{
+ outb(reg, dev->path.u.pnp.port);
+ outb(value, dev->path.u.pnp.port + 1);
+}
+
+uint8_t pnp_read_config(device_t dev, uint8_t reg)
+{
+ outb(reg, dev->path.u.pnp.port);
+ return inb(dev->path.u.pnp.port + 1);
+}
+
+void pnp_set_logical_device(device_t dev)
+{
+ pnp_write_config(dev, 0x07, dev->path.u.pnp.device);
+}
+
+void pnp_set_enable(device_t dev, int enable)
+{
+ pnp_write_config(dev, 0x30, enable?0x1:0x0);
+}
+
+int pnp_read_enable(device_t dev)
+{
+ return !!pnp_read_config(dev, 0x30);
+}
+
+void pnp_set_iobase(device_t dev, unsigned index, unsigned iobase)
+{
+ /* Index == 0x60 or 0x62 */
+ pnp_write_config(dev, index + 0, (iobase >> 8) & 0xff);
+ pnp_write_config(dev, index + 1, iobase & 0xff);
+}
+
+void pnp_set_irq(device_t dev, unsigned index, unsigned irq)
+{
+ /* Index == 0x70 or 0x72 */
+ pnp_write_config(dev, index, irq);
+}
+
+
+void pnp_set_drq(device_t dev, unsigned drq, unsigned index)
+{
+ /* Index == 0x74 */
+ pnp_write_config(dev, index, drq & 0xff);
+}
+
+/* PNP device operations */
+
+void pnp_read_resources(device_t dev)
+{
+ return;
+}
+
+static void pnp_set_resource(device_t dev, struct resource *resource)
+{
+ if (!(resource->flags & IORESOURCE_ASSIGNED)) {
+#if 1
+ printk_err("ERROR: %s %02x not allocated\n",
+ dev_path(dev), resource->index);
+#endif
+ return;
+ }
+ /* Now store the resource */
+ resource->flags |= IORESOURCE_STORED;
+ if (resource->flags & IORESOURCE_IO) {
+ pnp_set_iobase(dev, resource->index, resource->base);
+ }
+ else if (resource->flags & IORESOURCE_DRQ) {
+ pnp_set_drq(dev, resource->index, resource->base);
+ }
+ else if (resource->flags & IORESOURCE_IRQ) {
+ pnp_set_irq(dev, resource->index, resource->base);
+ }
+ else {
+ /* Don't let me think I stored the resource */
+ resource->flags &= IORESOURCE_STORED;
+ printk_err("ERROR: %s %02x unknown resource type\n",
+ dev_path(dev), resource->index);
+ return;
+ }
+
+ printk_debug(
+ "%s %02x <- [0x%08lx - 0x%08lx] %s\n",
+ dev_path(dev),
+ resource->index,
+ resource->base, resource->base + resource->size - 1,
+ (resource->flags & IORESOURCE_IO)? "io":
+ (resource->flags & IORESOURCE_DRQ)? "drq":
+ (resource->flags & IORESOURCE_IRQ)? "irq":
+ (resource->flags & IORESOURCE_MEM)? "mem":
+ "???");
+}
+
+void pnp_set_resources(device_t dev)
+{
+ int i;
+
+ /* Select the device */
+ pnp_set_logical_device(dev);
+
+ /* Paranoia says I should disable the device here... */
+ for(i = 0; i < dev->resources; i++) {
+ pnp_set_resource(dev, &dev->resource[i]);
+ }
+}
+
+void pnp_enable_resources(device_t dev)
+{
+ pnp_set_logical_device(dev);
+ pnp_set_enable(dev, 1);
+
+}
+
+void pnp_enable(device_t dev)
+{
+ pnp_set_logical_device(dev);
+ if (!dev->enable) {
+ pnp_set_enable(dev, 0);
+ }
+}
+
+struct device_operations pnp_ops = {
+ .read_resources = pnp_read_resources,
+ .set_resources = pnp_set_resources,
+ .enable_resources = pnp_enable_resources,
+ .enable = pnp_enable,
+};
+
+/* PNP chip opertations */
+
+static void pnp_get_ioresource(device_t dev, unsigned index, struct io_info *info)
+{
+ struct resource *resource;
+ uint32_t size;
+ resource = get_resource(dev, index);
+
+ /* Initilize the resource */
+ resource->limit = 0xffff;
+ resource->flags |= IORESOURCE_IO;
+
+ /* Set the resource size and alignment */
+ size = (0xffff & info->mask);
+ resource->size = (~(size | 0xfffff800) + 1);
+ resource->align = log2(resource->size);
+ resource->gran = resource->align;
+}
+
+static void get_resources(device_t dev, struct pnp_info *info)
+{
+ struct resource *resource;
+
+ pnp_set_logical_device(dev);
+
+ if (info->flags & PNP_IO0) {
+ pnp_get_ioresource(dev, PNP_IDX_IO0, &info->io0);
+ }
+ if (info->flags & PNP_IO1) {
+ pnp_get_ioresource(dev, PNP_IDX_IO1, &info->io1);
+ }
+ if (info->flags & PNP_IRQ0) {
+ resource = get_resource(dev, PNP_IDX_IRQ0);
+ resource->size = 1;
+ resource->flags |= IORESOURCE_IRQ;
+ }
+ if (info->flags & PNP_IRQ1) {
+ resource = get_resource(dev, PNP_IDX_IRQ1);
+ resource->size = 1;
+ resource->flags |= IORESOURCE_IRQ;
+ }
+ if (info->flags & PNP_DRQ0) {
+ resource = get_resource(dev, PNP_IDX_DRQ0);
+ resource->size = 1;
+ resource->flags |= IORESOURCE_DRQ;
+ }
+ if (info->flags & PNP_DRQ1) {
+ resource = get_resource(dev, PNP_IDX_DRQ1);
+ resource->size = 1;
+ resource->flags |= IORESOURCE_DRQ;
+ }
+
+}
+
+void pnp_enumerate(struct chip *chip, unsigned functions,
+ struct device_operations *ops, struct pnp_info *info)
+{
+ struct device_path path;
+ device_t dev;
+ int i;
+
+ chip_enumerate(chip);
+ path.type = DEVICE_PATH_PNP;
+ path.u.pnp.port = chip->dev->path.u.pnp.port;
+
+ /* Setup the ops and resources on the newly allocated devices */
+ for(i = 0; i < functions; i++) {
+ path.u.pnp.device = info[i].function;
+ dev = alloc_find_dev(chip->bus, &path);
+ dev->ops = ops;
+ get_resources(dev, &info[i]);
+ }
+}
diff --git a/src/include/cpu/k8/mtrr.h b/src/include/cpu/k8/mtrr.h
index 5a965eebb8..890820b12f 100644
--- a/src/include/cpu/k8/mtrr.h
+++ b/src/include/cpu/k8/mtrr.h
@@ -35,4 +35,7 @@
#define DC_CFG_MSR 0xC0011022
#define BU_CFG_MSR 0xC0011023
+#define TOP_MEM_MASK 0x007fffff
+#define TOP_MEM_MASK_KB (TOP_MEM_MASK >> 10)
+
#endif /* CPU_K8_MTRR_H */
diff --git a/src/include/cpu/p6/mtrr.h b/src/include/cpu/p6/mtrr.h
index 16af10b81b..92bf62e5c2 100644
--- a/src/include/cpu/p6/mtrr.h
+++ b/src/include/cpu/p6/mtrr.h
@@ -2,7 +2,7 @@
#define __LINUXBIOS_CPU_P6_MTRR_H
/* These are the region types */
-#define MTRR_TYPE_UNCACHABLE 0
+#define MTRR_TYPE_UNCACHEABLE 0
#define MTRR_TYPE_WRCOMB 1
/*#define MTRR_TYPE_ 2*/
/*#define MTRR_TYPE_ 3*/
diff --git a/src/include/cpu/p6/pgtbl.h b/src/include/cpu/p6/pgtbl.h
new file mode 100644
index 0000000000..68e327cd7a
--- /dev/null
+++ b/src/include/cpu/p6/pgtbl.h
@@ -0,0 +1,7 @@
+#ifndef CPU_P6_PGTBL_H
+#define CPU_P6_PGTBL_H
+
+#define MAPPING_ERROR ((void *)0xffffffffUL)
+void *map_2M_page(int cpu_index, unsigned long page);
+
+#endif /* CPU_P6_PGTBL_H */
diff --git a/src/include/device/chip.h b/src/include/device/chip.h
index dc078a96b7..7dface868f 100644
--- a/src/include/device/chip.h
+++ b/src/include/device/chip.h
@@ -1,6 +1,8 @@
#ifndef DEVICE_CHIP_H
+#define DEVICE_CHIP_H
#include <device/path.h>
+#include <device/device.h>
/* chips are arbitrary chips (superio, southbridge, etc.)
* They have private structures that define chip resources and default
@@ -16,21 +18,6 @@
#define CONFIGURE(pass)
#endif
-struct com_ports {
- unsigned int enable,baud, base, irq;
-};
-
-/* lpt port description.
- * Note that for many chips you only really need to define the
- * enable.
- */
-struct lpt_ports {
- unsigned int enable, // 1 if this port is enabled
- mode, // pp mode
- base, // IO base of the parallel port
- irq; // irq
-};
-
enum chip_pass {
CONF_PASS_PRE_CONSOLE,
CONF_PASS_PRE_PCI,
@@ -60,11 +47,17 @@ struct chip_control {
void (*enable_dev)(struct device *dev);
};
+struct chip_resource {
+ unsigned long flags;
+ unsigned long index;
+ unsigned long base;
+};
struct chip_device_path {
struct device_path path;
unsigned channel;
int enable;
+ struct chip_resource resource[MAX_RESOURCES];
};
struct device;
diff --git a/src/include/device/device.h b/src/include/device/device.h
index 1b2b0169dc..20d9c22298 100644
--- a/src/include/device/device.h
+++ b/src/include/device/device.h
@@ -28,7 +28,7 @@ struct bus {
unsigned char cap; /* PCi capability offset */
};
-#define MAX_RESOURCES 6
+#define MAX_RESOURCES 8
#define MAX_LINKS 3
/*
* There is one device structure for each slot-number/function-number
@@ -49,18 +49,6 @@ struct device {
unsigned int enable : 1; /* set if we should enable the device */
uint8_t command;
- /*
- * In theory, the irq level can be read from configuration
- * space and all would be fine. However, old PCI chips don't
- * support these registers and return 0 instead. For example,
- * the Vision864-P rev 0 chip can uses INTA, but returns 0 in
- * the interrupt line and pin registers. pci_init()
- * initializes this field with the value at PCI_INTERRUPT_LINE
- * and it is the job of pcibios_fixup() to change it if
- * necessary. The field must not be 0 unless the device
- * cannot generate interrupts at all.
- */
- unsigned int irq; /* irq generated by this device */
/* Base registers for this device, can be adjusted by
* pcibios_fixup() as necessary.
@@ -94,6 +82,8 @@ extern void assign_resources(struct bus *bus);
extern void enable_resources(struct device *dev);
extern void enumerate_static_device(void);
extern const char *dev_path(device_t dev);
+extern void compact_resources(device_t dev);
+extern struct resource *get_resource(device_t dev, unsigned index);
/* Helper functions */
device_t alloc_find_dev(struct bus *parent, struct device_path *path);
diff --git a/src/include/device/hypertransport.h b/src/include/device/hypertransport.h
index e342aeb506..410495cdcb 100644
--- a/src/include/device/hypertransport.h
+++ b/src/include/device/hypertransport.h
@@ -1,6 +1,8 @@
#ifndef DEVICE_HYPERTRANSPORT_H
#define DEVICE_HYPERTRANSPORT_H
+#include <device/hypertransport_def.h>
+
unsigned int hypertransport_scan_chain(struct bus *bus, unsigned int max);
#define HT_IO_HOST_ALIGN 4096
diff --git a/src/include/device/hypertransport_def.h b/src/include/device/hypertransport_def.h
new file mode 100644
index 0000000000..0b44109f9f
--- /dev/null
+++ b/src/include/device/hypertransport_def.h
@@ -0,0 +1,16 @@
+#ifndef DEVICE_HYPERTRANSPORT_DEF_H
+#define DEVICE_HYPERTRANSPORT_DEF_H
+
+#define HT_FREQ_200Mhz 0
+#define HT_FREQ_300Mhz 1
+#define HT_FREQ_400Mhz 2
+#define HT_FREQ_500Mhz 3
+#define HT_FREQ_600Mhz 4
+#define HT_FREQ_800Mhz 5
+#define HT_FREQ_1000Mhz 6
+#define HT_FREQ_1200Mhz 7
+#define HT_FREQ_1400Mhz 8
+#define HT_FREQ_1600Mhz 9
+#define HT_FREQ_VENDOR 15 /* AMD defines this to be 100Mhz */
+
+#endif /* DEVICE_HYPERTRANSPORT_DEF_H */
diff --git a/src/include/device/pci_def.h b/src/include/device/pci_def.h
index ad8f1e6b88..46229a12f4 100644
--- a/src/include/device/pci_def.h
+++ b/src/include/device/pci_def.h
@@ -179,7 +179,9 @@
#define PCI_CAP_ID_SLOTID 0x04 /* Slot Identification */
#define PCI_CAP_ID_MSI 0x05 /* Message Signalled Interrupts */
#define PCI_CAP_ID_CHSWP 0x06 /* CompactPCI HotSwap */
-#define PCI_CAP_ID_HT 0x08
+#define PCI_CAP_ID_PCIX 0x07 /* PCIX */
+#define PCI_CAP_ID_HT 0x08 /* Hypertransport */
+#define PCI_CAP_ID_PCIE 0x10 /* PCI Express */
#define PCI_CAP_LIST_NEXT 1 /* Next capability in the list */
#define PCI_CAP_FLAGS 2 /* Capability defined flags (16 bits) */
diff --git a/src/include/device/pnp.h b/src/include/device/pnp.h
index 0d39fc1663..508fac68ed 100644
--- a/src/include/device/pnp.h
+++ b/src/include/device/pnp.h
@@ -1,58 +1,49 @@
#ifndef DEVICE_PNP_H
#define DEVICE_PNP_H
-static inline void pnp_write_config(unsigned char port, unsigned char value, unsigned char reg)
-{
- outb(reg, port);
- outb(value, port +1);
-}
-
-static inline unsigned char pnp_read_config(unsigned char port, unsigned char reg)
-{
- outb(reg, port);
- return inb(port +1);
-}
-
-static inline void pnp_set_logical_device(unsigned char port, int device)
-{
- pnp_write_config(port, device, 0x07);
-}
-
-static inline void pnp_set_enable(unsigned char port, int enable)
-{
- pnp_write_config(port, enable?0x1:0x0, 0x30);
-}
-
-static inline int pnp_read_enable(unsigned char port)
-{
- return !!pnp_read_config(port, 0x30);
-}
-
-static inline void pnp_set_iobase0(unsigned char port, unsigned iobase)
-{
- pnp_write_config(port, (iobase >> 8) & 0xff, 0x60);
- pnp_write_config(port, iobase & 0xff, 0x61);
-}
-
-static inline void pnp_set_iobase1(unsigned char port, unsigned iobase)
-{
- pnp_write_config(port, (iobase >> 8) & 0xff, 0x62);
- pnp_write_config(port, iobase & 0xff, 0x63);
-}
-
-static inline void pnp_set_irq0(unsigned char port, unsigned irq)
-{
- pnp_write_config(port, irq, 0x70);
-}
-
-static inline void pnp_set_irq1(unsigned char port, unsigned irq)
-{
- pnp_write_config(port, irq, 0x72);
-}
-
-static inline void pnp_set_drq(unsigned char port, unsigned drq)
-{
- pnp_write_config(port, drq & 0xff, 0x74);
-}
+#include <stdint.h>
+#include <device/device.h>
+#include <device/pnp_def.h>
+#include <device/chip.h>
+
+/* Primitive pnp resource manipulation */
+void pnp_write_config(device_t dev, uint8_t reg, uint8_t value);
+uint8_t pnp_read_config(device_t dev, uint8_t reg);
+void pnp_set_logical_device(device_t dev);
+void pnp_set_enable(device_t dev, int enable);
+int pnp_read_enable(device_t dev);
+void pnp_set_iobase(device_t dev, unsigned index, unsigned iobase);
+void pnp_set_irq(device_t dev, unsigned index, unsigned irq);
+void pnp_set_drq(device_t dev, unsigned index, unsigned drq);
+
+/* PNP device operations */
+void pnp_read_resources(device_t dev);
+void pnp_set_resources(device_t dev);
+void pnp_enable_resources(device_t dev);
+void pnp_enable(device_t dev);
+
+struct device_operations pnp_ops;
+
+/* PNP helper operations */
+
+struct io_info {
+ unsigned mask, set;
+};
+
+struct pnp_info {
+ struct device_operations *ops;
+ unsigned function;
+ unsigned flags;
+#define PNP_IO0 0x01
+#define PNP_IO1 0x02
+#define PNP_IRQ0 0x04
+#define PNP_IRQ1 0x08
+#define PNP_DRQ0 0x10
+#define PNP_DRQ1 0x20
+ struct io_info io0, io1;
+};
+struct resource *pnp_get_resource(device_t dev, unsigned index);
+void pnp_enumerate(struct chip *chip, unsigned functions,
+ struct device_operations *ops, struct pnp_info *info);
#endif /* DEVICE_PNP_H */
diff --git a/src/include/device/pnp_def.h b/src/include/device/pnp_def.h
new file mode 100644
index 0000000000..b077837d02
--- /dev/null
+++ b/src/include/device/pnp_def.h
@@ -0,0 +1,12 @@
+#ifndef DEVICE_PNP_DEF_H
+#define DEVICE_PNP_DEF_H
+
+#define PNP_IDX_IO0 0x60
+#define PNP_IDX_IO1 0x62
+#define PNP_IDX_IRQ0 0x70
+#define PNP_IDX_IRQ1 0x72
+#define PNP_IDX_DRQ0 0x74
+#define PNP_IDX_DRQ1 0x75
+
+
+#endif /* DEVICE_PNP_DEF_H */
diff --git a/src/include/device/resource.h b/src/include/device/resource.h
index f90aba19f4..73a3f6e0d5 100644
--- a/src/include/device/resource.h
+++ b/src/include/device/resource.h
@@ -18,9 +18,9 @@
#define IORESOURCE_SUBTRACTIVE 0x00040000 /* This resource filters all of the unclaimed transactions
* to the bus below.
*/
-
-#define IORESOURCE_SET 0x80000000 /* An IO resource that has been assigned a value */
-#define IORESOURCE_FIXED 0x40000000 /* An IO resource the allocator must not change */
+#define IORESOURCE_STORED 0x20000000 /* The IO resource assignment has been stored in the device */
+#define IORESOURCE_ASSIGNED 0x40000000 /* An IO resource that has been assigned a value */
+#define IORESOURCE_FIXED 0x80000000 /* An IO resource the allocator must not change */
/* PCI specific resource bits */
#define IORESOURCE_PCI64 (1<<0) /* 64bit long pci resource */
diff --git a/src/include/pc80/keyboard.h b/src/include/pc80/keyboard.h
new file mode 100644
index 0000000000..775dbee6e4
--- /dev/null
+++ b/src/include/pc80/keyboard.h
@@ -0,0 +1,10 @@
+#ifndef PC80_KEYBOARD_H
+#define PC80_KEYBOARD_H
+
+struct pc_keyboard {
+ /* No initialization parameters for now */
+};
+
+void init_pc_keyboard(unsigned port0, unsigned port1, struct pc_keyboard *kbd);
+
+#endif /* PC80_KEYBOARD_H */
diff --git a/src/include/pc80/mc146818rtc.h b/src/include/pc80/mc146818rtc.h
index 1daf39aa25..e7e13c85b7 100644
--- a/src/include/pc80/mc146818rtc.h
+++ b/src/include/pc80/mc146818rtc.h
@@ -7,18 +7,6 @@
#define RTC_PORT(x) (RTC_BASE_PORT + (x))
-/* On PCs, the checksum is built only over bytes 16..45 */
-#define PC_CKS_RANGE_START 16
-#define PC_CKS_RANGE_END 45
-#define PC_CKS_LOC 46
-
-
-/* Linux bios checksum is built only over bytes 49..125 */
-#define LB_CKS_RANGE_START 49
-#define LB_CKS_RANGE_END 125
-#define LB_CKS_LOC 126
-
-
/* control registers - Moto names
*/
#define RTC_REG_A 10
@@ -88,22 +76,28 @@
# define RTC_VRT 0x80 /* valid RAM and time */
/**********************************************************************/
-
/* On PCs, the checksum is built only over bytes 16..45 */
#define PC_CKS_RANGE_START 16
#define PC_CKS_RANGE_END 45
#define PC_CKS_LOC 46
+/* Linux bios checksum is built only over bytes 49..125 */
+#ifndef LB_CKS_RANGE_START
#define LB_CKS_RANGE_START 49
+#endif
+#ifndef LB_CKS_RANGE_END
#define LB_CKS_RANGE_END 125
+#endif
+#ifndef LB_CKS_LOC
#define LB_CKS_LOC 126
+#endif
#if !defined(ASSEMBLY)
void rtc_init(int invalid);
#if USE_OPTION_TABLE == 1
int get_option(void *dest, char *name);
#else
-#define get_option(dest, name) (-2)
+static inline int get_option(void *dest, char *name) { return -2; }
#endif
#endif
diff --git a/src/include/string.h b/src/include/string.h
index cf9bbb14d2..111e23bc15 100644
--- a/src/include/string.h
+++ b/src/include/string.h
@@ -29,6 +29,7 @@ static inline size_t strlen(const char *src)
}
extern void *memcpy(void *dest, const void *src, size_t n);
+extern void *memmove(void *dest, const void *src, size_t n);
extern void *memset(void *s, int c, size_t n);
extern int memcmp(const void *s1, const void *s2, size_t n);
diff --git a/src/include/uart8250.h b/src/include/uart8250.h
index ae45615758..f610026614 100644
--- a/src/include/uart8250.h
+++ b/src/include/uart8250.h
@@ -1,7 +1,13 @@
#ifndef UART8250_H
#define UART8250_H
+struct uart8250 {
+ unsigned int baud;
+ /* Do I need an lcs parameter here? */
+};
+
void uart8250_tx_byte(unsigned base_port, unsigned char data);
void uart8250_init(unsigned base_port, unsigned divisor, unsigned lcs);
+void init_uart8250(unsigned base_port, struct uart8250 *uart);
#endif /* UART8250_H */
diff --git a/src/lib/Config.lb b/src/lib/Config.lb
index a0de47c570..bd6a2a9090 100644
--- a/src/lib/Config.lb
+++ b/src/lib/Config.lb
@@ -6,10 +6,11 @@ object uart8250.o
object memset.o
object memcpy.o
object memcmp.o
+object memmove.o
object malloc.o
object delay.o
if HAVE_FALLBACK_BOOT
- object fallback_boot.o
+ object fallback_boot.o
end
object compute_ip_checksum.o
object version.o
diff --git a/src/lib/memcpy.c b/src/lib/memcpy.c
index ad8e8bd3f0..16db67766d 100644
--- a/src/lib/memcpy.c
+++ b/src/lib/memcpy.c
@@ -1,11 +1,12 @@
#include <string.h>
-void *memcpy(void *__dest, __const void *__src, size_t __n)
+void *memcpy(void *vdest, const void *vsrc, size_t bytes)
{
+ const char *src = vsrc;
+ char *dest = vdest;
int i;
- char *d = (char *) __dest, *s = (char *) __src;
- for (i = 0; i < __n; i++)
- d[i] = s[i];
+ for (i = 0; i < bytes; i++)
+ dest[i] = src[i];
- return __dest;
+ return vdest;
}
diff --git a/src/lib/memmove.c b/src/lib/memmove.c
new file mode 100644
index 0000000000..0a4908325e
--- /dev/null
+++ b/src/lib/memmove.c
@@ -0,0 +1,20 @@
+#include <string.h>
+void *memmove(void *vdest, const void *vsrc, size_t count)
+{
+ const char *src = vsrc;
+ char *dest = vdest;
+ int i;
+
+ if (dest <= src) {
+ while (count--) {
+ *dest++ = *src++;
+ }
+ } else {
+ src += count - 1;
+ dest += count - 1;
+ while(count--) {
+ *dest-- = *src--;
+ }
+ }
+ return vdest;
+}
diff --git a/src/lib/uart8250.c b/src/lib/uart8250.c
index ceb4e4aa86..67b0a95cfb 100644
--- a/src/lib/uart8250.c
+++ b/src/lib/uart8250.c
@@ -58,3 +58,19 @@ void uart8250_init(unsigned base_port, unsigned divisor, unsigned lcs)
outb((divisor >> 8) & 0xFF, base_port + UART_DLM);
outb(lcs, base_port + UART_LCR);
}
+
+/* Initialize a generic uart */
+void init_uart8250(unsigned base_port, struct uart8250 *uart)
+{
+ int divisor;
+ int lcs;
+ divisor = 115200/(uart->baud ? uart->baud: 1);
+ lcs = 3;
+ if (base_port == TTYS0_BASE) {
+ /* Don't reinitialize the console serial port,
+ * This is espeically nasty in SMP.
+ */
+ return;
+ }
+ uart8250_init(base_port, divisor, lcs);
+}
diff --git a/src/mainboard/amd/quartet/Config.lb b/src/mainboard/amd/quartet/Config.lb
index 1a2d8cd09f..d38ab96407 100644
--- a/src/mainboard/amd/quartet/Config.lb
+++ b/src/mainboard/amd/quartet/Config.lb
@@ -251,19 +251,29 @@ northbridge amd/amdk8 "mc0"
pci 1:0.2 on
pci 1:1.0 on
superio NSC/pc87360 link 1
- pnp 2e.0
- pnp 2e.1
- pnp 2e.2
- pnp 2e.3
- pnp 2e.4
- pnp 2e.5
- pnp 2e.6
- pnp 2e.7
- pnp 2e.8
- pnp 2e.9
- pnp 2e.a
- register "com1" = "{1, 0, 0x3f8, 4}"
- register "lpt" = "{1}"
+ pnp 2e.0 off # Floppy
+ io 0x60 = 0x3f0
+ irq 0x70 = 6
+ drq 0x74 = 2
+ pnp 2e.1 off # Parallel Port
+ io 0x60 = 0x378
+ irq 0x70 = 7
+ pnp 2e.2 off # Com 2
+ io 0x60 = 0x2f8
+ irq 0x70 = 3
+ pnp 2e.3 on # Com 1
+ io 0x60 = 0x3f8
+ irq 0x70 = 4
+ pnp 2e.4 off # SWC
+ pnp 2e.5 off # Mouse
+ pnp 2e.6 on # Keyboard
+ io 0x60 = 0x60
+ io 0x62 = 0x64
+ irq 0x70 = 1
+ pnp 2e.7 off # GPIO
+ pnp 2e.8 off # ACB
+ pnp 2e.9 off # FSCM
+ pnp 2e.a off # WDT
end
end
end
diff --git a/src/mainboard/amd/solo/Config.lb b/src/mainboard/amd/solo/Config.lb
index 1372e46005..bb9044eb0a 100644
--- a/src/mainboard/amd/solo/Config.lb
+++ b/src/mainboard/amd/solo/Config.lb
@@ -23,6 +23,12 @@ uses XIP_ROM_BASE
uses STACK_SIZE
uses HEAP_SIZE
uses USE_OPTION_TABLE
+uses LB_CKS_RANGE_START
+uses LB_CKS_RANGE_END
+uses LB_CKS_LOC
+uses MAINBOARD_PART_NUMBER
+uses MAINBOARD_VENDOR
+
## ROM_SIZE is the size of boot ROM that this board will use.
default ROM_SIZE=262144
@@ -59,7 +65,14 @@ default HAVE_MP_TABLE=1
default HAVE_OPTION_TABLE=1
##
-## AMD Solo is a 1cpu board
+## Move the default LinuxBIOS cmos range off of AMD RTC registers
+##
+default LB_CKS_RANGE_START=49
+default LB_CKS_RANGE_END=122
+default LB_CKS_LOC=123
+
+##
+## AMD Solo is a 1cpu board
##
default CONFIG_SMP=1
default CONFIG_MAX_CPUS=1
@@ -152,7 +165,7 @@ object reset.o
## Romcc output
##
makerule ./failover.E
- depends "$(MAINBOARD)/failover.c"
+ depends "$(MAINBOARD)/failover.c"
action "$(CPP) -I$(TOP)/src $(ROMCCPPFLAGS) $(CPPFLAGS) $(MAINBOARD)/failover.c > ./failover.E"
end
@@ -161,13 +174,13 @@ makerule ./failover.inc
action "./romcc -O -o failover.inc --label-prefix=failover ./failover.E"
end
-makerule ./auto.E
- depends "$(MAINBOARD)/auto.c"
- action "$(CPP) -I$(TOP)/src $(ROMCCPPFLAGS) $(CPPFLAGS) $(MAINBOARD)/auto.c > ./auto.E"
+makerule ./auto.E
+ depends "$(MAINBOARD)/auto.c option_table.h "
+ action "$(CPP) -I$(TOP)/src -I. $(ROMCCPPFLAGS) $(CPPFLAGS) $(MAINBOARD)/auto.c > ./auto.E"
end
-makerule ./auto.inc
+makerule ./auto.inc
depends "./auto.E ./romcc"
- action "./romcc -mcpu=k8 -O ./auto.E > auto.inc"
+ action "./romcc -mcpu=k8 -O2 ./auto.E > auto.inc"
end
##
@@ -175,18 +188,19 @@ end
##
mainboardinit cpu/i386/entry16.inc
mainboardinit cpu/i386/entry32.inc
+#mainboardinit cpu/i386/bist32.inc
ldscript /cpu/i386/entry16.lds
ldscript /cpu/i386/entry32.lds
##
## Build our reset vector (This is where linuxBIOS is entered)
##
-if USE_FALLBACK_IMAGE
- mainboardinit cpu/i386/reset16.inc
- ldscript /cpu/i386/reset16.lds
+if USE_FALLBACK_IMAGE
+ mainboardinit cpu/i386/reset16.inc
+ ldscript /cpu/i386/reset16.lds
else
- mainboardinit cpu/i386/reset32.inc
- ldscript /cpu/i386/reset32.lds
+ mainboardinit cpu/i386/reset32.inc
+ ldscript /cpu/i386/reset32.lds
end
### Should this be in the northbridge code?
@@ -204,12 +218,12 @@ ldscript /arch/i386/lib/id.lds
mainboardinit cpu/k8/earlymtrr.inc
###
-### This is the early phase of linuxBIOS startup
+### This is the early phase of linuxBIOS startup
### Things are delicate and we test to see if we should
### failover to another image.
###
if USE_FALLBACK_IMAGE
- ldscript /arch/i386/lib/failover.lds
+ ldscript /arch/i386/lib/failover.lds
mainboardinit ./failover.inc
end
@@ -225,7 +239,7 @@ mainboardinit ./auto.inc
mainboardinit cpu/k8/disable_mmx_sse.inc
##
-## Include the secondary Configuration files
+## Include the secondary Configuration files
##
dir /pc80
config chip.h
@@ -254,19 +268,29 @@ northbridge amd/amdk8 "mc0"
pci 1:0.2 on
# pci 1:1.0 off
superio NSC/pc87360 link 1
- pnp 2e.0
- pnp 2e.1
- pnp 2e.2
- pnp 2e.3
- pnp 2e.4
- pnp 2e.5
- pnp 2e.6
- pnp 2e.7
- pnp 2e.8
- pnp 2e.9
- pnp 2e.a
- register "com1" = "{1, 0, 0x3f8, 4}"
- register "lpt" = "{1}"
+ pnp 2e.0 off # Floppy
+ io 0x60 = 0x3f0
+ irq 0x70 = 6
+ drq 0x74 = 2
+ pnp 2e.1 off # Parallel Port
+ io 0x60 = 0x378
+ irq 0x70 = 7
+ pnp 2e.2 off # Com 2
+ io 0x60 = 0x2f8
+ irq 0x70 = 3
+ pnp 2e.3 on # Com 1
+ io 0x60 = 0x3f8
+ irq 0x70 = 4
+ pnp 2e.4 off # SWC
+ pnp 2e.5 off # Mouse
+ pnp 2e.6 on # Keyboard
+ io 0x60 = 0x60
+ io 0x62 = 0x64
+ irq 0x70 = 1
+ pnp 2e.7 off # GPIO
+ pnp 2e.8 off # ACB
+ pnp 2e.9 off # FSCM
+ pnp 2e.a off # WDT
end
end
end
@@ -279,4 +303,5 @@ end
##
mainboardinit pc80/serial.inc
mainboardinit arch/i386/lib/console.inc
+#mainboardinit cpu/i386/bist32_fail.inc
diff --git a/src/mainboard/amd/solo/auto.c b/src/mainboard/amd/solo/auto.c
index 5963934fd5..3a80e4c1bd 100644
--- a/src/mainboard/amd/solo/auto.c
+++ b/src/mainboard/amd/solo/auto.c
@@ -1,14 +1,16 @@
#define ASSEMBLY 1
#include <stdint.h>
#include <device/pci_def.h>
-#include <cpu/p6/apic.h>
#include <arch/io.h>
#include <device/pnp.h>
#include <arch/romcc_io.h>
+#include <arch/smp/lapic.h>
+#include "option_table.h"
+#include "pc80/mc146818rtc_early.c"
#include "pc80/serial.c"
#include "arch/i386/lib/console.c"
#include "ram/ramtest.c"
-#include "northbridge/amd/amdk8/early_ht.c"
+#include "northbridge/amd/amdk8/incoherent_ht.c"
#include "southbridge/amd/amd8111/amd8111_early_smbus.c"
#include "northbridge/amd/amdk8/raminit.h"
#include "cpu/k8/apic_timer.c"
@@ -17,9 +19,26 @@
#include "northbridge/amd/amdk8/reset_test.c"
#include "debug.c"
#include "northbridge/amd/amdk8/cpu_rev.c"
+#include "superio/NSC/pc87360/pc87360_early_serial.c"
#define SIO_BASE 0x2e
+static void hard_reset(void)
+{
+ set_bios_reset();
+
+ /* enable cf9 */
+ pci_write_config8(PCI_DEV(0, 0x05, 3), 0x41, 0xf1);
+ /* reset */
+ outb(0x0e, 0x0cf9);
+}
+
+static void soft_reset(void)
+{
+ set_bios_reset();
+ pci_write_config8(PCI_DEV(0, 0x05, 0), 0x47, 1);
+}
+
static void memreset_setup(void)
{
if (is_cpu_pre_c0()) {
@@ -54,7 +73,7 @@ static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes)
static inline void activate_spd_rom(const struct mem_controller *ctrl)
{
- /* nothing here */
+ /* nothing to do */
}
static inline int spd_read_byte(unsigned device, unsigned address)
@@ -62,69 +81,11 @@ static inline int spd_read_byte(unsigned device, unsigned address)
return smbus_read_byte(device, address);
}
-/* no specific code here. this should go away completely */
-static void coherent_ht_mainboard(unsigned cpus)
-{
-}
#include "northbridge/amd/amdk8/raminit.c"
#include "northbridge/amd/amdk8/coherent_ht.c"
#include "sdram/generic_sdram.c"
-static void enable_lapic(void)
-{
-
- msr_t msr;
- msr = rdmsr(0x1b);
- msr.hi &= 0xffffff00;
- msr.lo &= 0x000007ff;
- msr.lo |= APIC_DEFAULT_BASE | (1 << 11);
- wrmsr(0x1b, msr);
-}
-
-static void stop_this_cpu(void)
-{
- unsigned apicid;
- apicid = apic_read(APIC_ID) >> 24;
-
- /* Send an APIC INIT to myself */
- apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
- apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT);
- /* Wait for the ipi send to finish */
- apic_wait_icr_idle();
-
- /* Deassert the APIC INIT */
- apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
- apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
- /* Wait for the ipi send to finish */
- apic_wait_icr_idle();
-
- /* If I haven't halted spin forever */
- for(;;) {
- hlt();
- }
-}
-
-#define PC87360_FDC 0x00
-#define PC87360_PP 0x01
-#define PC87360_SP2 0x02
-#define PC87360_SP1 0x03
-#define PC87360_SWC 0x04
-#define PC87360_KBCM 0x05
-#define PC87360_KBCK 0x06
-#define PC87360_GPIO 0x07
-#define PC87360_ACB 0x08
-#define PC87360_FSCM 0x09
-#define PC87360_WDT 0x0A
-
-/* FIXME: Do we really need this on Solo boards? */
-static void pc87360_enable_serial(void)
-{
- pnp_set_logical_device(SIO_BASE, PC87360_SP1);
- pnp_set_enable(SIO_BASE, 1);
- pnp_set_iobase0(SIO_BASE, 0x3f8);
-}
-
static void main(void)
{
static const struct mem_controller cpu[] = {
@@ -138,26 +99,29 @@ static void main(void)
.channel1 = { 0, 0, 0, 0 },
}
};
+ int needs_reset;
+ enable_lapic();
+ init_timer();
if (cpu_init_detected()) {
asm("jmp __cpu_reset");
}
enable_lapic();
init_timer();
-
-#if 0
- /* Enabling this will make romcc segfault - 2003/10/13 */
+ distinguish_cpu_resets();
if (!boot_cpu()) {
print_err("This LinuxBIOS image is built for UP only.\n");
+ stop_this_cpu();
}
-#endif
- pc87360_enable_serial();
+ pc87360_enable_serial(SIO_BASE, TTYS0_BASE);
uart_init();
console_init();
setup_default_resource_map();
- setup_coherent_ht_domain();
- enumerate_ht_chain(0);
- distinguish_cpu_resets(0);
-
+ needs_reset = setup_coherent_ht_domain();
+ needs_reset = ht_setup_chain(PCI_DEV(0, 0x18, 0), 0x80);
+ if (needs_reset) {
+ print_info("ht reset -");
+ soft_reset();
+ }
#if 0
print_pci_devices();
#endif
diff --git a/src/mainboard/amd/solo/cmos.layout b/src/mainboard/amd/solo/cmos.layout
index 5ba4c032c1..247715e6ac 100644
--- a/src/mainboard/amd/solo/cmos.layout
+++ b/src/mainboard/amd/solo/cmos.layout
@@ -29,6 +29,9 @@ entries
386 1 e 1 ECC_memory
388 4 r 0 reboot_bits
392 3 e 5 baud_rate
+395 1 e 1 hw_scrubber
+396 1 e 1 interleave_chip_selects
+397 2 e 8 max_mem_clock
400 1 e 1 power_on_after_fail
412 4 e 6 debug_level
416 4 e 7 boot_first
@@ -36,7 +39,14 @@ entries
424 4 e 7 boot_third
428 4 h 0 boot_index
432 8 h 0 boot_countdown
-1008 16 h 0 check_sum
+440 4 e 9 slow_cpu
+444 1 e 1 nmi
+728 256 h 0 user_data
+984 16 h 0 check_sum
+# Reserve the extended AMD configuration registers
+1000 24 r 0 reserved_memory
+
+
enumerations
@@ -66,9 +76,21 @@ enumerations
7 9 Fallback_HDD
7 10 Fallback_Floppy
#7 3 ROM
+8 0 200Mhz
+8 1 166Mhz
+8 2 133Mhz
+8 3 100Mhz
+9 0 off
+9 1 87.5%
+9 2 75.0%
+9 3 62.5%
+9 4 50.0%
+9 5 37.5%
+9 6 25.0%
+9 7 12.5%
checksums
-checksum 392 1007 1008
+checksum 392 983 984
diff --git a/src/mainboard/amd/solo/failover.c b/src/mainboard/amd/solo/failover.c
index bd9c17020e..bd5869fead 100644
--- a/src/mainboard/amd/solo/failover.c
+++ b/src/mainboard/amd/solo/failover.c
@@ -3,40 +3,78 @@
#include <device/pci_def.h>
#include <device/pci_ids.h>
#include <arch/io.h>
-#include "arch/romcc_io.h"
+#include <arch/romcc_io.h>
+#include <arch/smp/lapic.h>
#include "pc80/mc146818rtc_early.c"
#include "southbridge/amd/amd8111/amd8111_enable_rom.c"
#include "northbridge/amd/amdk8/early_ht.c"
#include "cpu/p6/boot_cpu.c"
#include "northbridge/amd/amdk8/reset_test.c"
+#define HAVE_REGPARM_SUPPORT 0
+#if HAVE_REGPARM_SUPPORT
+static unsigned long main(unsigned long bist)
+{
+#else
static void main(void)
{
- /* Nothing special needs to be done to find bus 0 */
- /* Allow the HT devices to be found */
- enumerate_ht_chain(0);
+ unsigned long bist = 0;
+#endif
+ /* Make cerain my local apic is useable */
+ enable_lapic();
- /* Setup the 8111 */
- amd8111_enable_rom();
-
- /* Is this a cpu reset? */
+ /* Is this a cpu only reset? */
if (cpu_init_detected()) {
if (last_boot_normal()) {
- asm("jmp __normal_image");
+ goto normal_image;
} else {
- asm("jmp __cpu_reset");
+ goto cpu_reset;
}
}
- /* Is this a deliberate reset by the bios */
- else if (bios_reset_detected() && last_boot_normal()) {
- asm("jmp __normal_image");
- }
/* Is this a secondary cpu? */
- else if (!boot_cpu() && last_boot_normal()) {
- asm("jmp __normal_image");
+ if (!boot_cpu()) {
+ if (last_boot_normal()) {
+ goto normal_image;
+ } else {
+ goto fallback_image;
+ }
+ }
+
+
+ /* Nothing special needs to be done to find bus 0 */
+ /* Allow the HT devices to be found */
+ enumerate_ht_chain(0);
+
+ /* Setup the 8111 */
+ amd8111_enable_rom();
+
+ /* Is this a deliberate reset by the bios */
+ if (bios_reset_detected() && last_boot_normal()) {
+ goto normal_image;
}
/* This is the primary cpu how should I boot? */
else if (do_normal_boot()) {
- asm("jmp __normal_image");
+ goto normal_image;
+ }
+ else {
+ goto fallback_image;
}
+ normal_image:
+ asm("jmp __normal_image"
+ : /* outputs */
+ : "a" (bist) /* inputs */
+ : /* clobbers */
+ );
+ cpu_reset:
+ asm("jmp __cpu_reset"
+ : /* outputs */
+ : "a"(bist) /* inputs */
+ : /* clobbers */
+ );
+ fallback_image:
+#if HAVE_REGPARM_SUPPORT
+ return bist;
+#else
+ return;
+#endif
}
diff --git a/src/mainboard/amd/solo/mptable.c b/src/mainboard/amd/solo/mptable.c
index dfe4320181..42c2e6b33c 100644
--- a/src/mainboard/amd/solo/mptable.c
+++ b/src/mainboard/amd/solo/mptable.c
@@ -178,7 +178,6 @@ void *smp_write_config_table(void *v, unsigned long * processor_map)
1, (5<<2)|1, 0x02, 0x11);
-
/* There is no extension information... */
/* Compute the checksums */
diff --git a/src/mainboard/arima/hdama/Config.lb b/src/mainboard/arima/hdama/Config.lb
index 60d74da0ab..fbb1a2bbee 100644
--- a/src/mainboard/arima/hdama/Config.lb
+++ b/src/mainboard/arima/hdama/Config.lb
@@ -23,6 +23,12 @@ uses XIP_ROM_BASE
uses STACK_SIZE
uses HEAP_SIZE
uses USE_OPTION_TABLE
+uses LB_CKS_RANGE_START
+uses LB_CKS_RANGE_END
+uses LB_CKS_LOC
+uses MAINBOARD_PART_NUMBER
+uses MAINBOARD_VENDOR
+
## ROM_SIZE is the size of boot ROM that this board will use.
default ROM_SIZE=524288
@@ -59,6 +65,13 @@ default HAVE_MP_TABLE=1
default HAVE_OPTION_TABLE=1
##
+## Move the default LinuxBIOS cmos range off of AMD RTC registers
+##
+default LB_CKS_RANGE_START=49
+default LB_CKS_RANGE_END=122
+default LB_CKS_LOC=123
+
+##
## Build code for SMP support
## Only worry about 2 micro processors
##
@@ -73,8 +86,8 @@ default CONFIG_IOAPIC=1
##
## Clean up the motherboard id strings
##
-#default MAINBOARD_PART_NUMBER="HDAMA"
-#default MAINBOARD_VENDOR="ARIMA"
+default MAINBOARD_PART_NUMBER="HDAMA"
+default MAINBOARD_VENDOR="ARIMA"
###
### LinuxBIOS layout values
@@ -144,9 +157,7 @@ arch i386 end
## Build the objects we have code for in this directory.
##
-#object mainboard.o
driver mainboard.o
-#object static_devices.o
if HAVE_MP_TABLE object mptable.o end
if HAVE_PIRQ_TABLE object irq_tables.o end
object reset.o
@@ -165,8 +176,8 @@ makerule ./failover.inc
end
makerule ./auto.E
- depends "$(MAINBOARD)/auto.c"
- action "$(CPP) -I$(TOP)/src $(ROMCCPPFLAGS) $(CPPFLAGS) $(MAINBOARD)/auto.c > ./auto.E"
+ depends "$(MAINBOARD)/auto.c option_table.h "
+ action "$(CPP) -I$(TOP)/src -I. $(ROMCCPPFLAGS) $(CPPFLAGS) $(MAINBOARD)/auto.c > ./auto.E"
end
makerule ./auto.inc
depends "./auto.E ./romcc"
@@ -178,6 +189,7 @@ end
##
mainboardinit cpu/i386/entry16.inc
mainboardinit cpu/i386/entry32.inc
+mainboardinit cpu/i386/bist32.inc
ldscript /cpu/i386/entry16.lds
ldscript /cpu/i386/entry32.lds
@@ -259,19 +271,29 @@ northbridge amd/amdk8 "mc0"
pci 1:0.2 on
pci 1:1.0 off
superio NSC/pc87360 link 1
- pnp 2e.0
- pnp 2e.1
- pnp 2e.2
- pnp 2e.3
- pnp 2e.4
- pnp 2e.5
- pnp 2e.6
- pnp 2e.7
- pnp 2e.8
- pnp 2e.9
- pnp 2e.a
- register "com1" = "{1, 0, 0x3f8, 4}"
- register "lpt" = "{1}"
+ pnp 2e.0 off # Floppy
+ io 0x60 = 0x3f0
+ irq 0x70 = 6
+ drq 0x74 = 2
+ pnp 2e.1 off # Parallel Port
+ io 0x60 = 0x378
+ irq 0x70 = 7
+ pnp 2e.2 off # Com 2
+ io 0x60 = 0x2f8
+ irq 0x70 = 3
+ pnp 2e.3 on # Com 1
+ io 0x60 = 0x3f8
+ irq 0x70 = 4
+ pnp 2e.4 off # SWC
+ pnp 2e.5 off # Mouse
+ pnp 2e.6 on # Keyboard
+ io 0x60 = 0x60
+ io 0x62 = 0x64
+ irq 0x70 = 1
+ pnp 2e.7 off # GPIO
+ pnp 2e.8 off # ACB
+ pnp 2e.9 off # FSCM
+ pnp 2e.a off # WDT
end
end
end
@@ -297,4 +319,5 @@ end
##
mainboardinit pc80/serial.inc
mainboardinit arch/i386/lib/console.inc
+mainboardinit cpu/i386/bist32_fail.inc
diff --git a/src/mainboard/arima/hdama/auto.c b/src/mainboard/arima/hdama/auto.c
index 689346e6f2..e011809f49 100644
--- a/src/mainboard/arima/hdama/auto.c
+++ b/src/mainboard/arima/hdama/auto.c
@@ -1,14 +1,16 @@
#define ASSEMBLY 1
#include <stdint.h>
#include <device/pci_def.h>
-#include <cpu/p6/apic.h>
#include <arch/io.h>
-#include <device/pnp.h>
+#include <device/pnp_def.h>
#include <arch/romcc_io.h>
+#include <arch/smp/lapic.h>
+#include "option_table.h"
+#include "pc80/mc146818rtc_early.c"
#include "pc80/serial.c"
#include "arch/i386/lib/console.c"
#include "ram/ramtest.c"
-#include "northbridge/amd/amdk8/early_ht.c"
+#include "northbridge/amd/amdk8/incoherent_ht.c"
#include "southbridge/amd/amd8111/amd8111_early_smbus.c"
#include "northbridge/amd/amdk8/raminit.h"
#include "cpu/k8/apic_timer.c"
@@ -17,8 +19,25 @@
#include "northbridge/amd/amdk8/reset_test.c"
#include "debug.c"
#include "northbridge/amd/amdk8/cpu_rev.c"
+#include "superio/NSC/pc87360/pc87360_early_serial.c"
-#define SIO_BASE 0x2e
+#define SERIAL_DEV PNP_DEV(0x2e, PC87360_SP1)
+
+static void hard_reset(void)
+{
+ set_bios_reset();
+
+ /* enable cf9 */
+ pci_write_config8(PCI_DEV(0, 0x04, 3), 0x41, 0xf1);
+ /* reset */
+ outb(0x0e, 0x0cf9);
+}
+
+static void soft_reset(void)
+{
+ set_bios_reset();
+ pci_write_config8(PCI_DEV(0, 0x04, 0), 0x47, 1);
+}
static void memreset_setup(void)
{
@@ -75,13 +94,13 @@ static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes)
{ 0x00010404, 0x00050101 }
};
- if(maxnodes>2) {
+ if(maxnodes > 2) {
print_debug("this mainboard is only designed for 2 cpus\r\n");
maxnodes=2;
}
- if (!(node>=maxnodes || row>=maxnodes)) {
+ if (!(node >= maxnodes || row >= maxnodes)) {
ret=rows_2p[node][row];
}
@@ -98,67 +117,12 @@ static inline int spd_read_byte(unsigned device, unsigned address)
return smbus_read_byte(device, address);
}
-/* no specific code here. this should go away completely */
-static void coherent_ht_mainboard(unsigned cpus)
-{
-}
-
#include "northbridge/amd/amdk8/raminit.c"
#include "northbridge/amd/amdk8/coherent_ht.c"
#include "sdram/generic_sdram.c"
-static void enable_lapic(void)
-{
- msr_t msr;
- msr = rdmsr(0x1b);
- msr.hi &= 0xffffff00;
- msr.lo &= 0x000007ff;
- msr.lo |= APIC_DEFAULT_BASE | (1 << 11);
- wrmsr(0x1b, msr);
-}
-
-static void stop_this_cpu(void)
-{
- unsigned apicid;
- apicid = apic_read(APIC_ID) >> 24;
- /* Send an APIC INIT to myself */
- apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
- apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT);
- /* Wait for the ipi send to finish */
- apic_wait_icr_idle();
-
- /* Deassert the APIC INIT */
- apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
- apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
- /* Wait for the ipi send to finish */
- apic_wait_icr_idle();
-
- /* If I haven't halted spin forever */
- for(;;) {
- hlt();
- }
-}
-
-#define PC87360_FDC 0x00
-#define PC87360_PP 0x01
-#define PC87360_SP2 0x02
-#define PC87360_SP1 0x03
-#define PC87360_SWC 0x04
-#define PC87360_KBCM 0x05
-#define PC87360_KBCK 0x06
-#define PC87360_GPIO 0x07
-#define PC87360_ACB 0x08
-#define PC87360_FSCM 0x09
-#define PC87360_WDT 0x0A
-
-static void pc87360_enable_serial(void)
-{
- pnp_set_logical_device(SIO_BASE, PC87360_SP1);
- pnp_set_enable(SIO_BASE, 1);
- pnp_set_iobase0(SIO_BASE, 0x3f8);
-}
#define FIRST_CPU 1
#define SECOND_CPU 1
@@ -193,22 +157,26 @@ static void main(void)
},
#endif
};
+ int needs_reset;
+ enable_lapic();
+ init_timer();
if (cpu_init_detected()) {
asm("jmp __cpu_reset");
}
- enable_lapic();
- init_timer();
+ distinguish_cpu_resets();
if (!boot_cpu()) {
stop_this_cpu();
}
- pc87360_enable_serial();
+ pc87360_enable_serial(SERIAL_DEV, TTYS0_BASE);
uart_init();
console_init();
setup_default_resource_map();
- setup_coherent_ht_domain();
- enumerate_ht_chain(0);
- distinguish_cpu_resets(0);
-
+ needs_reset = setup_coherent_ht_domain();
+ needs_reset |= ht_setup_chain(PCI_DEV(0, 0x18, 0), 0x80);
+ if (needs_reset) {
+ print_info("ht reset -");
+ soft_reset();
+ }
#if 0
print_pci_devices();
#endif
@@ -219,39 +187,15 @@ static void main(void)
memreset_setup();
sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu);
-#if 1
+#if 0
dump_pci_devices();
#endif
#if 0
dump_pci_device(PCI_DEV(0, 0x18, 2));
#endif
- /* Check all of memory */
-#if 0
- msr_t msr;
- msr = rdmsr(TOP_MEM);
- print_debug("TOP_MEM: ");
- print_debug_hex32(msr.hi);
- print_debug_hex32(msr.lo);
- print_debug("\r\n");
-#endif
-#if 0
- ram_check(0x00000000, msr.lo);
-#endif
#if 0
- static const struct {
- unsigned long lo, hi;
- } check_addrs[] = {
- /* Check 16MB of memory @ 0*/
- { 0x00000000, 0x01000000 },
-#if TOTAL_CPUS > 1
- /* Check 16MB of memory @ 2GB */
- { 0x80000000, 0x81000000 },
-#endif
- };
- int i;
- for(i = 0; i < sizeof(check_addrs)/sizeof(check_addrs[0]); i++) {
- ram_check(check_addrs[i].lo, check_addrs[i].hi);
- }
+ /* Check the first 1M */
+ ram_check(0x00000000, 0x000100000);
#endif
}
diff --git a/src/mainboard/arima/hdama/cmos.layout b/src/mainboard/arima/hdama/cmos.layout
index 5ba4c032c1..247715e6ac 100644
--- a/src/mainboard/arima/hdama/cmos.layout
+++ b/src/mainboard/arima/hdama/cmos.layout
@@ -29,6 +29,9 @@ entries
386 1 e 1 ECC_memory
388 4 r 0 reboot_bits
392 3 e 5 baud_rate
+395 1 e 1 hw_scrubber
+396 1 e 1 interleave_chip_selects
+397 2 e 8 max_mem_clock
400 1 e 1 power_on_after_fail
412 4 e 6 debug_level
416 4 e 7 boot_first
@@ -36,7 +39,14 @@ entries
424 4 e 7 boot_third
428 4 h 0 boot_index
432 8 h 0 boot_countdown
-1008 16 h 0 check_sum
+440 4 e 9 slow_cpu
+444 1 e 1 nmi
+728 256 h 0 user_data
+984 16 h 0 check_sum
+# Reserve the extended AMD configuration registers
+1000 24 r 0 reserved_memory
+
+
enumerations
@@ -66,9 +76,21 @@ enumerations
7 9 Fallback_HDD
7 10 Fallback_Floppy
#7 3 ROM
+8 0 200Mhz
+8 1 166Mhz
+8 2 133Mhz
+8 3 100Mhz
+9 0 off
+9 1 87.5%
+9 2 75.0%
+9 3 62.5%
+9 4 50.0%
+9 5 37.5%
+9 6 25.0%
+9 7 12.5%
checksums
-checksum 392 1007 1008
+checksum 392 983 984
diff --git a/src/mainboard/arima/hdama/failover.c b/src/mainboard/arima/hdama/failover.c
index bd9c17020e..b22abfea06 100644
--- a/src/mainboard/arima/hdama/failover.c
+++ b/src/mainboard/arima/hdama/failover.c
@@ -3,40 +3,78 @@
#include <device/pci_def.h>
#include <device/pci_ids.h>
#include <arch/io.h>
-#include "arch/romcc_io.h"
+#include <arch/romcc_io.h>
+#include <arch/smp/lapic.h>
#include "pc80/mc146818rtc_early.c"
#include "southbridge/amd/amd8111/amd8111_enable_rom.c"
#include "northbridge/amd/amdk8/early_ht.c"
#include "cpu/p6/boot_cpu.c"
#include "northbridge/amd/amdk8/reset_test.c"
+#define HAVE_REGPARM_SUPPORT 0
+#if HAVE_REGPARM_SUPPORT
+static unsigned long main(unsigned long bist)
+{
+#else
static void main(void)
{
- /* Nothing special needs to be done to find bus 0 */
- /* Allow the HT devices to be found */
- enumerate_ht_chain(0);
-
- /* Setup the 8111 */
- amd8111_enable_rom();
+ unsigned long bist = 0;
+#endif
+ /* Make cerain my local apic is useable */
+ enable_lapic();
- /* Is this a cpu reset? */
+ /* Is this a cpu only reset? */
if (cpu_init_detected()) {
if (last_boot_normal()) {
- asm("jmp __normal_image");
+ goto normal_image;
} else {
- asm("jmp __cpu_reset");
+ goto cpu_reset;
}
}
- /* Is this a deliberate reset by the bios */
- else if (bios_reset_detected() && last_boot_normal()) {
- asm("jmp __normal_image");
- }
/* Is this a secondary cpu? */
- else if (!boot_cpu() && last_boot_normal()) {
- asm("jmp __normal_image");
+ if (!boot_cpu()) {
+ if (last_boot_normal()) {
+ goto normal_image;
+ } else {
+ goto fallback_image;
+ }
+ }
+
+
+ /* Nothing special needs to be done to find bus 0 */
+ /* Allow the HT devices to be found */
+ enumerate_ht_chain();
+
+ /* Setup the 8111 */
+ amd8111_enable_rom();
+
+ /* Is this a deliberate reset by the bios */
+ if (bios_reset_detected() && last_boot_normal()) {
+ goto normal_image;
}
/* This is the primary cpu how should I boot? */
else if (do_normal_boot()) {
- asm("jmp __normal_image");
+ goto normal_image;
+ }
+ else {
+ goto fallback_image;
}
+ normal_image:
+ asm("jmp __normal_image"
+ : /* outputs */
+ : "a" (bist) /* inputs */
+ : /* clobbers */
+ );
+ cpu_reset:
+ asm("jmp __cpu_reset"
+ : /* outputs */
+ : "a"(bist) /* inputs */
+ : /* clobbers */
+ );
+ fallback_image:
+#if HAVE_REGPARM_SUPPORT
+ return bist;
+#else
+ return;
+#endif
}
diff --git a/src/mainboard/arima/hdama/irq_tables.c b/src/mainboard/arima/hdama/irq_tables.c
index 9be2d1cf14..c54d43bbd1 100644
--- a/src/mainboard/arima/hdama/irq_tables.c
+++ b/src/mainboard/arima/hdama/irq_tables.c
@@ -17,36 +17,28 @@
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 IRQ_SLOT_COUNT
- * devices on the bus */
+ PIRQ_VERSION, /* u16 version */
+ 32+16*IRQ_SLOT_COUNT, /* there can be total IRQ_SLOT_COUNT table entries */
IRQ_ROUTER_BUS, /* Where the interrupt router lies (bus) */
IRQ_ROUTER_DEVFN, /* Where the interrupt router lies (dev) */
0x00, /* IRQs devoted exclusively to PCI usage */
IRQ_ROUTER_VENDOR, /* Vendor */
IRQ_ROUTER_DEVICE, /* Device */
0x00, /* Crap (miniport) */
- { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
- 0x00, /* u8 checksum , mod 256 checksum must give
- * zero, will be corrected later
- */
- {
-
- /* slot(0=onboard), devfn, irqlinks (line id, 0=not routed) */
-
+ { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
+ 0xb0, /* u8 checksum , mod 256 checksum must give zero */
+ { /* slot(0=onboard), devfn, irqlinks (line id, 0=not routed) */
/* PCI Slot 1-6 */
- IRQ_SLOT (1, 3,1,0, 2,3,4,1 ),
- IRQ_SLOT (2, 3,2,0, 3,4,1,2 ),
- IRQ_SLOT (3, 2,1,0, 2,3,4,1 ),
- IRQ_SLOT (4, 2,2,0, 3,4,1,2 ),
- IRQ_SLOT (5, 4,5,0, 2,3,4,1 ),
- IRQ_SLOT (6, 4,4,0, 1,2,3,4 ),
-
+ IRQ_SLOT(1, 3,1,0, 2,3,4,1 ),
+ IRQ_SLOT(2, 3,2,0, 3,4,1,2 ),
+ IRQ_SLOT(3, 2,1,0, 2,3,4,1 ),
+ IRQ_SLOT(4, 2,2,0, 3,4,1,2 ),
+ IRQ_SLOT(5, 4,5,0, 2,3,4,1 ),
+ IRQ_SLOT(6, 4,4,0, 1,2,3,4 ),
/* Onboard NICs */
- IRQ_SLOT (0, 2,3,0, 4,0,0,0 ),
- IRQ_SLOT (0, 2,4,0, 4,0,0,0 ),
-
+ IRQ_SLOT(0, 2,3,0, 4,0,0,0 ),
+ IRQ_SLOT(0, 2,4,0, 4,0,0,0 ),
/* Let Linux know about bus 1 */
- IRQ_SLOT (0, 1,4,3, 0,0,0,0 ),
+ IRQ_SLOT(0, 1,4,3, 0,0,0,0 ),
}
};
diff --git a/src/mainboard/arima/hdama/mainboard.c b/src/mainboard/arima/hdama/mainboard.c
index 82041282f6..bbc6f53716 100644
--- a/src/mainboard/arima/hdama/mainboard.c
+++ b/src/mainboard/arima/hdama/mainboard.c
@@ -3,23 +3,268 @@
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
+#include <cpu/p6/msr.h>
#include <arch/io.h>
#include <device/chip.h>
#include "../../../northbridge/amd/amdk8/northbridge.h"
#include "chip.h"
+#include "pc80/mc146818rtc.h"
+
+
unsigned long initial_apicid[CONFIG_MAX_CPUS] =
{
0, 1,
};
+#define SMBGSTATUS 0xe0
+#define SMBGCTL 0xe2
+#define SMBHSTADDR 0xe4
+#define SMBHSTDAT 0xe6
+#define SMBHSTCMD 0xe8
+#define SMBHSTFIFO 0xe9
+
+#define SMBUS_TIMEOUT (100*1000*10)
+
+static inline void smbus_delay(void)
+{
+ outb(0x80, 0x80);
+}
+
+static int smbus_wait_until_ready(unsigned smbus_io_base)
+{
+ unsigned long loops;
+ loops = SMBUS_TIMEOUT;
+ do {
+ unsigned short val;
+ smbus_delay();
+ val = inw(smbus_io_base + SMBGSTATUS);
+ if ((val & 0x800) == 0) {
+ break;
+ }
+ if(loops == (SMBUS_TIMEOUT / 2)) {
+ outw(inw(smbus_io_base + SMBGSTATUS),
+ smbus_io_base + SMBGSTATUS);
+ }
+ } while(--loops);
+ return loops?0:-2;
+}
+
+static int smbus_wait_until_done(unsigned smbus_io_base)
+{
+ unsigned long loops;
+ loops = SMBUS_TIMEOUT;
+ do {
+ unsigned short val;
+ smbus_delay();
+
+ val = inw(smbus_io_base + SMBGSTATUS);
+ if (((val & 0x8) == 0) | ((val & 0x437) != 0)) {
+ break;
+ }
+ } while(--loops);
+ return loops?0:-3;
+}
+
+static int smbus_send_byte(unsigned smbus_io_base, unsigned device, unsigned value)
+{
+ unsigned char global_status_register;
+
+ if (smbus_wait_until_ready(smbus_io_base) < 0) {
+ return -2;
+ }
+
+ /* setup transaction */
+ /* disable interrupts */
+ outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL);
+ /* set the device I'm talking too */
+ outw(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
+ /* set the command/address... */
+ outb(0, smbus_io_base + SMBHSTCMD);
+ /* set up for a send byte */
+ outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x1), smbus_io_base + SMBGCTL);
+
+ /* clear any lingering errors, so the transaction will run */
+ /* Do I need to write the bits to a 1 to clear an error? */
+ outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS);
+
+ /* set the data word...*/
+ outw(value, smbus_io_base + SMBHSTDAT);
+
+ /* start the command */
+ outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL);
+
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(smbus_io_base) < 0) {
+ return -3;
+ }
+ global_status_register = inw(smbus_io_base + SMBGSTATUS);
+
+ if (global_status_register != (1 << 4)) {
+ return -1;
+ }
+ return 0;
+}
+
+static int smbus_recv_byte(unsigned smbus_io_base, unsigned device)
+{
+ unsigned char global_status_register;
+ unsigned char byte;
+
+ if (smbus_wait_until_ready(smbus_io_base) < 0) {
+ return -2;
+ }
+
+ /* setup transaction */
+ /* disable interrupts */
+ outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL);
+ /* set the device I'm talking too */
+ outw(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
+ /* set the command/address... */
+ outb(0, smbus_io_base + SMBHSTCMD);
+ /* set up for a send byte */
+ outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x1), smbus_io_base + SMBGCTL);
+
+ /* clear any lingering errors, so the transaction will run */
+ /* Do I need to write the bits to a 1 to clear an error? */
+ outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS);
+
+ /* set the data word...*/
+ outw(0, smbus_io_base + SMBHSTDAT);
+
+ /* start the command */
+ outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL);
+
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(smbus_io_base) < 0) {
+ return -3;
+ }
+
+ global_status_register = inw(smbus_io_base + SMBGSTATUS);
+
+ /* read results of transaction */
+ byte = inw(smbus_io_base + SMBHSTDAT) & 0xff;
+
+ if (global_status_register != (1 << 4)) {
+ return -1;
+ }
+ return byte;
+}
+
+#if 0
+static int smbus_read_byte(unsigned smbus_io_base, unsigned device, unsigned address)
+{
+ unsigned char global_status_register;
+ unsigned char byte;
+
+ if (smbus_wait_until_ready(smbus_io_base) < 0) {
+ return -2;
+ }
+
+ /* setup transaction */
+ /* disable interrupts */
+ outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)), smbus_io_base + SMBGCTL);
+ /* set the device I'm talking too */
+ outw(((device & 0x7f) << 1) | 1, smbus_io_base + SMBHSTADDR);
+ /* set the command/address... */
+ outb(address & 0xFF, smbus_io_base + SMBHSTCMD);
+ /* set up for a byte data read */
+ outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x2), smbus_io_base + SMBGCTL);
+
+ /* clear any lingering errors, so the transaction will run */
+ /* Do I need to write the bits to a 1 to clear an error? */
+ outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS);
+
+ /* clear the data word...*/
+ outw(0, smbus_io_base + SMBHSTDAT);
+
+ /* start the command */
+ outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL);
+
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(smbus_io_base) < 0) {
+ return -3;
+ }
+
+ global_status_register = inw(smbus_io_base + SMBGSTATUS);
+
+ /* read results of transaction */
+ byte = inw(smbus_io_base + SMBHSTDAT) & 0xff;
+
+ if (global_status_register != (1 << 4)) {
+ return -1;
+ }
+ return byte;
+}
+
+static int smbus_write_byte(unsigned smbus_io_base, unsigned device, unsigned address, unsigned char val)
+{
+ if (smbus_wait_until_ready(smbus_io_base) < 0) {
+ return -2;
+ }
+
+ /* setup transaction */
+ /* disable interrupts */
+ outw(inw(smbus_io_base + SMBGCTL) & ~((1<<10)|(1<<9)|(1<<8)|(1<<4)),
+ smbus_io_base + SMBGCTL);
+ /* set the device I'm talking too */
+ outw(((device & 0x7f) << 1) | 0, smbus_io_base + SMBHSTADDR);
+ outb(address & 0xFF, smbus_io_base + SMBHSTCMD);
+ /* set up for a byte data write */ /* FIXME */
+ outw((inw(smbus_io_base + SMBGCTL) & ~7) | (0x1), smbus_io_base + SMBGCTL);
+ /* clear any lingering errors, so the transaction will run */
+ /* Do I need to write the bits to a 1 to clear an error? */
+ outw(inw(smbus_io_base + SMBGSTATUS), smbus_io_base + SMBGSTATUS);
+
+ /* clear the data word...*/
+ outw(val, smbus_io_base + SMBHSTDAT);
+
+ /* start the command */
+ outw((inw(smbus_io_base + SMBGCTL) | (1 << 3)), smbus_io_base + SMBGCTL);
+
+ /* poll for transaction completion */
+ if (smbus_wait_until_done(smbus_io_base) < 0) {
+ return -3;
+ }
+ return 0;
+}
+#endif
+
+#define SMBUS_MUX 0x70
+static void mainboard_init(device_t dev)
+{
+ /* Set the mux to see the temperature sensors */
+ dev = dev_find_device(0x1022, 0x746b, 0);
+ if (dev) {
+ unsigned smbus_io_base;
+ unsigned device;
+ int result;
+ int mux_setting;
+ device = SMBUS_MUX;
+ mux_setting = 1;
+ smbus_io_base = pci_read_config32(dev, 0x58) & ~1;;
+ result = smbus_send_byte(smbus_io_base, device, mux_setting);
+ if ((result < 0) ||
+ (smbus_recv_byte(smbus_io_base, device) != mux_setting)) {
+ printk_err("SMBUS mux would not set to %d\n", mux_setting);
+ }
+
+ }
+ else {
+ printk_err("SMBUS_controller not found\n");
+ }
+}
+
static struct device_operations mainboard_operations = {
.read_resources = root_dev_read_resources,
.set_resources = root_dev_set_resources,
.enable_resources = enable_childrens_resources,
- .init = 0,
+ .init = mainboard_init,
.scan_bus = amdk8_scan_root_bus,
.enable = 0,
};
diff --git a/src/mainboard/newisys/khepri/Config.lb b/src/mainboard/newisys/khepri/Config.lb
index 6deb3611ba..f0ffeb4e76 100644
--- a/src/mainboard/newisys/khepri/Config.lb
+++ b/src/mainboard/newisys/khepri/Config.lb
@@ -252,19 +252,29 @@ northbridge amd/amdk8 "mc0"
pci 1:0.2 on
pci 1:1.0 on
superio NSC/pc87360 link 1
- pnp 2e.0
- pnp 2e.1
- pnp 2e.2
- pnp 2e.3
- pnp 2e.4
- pnp 2e.5
- pnp 2e.6
- pnp 2e.7
- pnp 2e.8
- pnp 2e.9
- pnp 2e.a
- register "com1" = "{1, 0, 0x3f8, 4}"
- register "lpt" = "{1}"
+ pnp 2e.0 off # Floppy
+ io 0x60 = 0x3f0
+ irq 0x70 = 6
+ drq 0x74 = 2
+ pnp 2e.1 off # Parallel Port
+ io 0x60 = 0x378
+ irq 0x70 = 7
+ pnp 2e.2 off # Com 2
+ io 0x60 = 0x2f8
+ irq 0x70 = 3
+ pnp 2e.3 on # Com 1
+ io 0x60 = 0x3f8
+ irq 0x70 = 4
+ pnp 2e.4 off # SWC
+ pnp 2e.5 off # Mouse
+ pnp 2e.6 on # Keyboard
+ io 0x60 = 0x60
+ io 0x62 = 0x64
+ irq 0x70 = 1
+ pnp 2e.7 off # GPIO
+ pnp 2e.8 off # ACB
+ pnp 2e.9 off # FSCM
+ pnp 2e.a off # WDT
end
end
end
diff --git a/src/mainboard/newisys/khepri/auto.c b/src/mainboard/newisys/khepri/auto.c
index df6ad6c88c..44f128addc 100644
--- a/src/mainboard/newisys/khepri/auto.c
+++ b/src/mainboard/newisys/khepri/auto.c
@@ -2,17 +2,19 @@
#define MAXIMUM_CONSOLE_LOGLEVEL 9
#define DEFAULT_CONSOLE_LOGLEVEL 9
-
#include <stdint.h>
#include <device/pci_def.h>
#include <cpu/p6/apic.h>
#include <arch/io.h>
#include <device/pnp.h>
#include <arch/romcc_io.h>
+#include <arch/smp/lapic.h>
+#include "option_table.h"
+#include "pc80/mc146818rtc_early.c"
#include "pc80/serial.c"
#include "arch/i386/lib/console.c"
#include "ram/ramtest.c"
-#include "northbridge/amd/amdk8/early_ht.c"
+#include "northbridge/amd/amdk8/incoherent_ht.c"
#include "southbridge/amd/amd8111/amd8111_early_smbus.c"
#include "northbridge/amd/amdk8/raminit.h"
#include "cpu/k8/apic_timer.c"
@@ -21,8 +23,25 @@
#include "northbridge/amd/amdk8/reset_test.c"
#include "debug.c"
#include "northbridge/amd/amdk8/cpu_rev.c"
+#include "superio/NSC/pc87360/pc87360_early_serial.c"
+
+#define SERIAL_DEV PNP_DEV(0x2e, PC87360_SP1)
+
+static void hard_reset(void)
+{
+ set_bios_reset();
+
+ /* enable cf9 */
+ pci_write_config8(PCI_DEV(0, 0x04, 3), 0x41, 0xf1);
+ /* reset */
+ outb(0x0e, 0x0cf9);
+}
-#define SIO_BASE 0x2e
+static void soft_reset(void)
+{
+ set_bios_reset();
+ pci_write_config8(PCI_DEV(0, 0x04, 0), 0x47, 1);
+}
static void memreset_setup(void)
{
@@ -102,11 +121,6 @@ static inline int spd_read_byte(unsigned device, unsigned address)
return smbus_read_byte(device, address);
}
-/* no specific code here. this should go away completely */
-static void coherent_ht_mainboard(unsigned cpus)
-{
-}
-
#include "northbridge/amd/amdk8/raminit.c"
#define CONNECTION_0_1 DOWN
@@ -116,59 +130,6 @@ static void coherent_ht_mainboard(unsigned cpus)
#include "resourcemap.c" /* newisys khepri does not want the default */
-static void enable_lapic(void)
-{
-
- msr_t msr;
- msr = rdmsr(0x1b);
- msr.hi &= 0xffffff00;
- msr.lo &= 0x000007ff;
- msr.lo |= APIC_DEFAULT_BASE | (1 << 11);
- wrmsr(0x1b, msr);
-}
-
-static void stop_this_cpu(void)
-{
- unsigned apicid;
- apicid = apic_read(APIC_ID) >> 24;
-
- /* Send an APIC INIT to myself */
- apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
- apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT | APIC_DM_INIT);
- /* Wait for the ipi send to finish */
- apic_wait_icr_idle();
-
- /* Deassert the APIC INIT */
- apic_write(APIC_ICR2, SET_APIC_DEST_FIELD(apicid));
- apic_write(APIC_ICR, APIC_INT_LEVELTRIG | APIC_DM_INIT);
- /* Wait for the ipi send to finish */
- apic_wait_icr_idle();
-
- /* If I haven't halted spin forever */
- for(;;) {
- hlt();
- }
-}
-
-#define PC87360_FDC 0x00
-#define PC87360_PP 0x01
-#define PC87360_SP2 0x02
-#define PC87360_SP1 0x03
-#define PC87360_SWC 0x04
-#define PC87360_KBCM 0x05
-#define PC87360_KBCK 0x06
-#define PC87360_GPIO 0x07
-#define PC87360_ACB 0x08
-#define PC87360_FSCM 0x09
-#define PC87360_WDT 0x0A
-
-static void pc87360_enable_serial(void)
-{
- pnp_set_logical_device(SIO_BASE, PC87360_SP1);
- pnp_set_enable(SIO_BASE, 1);
- pnp_set_iobase0(SIO_BASE, 0x3f8);
-}
-
static void main(void)
{
/*
@@ -195,21 +156,26 @@ static void main(void)
.channel1 = { (0xa<<3)|5, (0xa<<3)|7, 0, 0 },
},
};
+ int needs_reset;
+ enable_lapic();
+ init_timer();
if (cpu_init_detected()) {
asm("jmp __cpu_reset");
}
- enable_lapic();
- init_timer();
+ distinguish_cpu_resets();
if (!boot_cpu()) {
stop_this_cpu();
}
- pc87360_enable_serial();
+ pc87360_enable_serial(SERIAL_DEV, TTYS0_BASE);
uart_init();
console_init();
setup_khepri_resource_map();
- setup_coherent_ht_domain();
- enumerate_ht_chain(0);
- distinguish_cpu_resets(0);
+ needs_reset = setup_coherent_ht_domain();
+ needs_reset |= ht_setup_chain(PCI_DEV(0, 0x18, 0), 0x80);
+ if (needs_reset) {
+ print_info("ht reset -");
+ soft_reset();
+ }
#if 0
print_pci_devices();
@@ -230,30 +196,7 @@ static void main(void)
/* Check all of memory */
#if 0
- msr_t msr;
- msr = rdmsr(TOP_MEM);
- print_debug("TOP_MEM: ");
- print_debug_hex32(msr.hi);
- print_debug_hex32(msr.lo);
- print_debug("\r\n");
-#endif
-#if 0
- ram_check(0x00000000, msr.lo);
-#endif
-#if 0
- static const struct {
- unsigned long lo, hi;
- } check_addrs[] = {
- /* Check 16MB of memory @ 0*/
- { 0x00000000, 0x01000000 },
-#if TOTAL_CPUS > 1
- /* Check 16MB of memory @ 2GB */
- { 0x80000000, 0x81000000 },
-#endif
- };
- int i;
- for(i = 0; i < sizeof(check_addrs)/sizeof(check_addrs[0]); i++) {
- ram_check(check_addrs[i].lo, check_addrs[i].hi);
- }
+ /* Check the first 1M */
+ ram_check(0x00000000, 0x000100000);
#endif
}
diff --git a/src/northbridge/amd/amdk8/Config.lb b/src/northbridge/amd/amdk8/Config.lb
index 0110e218ce..3b249161fd 100644
--- a/src/northbridge/amd/amdk8/Config.lb
+++ b/src/northbridge/amd/amdk8/Config.lb
@@ -1,4 +1,9 @@
config chip.h
object northbridge.o
driver misc_control.o
-driver mcf0_control.o
+
+makerule raminit_test
+ depends "$(TOP)/src/northbridge/amd/amdk8/raminit_test.c"
+ depends "$(TOP)/src/northbridge/amd/amdk8/raminit.c"
+ action "$(HOSTCC) $(HOSTCFLAGS) $(CPUFLAGS) -Wno-unused-function -I$(TOP)/src/include -g $< -o $@"
+end
diff --git a/src/northbridge/amd/amdk8/amdk8.h b/src/northbridge/amd/amdk8/amdk8.h
index c8ae95e383..ca8e8dc3d2 100644
--- a/src/northbridge/amd/amdk8/amdk8.h
+++ b/src/northbridge/amd/amdk8/amdk8.h
@@ -38,6 +38,15 @@
#define HTTC_HI_PRI_BYP_CNT_MASK 3
+/* Function 1 */
+#define PCI_IO_BASE0 0xc0
+#define PCI_IO_BASE1 0xc8
+#define PCI_IO_BASE2 0xd0
+#define PCI_IO_BASE3 0xd8
+#define PCI_IO_BASE_VGA_EN (1 << 4)
+#define PCI_IO_BASE_NO_ISA (1 << 5)
+
+
/* Function 2 */
#define DRAM_CSBASE 0x40
#define DRAM_CSMASK 0x60
@@ -124,6 +133,9 @@
#define DCL_UnBufDimm (1<<18)
#define DCL_32ByteEn (1<<19)
#define DCL_x4DIMM_SHIFT 20
+#define DCL_DisInRcvrs (1<<24)
+#define DCL_BypMax_SHIFT 25
+#define DCL_En2T (1<<28)
#define DRAM_CONFIG_HIGH 0x94
#define DCH_ASYNC_LAT_SHIFT 0
#define DCH_ASYNC_LAT_MASK 0xf
diff --git a/src/northbridge/amd/amdk8/coherent_ht.c b/src/northbridge/amd/amdk8/coherent_ht.c
index 83fbd40beb..5b6ea16e4e 100644
--- a/src/northbridge/amd/amdk8/coherent_ht.c
+++ b/src/northbridge/amd/amdk8/coherent_ht.c
@@ -14,7 +14,10 @@
*/
#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <device/hypertransport_def.h>
#include "arch/romcc_io.h"
+#include "amdk8.h"
/*
* Until we have a completely dynamic setup we want
@@ -39,10 +42,6 @@
#define CONNECTION_0_2 UP
#endif
-#ifndef CONNECTION_1_0
-#define CONNECTION_1_0 ACROSS
-#endif
-
#ifndef CONNECTION_1_3
#define CONNECTION_1_3 UP
#endif
@@ -63,7 +62,7 @@
typedef uint8_t u8;
typedef uint32_t u32;
-typedef int8_t bool;
+typedef int bool;
#define TRUE (-1)
#define FALSE (0)
@@ -95,51 +94,15 @@ static void disable_probes(void)
u32 val;
- print_debug("Disabling read/write/fill probes for UP... ");
+ print_spew("Disabling read/write/fill probes for UP... ");
val=pci_read_config32(NODE_HT(0), 0x68);
val |= (1<<10)|(1<<9)|(1<<8)|(1<<4)|(1<<3)|(1<<2)|(1<<1)|(1 << 0);
pci_write_config32(NODE_HT(0), 0x68, val);
- print_debug("done.\r\n");
+ print_spew("done.\r\n");
}
-//BY LYH
-#if 0
-#define WAIT_TIMES 1000
-static void wait_ap_stop(u8 node)
-{
- unsigned long reg;
- unsigned long i;
- for(i=0;i<WAIT_TIMES;i++) {
- unsigned long regx;
- regx = pci_read_config32(NODE_HT(node),0x6c);
- if((regx & (1<<4))==1) break;
- }
- reg = pci_read_config32(NODE_HT(node),0x6c);
- reg &= ~(1<<4); // clear it
- pci_write_config32(NODE_HT(node), 0x6c, reg);
-
-}
-static void notify_bsp_ap_is_stopped(void)
-{
- unsigned long reg;
- unsigned long apic_id;
- apic_id = *((volatile unsigned long *)(APIC_DEFAULT_BASE+APIC_ID));
- apic_id >>= 24;
-/* print_debug("applicaton cpu apic_id: ");
- print_debug_hex32(apic_id);
- }*/
- if(apic_id!=0) { //AP apic_id == node_id ??
-// set the ColdResetbit to notify BSP that AP is stopped
- reg = pci_read_config32(NODE_HT(apic_id), 0x6C);
- reg |= 1<<4;
- pci_write_config32(NODE_HT(apic_id), 0x6C, reg);
- }
-
-}
-#endif
-//BY LYH END
static void enable_routing(u8 node)
{
@@ -168,14 +131,14 @@ static void enable_routing(u8 node)
*/
/* Enable routing table */
- print_debug("Enabling routing table for node ");
- print_debug_hex32(node);
+ print_spew("Enabling routing table for node ");
+ print_spew_hex32(node);
val=pci_read_config32(NODE_HT(node), 0x6c);
- val &= ~((1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0));
+ val &= ~((1<<1)|(1<<0));
pci_write_config32(NODE_HT(node), 0x6c, val);
- print_debug(" done.\r\n");
+ print_spew(" done.\r\n");
}
#if CONFIG_MAX_CPUS > 1
@@ -184,84 +147,97 @@ static void rename_temp_node(u8 node)
{
uint32_t val;
- print_debug("Renaming current temp node to ");
- print_debug_hex32(node);
+ print_spew("Renaming current temp node to ");
+ print_spew_hex32(node);
val=pci_read_config32(NODE_HT(7), 0x60);
val &= (~7); /* clear low bits. */
val |= node; /* new node */
pci_write_config32(NODE_HT(7), 0x60, val);
-//BY LYH
-#if 0
- if(node!=0) {
- wait_ap_stop(node);
- }
-#endif
-//BY LYH END
-
-
- print_debug(" done.\r\n");
-
-
+ print_spew(" done.\r\n");
}
static bool check_connection(u8 src, u8 dest, u8 link)
{
- /* this function does 2 things:
- * 1) detect whether the coherent HT link is connected.
- * 2) verify that the coherent hypertransport link
- * is established and actually working by reading the
- * remote node's vendor/device id
- */
-
+ /* See if we have a valid connection to dest */
u32 val;
- /* 1) */
- val=pci_read_config32(NODE_HT(src), 0x98+link);
+ /* Detect if the coherent HT link is connected. */
+ val = pci_read_config32(NODE_HT(src), 0x98+link);
if ( (val&0x17) != 0x03)
return 0;
- /* 2) */
- val=pci_read_config32(NODE_HT(dest),0);
+ /* Verify that the coherent hypertransport link is
+ * established and actually working by reading the
+ * remode node's vendor/device id
+ */
+ val = pci_read_config32(NODE_HT(dest),0);
if(val != 0x11001022)
return 0;
return 1;
}
-static void optimize_connection(u8 node1, u8 link1, u8 node2, u8 link2)
+static unsigned read_freq_cap(device_t dev, unsigned pos)
+{
+ /* Handle bugs in valid hypertransport frequency reporting */
+ unsigned freq_cap;
+ uint32_t id;
+
+ freq_cap = pci_read_config16(dev, pos);
+ freq_cap &= ~(1 << HT_FREQ_VENDOR); /* Ignore Vendor HT frequencies */
+
+ id = pci_read_config32(dev, 0);
+
+ /* AMD 8131 Errata 48 */
+ if (id == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8131_PCIX << 16))) {
+ freq_cap &= ~(1 << HT_FREQ_800Mhz);
+ }
+ /* AMD 8151 Errata 23 */
+ if (id == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8151_SYSCTRL << 16))) {
+ freq_cap &= ~(1 << HT_FREQ_800Mhz);
+ }
+ /* AMD K8 Unsupported 1Ghz? */
+ if (id == (PCI_VENDOR_ID_AMD | (0x1100 << 16))) {
+ freq_cap &= ~(1 << HT_FREQ_1000Mhz);
+ }
+ return freq_cap;
+}
+
+static int optimize_connection(device_t node1, uint8_t link1, device_t node2, uint8_t link2)
{
static const uint8_t link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 };
static const uint8_t pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 };
uint16_t freq_cap1, freq_cap2, freq_cap, freq_mask;
- uint8_t width_cap1, width_cap2, width_cap, width, ln_width1, ln_width2;
- uint8_t freq;
+ uint8_t width_cap1, width_cap2, width_cap, width, old_width, ln_width1, ln_width2;
+ uint8_t freq, old_freq;
+ int needs_reset;
/* Set link width and frequency */
+ /* Initially assume everything is already optimized and I don't need a reset */
+ needs_reset = 0;
+
/* Get the frequency capabilities */
- freq_cap1 = pci_read_config16(NODE_HT(node1), 0x80 + link1 + PCI_HT_CAP_HOST_FREQ_CAP);
- freq_cap2 = pci_read_config16(NODE_HT(node2), 0x80 + link2 + PCI_HT_CAP_HOST_FREQ_CAP);
+ freq_cap1 = read_freq_cap(node1, link1 + PCI_HT_CAP_HOST_FREQ_CAP);
+ freq_cap2 = read_freq_cap(node2, link2 + PCI_HT_CAP_HOST_FREQ_CAP);
/* Calculate the highest possible frequency */
-#if 1
- /* FIXME!!!!!!!
- * This method of computing the fastes frequency is broken.
- * Because the frequencies (i.e. 100Mhz) are not ordered.
- */
- freq = log2(freq_cap1 & freq_cap2 & 0xff);
-#else
- /* Only allow supported frequencies 800Mhz and below */
- freq = log2(freq_cap1 & freq_cap2 & 0x3f);
-#endif
+ freq = log2(freq_cap1 & freq_cap2);
+
+ /* See if I am changing the link freqency */
+ old_freq = pci_read_config8(node1, link1 + PCI_HT_CAP_HOST_FREQ);
+ needs_reset |= old_freq != freq;
+ old_freq = pci_read_config8(node2, link2 + PCI_HT_CAP_HOST_FREQ);
+ needs_reset |= old_freq != freq;
/* Set the Calulcated link frequency */
- pci_write_config8(NODE_HT(node1), 0x80 + link1 + PCI_HT_CAP_HOST_FREQ, freq);
- pci_write_config8(NODE_HT(node2), 0x80 + link2 + PCI_HT_CAP_HOST_FREQ, freq);
+ pci_write_config8(node1, link1 + PCI_HT_CAP_HOST_FREQ, freq);
+ pci_write_config8(node2, link2 + PCI_HT_CAP_HOST_FREQ, freq);
/* Get the width capabilities */
- width_cap1 = pci_read_config8(NODE_HT(node1), 0x80 + link1 + PCI_HT_CAP_HOST_WIDTH);
- width_cap2 = pci_read_config8(NODE_HT(node2), 0x80 + link2 + PCI_HT_CAP_HOST_WIDTH);
+ width_cap1 = pci_read_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH);
+ width_cap2 = pci_read_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH);
/* Calculate node1's input width */
ln_width1 = link_width_to_pow2[width_cap1 & 7];
@@ -278,45 +254,38 @@ static void optimize_connection(u8 node1, u8 link1, u8 node2, u8 link2)
}
width |= pow2_to_link_width[ln_width1] << 4;
+ /* See if I am changing node1's width */
+ old_width = pci_read_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH + 1);
+ needs_reset |= old_width != width;
+
/* Set node1's widths */
- pci_write_config8(NODE_HT(node1), 0x80 + link1 + PCI_HT_CAP_HOST_WIDTH + 1, width);
+ pci_write_config8(node1, link1 + PCI_HT_CAP_HOST_WIDTH + 1, width);
- /* Set node2's widths */
+ /* Calculate node2's width */
width = ((width & 0x70) >> 4) | ((width & 0x7) << 4);
- pci_write_config8(NODE_HT(node2), 0x80 + link2 + PCI_HT_CAP_HOST_WIDTH + 1, width);
+
+ /* See if I am changing node2's width */
+ old_width = pci_read_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH + 1);
+ needs_reset |= old_width != width;
+
+ /* Set node2's widths */
+ pci_write_config8(node2, link2 + PCI_HT_CAP_HOST_WIDTH + 1, width);
+
+ return needs_reset;
}
static void fill_row(u8 node, u8 row, u32 value)
{
-#if 0
- print_debug("fill_row: pci_write_config32(");
- print_debug_hex32(NODE_HT(node));
- print_debug_char(',');
- print_debug_hex32(0x40 + (row << 2));
- print_debug_char(',');
- print_debug_hex32(value);
- print_debug(")\r\n");
-#endif
pci_write_config32(NODE_HT(node), 0x40+(row<<2), value);
}
static void setup_row(u8 source, u8 dest, u8 cpus)
{
-#if 0
- printk_spew("setting up link from node %d to %d (%d cpus)\r\n",
- source, dest, cpus);
-#endif
-
fill_row(source,dest,generate_row(source,dest,cpus));
}
static void setup_temp_row(u8 source, u8 dest, u8 cpus)
{
-#if 0
- printk_spew("setting up temp. link from node %d to %d (%d cpus)\r\n",
- source, dest, cpus);
-#endif
-
fill_row(source,7,generate_temp_row(source,dest,cpus));
}
@@ -345,9 +314,8 @@ static void setup_remote_node(u8 node, u8 cpus)
};
uint8_t row;
int i;
-#if 1
- print_debug("setup_remote_node\r\n");
-#endif
+
+ print_spew("setup_remote_node\r\n");
for(row=0; row<cpus; row++)
setup_remote_row(node, row, cpus);
@@ -356,18 +324,11 @@ static void setup_remote_node(u8 node, u8 cpus)
uint32_t value;
uint8_t reg;
reg = pci_reg[i];
-#if 0
- print_debug("copying reg: ");
- print_debug_hex8(reg);
- print_debug("\r\n");
-#endif
value = pci_read_config32(NODE_MP(0), reg);
pci_write_config32(NODE_MP(7), reg, value);
}
-#if 1
- print_debug("setup_remote_done\r\n");
-#endif
+ print_spew("setup_remote_done\r\n");
}
#endif
@@ -381,79 +342,91 @@ static void setup_temp_node(u8 node, u8 cpus)
}
#endif
-static u8 setup_uniprocessor(void)
+static void setup_uniprocessor(void)
{
- print_debug("Enabling UP settings\r\n");
+ print_spew("Enabling UP settings\r\n");
disable_probes();
- return 1;
}
+struct setup_smp_result {
+ int cpus;
+ int needs_reset;
+};
+
#if CONFIG_MAX_CPUS > 1
-static u8 setup_smp(void)
+static struct setup_smp_result setup_smp(void)
{
- u8 cpus=2;
+ struct setup_smp_result result;
+ result.cpus = 2;
+ result.needs_reset = 0;
- print_debug("Enabling SMP settings\r\n");
+ print_spew("Enabling SMP settings\r\n");
- setup_row(0,0,cpus);
+ setup_row(0, 0, result.cpus);
/* Setup and check a temporary connection to node 1 */
- setup_temp_row(0,1,cpus);
+ setup_temp_row(0, 1, result.cpus);
if (!check_connection(0, 7, CONNECTION_0_1)) {
- print_debug("No connection to Node 1.\r\n");
+ print_spew("No connection to Node 1.\r\n");
clear_temp_row(0); /* delete temp connection */
setup_uniprocessor(); /* and get up working */
- return 1;
+ result.cpus = 1;
+ return result;
}
/* We found 2 nodes so far */
- optimize_connection(0, CONNECTION_0_1, 7, CONNECTION_1_0);
- setup_node(0, cpus); /* Node 1 is there. Setup Node 0 correctly */
- setup_remote_node(1, cpus); /* Setup the routes on the remote node */
+ result.needs_reset =
+ optimize_connection(NODE_HT(0), 0x80 + CONNECTION_0_1, NODE_HT(7), 0x80 + CONNECTION_0_1);
+ setup_node(0, result.cpus); /* Node 1 is there. Setup Node 0 correctly */
+ setup_remote_node(1, result.cpus); /* Setup the routes on the remote node */
rename_temp_node(1); /* Rename Node 7 to Node 1 */
enable_routing(1); /* Enable routing on Node 1 */
clear_temp_row(0); /* delete temporary connection */
#if CONFIG_MAX_CPUS > 2
- cpus=4;
+ result.cpus=4;
/* Setup and check temporary connection from Node 0 to Node 2 */
- setup_temp_row(0,2,cpus);
+ setup_temp_row(0,2, result.cpus);
if (!check_connection(0, 7, CONNECTION_0_2)) {
- print_debug("No connection to Node 2.\r\n");
+ print_spew("No connection to Node 2.\r\n");
clear_temp_row(0); /* delete temp connection */
- return 2;
+ result.cpus = 2;
+ return result;
}
/* We found 3 nodes so far. Now setup a temporary
* connection from node 0 to node 3 via node 1
*/
- setup_temp_row(0,1,cpus); /* temp. link between nodes 0 and 1 */
- setup_temp_row(1,3,cpus); /* temp. link between nodes 1 and 3 */
+ setup_temp_row(0,1, result.cpus); /* temp. link between nodes 0 and 1 */
+ setup_temp_row(1,3, result.cpus); /* temp. link between nodes 1 and 3 */
if (!check_connection(1, 7, CONNECTION_1_3)) {
- print_debug("No connection to Node 3.\r\n");
+ print_spew("No connection to Node 3.\r\n");
clear_temp_row(0); /* delete temp connection */
clear_temp_row(1); /* delete temp connection */
- return 2;
+ result.cpus = 2;
+ return result;
}
+#warning "FIXME optimize the physical connections"
+
/* We found 4 nodes so far. Now setup all nodes for 4p */
- setup_node(0, cpus); /* The first 2 nodes are configured */
- setup_node(1, cpus); /* already. Just configure them for 4p */
+ setup_node(0, result.cpus); /* The first 2 nodes are configured */
+ setup_node(1, result.cpus); /* already. Just configure them for 4p */
- setup_temp_row(0,2,cpus);
- setup_temp_node(2,cpus);
+ setup_temp_row(0,2, result.cpus);
+ setup_temp_node(2, result.cpus);
rename_temp_node(2);
enable_routing(2);
- setup_temp_row(0,1,cpus);
- setup_temp_row(1,3,cpus);
- setup_temp_node(3,cpus);
+ setup_temp_row(0,1, result.cpus);
+ setup_temp_row(1,3, result.cpus);
+ setup_temp_node(3, result.cpus);
rename_temp_node(3);
enable_routing(3); /* enable routing on node 3 (temp.) */
@@ -463,52 +436,52 @@ static u8 setup_smp(void)
clear_temp_row(3);
#endif
- print_debug_hex32(cpus);
+ print_debug_hex32(result.cpus);
print_debug(" nodes initialized.\r\n");
- return cpus;
+ return result;
}
#endif
#if CONFIG_MAX_CPUS > 1
-static unsigned detect_mp_capabilities(unsigned cpus)
+static unsigned verify_mp_capabilities(unsigned cpus)
{
unsigned node, row, mask;
bool mp_cap=TRUE;
-#if 1
- print_debug("detect_mp_capabilities: ");
- print_debug_hex32(cpus);
- print_debug("\r\n");
-#endif
- if (cpus>2)
+ if (cpus > 2) {
mask=0x06; /* BigMPCap */
- else
+ } else {
mask=0x02; /* MPCap */
+ }
for (node=0; node<cpus; node++) {
- if ((pci_read_config32(NODE_MC(node), 0xe8) & mask)!=mask)
- mp_cap=FALSE;
+ if ((pci_read_config32(NODE_MC(node), 0xe8) & mask) != mask) {
+ mp_cap = FALSE;
+ }
}
- if (mp_cap)
+ if (mp_cap) {
return cpus;
+ }
/* one of our cpus is not mp capable */
- print_debug("One of the CPUs is not MP capable. Going back to UP\r\n");
+ print_err("One of the CPUs is not MP capable. Going back to UP\r\n");
- for (node=cpus; node>0; node--)
- for (row=cpus; row>0; row--)
- fill_row(NODE_HT(node-1), row-1, DEFAULT);
-
- return setup_uniprocessor();
+ for (node = cpus; node > 0; node--) {
+ for (row = cpus; row > 0; row--) {
+ fill_row(NODE_HT(node-1), row-1, DEFAULT);
+ }
+ }
+ setup_uniprocessor();
+ return 1;
}
#endif
static void coherent_ht_finalize(unsigned cpus)
{
- int node;
+ unsigned node;
bool rev_a0;
/* set up cpu count and node count and enable Limit
@@ -517,53 +490,149 @@ static void coherent_ht_finalize(unsigned cpus)
* registers on Hammer A0 revision.
*/
-#if 1
+#if 0
print_debug("coherent_ht_finalize\r\n");
#endif
- rev_a0= is_cpu_rev_a0();
-
- for (node=0; node<cpus; node++) {
- u32 val;
- val=pci_read_config32(NODE_HT(node), 0x60);
+ rev_a0 = is_cpu_rev_a0();
+ for (node = 0; node < cpus; node++) {
+ device_t dev;
+ uint32_t val;
+ dev = NODE_HT(node);
+
+ /* Set the Total CPU and Node count in the system */
+ val = pci_read_config32(dev, 0x60);
val &= (~0x000F0070);
val |= ((cpus-1)<<16)|((cpus-1)<<4);
- pci_write_config32(NODE_HT(node),0x60,val);
-
- val=pci_read_config32(NODE_HT(node), 0x68);
-#if 1
- val |= 0x00008000;
-#else
- val |= 0x0f00c800; // 0x00008000->0f00c800 BY LYH
-#endif
- pci_write_config32(NODE_HT(node),0x68,val);
+ pci_write_config32(dev, 0x60, val);
+
+ /* Only respond to real cpu pci configuration cycles
+ * and optimize the HT settings
+ */
+ val=pci_read_config32(dev, 0x68);
+ val &= ~((HTTC_BUF_REL_PRI_MASK << HTTC_BUF_REL_PRI_SHIFT) |
+ (HTTC_MED_PRI_BYP_CNT_MASK << HTTC_MED_PRI_BYP_CNT_SHIFT) |
+ (HTTC_HI_PRI_BYP_CNT_MASK << HTTC_HI_PRI_BYP_CNT_SHIFT));
+ val |= HTTC_LIMIT_CLDT_CFG |
+ (HTTC_BUF_REL_PRI_8 << HTTC_BUF_REL_PRI_SHIFT) |
+ HTTC_RSP_PASS_PW |
+ (3 << HTTC_MED_PRI_BYP_CNT_SHIFT) |
+ (3 << HTTC_HI_PRI_BYP_CNT_SHIFT);
+ pci_write_config32(dev, 0x68, val);
if (rev_a0) {
- pci_write_config32(NODE_HT(node),0x94,0);
- pci_write_config32(NODE_HT(node),0xb4,0);
- pci_write_config32(NODE_HT(node),0xd4,0);
+ pci_write_config32(dev, 0x94, 0);
+ pci_write_config32(dev, 0xb4, 0);
+ pci_write_config32(dev, 0xd4, 0);
}
+
+
}
-#if 1
+
+#if 0
print_debug("done\r\n");
#endif
}
+static int apply_cpu_errata_fixes(unsigned cpus, int needs_reset)
+{
+ unsigned node;
+ for(node = 0; node < cpus; node++) {
+ device_t dev;
+ uint32_t cmd;
+ dev = NODE_MC(node);
+ if (is_cpu_pre_c0()) {
+
+ /* Errata 66
+ * Limit the number of downstream posted requests to 1
+ */
+ cmd = pci_read_config32(dev, 0x70);
+ if ((cmd & (3 << 0)) != 2) {
+ cmd &= ~(3<<0);
+ cmd |= (2<<0);
+ pci_write_config32(dev, 0x70, cmd );
+ needs_reset = 1;
+ }
+ cmd = pci_read_config32(dev, 0x7c);
+ if ((cmd & (3 << 4)) != 0) {
+ cmd &= ~(3<<4);
+ cmd |= (0<<4);
+ pci_write_config32(dev, 0x7c, cmd );
+ needs_reset = 1;
+ }
+ /* Clock Power/Timing Low */
+ cmd = pci_read_config32(dev, 0xd4);
+ if (cmd != 0x000D0001) {
+ cmd = 0x000D0001;
+ pci_write_config32(dev, 0xd4, cmd);
+ needs_reset = 1; /* Needed? */
+ }
+
+ }
+ else {
+ uint32_t cmd_ref;
+ /* Errata 98
+ * Set Clk Ramp Hystersis to 7
+ * Clock Power/Timing Low
+ */
+ cmd_ref = 0x04e20707; /* Registered */
+ cmd = pci_read_config32(dev, 0xd4);
+ if(cmd != cmd_ref) {
+ pci_write_config32(dev, 0xd4, cmd_ref );
+ needs_reset = 1; /* Needed? */
+ }
+ }
+ }
+ return needs_reset;
+}
+
+static int optimize_link_read_pointers(unsigned cpus, int needs_reset)
+{
+ unsigned node;
+ for(node = 0; node < cpus; node = node + 1) {
+ device_t f0_dev, f3_dev;
+ uint32_t cmd_ref, cmd;
+ int link;
+ f0_dev = NODE_HT(node);
+ f3_dev = NODE_MC(node);
+ cmd_ref = cmd = pci_read_config32(f3_dev, 0xdc);
+ for(link = 0; link < 3; link = link + 1) {
+ uint32_t link_type;
+ unsigned reg;
+ reg = 0x98 + (link * 0x20);
+ link_type = pci_read_config32(f0_dev, reg);
+ if (link_type & LinkConnected) {
+ cmd &= 0xff << (link *8);
+ /* FIXME this assumes the device on the other side is an AMD device */
+ cmd |= 0x25 << (link *8);
+ }
+ }
+ if (cmd != cmd_ref) {
+ pci_write_config32(f3_dev, 0xdc, cmd);
+ needs_reset = 1;
+ }
+ }
+ return needs_reset;
+}
+
static int setup_coherent_ht_domain(void)
{
- unsigned cpus;
- int reset_needed = 0;
+ struct setup_smp_result result;
+ result.cpus = 1;
+ result.needs_reset = 0;
enable_bsp_routing();
#if CONFIG_MAX_CPUS == 1
- cpus=setup_uniprocessor();
+ setup_uniprocessor();
#else
- cpus=setup_smp();
- cpus=detect_mp_capabilities(cpus);
+ result = setup_smp();
+ result.cpus = verify_mp_capabilities(result.cpus);
+#endif
+ coherent_ht_finalize(result.cpus);
+ result.needs_reset = apply_cpu_errata_fixes(result.cpus, result.needs_reset);
+#if CONFIG_MAX_CPUS > 1 /* Why doesn't this work on the solo? */
+ result.needs_reset = optimize_link_read_pointers(result.cpus, result.needs_reset);
#endif
- coherent_ht_finalize(cpus);
- /* FIXME this should probably go away again. */
- coherent_ht_mainboard(cpus);
- return reset_needed;
+ return result.needs_reset;
}
diff --git a/src/northbridge/amd/amdk8/cpu_rev.c b/src/northbridge/amd/amdk8/cpu_rev.c
index 51f235905e..0c4c5f8fbd 100644
--- a/src/northbridge/amd/amdk8/cpu_rev.c
+++ b/src/northbridge/amd/amdk8/cpu_rev.c
@@ -16,10 +16,15 @@ static unsigned int cpuid(unsigned int op)
static int is_cpu_rev_a0(void)
{
- return (cpuid(1) & 0xffff) == 0x0f10;
+ return (cpuid(1) & 0xffef) == 0x0f00;
}
static int is_cpu_pre_c0(void)
{
return (cpuid(1) & 0xffef) < 0x0f48;
}
+
+static int is_cpu_pre_b3(void)
+{
+ return (cpuid(1) & 0xffef) < 0x0f41;
+}
diff --git a/src/northbridge/amd/amdk8/early_ht.c b/src/northbridge/amd/amdk8/early_ht.c
index 4de8fa1075..90f258e1bc 100644
--- a/src/northbridge/amd/amdk8/early_ht.c
+++ b/src/northbridge/amd/amdk8/early_ht.c
@@ -1,4 +1,4 @@
-static int enumerate_ht_chain(unsigned link)
+static int enumerate_ht_chain(void)
{
/* Assumption the HT chain that is bus 0 has the HT I/O Hub on it.
* On most boards this just happens. If a cpu has multiple
@@ -49,3 +49,4 @@ static int enumerate_ht_chain(unsigned link)
} while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
return reset_needed;
}
+
diff --git a/src/northbridge/amd/amdk8/incoherent_ht.c b/src/northbridge/amd/amdk8/incoherent_ht.c
new file mode 100644
index 0000000000..711100a045
--- /dev/null
+++ b/src/northbridge/amd/amdk8/incoherent_ht.c
@@ -0,0 +1,244 @@
+#include <device/pci_def.h>
+#include <device/pci_ids.h>
+#include <device/hypertransport_def.h>
+
+static unsigned ht_lookup_slave_capability(device_t dev)
+{
+ unsigned pos;
+ uint8_t hdr_type;
+
+ hdr_type = pci_read_config8(dev, PCI_HEADER_TYPE);
+ pos = 0;
+ hdr_type &= 0x7f;
+
+ if ((hdr_type == PCI_HEADER_TYPE_NORMAL) ||
+ (hdr_type == PCI_HEADER_TYPE_BRIDGE)) {
+ pos = PCI_CAPABILITY_LIST;
+ }
+ if (pos > PCI_CAP_LIST_NEXT) {
+ pos = pci_read_config8(dev, pos);
+ }
+ while(pos != 0) { /* loop through the linked list */
+ uint8_t cap;
+ cap = pci_read_config8(dev, pos + PCI_CAP_LIST_ID);
+ if (cap == PCI_CAP_ID_HT) {
+ uint16_t flags;
+
+ flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
+ if ((flags >> 13) == 0) {
+ /* Entry is a Slave secondary, success... */
+ break;
+ }
+ }
+ pos = pci_read_config8(dev, pos + PCI_CAP_LIST_NEXT);
+ }
+ return pos;
+}
+
+static void ht_collapse_previous_enumeration(unsigned bus)
+{
+ device_t dev;
+
+ /* Spin through the devices and collapse any previous
+ * hypertransport enumeration.
+ */
+ for(dev = PCI_DEV(bus, 0, 0); dev <= PCI_DEV(bus, 0x1f, 0x7); dev += PCI_DEV(0, 1, 0)) {
+ uint32_t id;
+ unsigned pos, flags;
+
+ id = pci_read_config32(dev, PCI_VENDOR_ID);
+ if ((id == 0xffffffff) || (id == 0x00000000) ||
+ (id == 0x0000ffff) || (id == 0xffff0000)) {
+ continue;
+ }
+ pos = ht_lookup_slave_capability(dev);
+ if (!pos) {
+ continue;
+ }
+
+ /* Clear the unitid */
+ flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
+ flags &= ~0x1f;
+ pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags);
+ }
+}
+
+
+static unsigned ht_read_freq_cap(device_t dev, unsigned pos)
+{
+ /* Handle bugs in valid hypertransport frequency reporting */
+ unsigned freq_cap;
+ uint32_t id;
+
+ freq_cap = pci_read_config16(dev, pos);
+ freq_cap &= ~(1 << HT_FREQ_VENDOR); /* Ignore Vendor HT frequencies */
+
+ id = pci_read_config32(dev, 0);
+
+ /* AMD 8131 Errata 48 */
+ if (id == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8131_PCIX << 16))) {
+ freq_cap &= ~(1 << HT_FREQ_800Mhz);
+ }
+ /* AMD 8151 Errata 23 */
+ if (id == (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8151_SYSCTRL << 16))) {
+ freq_cap &= ~(1 << HT_FREQ_800Mhz);
+ }
+ /* AMD K8 Unsupported 1Ghz? */
+ if (id == (PCI_VENDOR_ID_AMD | (0x1100 << 16))) {
+ freq_cap &= ~(1 << HT_FREQ_1000Mhz);
+ }
+ return freq_cap;
+}
+
+#define LINK_OFFS(WIDTH,FREQ,FREQ_CAP) \
+ (((WIDTH & 0xff) << 16) | ((FREQ & 0xff) << 8) | (FREQ_CAP & 0xFF))
+
+#define LINK_WIDTH(OFFS) ((OFFS >> 16) & 0xFF)
+#define LINK_FREQ(OFFS) ((OFFS >> 8) & 0xFF)
+#define LINK_FREQ_CAP(OFFS) ((OFFS) & 0xFF)
+
+#define PCI_HT_HOST_OFFS LINK_OFFS( \
+ PCI_HT_CAP_HOST_WIDTH, \
+ PCI_HT_CAP_HOST_FREQ, \
+ PCI_HT_CAP_HOST_FREQ_CAP)
+
+#define PCI_HT_SLAVE0_OFFS LINK_OFFS( \
+ PCI_HT_CAP_SLAVE_WIDTH0, \
+ PCI_HT_CAP_SLAVE_FREQ0, \
+ PCI_HT_CAP_SLAVE_FREQ_CAP0)
+
+#define PCI_HT_SLAVE1_OFFS LINK_OFFS( \
+ PCI_HT_CAP_SLAVE_WIDTH1, \
+ PCI_HT_CAP_SLAVE_FREQ1, \
+ PCI_HT_CAP_SLAVE_FREQ_CAP1)
+
+static int ht_optimize_link(
+ device_t dev1, uint8_t pos1, unsigned offs1,
+ device_t dev2, uint8_t pos2, unsigned offs2)
+{
+ static const uint8_t link_width_to_pow2[]= { 3, 4, 0, 5, 1, 2, 0, 0 };
+ static const uint8_t pow2_to_link_width[] = { 0x7, 4, 5, 0, 1, 3 };
+ uint16_t freq_cap1, freq_cap2, freq_cap, freq_mask;
+ uint8_t width_cap1, width_cap2, width_cap, width, old_width, ln_width1, ln_width2;
+ uint8_t freq, old_freq;
+ int needs_reset;
+ /* Set link width and frequency */
+
+ /* Initially assume everything is already optimized and I don't need a reset */
+ needs_reset = 0;
+
+ /* Get the frequency capabilities */
+ freq_cap1 = ht_read_freq_cap(dev1, pos1 + LINK_FREQ_CAP(offs1));
+ freq_cap2 = ht_read_freq_cap(dev2, pos2 + LINK_FREQ_CAP(offs2));
+
+ /* Calculate the highest possible frequency */
+ freq = log2(freq_cap1 & freq_cap2);
+
+ /* See if I am changing the link freqency */
+ old_freq = pci_read_config8(dev1, pos1 + LINK_FREQ(offs1));
+ needs_reset |= old_freq != freq;
+ old_freq = pci_read_config8(dev2, pos2 + LINK_FREQ(offs2));
+ needs_reset |= old_freq != freq;
+
+ /* Set the Calulcated link frequency */
+ pci_write_config8(dev1, pos1 + LINK_FREQ(offs1), freq);
+ pci_write_config8(dev2, pos2 + LINK_FREQ(offs2), freq);
+
+ /* Get the width capabilities */
+ width_cap1 = pci_read_config8(dev1, pos1 + LINK_WIDTH(offs1));
+ width_cap2 = pci_read_config8(dev2, pos2 + LINK_WIDTH(offs2));
+
+ /* Calculate dev1's input width */
+ ln_width1 = link_width_to_pow2[width_cap1 & 7];
+ ln_width2 = link_width_to_pow2[(width_cap2 >> 4) & 7];
+ if (ln_width1 > ln_width2) {
+ ln_width1 = ln_width2;
+ }
+ width = pow2_to_link_width[ln_width1];
+ /* Calculate dev1's output width */
+ ln_width1 = link_width_to_pow2[(width_cap1 >> 4) & 7];
+ ln_width2 = link_width_to_pow2[width_cap2 & 7];
+ if (ln_width1 > ln_width2) {
+ ln_width1 = ln_width2;
+ }
+ width |= pow2_to_link_width[ln_width1] << 4;
+
+ /* See if I am changing dev1's width */
+ old_width = pci_read_config8(dev1, pos1 + LINK_WIDTH(offs1) + 1);
+ needs_reset |= old_width != width;
+
+ /* Set dev1's widths */
+ pci_write_config8(dev1, pos1 + LINK_WIDTH(offs1) + 1, width);
+
+ /* Calculate dev2's width */
+ width = ((width & 0x70) >> 4) | ((width & 0x7) << 4);
+
+ /* See if I am changing dev2's width */
+ old_width = pci_read_config8(dev2, pos2 + LINK_WIDTH(offs2) + 1);
+ needs_reset |= old_width != width;
+
+ /* Set dev2's widths */
+ pci_write_config8(dev2, pos2 + LINK_WIDTH(offs2) + 1, width);
+
+ return needs_reset;
+}
+
+static int ht_setup_chain(device_t udev, unsigned upos)
+{
+ /* Assumption the HT chain that is bus 0 has the HT I/O Hub on it.
+ * On most boards this just happens. If a cpu has multiple
+ * non Coherent links the appropriate bus registers for the
+ * links needs to be programed to point at bus 0.
+ */
+ unsigned next_unitid, last_unitid;
+ int reset_needed;
+ unsigned uoffs;
+
+#warning "FIXME handle multiple chains!"
+
+ /* Make certain the HT bus is not enumerated */
+ ht_collapse_previous_enumeration(0);
+
+ reset_needed = 0;
+ uoffs = PCI_HT_HOST_OFFS;
+ next_unitid = 1;
+ do {
+ uint32_t id;
+ uint8_t pos;
+ unsigned flags, count;
+ device_t dev = PCI_DEV(0, 0, 0);
+ last_unitid = next_unitid;
+
+ id = pci_read_config32(dev, PCI_VENDOR_ID);
+ /* If the chain is enumerated quit */
+ if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) ||
+ (((id >> 16) & 0xffff) == 0xffff) ||
+ (((id >> 16) & 0xffff) == 0x0000)) {
+ break;
+ }
+ pos = ht_lookup_slave_capability(dev);
+ if (!pos) {
+ print_err("HT link capability not found\r\n");
+ break;
+ }
+ /* Setup the Hypertransport link */
+ reset_needed |= ht_optimize_link(udev, upos, uoffs, dev, pos, PCI_HT_SLAVE0_OFFS);
+
+ /* Update the Unitid of the current device */
+ flags = pci_read_config16(dev, pos + PCI_CAP_FLAGS);
+ flags &= ~0x1f; /* mask out the bse Unit ID */
+ flags |= next_unitid & 0x1f;
+ pci_write_config16(dev, pos + PCI_CAP_FLAGS, flags);
+
+ /* Remeber the location of the last device */
+ udev = PCI_DEV(0, next_unitid, 0);
+ upos = pos;
+ uoffs = PCI_HT_SLAVE1_OFFS;
+
+ /* Compute the number of unitids consumed */
+ count = (flags >> 5) & 0x1f;
+ next_unitid += count;
+
+ } while((last_unitid != next_unitid) && (next_unitid <= 0x1f));
+ return reset_needed;
+}
diff --git a/src/northbridge/amd/amdk8/misc_control.c b/src/northbridge/amd/amdk8/misc_control.c
index fe797aa580..df28bd0331 100644
--- a/src/northbridge/amd/amdk8/misc_control.c
+++ b/src/northbridge/amd/amdk8/misc_control.c
@@ -14,21 +14,96 @@
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
+#include <part/hard_reset.h>
#include "./cpu_rev.c"
+#include "amdk8.h"
+
+#define IOMMU_APETURE_SIZE (64*1024*1024) /* 64M */
+static void mcf3_read_resources(device_t dev)
+{
+ struct resource *resource;
+ /* Read the generic PCI resources */
+ pci_dev_read_resources(dev);
+
+ /* If we are not the first processor don't allocate the gart apeture */
+ if (dev->path.u.pci.devfn != PCI_DEVFN(24, 3)) {
+ return;
+ }
+
+ /* Add a 64M Gart apeture resource */
+ if (dev->resources < MAX_RESOURCES) {
+ resource = &dev->resource[dev->resources];
+ dev->resources++;
+ resource->base = 0;
+ resource->size = IOMMU_APETURE_SIZE;
+ resource->align = log2(resource->size);
+ resource->gran = log2(resource->size);
+ resource->limit = 0xffffffff; /* 4G */
+ resource->flags = IORESOURCE_MEM;
+ resource->index = 0x94;
+ }
+ else {
+ printk_err("%s Unexpeted resource shortage\n", dev_path(dev));
+ }
+}
+
+static void mcf3_set_resources(device_t dev)
+{
+ struct resource *resource, *last;
+ last = &dev->resource[dev->resources];
+ for(resource = &dev->resource[0]; resource < last; resource++) {
+ if (resource->index == 0x94) {
+ device_t pdev;
+ uint32_t base;
+ uint32_t size;
+
+ size = (0<<6)|(0<<5)|(0<<4)|((log2(resource->size) - 25) << 1)|(0<<0);
+ base = ((resource->base) >> 25) & 0x00007fff;
+
+ pdev = 0;
+ while(pdev = dev_find_device(PCI_VENDOR_ID_AMD, 0x1103, pdev)) {
+ /* I want a 64M GART apeture */
+ pci_write_config32(pdev, 0x90, (0<<6)|(0<<5)|(0<<4)|(1<<1)|(0<<0));
+ /* Store the GART base address */
+ pci_write_config32(pdev, 0x94, base);
+ /* Don't set the GART Table base address */
+ pci_write_config32(pdev, 0x98, 0);
+
+ printk_debug(
+ "%s %02x <- [0x%08lx - 0x%08lx] mem <gart>\n",
+ dev_path(pdev),
+ resource->index,
+ resource->base, resource->base + resource->size - 1);
+ }
+ /* Remember this resource has been stored */
+ resource->flags |= IORESOURCE_STORED;
+
+ }
+ }
+ /* Set the generic PCI resources */
+ pci_dev_set_resources(dev);
+}
-static cpu_reset_count = 0;
static void misc_control_init(struct device *dev)
{
- uint32_t cmd;
+ uint32_t cmd, cmd_ref;
+ int needs_reset;
+ struct device *f0_dev, *f2_dev;
printk_debug("NB: Function 3 Misc Control.. ");
-
- /* disable error reporting */
+ needs_reset = 0;
+
+ /* Disable Machine checks from Invalid Locations.
+ * This is needed for PC backwards compatibility.
+ */
cmd = pci_read_config32(dev, 0x44);
cmd |= (1<<6) | (1<<25);
pci_write_config32(dev, 0x44, cmd );
if (is_cpu_pre_c0()) {
- /* errata 58 */
+
+ /* Errata 58
+ * Disable CPU low power states C2, C1 and throttling
+ */
cmd = pci_read_config32(dev, 0x80);
cmd &= ~(1<<0);
pci_write_config32(dev, 0x80, cmd );
@@ -36,62 +111,86 @@ static void misc_control_init(struct device *dev)
cmd &= ~(1<<24);
cmd &= ~(1<<8);
pci_write_config32(dev, 0x84, cmd );
- /* errata 66 */
+
+ /* Errata 66
+ * Limit the number of downstream posted requests to 1
+ */
cmd = pci_read_config32(dev, 0x70);
- cmd &= ~(1<<0);
- cmd |= (1<<1);
- pci_write_config32(dev, 0x70, cmd );
+ if ((cmd & (3 << 0)) != 2) {
+ cmd &= ~(3<<0);
+ cmd |= (2<<0);
+ pci_write_config32(dev, 0x70, cmd );
+ needs_reset = 1;
+ }
cmd = pci_read_config32(dev, 0x7c);
- cmd &= ~(3<<4);
- pci_write_config32(dev, 0x7c, cmd );
+ if ((cmd & (3 << 4)) != 0) {
+ cmd &= ~(3<<4);
+ cmd |= (0<<4);
+ pci_write_config32(dev, 0x7c, cmd );
+ needs_reset = 1;
+ }
+ /* Clock Power/Timing Low */
+ cmd = pci_read_config32(dev, 0xd4);
+ if (cmd != 0x000D0001) {
+ cmd = 0x000D0001;
+ pci_write_config32(dev, 0xd4, cmd);
+ needs_reset = 1; /* Needed? */
+ }
}
else {
- /* errata 98 */
-#if 0
+ uint32_t dcl;
+ f2_dev = dev_find_slot(0, dev->path.u.pci.devfn - 3 + 2);
+ /* Errata 98
+ * Set Clk Ramp Hystersis to 7
+ * Clock Power/Timing Low
+ */
+ cmd_ref = 0x04e20707; /* Registered */
+ dcl = pci_read_config32(f2_dev, DRAM_CONFIG_LOW);
+ if (dcl & DCL_UnBufDimm) {
+ cmd_ref = 0x000D0701; /* Unbuffered */
+ }
cmd = pci_read_config32(dev, 0xd4);
- if(cmd != 0x04e20707) {
- cmd = 0x04e20707;
- pci_write_config32(dev, 0xd4, cmd );
- hard_reset();
+ if(cmd != cmd_ref) {
+ pci_write_config32(dev, 0xd4, cmd_ref );
+ needs_reset = 1; /* Needed? */
}
-#endif
-
- cmd = 0x04e20707;
- pci_write_config32(dev, 0xd4, cmd );
}
-
-/*
- * FIXME: This preprocessor check is a mere workaround.
- * The right fix is to walk over all links on all nodes
- * and set the FIFO read pointer optimization value to
- * 0x25 for each link connected to an AMD HT device.
- *
- * The reason this is only enabled for machines with more
- * than one CPU is that Athlon64 machines don't have the
- * link at all that is optimized in the code.
- */
-
-#if CONFIG_MAX_CPUS > 1
-#if HAVE_HARD_RESET==1
- cpu_reset_count++;
- cmd = pci_read_config32(dev, 0xdc);
- if((cmd & 0x0000ff00) != 0x02500) {
- cmd &= 0xffff00ff;
- cmd |= 0x00002500;
- pci_write_config32(dev, 0xdc, cmd );
- if(cpu_reset_count==CONFIG_MAX_CPUS) {
- printk_debug("resetting cpu\n");
- hard_reset();
+ /* Optimize the Link read pointers */
+ f0_dev = dev_find_slot(0, dev->path.u.pci.devfn - 3);
+ if (f0_dev) {
+ int link;
+ cmd_ref = cmd = pci_read_config32(dev, 0xdc);
+ for(link = 0; link < 3; link++) {
+ uint32_t link_type;
+ unsigned reg;
+ /* This works on an Athlon64 because unimplemented links return 0 */
+ reg = 0x98 + (link * 0x20);
+ link_type = pci_read_config32(f0_dev, reg);
+ if (link_type & LinkConnected) {
+ cmd &= 0xff << (link *8);
+ /* FIXME this assumes the device on the other side is an AMD device */
+ cmd |= 0x25 << (link *8);
+ }
+ }
+ if (cmd != cmd_ref) {
+ pci_write_config32(dev, 0xdc, cmd);
+ needs_reset = 1;
}
- }
-#endif
-#endif
+ }
+ else {
+ printk_err("Missing f0 device!\n");
+ }
+ if (needs_reset) {
+ printk_debug("resetting cpu\n");
+ hard_reset();
+ }
printk_debug("done.\n");
}
+
static struct device_operations mcf3_ops = {
- .read_resources = pci_dev_read_resources,
- .set_resources = pci_dev_set_resources,
+ .read_resources = mcf3_read_resources,
+ .set_resources = mcf3_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = misc_control_init,
.scan_bus = 0,
@@ -102,4 +201,3 @@ static struct pci_driver mcf3_driver __pci_driver = {
.vendor = PCI_VENDOR_ID_AMD,
.device = 0x1103,
};
-
diff --git a/src/northbridge/amd/amdk8/northbridge.c b/src/northbridge/amd/amdk8/northbridge.c
index e62aded451..12d8f73c0b 100644
--- a/src/northbridge/amd/amdk8/northbridge.c
+++ b/src/northbridge/amd/amdk8/northbridge.c
@@ -38,7 +38,7 @@ struct mem_range *sizeram(void)
mmio_basek &= ~((256*1024) - 1);
#endif
-#if 1
+#if 0
printk_debug("mmio_base: %dKB\n", mmio_basek);
#endif
@@ -383,8 +383,14 @@ static void amdk8_set_resource(device_t dev, struct resource *resource, unsigned
{
unsigned long rbase, rlimit;
unsigned reg, link;
+
/* Make certain the resource has actually been set */
- if (!(resource->flags & IORESOURCE_SET)) {
+ if (!(resource->flags & IORESOURCE_ASSIGNED)) {
+ return;
+ }
+
+ /* If I have already stored this resource don't worry about it */
+ if (resource->flags & IORESOURCE_STORED) {
return;
}
@@ -401,7 +407,7 @@ static void amdk8_set_resource(device_t dev, struct resource *resource, unsigned
/* Get the register and link */
reg = resource->index & ~3;
link = resource->index & 3;
-
+
if (resource->flags & IORESOURCE_IO) {
uint32_t base, limit;
compute_allocate_resource(&dev->link[link], resource,
@@ -415,13 +421,14 @@ static void amdk8_set_resource(device_t dev, struct resource *resource, unsigned
limit |= rlimit & 0x01fff000;
limit |= (link & 3) << 4;
limit |= (nodeid & 7);
- if (reg == 0xc8){
- /* hack to set vga for test */
- /* factory: b0: 03 0a 00 00 00 0b 00 00 */
- f1_write_config32(0xb0, 0xa03);
- f1_write_config32(0xb4, 0xb00);
- base |= 0x30;
+
+ if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA) {
+ base |= PCI_IO_BASE_VGA_EN;
+ }
+ if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_NO_ISA) {
+ base |= PCI_IO_BASE_NO_ISA;
}
+
f1_write_config32(reg + 0x4, limit);
f1_write_config32(reg, base);
}
@@ -441,6 +448,7 @@ static void amdk8_set_resource(device_t dev, struct resource *resource, unsigned
f1_write_config32(reg + 0x4, limit);
f1_write_config32(reg, base);
}
+ resource->flags |= IORESOURCE_STORED;
printk_debug(
"%s %02x <- [0x%08lx - 0x%08lx] node %d link %d %s\n",
dev_path(dev),
@@ -483,51 +491,46 @@ unsigned int amdk8_scan_root_bus(device_t root, unsigned int max)
return max;
}
-void amdk8_enable_resources(struct device *dev)
+static void mcf0_control_init(struct device *dev)
{
- uint16_t ctrl;
- unsigned link;
- unsigned int vgalink = -1;
-
- ctrl = pci_read_config16(dev, PCI_BRIDGE_CONTROL);
- ctrl |= dev->link[0].bridge_ctrl;
- printk_debug("%s bridge ctrl <- %04x\n", dev_path(dev), ctrl);
- printk_err("%s bridge ctrl <- %04x\n", dev_path(dev), ctrl);
- pci_write_config16(dev, PCI_BRIDGE_CONTROL, ctrl);
-
-#if 0
- /* let's see what link VGA is on */
- for(link = 0; link < dev->links; link++) {
- device_t child;
- printk_err("Kid %d of k8: bridge ctrl says: 0x%x\n", link, dev->link[link].bridge_ctrl);
- if (dev->link[link].bridge_ctrl & PCI_BRIDGE_CTL_VGA)
- vgalink = link;
- }
-
- if (vgalink != =1) {
- /* now find the IOPAIR that goes to vgalink and set the vga enable in the base part (0x30) */
- /* now allocate an MMIOPAIR and point it to the CPU0, LINK=vgalink */
- /* now set IORR1 so it has a hole for the 0xa0000-0xcffff region */
- }
+ uint32_t cmd;
+
+#if 1
+ printk_debug("NB: Function 0 Misc Control.. ");
+ /* improve latency and bandwith on HT */
+ cmd = pci_read_config32(dev, 0x68);
+ cmd &= 0xffff80ff;
+ cmd |= 0x00004800;
+ pci_write_config32(dev, 0x68, cmd );
#endif
- pci_dev_enable_resources(dev);
- //enable_childrens_resources(dev);
+#if 0
+ /* over drive the ht port to 1000 Mhz */
+ cmd = pci_read_config32(dev, 0xa8);
+ cmd &= 0xfffff0ff;
+ cmd |= 0x00000600;
+ pci_write_config32(dev, 0xdc, cmd );
+#endif
+ printk_debug("done.\n");
}
-
-
static struct device_operations northbridge_operations = {
.read_resources = amdk8_read_resources,
.set_resources = amdk8_set_resources,
-// .enable_resources = pci_dev_enable_resources,
- .enable_resources = amdk8_enable_resources,
- .init = 0,
+ .enable_resources = pci_dev_enable_resources,
+ .init = mcf0_control_init,
.scan_bus = amdk8_scan_chains,
.enable = 0,
};
+static struct pci_driver mcf0_driver __pci_driver = {
+ .ops = &northbridge_operations,
+ .vendor = PCI_VENDOR_ID_AMD,
+ .device = 0x1100,
+};
+
+
static void enumerate(struct chip *chip)
{
chip_enumerate(chip);
@@ -538,4 +541,3 @@ struct chip_control northbridge_amd_amdk8_control = {
.name = "AMD K8 Northbridge",
.enumerate = enumerate,
};
-
diff --git a/src/northbridge/amd/amdk8/raminit.c b/src/northbridge/amd/amdk8/raminit.c
index 006ab196df..bc73fcba16 100644
--- a/src/northbridge/amd/amdk8/raminit.c
+++ b/src/northbridge/amd/amdk8/raminit.c
@@ -1,202 +1,21 @@
#include <cpu/k8/mtrr.h>
#include "raminit.h"
+#include "amdk8.h"
-#define ENABLE_IOMMU 1
-
-/* Function 2 */
-#define DRAM_CSBASE 0x40
-#define DRAM_CSMASK 0x60
-#define DRAM_BANK_ADDR_MAP 0x80
-#define DRAM_TIMING_LOW 0x88
-#define DTL_TCL_SHIFT 0
-#define DTL_TCL_MASK 0x7
-#define DTL_CL_2 1
-#define DTL_CL_3 2
-#define DTL_CL_2_5 5
-#define DTL_TRC_SHIFT 4
-#define DTL_TRC_MASK 0xf
-#define DTL_TRC_BASE 7
-#define DTL_TRC_MIN 7
-#define DTL_TRC_MAX 22
-#define DTL_TRFC_SHIFT 8
-#define DTL_TRFC_MASK 0xf
-#define DTL_TRFC_BASE 9
-#define DTL_TRFC_MIN 9
-#define DTL_TRFC_MAX 24
-#define DTL_TRCD_SHIFT 12
-#define DTL_TRCD_MASK 0x7
-#define DTL_TRCD_BASE 0
-#define DTL_TRCD_MIN 2
-#define DTL_TRCD_MAX 6
-#define DTL_TRRD_SHIFT 16
-#define DTL_TRRD_MASK 0x7
-#define DTL_TRRD_BASE 0
-#define DTL_TRRD_MIN 2
-#define DTL_TRRD_MAX 4
-#define DTL_TRAS_SHIFT 20
-#define DTL_TRAS_MASK 0xf
-#define DTL_TRAS_BASE 0
-#define DTL_TRAS_MIN 5
-#define DTL_TRAS_MAX 15
-#define DTL_TRP_SHIFT 24
-#define DTL_TRP_MASK 0x7
-#define DTL_TRP_BASE 0
-#define DTL_TRP_MIN 2
-#define DTL_TRP_MAX 6
-#define DTL_TWR_SHIFT 28
-#define DTL_TWR_MASK 0x1
-#define DTL_TWR_BASE 2
-#define DTL_TWR_MIN 2
-#define DTL_TWR_MAX 3
-#define DRAM_TIMING_HIGH 0x8c
-#define DTH_TWTR_SHIFT 0
-#define DTH_TWTR_MASK 0x1
-#define DTH_TWTR_BASE 1
-#define DTH_TWTR_MIN 1
-#define DTH_TWTR_MAX 2
-#define DTH_TRWT_SHIFT 4
-#define DTH_TRWT_MASK 0x7
-#define DTH_TRWT_BASE 1
-#define DTH_TRWT_MIN 1
-#define DTH_TRWT_MAX 6
-#define DTH_TREF_SHIFT 8
-#define DTH_TREF_MASK 0x1f
-#define DTH_TREF_100MHZ_4K 0x00
-#define DTH_TREF_133MHZ_4K 0x01
-#define DTH_TREF_166MHZ_4K 0x02
-#define DTH_TREF_200MHZ_4K 0x03
-#define DTH_TREF_100MHZ_8K 0x08
-#define DTH_TREF_133MHZ_8K 0x09
-#define DTH_TREF_166MHZ_8K 0x0A
-#define DTH_TREF_200MHZ_8K 0x0B
-#define DTH_TWCL_SHIFT 20
-#define DTH_TWCL_MASK 0x7
-#define DTH_TWCL_BASE 1
-#define DTH_TWCL_MIN 1
-#define DTH_TWCL_MAX 2
-#define DRAM_CONFIG_LOW 0x90
-#define DCL_DLL_Disable (1<<0)
-#define DCL_D_DRV (1<<1)
-#define DCL_QFC_EN (1<<2)
-#define DCL_DisDqsHys (1<<3)
-#define DCL_DramInit (1<<8)
-#define DCL_DramEnable (1<<10)
-#define DCL_MemClrStatus (1<<11)
-#define DCL_ESR (1<<12)
-#define DCL_SRS (1<<13)
-#define DCL_128BitEn (1<<16)
-#define DCL_DimmEccEn (1<<17)
-#define DCL_UnBufDimm (1<<18)
-#define DCL_32ByteEn (1<<19)
-#define DCL_x4DIMM_SHIFT 20
-#define DRAM_CONFIG_HIGH 0x94
-#define DCH_ASYNC_LAT_SHIFT 0
-#define DCH_ASYNC_LAT_MASK 0xf
-#define DCH_ASYNC_LAT_BASE 0
-#define DCH_ASYNC_LAT_MIN 0
-#define DCH_ASYNC_LAT_MAX 15
-#define DCH_RDPREAMBLE_SHIFT 8
-#define DCH_RDPREAMBLE_MASK 0xf
-#define DCH_RDPREAMBLE_BASE ((2<<1)+0) /* 2.0 ns */
-#define DCH_RDPREAMBLE_MIN ((2<<1)+0) /* 2.0 ns */
-#define DCH_RDPREAMBLE_MAX ((9<<1)+1) /* 9.5 ns */
-#define DCH_IDLE_LIMIT_SHIFT 16
-#define DCH_IDLE_LIMIT_MASK 0x7
-#define DCH_IDLE_LIMIT_0 0
-#define DCH_IDLE_LIMIT_4 1
-#define DCH_IDLE_LIMIT_8 2
-#define DCH_IDLE_LIMIT_16 3
-#define DCH_IDLE_LIMIT_32 4
-#define DCH_IDLE_LIMIT_64 5
-#define DCH_IDLE_LIMIT_128 6
-#define DCH_IDLE_LIMIT_256 7
-#define DCH_DYN_IDLE_CTR_EN (1 << 19)
-#define DCH_MEMCLK_SHIFT 20
-#define DCH_MEMCLK_MASK 0x7
-#define DCH_MEMCLK_100MHZ 0
-#define DCH_MEMCLK_133MHZ 2
-#define DCH_MEMCLK_166MHZ 5
-#define DCH_MEMCLK_200MHZ 7
-#define DCH_MEMCLK_VALID (1 << 25)
-#define DCH_MEMCLK_EN0 (1 << 26)
-#define DCH_MEMCLK_EN1 (1 << 27)
-#define DCH_MEMCLK_EN2 (1 << 28)
-#define DCH_MEMCLK_EN3 (1 << 29)
-
-/* Function 3 */
-#define MCA_NB_CONFIG 0x44
-#define MNC_ECC_EN (1 << 22)
-#define MNC_CHIPKILL_EN (1 << 23)
-#define SCRUB_CONTROL 0x58
-#define SCRUB_NONE 0
-#define SCRUB_40ns 1
-#define SCRUB_80ns 2
-#define SCRUB_160ns 3
-#define SCRUB_320ns 4
-#define SCRUB_640ns 5
-#define SCRUB_1_28us 6
-#define SCRUB_2_56us 7
-#define SCRUB_5_12us 8
-#define SCRUB_10_2us 9
-#define SCRUB_20_5us 10
-#define SCRUB_41_0us 11
-#define SCRUB_81_9us 12
-#define SCRUB_163_8us 13
-#define SCRUB_327_7us 14
-#define SCRUB_655_4us 15
-#define SCRUB_1_31ms 16
-#define SCRUB_2_62ms 17
-#define SCRUB_5_24ms 18
-#define SCRUB_10_49ms 19
-#define SCRUB_20_97ms 20
-#define SCRUB_42ms 21
-#define SCRUB_84ms 22
-#define SC_DRAM_SCRUB_RATE_SHFIT 0
-#define SC_DRAM_SCRUB_RATE_MASK 0x1f
-#define SC_L2_SCRUB_RATE_SHIFT 8
-#define SC_L2_SCRUB_RATE_MASK 0x1f
-#define SC_L1D_SCRUB_RATE_SHIFT 16
-#define SC_L1D_SCRUB_RATE_MASK 0x1f
-#define SCRUB_ADDR_LOW 0x5C
-#define SCRUB_ADDR_HIGH 0x60
-#define NORTHBRIDGE_CAP 0xE8
-#define NBCAP_128Bit 0x0001
-#define NBCAP_MP 0x0002
-#define NBCAP_BIG_MP 0x0004
-#define NBCAP_ECC 0x0004
-#define NBCAP_CHIPKILL_ECC 0x0010
-#define NBCAP_MEMCLK_SHIFT 5
-#define NBCAP_MEMCLK_MASK 3
-#define NBCAP_MEMCLK_100MHZ 3
-#define NBCAP_MEMCLK_133MHZ 2
-#define NBCAP_MEMCLK_166MHZ 1
-#define NBCAP_MEMCLK_200MHZ 0
-#define NBCAP_MEMCTRL 0x0100
-
-
+#if (CONFIG_LB_MEM_TOPK & (CONFIG_LB_MEM_TOPK -1)) != 0
+# error "CONFIG_LB_MEM_TOPK must be a power of 2"
+#endif
static void setup_resource_map(const unsigned int *register_values, int max)
{
int i;
-
- unsigned int amd8111_link_nr;
-
- print_debug("setting up resource map....\r\n");
- /*
- * determine the HT link number the southbridge is connected to
- * bits 8-9 of the Unit ID register
- */
- amd8111_link_nr = (pci_read_config32(PCI_DEV(0, 0x18, 0), 0x64) & 0x00000300) >> 8;
- print_debug(" AMD8111 southbridge is connected to HT link ");
- print_debug_hex32(amd8111_link_nr);
- print_debug("\r\n");
-
-
- print_debug("setting up resource map....\r\n");
+ print_debug("setting up resource map....");
+#if 0
+ print_debug("\r\n");
+#endif
for(i = 0; i < max; i += 3) {
device_t dev;
unsigned where;
unsigned long reg;
-
#if 0
print_debug_hex32(register_values[i]);
print_debug(" <-");
@@ -208,19 +27,6 @@ static void setup_resource_map(const unsigned int *register_values, int max)
reg = pci_read_config32(dev, where);
reg &= register_values[i+1];
reg |= register_values[i+2];
-
- /*
- * set correct HT link to the southbridge
- * otherwise we cut of the acces to the flash we are from
- *
- */
- if (where == 0xBC)
- reg |= amd8111_link_nr << 4;
- if (where == 0xC4)
- reg |= amd8111_link_nr << 4;
- if (where == 0xE0)
- reg |= amd8111_link_nr << 8;
-
pci_write_config32(dev, where, reg);
#if 0
reg = pci_read_config32(register_values[i]);
@@ -952,29 +758,22 @@ static void sdram_set_registers(const struct mem_controller *ctrl)
* [31: 8] Reserved
*/
PCI_ADDR(0, 0x18, 3, 0x60), 0xffffff00, 0x00000000,
-
-#if ENABLE_IOMMU != 0
- /* BY LYH add IOMMU 64M APERTURE */
- PCI_ADDR(0, 0x18, 3, 0x94), 0xffff8000, 0x00000f70,
- PCI_ADDR(0, 0x18, 3, 0x90), 0xffffff80, 0x00000002,
- PCI_ADDR(0, 0x18, 3, 0x98), 0x0000000f, 0x00068300,
-#endif
};
int i;
int max;
- print_debug("setting up CPU");
- print_debug_hex8(ctrl->node_id);
- print_debug(" northbridge registers\r\n");
+ print_spew("setting up CPU");
+ print_spew_hex8(ctrl->node_id);
+ print_spew(" northbridge registers\r\n");
max = sizeof(register_values)/sizeof(register_values[0]);
for(i = 0; i < max; i += 3) {
device_t dev;
unsigned where;
unsigned long reg;
#if 0
- print_debug_hex32(register_values[i]);
- print_debug(" <-");
- print_debug_hex32(register_values[i+2]);
- print_debug("\r\n");
+ print_spew_hex32(register_values[i]);
+ print_spew(" <-");
+ print_spew_hex32(register_values[i+2]);
+ print_spew("\r\n");
#endif
dev = (register_values[i] & ~0xff) - PCI_DEV(0, 0x18, 0) + ctrl->f0;
where = register_values[i] & 0xff;
@@ -990,10 +789,26 @@ static void sdram_set_registers(const struct mem_controller *ctrl)
pci_write_config32(register_values[i], reg);
#endif
}
- print_debug("done.\r\n");
+ print_spew("done.\r\n");
}
+static void hw_enable_ecc(const struct mem_controller *ctrl)
+{
+ uint32_t dcl, nbcap;
+ nbcap = pci_read_config32(ctrl->f3, NORTHBRIDGE_CAP);
+ dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW);
+ dcl &= ~DCL_DimmEccEn;
+ if (nbcap & NBCAP_ECC) {
+ dcl |= DCL_DimmEccEn;
+ }
+ if (read_option(CMOS_VSTART_ECC_memory, CMOS_VLEN_ECC_memory, 1) == 0) {
+ dcl &= ~DCL_DimmEccEn;
+ }
+ pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl);
+
+}
+
static int is_dual_channel(const struct mem_controller *ctrl)
{
uint32_t dcl;
@@ -1042,46 +857,60 @@ static struct dimm_size spd_get_dimm_size(unsigned device)
* sides of an assymetric dimm.
*/
value = spd_read_byte(device, 3); /* rows */
- if (value < 0) goto out;
+ if (value < 0) goto hw_err;
+ if ((value & 0xf) == 0) goto val_err;
sz.side1 += value & 0xf;
value = spd_read_byte(device, 4); /* columns */
- if (value < 0) goto out;
+ if (value < 0) goto hw_err;
+ if ((value & 0xf) == 0) goto val_err;
sz.side1 += value & 0xf;
value = spd_read_byte(device, 17); /* banks */
- if (value < 0) goto out;
+ if (value < 0) goto hw_err;
+ if ((value & 0xff) == 0) goto val_err;
sz.side1 += log2(value & 0xff);
/* Get the module data width and convert it to a power of two */
value = spd_read_byte(device, 7); /* (high byte) */
- if (value < 0) goto out;
+ if (value < 0) goto hw_err;
value &= 0xff;
value <<= 8;
low = spd_read_byte(device, 6); /* (low byte) */
- if (low < 0) goto out;
+ if (low < 0) goto hw_err;
value = value | (low & 0xff);
+ if ((value != 72) && (value &= 64)) goto val_err;
sz.side1 += log2(value);
/* side 2 */
value = spd_read_byte(device, 5); /* number of physical banks */
- if (value <= 1) goto out;
+ if (value < 0) goto hw_err;
+ if (value == 1) goto out;
+ if (value != 2) goto val_err;
/* Start with the symmetrical case */
sz.side2 = sz.side1;
value = spd_read_byte(device, 3); /* rows */
- if (value < 0) goto out;
+ if (value < 0) goto hw_err;
if ((value & 0xf0) == 0) goto out; /* If symmetrical we are done */
sz.side2 -= (value & 0x0f); /* Subtract out rows on side 1 */
sz.side2 += ((value >> 4) & 0x0f); /* Add in rows on side 2 */
value = spd_read_byte(device, 4); /* columns */
- if (value < 0) goto out;
+ if (value < 0) goto hw_err;
+ if ((value & 0xff) == 0) goto val_err;
sz.side2 -= (value & 0x0f); /* Subtract out columns on side 1 */
sz.side2 += ((value >> 4) & 0x0f); /* Add in columsn on side 2 */
+ goto out;
+ val_err:
+ die("Bad SPD value\r\n");
+ /* If an hw_error occurs report that I have no memory */
+hw_err:
+ sz.side1 = 0;
+ sz.side2 = 0;
out:
return sz;
}
@@ -1091,15 +920,6 @@ static void set_dimm_size(const struct mem_controller *ctrl, struct dimm_size sz
uint32_t base0, base1, map;
uint32_t dch;
-#if 0
- print_debug("set_dimm_size: (");
- print_debug_hex32(sz.side1);
- print_debug_char(',');
- print_debug_hex32(sz.side2);
- print_debug_char(',');
- print_debug_hex32(index);
- print_debug(")\r\n");
-#endif
if (sz.side1 != sz.side2) {
sz.side2 = 0;
}
@@ -1147,15 +967,22 @@ static void set_dimm_size(const struct mem_controller *ctrl, struct dimm_size sz
}
}
-static void spd_set_ram_size(const struct mem_controller *ctrl)
+static long spd_set_ram_size(const struct mem_controller *ctrl, long dimm_mask)
{
int i;
- for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
+ for(i = 0; i < DIMM_SOCKETS; i++) {
struct dimm_size sz;
+ if (!(dimm_mask & (1 << i))) {
+ continue;
+ }
sz = spd_get_dimm_size(ctrl->channel0[i]);
+ if (sz.side1 == 0) {
+ return -1; /* Report SPD error */
+ }
set_dimm_size(ctrl, sz, i);
}
+ return dimm_mask;
}
static void route_dram_accesses(const struct mem_controller *ctrl,
@@ -1191,20 +1018,13 @@ static void set_top_mem(unsigned tom_k)
{
/* Error if I don't have memory */
if (!tom_k) {
- set_bios_reset();
- print_debug("No memory - reset");
- /* enable cf9 */
- pci_write_config8(PCI_DEV(0, 0x04, 3), 0x41, 0xf1);
- /* reset */
- outb(0x0e, 0x0cf9);
+ die("No memory?");
}
-#if 1
/* Report the amount of memory. */
- print_debug("RAM: 0x");
- print_debug_hex32(tom_k);
- print_debug(" KB\r\n");
-#endif
+ print_spew("RAM: 0x");
+ print_spew_hex32(tom_k);
+ print_spew(" KB\r\n");
/* Now set top of memory */
msr_t msr;
@@ -1238,7 +1058,6 @@ static unsigned long interleave_chip_selects(const struct mem_controller *ctrl)
uint32_t csbase_inc;
int chip_selects, index;
int bits;
- int dual_channel;
unsigned common_size;
uint32_t csbase, csmask;
@@ -1306,9 +1125,8 @@ static unsigned long interleave_chip_selects(const struct mem_controller *ctrl)
csbase += csbase_inc;
}
-#if 1
- print_debug("Interleaved\r\n");
-#endif
+ print_spew("Interleaved\r\n");
+
/* Return the memory size in K */
return common_size << (15 + bits);
}
@@ -1368,7 +1186,6 @@ static unsigned long order_chip_selects(const struct mem_controller *ctrl)
/* Compute the memory mask */
csmask = ((size -1) << 21);
csmask |= 0xfe00; /* For now don't optimize */
-#warning "Don't forget to optimize the DIMM size"
/* Write the new base register */
pci_write_config32(ctrl->f2, DRAM_CSBASE + (canidate << 2), csbase);
@@ -1380,18 +1197,13 @@ static unsigned long order_chip_selects(const struct mem_controller *ctrl)
return (tom & ~0xff000000) << 15;
}
-static void order_dimms(const struct mem_controller *ctrl)
+unsigned long memory_end_k(const struct mem_controller *ctrl, int max_node_id)
{
- unsigned long tom, tom_k, base_k;
unsigned node_id;
-
- tom_k = interleave_chip_selects(ctrl);
- if (!tom_k) {
- tom_k = order_chip_selects(ctrl);
- }
- /* Compute the memory base address */
- base_k = 0;
- for(node_id = 0; node_id < ctrl->node_id; node_id++) {
+ unsigned end_k;
+ /* Find the last memory address used */
+ end_k = 0;
+ for(node_id = 0; node_id < max_node_id; node_id++) {
uint32_t limit, base;
unsigned index;
index = node_id << 3;
@@ -1399,32 +1211,44 @@ static void order_dimms(const struct mem_controller *ctrl)
/* Only look at the limit if the base is enabled */
if ((base & 3) == 3) {
limit = pci_read_config32(ctrl->f1, 0x44 + index);
- base_k = ((limit + 0x00010000) & 0xffff0000) >> 2;
+ end_k = ((limit + 0x00010000) & 0xffff0000) >> 2;
}
}
+ return end_k;
+}
+
+static void order_dimms(const struct mem_controller *ctrl)
+{
+ unsigned long tom_k, base_k;
+
+ if (read_option(CMOS_VSTART_interleave_chip_selects, CMOS_VLEN_interleave_chip_selects, 1) != 0) {
+ tom_k = interleave_chip_selects(ctrl);
+ } else {
+ print_debug("Interleaving disabled\r\n");
+ tom_k = 0;
+ }
+ if (!tom_k) {
+ tom_k = order_chip_selects(ctrl);
+ }
+ /* Compute the memory base address */
+ base_k = memory_end_k(ctrl, ctrl->node_id);
tom_k += base_k;
-#if 0
- print_debug("base_k: ");
- print_debug_hex32(base_k);
- print_debug(" tom_k: ");
- print_debug_hex32(tom_k);
- print_debug("\r\n");
-#endif
route_dram_accesses(ctrl, base_k, tom_k);
set_top_mem(tom_k);
}
-static void disable_dimm(const struct mem_controller *ctrl, unsigned index)
+static long disable_dimm(const struct mem_controller *ctrl, unsigned index, long dimm_mask)
{
print_debug("disabling dimm");
print_debug_hex8(index);
print_debug("\r\n");
pci_write_config32(ctrl->f2, DRAM_CSBASE + (((index << 1)+0)<<2), 0);
pci_write_config32(ctrl->f2, DRAM_CSBASE + (((index << 1)+1)<<2), 0);
+ dimm_mask &= ~(1 << index);
+ return dimm_mask;
}
-
-static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl)
+static long spd_handle_unbuffered_dimms(const struct mem_controller *ctrl, long dimm_mask)
{
int i;
int registered;
@@ -1432,12 +1256,14 @@ static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl)
uint32_t dcl;
unbuffered = 0;
registered = 0;
- for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
+ for(i = 0; (i < DIMM_SOCKETS); i++) {
int value;
+ if (!(dimm_mask & (1 << i))) {
+ continue;
+ }
value = spd_read_byte(ctrl->channel0[i], 21);
if (value < 0) {
- disable_dimm(ctrl, i);
- continue;
+ return -1;
}
/* Registered dimm ? */
if (value & (1 << 1)) {
@@ -1468,15 +1294,40 @@ static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl)
print_debug("Unbuffered\r\n");
}
#endif
+ return dimm_mask;
}
-static void spd_enable_2channels(const struct mem_controller *ctrl)
+static unsigned int spd_detect_dimms(const struct mem_controller *ctrl)
+{
+ unsigned dimm_mask;
+ int i;
+ dimm_mask = 0;
+ for(i = 0; i < DIMM_SOCKETS; i++) {
+ int byte;
+ unsigned device;
+ device = ctrl->channel0[i];
+ if (device) {
+ byte = spd_read_byte(ctrl->channel0[i], 2); /* Type */
+ if (byte == 7) {
+ dimm_mask |= (1 << i);
+ }
+ }
+ device = ctrl->channel1[i];
+ if (device) {
+ byte = spd_read_byte(ctrl->channel1[i], 2);
+ if (byte == 7) {
+ dimm_mask |= (1 << (i + DIMM_SOCKETS));
+ }
+ }
+ }
+ return dimm_mask;
+}
+
+static long spd_enable_2channels(const struct mem_controller *ctrl, long dimm_mask)
{
int i;
uint32_t nbcap;
/* SPD addresses to verify are identical */
-#warning "FINISHME review and see if these are the bytes I need"
- /* FINISHME review and see if these are the bytes I need */
static const unsigned addresses[] = {
2, /* Type should be DDR SDRAM */
3, /* *Row addresses */
@@ -1499,40 +1350,52 @@ static void spd_enable_2channels(const struct mem_controller *ctrl)
41, /* *Minimum Active to Active/Auto Refresh Time(Trc) */
42, /* *Minimum Auto Refresh Command Time(Trfc) */
};
+ /* If the dimms are not in pairs do not do dual channels */
+ if ((dimm_mask & ((1 << DIMM_SOCKETS) - 1)) !=
+ ((dimm_mask >> DIMM_SOCKETS) & ((1 << DIMM_SOCKETS) - 1))) {
+ goto single_channel;
+ }
+ /* If the cpu is not capable of doing dual channels don't do dual channels */
nbcap = pci_read_config32(ctrl->f3, NORTHBRIDGE_CAP);
if (!(nbcap & NBCAP_128Bit)) {
- return;
+ goto single_channel;
}
for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
unsigned device0, device1;
int value0, value1;
int j;
+ /* If I don't have a dimm skip this one */
+ if (!(dimm_mask & (1 << i))) {
+ continue;
+ }
device0 = ctrl->channel0[i];
device1 = ctrl->channel1[i];
- if (!device1)
- return;
for(j = 0; j < sizeof(addresses)/sizeof(addresses[0]); j++) {
unsigned addr;
addr = addresses[j];
value0 = spd_read_byte(device0, addr);
if (value0 < 0) {
- break;
+ return -1;
}
value1 = spd_read_byte(device1, addr);
if (value1 < 0) {
- return;
+ return -1;
}
if (value0 != value1) {
- return;
+ goto single_channel;
}
}
}
- print_debug("Enabling dual channel memory\r\n");
+ print_spew("Enabling dual channel memory\r\n");
uint32_t dcl;
dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW);
dcl &= ~DCL_32ByteEn;
dcl |= DCL_128BitEn;
pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl);
+ return dimm_mask;
+ single_channel:
+ dimm_mask &= ~((1 << (DIMM_SOCKETS *2)) - (1 << DIMM_SOCKETS));
+ return dimm_mask;
}
struct mem_param {
@@ -1606,17 +1469,22 @@ static const struct mem_param *get_mem_param(unsigned min_cycle_time)
if (!param->cycle_time) {
die("min_cycle_time to low");
}
-#if 1
+ print_spew(param->name);
+#ifdef DRAM_MIN_CYCLE_TIME
print_debug(param->name);
#endif
return param;
}
-static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
+struct spd_set_memclk_result {
+ const struct mem_param *param;
+ long dimm_mask;
+};
+static struct spd_set_memclk_result spd_set_memclk(const struct mem_controller *ctrl, long dimm_mask)
{
/* Compute the minimum cycle time for these dimms */
- const struct mem_param *param;
- unsigned min_cycle_time, min_latency;
+ struct spd_set_memclk_result result;
+ unsigned min_cycle_time, min_latency, bios_cycle_time;
int i;
uint32_t value;
@@ -1631,25 +1499,26 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
value = pci_read_config32(ctrl->f3, NORTHBRIDGE_CAP);
min_cycle_time = min_cycle_times[(value >> NBCAP_MEMCLK_SHIFT) & NBCAP_MEMCLK_MASK];
+ bios_cycle_time = min_cycle_times[
+ read_option(CMOS_VSTART_max_mem_clock, CMOS_VLEN_max_mem_clock, 0)];
+ if (bios_cycle_time > min_cycle_time) {
+ min_cycle_time = bios_cycle_time;
+ }
min_latency = 2;
-#if 0
- print_debug("min_cycle_time: ");
- print_debug_hex8(min_cycle_time);
- print_debug(" min_latency: ");
- print_debug_hex8(min_latency);
- print_debug("\r\n");
-#endif
-
/* Compute the least latency with the fastest clock supported
* by both the memory controller and the dimms.
*/
- for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
+ for(i = 0; i < DIMM_SOCKETS; i++) {
int new_cycle_time, new_latency;
int index;
int latencies;
int latency;
+ if (!(dimm_mask & (1 << i))) {
+ continue;
+ }
+
/* First find the supported CAS latencies
* Byte 18 for DDR SDRAM is interpreted:
* bit 0 == CAS Latency = 1.0
@@ -1679,7 +1548,7 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
}
value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
if (value < 0) {
- continue;
+ goto hw_error;
}
/* Only increase the latency if we decreas the clock */
@@ -1699,15 +1568,6 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
if (new_latency > min_latency) {
min_latency = new_latency;
}
-#if 0
- print_debug("i: ");
- print_debug_hex8(i);
- print_debug(" min_cycle_time: ");
- print_debug_hex8(min_cycle_time);
- print_debug(" min_latency: ");
- print_debug_hex8(min_latency);
- print_debug("\r\n");
-#endif
}
/* Make a second pass through the dimms and disable
* any that cannot support the selected memclk and cas latency.
@@ -1718,9 +1578,12 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
int latency;
int index;
int value;
- int dimm;
+ if (!(dimm_mask & (1 << i))) {
+ continue;
+ }
latencies = spd_read_byte(ctrl->channel0[i], 18);
- if (latencies <= 0) {
+ if (latencies < 0) goto hw_error;
+ if (latencies == 0) {
goto dimm_err;
}
@@ -1742,6 +1605,7 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
/* Read the min_cycle_time for this latency */
value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
+ if (value < 0) goto hw_error;
/* All is good if the selected clock speed
* is what I need or slower.
@@ -1751,22 +1615,15 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
}
/* Otherwise I have an error, disable the dimm */
dimm_err:
- disable_dimm(ctrl, i);
+ dimm_mask = disable_dimm(ctrl, i, dimm_mask);
}
-#if 0
- print_debug("min_cycle_time: ");
- print_debug_hex8(min_cycle_time);
- print_debug(" min_latency: ");
- print_debug_hex8(min_latency);
- print_debug("\r\n");
-#endif
/* Now that I know the minimum cycle time lookup the memory parameters */
- param = get_mem_param(min_cycle_time);
+ result.param = get_mem_param(min_cycle_time);
/* Update DRAM Config High with our selected memory speed */
value = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH);
value &= ~(DCH_MEMCLK_MASK << DCH_MEMCLK_SHIFT);
- value |= param->dch_memclk;
+ value |= result.param->dch_memclk;
pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, value);
static const unsigned latencies[] = { DTL_CL_2, DTL_CL_2_5, DTL_CL_3 };
@@ -1776,7 +1633,12 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
value |= latencies[min_latency - 2] << DTL_TCL_SHIFT;
pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, value);
- return param;
+ result.dimm_mask = dimm_mask;
+ return result;
+ hw_error:
+ result.param = (const struct mem_param *)0;
+ result.dimm_mask = -1;
+ return result;
}
@@ -1795,7 +1657,7 @@ static int update_dimm_Trc(const struct mem_controller *ctrl, const struct mem_p
clocks = DTL_TRC_MIN;
}
if (clocks > DTL_TRC_MAX) {
- return -1;
+ return 0;
}
dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW);
@@ -1806,7 +1668,7 @@ static int update_dimm_Trc(const struct mem_controller *ctrl, const struct mem_p
dtl &= ~(DTL_TRC_MASK << DTL_TRC_SHIFT);
dtl |= ((clocks - DTL_TRC_BASE) << DTL_TRC_SHIFT);
pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, dtl);
- return 0;
+ return 1;
}
static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
@@ -1824,7 +1686,7 @@ static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_
clocks = DTL_TRFC_MIN;
}
if (clocks > DTL_TRFC_MAX) {
- return -1;
+ return 0;
}
dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW);
old_clocks = ((dtl >> DTL_TRFC_SHIFT) & DTL_TRFC_MASK) + DTL_TRFC_BASE;
@@ -1834,7 +1696,7 @@ static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_
dtl &= ~(DTL_TRFC_MASK << DTL_TRFC_SHIFT);
dtl |= ((clocks - DTL_TRFC_BASE) << DTL_TRFC_SHIFT);
pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, dtl);
- return 0;
+ return 1;
}
@@ -1845,16 +1707,12 @@ static int update_dimm_Trcd(const struct mem_controller *ctrl, const struct mem_
int value;
value = spd_read_byte(ctrl->channel0[i], 29);
if (value < 0) return -1;
-#if 0
clocks = (value + (param->divisor << 1) -1)/(param->divisor << 1);
-#else
- clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
-#endif
if (clocks < DTL_TRCD_MIN) {
clocks = DTL_TRCD_MIN;
}
if (clocks > DTL_TRCD_MAX) {
- return -1;
+ return 0;
}
dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW);
old_clocks = ((dtl >> DTL_TRCD_SHIFT) & DTL_TRCD_MASK) + DTL_TRCD_BASE;
@@ -1864,7 +1722,7 @@ static int update_dimm_Trcd(const struct mem_controller *ctrl, const struct mem_
dtl &= ~(DTL_TRCD_MASK << DTL_TRCD_SHIFT);
dtl |= ((clocks - DTL_TRCD_BASE) << DTL_TRCD_SHIFT);
pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, dtl);
- return 0;
+ return 1;
}
static int update_dimm_Trrd(const struct mem_controller *ctrl, const struct mem_param *param, int i)
@@ -1874,12 +1732,12 @@ static int update_dimm_Trrd(const struct mem_controller *ctrl, const struct mem_
int value;
value = spd_read_byte(ctrl->channel0[i], 28);
if (value < 0) return -1;
- clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
+ clocks = (value + (param->divisor << 1) -1)/(param->divisor << 1);
if (clocks < DTL_TRRD_MIN) {
clocks = DTL_TRRD_MIN;
}
if (clocks > DTL_TRRD_MAX) {
- return -1;
+ return 0;
}
dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW);
old_clocks = ((dtl >> DTL_TRRD_SHIFT) & DTL_TRRD_MASK) + DTL_TRRD_BASE;
@@ -1889,7 +1747,7 @@ static int update_dimm_Trrd(const struct mem_controller *ctrl, const struct mem_
dtl &= ~(DTL_TRRD_MASK << DTL_TRRD_SHIFT);
dtl |= ((clocks - DTL_TRRD_BASE) << DTL_TRRD_SHIFT);
pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, dtl);
- return 0;
+ return 1;
}
static int update_dimm_Tras(const struct mem_controller *ctrl, const struct mem_param *param, int i)
@@ -1904,7 +1762,7 @@ static int update_dimm_Tras(const struct mem_controller *ctrl, const struct mem_
clocks = DTL_TRAS_MIN;
}
if (clocks > DTL_TRAS_MAX) {
- return -1;
+ return 0;
}
dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW);
old_clocks = ((dtl >> DTL_TRAS_SHIFT) & DTL_TRAS_MASK) + DTL_TRAS_BASE;
@@ -1914,7 +1772,7 @@ static int update_dimm_Tras(const struct mem_controller *ctrl, const struct mem_
dtl &= ~(DTL_TRAS_MASK << DTL_TRAS_SHIFT);
dtl |= ((clocks - DTL_TRAS_BASE) << DTL_TRAS_SHIFT);
pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, dtl);
- return 0;
+ return 1;
}
static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_param *param, int i)
@@ -1924,25 +1782,12 @@ static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_p
int value;
value = spd_read_byte(ctrl->channel0[i], 27);
if (value < 0) return -1;
-#if 0
clocks = (value + (param->divisor << 1) - 1)/(param->divisor << 1);
-#else
- clocks = (value + ((param->divisor & 0xff) << 1) - 1)/((param->divisor & 0xff) << 1);
-#endif
-#if 0
- print_debug("Trp: ");
- print_debug_hex8(clocks);
- print_debug(" spd value: ");
- print_debug_hex8(value);
- print_debug(" divisor: ");
- print_debug_hex8(param->divisor);
- print_debug("\r\n");
-#endif
if (clocks < DTL_TRP_MIN) {
clocks = DTL_TRP_MIN;
}
if (clocks > DTL_TRP_MAX) {
- return -1;
+ return 0;
}
dtl = pci_read_config32(ctrl->f2, DRAM_TIMING_LOW);
old_clocks = ((dtl >> DTL_TRP_SHIFT) & DTL_TRP_MASK) + DTL_TRP_BASE;
@@ -1952,7 +1797,7 @@ static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_p
dtl &= ~(DTL_TRP_MASK << DTL_TRP_SHIFT);
dtl |= ((clocks - DTL_TRP_BASE) << DTL_TRP_SHIFT);
pci_write_config32(ctrl->f2, DRAM_TIMING_LOW, dtl);
- return 0;
+ return 1;
}
static void set_Twr(const struct mem_controller *ctrl, const struct mem_param *param)
@@ -1998,7 +1843,7 @@ static int update_dimm_Tref(const struct mem_controller *ctrl, const struct mem_
dth &= ~(DTH_TREF_MASK << DTH_TREF_SHIFT);
dth |= (tref << DTH_TREF_SHIFT);
pci_write_config32(ctrl->f2, DRAM_TIMING_HIGH, dth);
- return 0;
+ return 1;
}
@@ -2019,7 +1864,7 @@ static int update_dimm_x4(const struct mem_controller *ctrl, const struct mem_pa
dcl |= (1 << dimm);
}
pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl);
- return 0;
+ return 1;
}
static int update_dimm_ecc(const struct mem_controller *ctrl, const struct mem_param *param, int i)
@@ -2035,7 +1880,7 @@ static int update_dimm_ecc(const struct mem_controller *ctrl, const struct mem_p
dcl &= ~DCL_DimmEccEn;
pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl);
}
- return 0;
+ return 1;
}
static int count_dimms(const struct mem_controller *ctrl)
@@ -2045,7 +1890,7 @@ static int count_dimms(const struct mem_controller *ctrl)
dimms = 0;
for(index = 0; index < 8; index += 2) {
uint32_t csbase;
- csbase = pci_read_config32(ctrl->f2, (DRAM_CSBASE + index << 2));
+ csbase = pci_read_config32(ctrl->f2, (DRAM_CSBASE + (index << 2)));
if (csbase & 1) {
dimms += 1;
}
@@ -2126,7 +1971,7 @@ static void set_Trwt(const struct mem_controller *ctrl, const struct mem_param *
}
}
if ((clocks < DTH_TRWT_MIN) || (clocks > DTH_TRWT_MAX)) {
- die("Unknown Trwt");
+ die("Unknown Trwt\r\n");
}
dth = pci_read_config32(ctrl->f2, DRAM_TIMING_HIGH);
@@ -2240,7 +2085,6 @@ static void set_read_preamble(const struct mem_controller *ctrl, const struct me
static void set_max_async_latency(const struct mem_controller *ctrl, const struct mem_param *param)
{
uint32_t dch;
- int i;
unsigned async_lat;
int dimms;
@@ -2287,33 +2131,37 @@ static void set_idle_cycle_limit(const struct mem_controller *ctrl, const struct
pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, dch);
}
-static void spd_set_dram_timing(const struct mem_controller *ctrl, const struct mem_param *param)
+static long spd_set_dram_timing(const struct mem_controller *ctrl, const struct mem_param *param, long dimm_mask)
{
- int dimms;
int i;
- int rc;
init_Tref(ctrl, param);
- for(i = 0; (i < 4) && ctrl->channel0[i]; i++) {
+ for(i = 0; i < DIMM_SOCKETS; i++) {
int rc;
+ if (!(dimm_mask & (1 << i))) {
+ continue;
+ }
/* DRAM Timing Low Register */
- if (update_dimm_Trc (ctrl, param, i) < 0) goto dimm_err;
- if (update_dimm_Trfc(ctrl, param, i) < 0) goto dimm_err;
- if (update_dimm_Trcd(ctrl, param, i) < 0) goto dimm_err;
- if (update_dimm_Trrd(ctrl, param, i) < 0) goto dimm_err;
- if (update_dimm_Tras(ctrl, param, i) < 0) goto dimm_err;
- if (update_dimm_Trp (ctrl, param, i) < 0) goto dimm_err;
+ if ((rc = update_dimm_Trc (ctrl, param, i)) <= 0) goto dimm_err;
+ if ((rc = update_dimm_Trfc(ctrl, param, i)) <= 0) goto dimm_err;
+ if ((rc = update_dimm_Trcd(ctrl, param, i)) <= 0) goto dimm_err;
+ if ((rc = update_dimm_Trrd(ctrl, param, i)) <= 0) goto dimm_err;
+ if ((rc = update_dimm_Tras(ctrl, param, i)) <= 0) goto dimm_err;
+ if ((rc = update_dimm_Trp (ctrl, param, i)) <= 0) goto dimm_err;
/* DRAM Timing High Register */
- if (update_dimm_Tref(ctrl, param, i) < 0) goto dimm_err;
+ if ((rc = update_dimm_Tref(ctrl, param, i)) <= 0) goto dimm_err;
+
/* DRAM Config Low */
- if (update_dimm_x4 (ctrl, param, i) < 0) goto dimm_err;
- if (update_dimm_ecc(ctrl, param, i) < 0) goto dimm_err;
+ if ((rc = update_dimm_x4 (ctrl, param, i)) <= 0) goto dimm_err;
+ if ((rc = update_dimm_ecc(ctrl, param, i)) <= 0) goto dimm_err;
continue;
dimm_err:
- disable_dimm(ctrl, i);
-
+ if (rc < 0) {
+ return -1;
+ }
+ dimm_mask = disable_dimm(ctrl, i, dimm_mask);
}
/* DRAM Timing Low Register */
set_Twr(ctrl, param);
@@ -2327,18 +2175,45 @@ static void spd_set_dram_timing(const struct mem_controller *ctrl, const struct
set_read_preamble(ctrl, param);
set_max_async_latency(ctrl, param);
set_idle_cycle_limit(ctrl, param);
+ return dimm_mask;
}
static void sdram_set_spd_registers(const struct mem_controller *ctrl)
{
+ struct spd_set_memclk_result result;
const struct mem_param *param;
+ long dimm_mask;
+ hw_enable_ecc(ctrl);
activate_spd_rom(ctrl);
- spd_enable_2channels(ctrl);
- spd_set_ram_size(ctrl);
- spd_handle_unbuffered_dimms(ctrl);
- param = spd_set_memclk(ctrl);
- spd_set_dram_timing(ctrl, param);
+ dimm_mask = spd_detect_dimms(ctrl);
+ if (!(dimm_mask & ((1 << DIMM_SOCKETS) - 1))) {
+ print_debug("No memory for this cpu\r\n");
+ return;
+ }
+ dimm_mask = spd_enable_2channels(ctrl, dimm_mask);
+ if (dimm_mask < 0)
+ goto hw_spd_err;
+ dimm_mask = spd_set_ram_size(ctrl , dimm_mask);
+ if (dimm_mask < 0)
+ goto hw_spd_err;
+ dimm_mask = spd_handle_unbuffered_dimms(ctrl, dimm_mask);
+ if (dimm_mask < 0)
+ goto hw_spd_err;
+ result = spd_set_memclk(ctrl, dimm_mask);
+ param = result.param;
+ dimm_mask = result.dimm_mask;
+ if (dimm_mask < 0)
+ goto hw_spd_err;
+ dimm_mask = spd_set_dram_timing(ctrl, param , dimm_mask);
+ if (dimm_mask < 0)
+ goto hw_spd_err;
order_dimms(ctrl);
+ return;
+ hw_spd_err:
+ /* Unrecoverable error reading SPD data */
+ print_err("SPD error - reset\r\n");
+ hard_reset();
+ return;
}
#define TIMEOUT_LOOPS 300000
@@ -2346,29 +2221,44 @@ static void sdram_enable(int controllers, const struct mem_controller *ctrl)
{
int i;
+ /* Error if I don't have memory */
+ if (memory_end_k(ctrl, controllers) == 0) {
+ die("No memory\r\n");
+ }
+
/* Before enabling memory start the memory clocks */
for(i = 0; i < controllers; i++) {
uint32_t dch;
dch = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_HIGH);
- dch |= DCH_MEMCLK_VALID;
- pci_write_config32(ctrl[i].f2, DRAM_CONFIG_HIGH, dch);
+ if (dch & (DCH_MEMCLK_EN0|DCH_MEMCLK_EN1|DCH_MEMCLK_EN2|DCH_MEMCLK_EN3)) {
+ dch |= DCH_MEMCLK_VALID;
+ pci_write_config32(ctrl[i].f2, DRAM_CONFIG_HIGH, dch);
+ }
+ else {
+ /* Disable dram receivers */
+ uint32_t dcl;
+ dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
+ dcl |= DCL_DisInRcvrs;
+ pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
+ }
}
/* And if necessary toggle the the reset on the dimms by hand */
memreset(controllers, ctrl);
for(i = 0; i < controllers; i++) {
- uint32_t dcl;
+ uint32_t dcl, dch;
+ /* Skip everything if I don't have any memory on this controller */
+ dch = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_HIGH);
+ if (!(dch & DCH_MEMCLK_VALID)) {
+ continue;
+ }
+
/* Toggle DisDqsHys to get it working */
dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
-#if 0
- print_debug("dcl: ");
- print_debug_hex32(dcl);
- print_debug("\r\n");
-#endif
if (dcl & DCL_DimmEccEn) {
uint32_t mnc;
- print_debug("ECC enabled\r\n");
+ print_spew("ECC enabled\r\n");
mnc = pci_read_config32(ctrl[i].f3, MCA_NB_CONFIG);
mnc |= MNC_ECC_EN;
if (dcl & DCL_128BitEn) {
@@ -2387,7 +2277,13 @@ static void sdram_enable(int controllers, const struct mem_controller *ctrl)
}
for(i = 0; i < controllers; i++) {
- uint32_t dcl;
+ uint32_t dcl, dch;
+ /* Skip everything if I don't have any memory on this controller */
+ dch = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_HIGH);
+ if (!(dch & DCH_MEMCLK_VALID)) {
+ continue;
+ }
+
print_debug("Initializing memory: ");
int loops = 0;
do {
@@ -2399,151 +2295,98 @@ static void sdram_enable(int controllers, const struct mem_controller *ctrl)
} while(((dcl & DCL_DramInit) != 0) && (loops < TIMEOUT_LOOPS));
if (loops >= TIMEOUT_LOOPS) {
print_debug(" failed\r\n");
- } else {
- print_debug(" done\r\n");
+ continue;
}
- if (dcl & DCL_DimmEccEn) {
- print_debug("Clearing memory: ");
- if (!is_cpu_pre_c0()) {
- /* Wait until the automatic ram scrubber is finished */
- dcl &= ~(DCL_MemClrStatus | DCL_DramEnable);
- pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
- do {
- dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
- } while(((dcl & DCL_MemClrStatus) == 0) || ((dcl & DCL_DramEnable) == 0) );
- }
- uint32_t base, last_scrub_k, scrub_k;
- uint32_t cnt,zstart,zend;
- msr_t msr,msr_201;
-
- /* First make certain the scrubber is disabled */
- pci_write_config32(ctrl[i].f3, SCRUB_CONTROL,
- (SCRUB_NONE << 16) | (SCRUB_NONE << 8) | (SCRUB_NONE << 0));
-
- /* load the start and end for the memory block to clear */
- msr_201 = rdmsr(0x201);
- zstart = pci_read_config32(ctrl[0].f1, 0x40 + (i*8));
- zend = pci_read_config32(ctrl[0].f1, 0x44 + (i*8));
- zstart >>= 16;
- zend >>=16;
-#if 1
- print_debug("addr ");
- print_debug_hex32(zstart);
- print_debug("-");
- print_debug_hex32(zend);
- print_debug("\r\n");
-#endif
-
- /* Disable fixed mtrrs */
- msr = rdmsr(MTRRdefType_MSR);
- msr.lo &= ~(1<<10);
- wrmsr(MTRRdefType_MSR, msr);
-
- /* turn on the wrap 32 disable */
- msr = rdmsr(0xc0010015);
- msr.lo |= (1<<17);
- wrmsr(0xc0010015,msr);
-
- for(;zstart<zend;zstart+=4) {
-
- /* test for the last 64 meg of 4 gig space */
- if(zstart == 0x0fc)
- continue;
-
- /* disable cache */
- __asm__ volatile(
- "movl %%cr0, %0\n\t"
- "orl $0x40000000, %0\n\t"
- "movl %0, %%cr0\n\t"
- :"=r" (cnt)
- );
-
- /* Set the variable mtrrs to write combine */
- msr.lo = 1 + ((zstart&0x0ff)<<24);
- msr.hi = (zstart&0x0ff00)>>8;
- wrmsr(0x200,msr);
-
- /* Set the limit to 64 meg of ram */
- msr.hi = 0x000000ff;
- msr.lo = 0xfc000800;
- wrmsr(0x201,msr);
-
- /* enable cache */
- __asm__ volatile(
- "movl %%cr0, %0\n\t"
- "andl $0x9fffffff, %0\n\t"
- "movl %0, %%cr0\n\t"
- :"=r" (cnt)
- );
- /* Set fs base address */
- msr.lo = (zstart&0xff) << 24;
- msr.hi = (zstart&0xff00) >> 8;
- wrmsr(0xc0000100,msr);
-
- print_debug_char((zstart > 0x0ff)?'+':'-');
-
- /* clear memory 64meg */
- __asm__ volatile(
- "1: \n\t"
- "movl %0, %%fs:(%1)\n\t"
- "addl $4,%1\n\t"
- "subl $1,%2\n\t"
- "jnz 1b\n\t"
- :
- : "a" (0), "D" (0), "c" (0x01000000)
- );
- }
-
- /* disable cache */
- __asm__ volatile(
- "movl %%cr0, %0\n\t"
- "orl $0x40000000, %0\n\t"
- "movl %0, %%cr0\n\t"
- :"=r" (cnt)
- );
-
- /* restore msr registers */
- msr = rdmsr(MTRRdefType_MSR);
- msr.lo |= 0x0400;
- wrmsr(MTRRdefType_MSR, msr);
-
- /* Restore the variable mtrrs */
- msr.lo = 6;
- msr.hi = 0;
- wrmsr(0x200,msr);
- wrmsr(0x201,msr_201);
-
- /* Set fs base to 0 */
- msr.lo = 0;
- msr.hi = 0;
- wrmsr(0xc0000100,msr);
-
- /* enable cache */
- __asm__ volatile(
- "movl %%cr0, %0\n\t"
- "andl $0x9fffffff, %0\n\t"
- "movl %0, %%cr0\n\t"
- :"=r" (cnt)
- );
-
- /* turn off the wrap 32 disable */
- msr = rdmsr(0xc0010015);
- msr.lo &= ~(1<<17);
- wrmsr(0xc0010015,msr);
-
- /* Find the Srub base address for this cpu */
- base = pci_read_config32(ctrl[i].f1, 0x40 + (ctrl[i].node_id << 3));
- base &= 0xffff0000;
-
- /* Set the scrub base address registers */
- pci_write_config32(ctrl[i].f3, SCRUB_ADDR_LOW, base << 8);
- pci_write_config32(ctrl[i].f3, SCRUB_ADDR_HIGH, base >> 24);
-
- /* Enable scrubbing at the lowest possible rate */
- pci_write_config32(ctrl[i].f3, SCRUB_CONTROL,
- (SCRUB_84ms << 16) | (SCRUB_84ms << 8) | (SCRUB_84ms << 0));
-
- print_debug("done\r\n");
+ if (!is_cpu_pre_c0()) {
+ /* Wait until it is safe to touch memory */
+ dcl &= ~(DCL_MemClrStatus | DCL_DramEnable);
+ pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
+ do {
+ dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
+ } while(((dcl & DCL_MemClrStatus) == 0) || ((dcl & DCL_DramEnable) == 0) );
}
+ print_debug(" done\r\n");
}
+
+ /* Make certain the first 1M of memory is intialized */
+ msr_t msr, msr_201;
+ uint32_t cnt;
+
+ /* Save the value of msr_201 */
+ msr_201 = rdmsr(0x201);
+
+ print_debug("Clearing LinuxBIOS memory: ");
+
+ /* disable cache */
+ __asm__ volatile(
+ "movl %%cr0, %0\n\t"
+ "orl $0x40000000, %0\n\t"
+ "movl %0, %%cr0\n\t"
+ :"=r" (cnt)
+ );
+
+ /* Disable fixed mtrrs */
+ msr = rdmsr(MTRRdefType_MSR);
+ msr.lo &= ~(1<<10);
+ wrmsr(MTRRdefType_MSR, msr);
+
+
+ /* Set the variable mtrrs to write combine */
+ msr.hi = 0;
+ msr.lo = 0 | MTRR_TYPE_WRCOMB;
+ wrmsr(0x200, msr);
+
+ /* Set the limit to 1M of ram */
+ msr.hi = 0x000000ff;
+ msr.lo = (~((CONFIG_LB_MEM_TOPK << 10) - 1)) | 0x800;
+ wrmsr(0x201, msr);
+
+ /* enable cache */
+ __asm__ volatile(
+ "movl %%cr0, %0\n\t"
+ "andl $0x9fffffff, %0\n\t"
+ "movl %0, %%cr0\n\t"
+ :"=r" (cnt)
+ );
+
+ /* clear memory 1meg */
+ __asm__ volatile(
+ "1: \n\t"
+ "movl %0, %%fs:(%1)\n\t"
+ "addl $4,%1\n\t"
+ "subl $4,%2\n\t"
+ "jnz 1b\n\t"
+ :
+ : "a" (0), "D" (0), "c" (1024*1024)
+ );
+
+ /* disable cache */
+ __asm__ volatile(
+ "movl %%cr0, %0\n\t"
+ "orl $0x40000000, %0\n\t"
+ "movl %0, %%cr0\n\t"
+ :"=r" (cnt)
+ );
+
+ /* restore msr registers */
+ msr = rdmsr(MTRRdefType_MSR);
+ msr.lo |= 0x0400;
+ wrmsr(MTRRdefType_MSR, msr);
+
+
+ /* Restore the variable mtrrs */
+ msr.hi = 0;
+ msr.lo = MTRR_TYPE_WRBACK;
+ wrmsr(0x200, msr);
+ wrmsr(0x201, msr_201);
+
+ /* enable cache */
+ __asm__ volatile(
+ "movl %%cr0, %0\n\t"
+ "andl $0x9fffffff, %0\n\t"
+ "movl %0, %%cr0\n\t"
+ :"=r" (cnt)
+ );
+
+ print_debug(" done\r\n");
}
diff --git a/src/northbridge/amd/amdk8/raminit.h b/src/northbridge/amd/amdk8/raminit.h
index 7622cb7621..157dd13ee3 100644
--- a/src/northbridge/amd/amdk8/raminit.h
+++ b/src/northbridge/amd/amdk8/raminit.h
@@ -1,11 +1,12 @@
#ifndef RAMINIT_H
#define RAMINIT_H
+#define DIMM_SOCKETS 4
struct mem_controller {
unsigned node_id;
device_t f0, f1, f2, f3;
- uint16_t channel0[4]; //By LYH
- uint16_t channel1[4]; //By LYH
+ uint16_t channel0[DIMM_SOCKETS];
+ uint16_t channel1[DIMM_SOCKETS];
};
diff --git a/src/northbridge/amd/amdk8/raminit_test.c b/src/northbridge/amd/amdk8/raminit_test.c
new file mode 100644
index 0000000000..8e323ea859
--- /dev/null
+++ b/src/northbridge/amd/amdk8/raminit_test.c
@@ -0,0 +1,442 @@
+#include <unistd.h>
+#include <limits.h>
+#include <stdint.h>
+#include <string.h>
+#include <setjmp.h>
+#include <device/pci_def.h>
+#include "amdk8.h"
+
+jmp_buf end_buf;
+
+static int is_cpu_pre_c0(void)
+{
+ return 0;
+}
+
+#define PCI_ADDR(BUS, DEV, FN, WHERE) ( \
+ (((BUS) & 0xFF) << 16) | \
+ (((DEV) & 0x1f) << 11) | \
+ (((FN) & 0x07) << 8) | \
+ ((WHERE) & 0xFF))
+
+#define PCI_DEV(BUS, DEV, FN) ( \
+ (((BUS) & 0xFF) << 16) | \
+ (((DEV) & 0x1f) << 11) | \
+ (((FN) & 0x7) << 8))
+
+#define PCI_ID(VENDOR_ID, DEVICE_ID) \
+ ((((DEVICE_ID) & 0xFFFF) << 16) | ((VENDOR_ID) & 0xFFFF))
+
+typedef unsigned device_t;
+
+unsigned char pci_register[256*5*3*256];
+
+static uint8_t pci_read_config8(device_t dev, unsigned where)
+{
+ unsigned addr;
+ addr = dev | where;
+ return pci_register[addr];
+}
+
+static uint16_t pci_read_config16(device_t dev, unsigned where)
+{
+ unsigned addr;
+ addr = dev | where;
+ return pci_register[addr] | (pci_register[addr + 1] << 8);
+}
+
+static uint32_t pci_read_config32(device_t dev, unsigned where)
+{
+ unsigned addr;
+ uint32_t value;
+ addr = dev | where;
+ value = pci_register[addr] |
+ (pci_register[addr + 1] << 8) |
+ (pci_register[addr + 2] << 16) |
+ (pci_register[addr + 3] << 24);
+
+#if 0
+ print_debug("pcir32(");
+ print_debug_hex32(addr);
+ print_debug("):");
+ print_debug_hex32(value);
+ print_debug("\n");
+#endif
+ return value;
+
+}
+
+static void pci_write_config8(device_t dev, unsigned where, uint8_t value)
+{
+ unsigned addr;
+ addr = dev | where;
+ pci_register[addr] = value;
+}
+
+static void pci_write_config16(device_t dev, unsigned where, uint16_t value)
+{
+ unsigned addr;
+ addr = dev | where;
+ pci_register[addr] = value & 0xff;
+ pci_register[addr + 1] = (value >> 8) & 0xff;
+}
+
+static void pci_write_config32(device_t dev, unsigned where, uint32_t value)
+{
+ unsigned addr;
+ addr = dev | where;
+ pci_register[addr] = value & 0xff;
+ pci_register[addr + 1] = (value >> 8) & 0xff;
+ pci_register[addr + 2] = (value >> 16) & 0xff;
+ pci_register[addr + 3] = (value >> 24) & 0xff;
+
+#if 0
+ print_debug("pciw32(");
+ print_debug_hex32(addr);
+ print_debug(", ");
+ print_debug_hex32(value);
+ print_debug(")\n");
+#endif
+}
+
+#define PCI_DEV_INVALID (0xffffffffU)
+static device_t pci_locate_device(unsigned pci_id, device_t dev)
+{
+ for(; dev <= PCI_DEV(255, 31, 7); dev += PCI_DEV(0,0,1)) {
+ unsigned int id;
+ id = pci_read_config32(dev, 0);
+ if (id == pci_id) {
+ return dev;
+ }
+ }
+ return PCI_DEV_INVALID;
+}
+
+
+
+
+static void uart_tx_byte(unsigned char data)
+{
+ write(STDOUT_FILENO, &data, 1);
+}
+static void hlt(void)
+{
+ longjmp(end_buf, 2);
+}
+#include "../../../arch/i386/lib/console.c"
+
+unsigned long log2(unsigned long x)
+{
+ // assume 8 bits per byte.
+ unsigned long i = 1 << (sizeof(x)*8 - 1);
+ unsigned long pow = sizeof(x) * 8 - 1;
+
+ if (! x) {
+ static const char errmsg[] = " called with invalid parameter of 0\n";
+ write(STDERR_FILENO, __func__, sizeof(__func__) - 1);
+ write(STDERR_FILENO, errmsg, sizeof(errmsg) - 1);
+ hlt();
+ }
+ for(; i > x; i >>= 1, pow--)
+ ;
+
+ return pow;
+}
+
+typedef struct msr_struct
+{
+ unsigned lo;
+ unsigned hi;
+} msr_t;
+
+static inline msr_t rdmsr(unsigned index)
+{
+ msr_t result;
+ result.lo = 0;
+ result.hi = 0;
+ return result;
+}
+
+static inline void wrmsr(unsigned index, msr_t msr)
+{
+}
+
+#include "raminit.h"
+
+#define SIO_BASE 0x2e
+
+static void hard_reset(void)
+{
+ /* FIXME implement the hard reset case... */
+ longjmp(end_buf, 3);
+}
+
+static void memreset_setup(void)
+{
+ /* Nothing to do */
+}
+
+static void memreset(int controllers, const struct mem_controller *ctrl)
+{
+ /* Nothing to do */
+}
+
+static inline void activate_spd_rom(const struct mem_controller *ctrl)
+{
+ /* nothing to do */
+}
+
+
+static uint8_t spd_mt4lsdt464a[256] =
+{
+ 0x80, 0x08, 0x04, 0x0C, 0x08, 0x01, 0x40, 0x00, 0x01, 0x70,
+ 0x54, 0x00, 0x80, 0x10, 0x00, 0x01, 0x8F, 0x04, 0x06, 0x01,
+ 0x01, 0x00, 0x0E, 0x75, 0x54, 0x00, 0x00, 0x0F, 0x0E, 0x0F,
+
+ 0x25, 0x08, 0x15, 0x08, 0x15, 0x08, 0x00, 0x12, 0x01, 0x4E,
+ 0x9C, 0xE4, 0xB7, 0x46, 0x2C, 0xFF, 0x01, 0x02, 0x03, 0x04,
+ 0x05, 0x06, 0x07, 0x08, 0x09, 0x01, 0x02, 0x03, 0x04, 0x05,
+ 0x06, 0x07, 0x08, 0x09, 0x00,
+};
+
+static uint8_t spd_micron_512MB_DDR333[256] =
+{
+ 0x80, 0x08, 0x07, 0x0d, 0x0b, 0x02, 0x48, 0x00, 0x04, 0x60,
+ 0x70, 0x02, 0x82, 0x04, 0x04, 0x01, 0x0e, 0x04, 0x0c, 0x01,
+ 0x02, 0x26, 0xc0, 0x75, 0x70, 0x00, 0x00, 0x48, 0x30, 0x48,
+ 0x2a, 0x80, 0x80, 0x80, 0x45, 0x45, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3c, 0x48, 0x30, 0x28, 0x50, 0x00, 0x01, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x10, 0x6f, 0x2c, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x01, 0x33, 0x36, 0x56, 0x44, 0x44, 0x46, 0x31,
+ 0x32, 0x38, 0x37, 0x32, 0x47, 0x2d, 0x33, 0x33, 0x35, 0x43,
+ 0x33, 0x03, 0x00, 0x03, 0x23, 0x17, 0x07, 0x5a, 0xb2, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff
+};
+
+static uint8_t spd_micron_256MB_DDR333[256] =
+{
+ 0x80, 0x08, 0x07, 0x0d, 0x0b, 0x01, 0x48, 0x00, 0x04, 0x60,
+ 0x70, 0x02, 0x82, 0x04, 0x04, 0x01, 0x0e, 0x04, 0x0c, 0x01,
+ 0x02, 0x26, 0xc0, 0x75, 0x70, 0x00, 0x00, 0x48, 0x30, 0x48,
+ 0x2a, 0x80, 0x80, 0x80, 0x45, 0x45, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x3c, 0x48, 0x30, 0x23, 0x50, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x58, 0x2c, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0x01, 0x31, 0x38, 0x56, 0x44, 0x44, 0x46, 0x36,
+ 0x34, 0x37, 0x32, 0x47, 0x2d, 0x33, 0x33, 0x35, 0x43, 0x31,
+ 0x20, 0x01, 0x00, 0x03, 0x19, 0x17, 0x05, 0xb2, 0xf4, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00,
+ 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0x00, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+ 0xff, 0xff, 0xff, 0xff, 0xff, 0xff,
+};
+
+#define MAX_DIMMS 16
+static uint8_t spd_data[MAX_DIMMS*256];
+
+static unsigned spd_count, spd_fail_count;
+static int spd_read_byte(unsigned device, unsigned address)
+{
+ int result;
+ spd_count++;
+ if ((device < 0x50) || (device >= (0x50 +MAX_DIMMS))) {
+ result = -1;
+ }
+ else {
+ device -= 0x50;
+
+ if (address > 256) {
+ result = -1;
+ }
+ else if (spd_data[(device << 8) | 2] != 7) {
+ result = -1;
+ }
+ else {
+ result = spd_data[(device << 8) | address];
+ }
+ }
+#if 0
+ print_debug("spd_read_byte(");
+ print_debug_hex32(device);
+ print_debug(", ");
+ print_debug_hex32(address);
+ print_debug(") -> ");
+ print_debug_hex32(result);
+ print_debug("\n");
+#endif
+ if (spd_count >= spd_fail_count) {
+ result = -1;
+ }
+ return result;
+}
+
+/* no specific code here. this should go away completely */
+static void coherent_ht_mainboard(unsigned cpus)
+{
+}
+
+#include "raminit.c"
+#include "../../../sdram/generic_sdram.c"
+
+#define FIRST_CPU 1
+#define SECOND_CPU 1
+#define TOTAL_CPUS (FIRST_CPU + SECOND_CPU)
+static void raminit_main(void)
+{
+ /*
+ * GPIO28 of 8111 will control H0_MEMRESET_L
+ * GPIO29 of 8111 will control H1_MEMRESET_L
+ */
+ static const struct mem_controller cpu[] = {
+#if FIRST_CPU
+ {
+ .node_id = 0,
+ .f0 = PCI_DEV(0, 0x18, 0),
+ .f1 = PCI_DEV(0, 0x18, 1),
+ .f2 = PCI_DEV(0, 0x18, 2),
+ .f3 = PCI_DEV(0, 0x18, 3),
+ .channel0 = { 0x50+0, 0x50+2, 0x50+4, 0x50+6 },
+ .channel1 = { 0x50+1, 0x50+3, 0x50+5, 0x50+7 },
+ },
+#endif
+#if SECOND_CPU
+ {
+ .node_id = 1,
+ .f0 = PCI_DEV(0, 0x19, 0),
+ .f1 = PCI_DEV(0, 0x19, 1),
+ .f2 = PCI_DEV(0, 0x19, 2),
+ .f3 = PCI_DEV(0, 0x19, 3),
+ .channel0 = { 0x50+8, 0x50+10, 0x50+12, 0x50+14 },
+ .channel1 = { 0x50+9, 0x50+11, 0x50+13, 0x50+15 },
+ },
+#endif
+ };
+ console_init();
+ memreset_setup();
+ sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu);
+
+}
+
+static void reset_tests(void)
+{
+ /* Clear the results of any previous tests */
+ memset(pci_register, 0, sizeof(pci_register));
+ memset(spd_data, 0, sizeof(spd_data));
+ spd_count = 0;
+ spd_fail_count = UINT_MAX;
+
+ pci_write_config32(PCI_DEV(0, 0x18, 3), NORTHBRIDGE_CAP,
+ NBCAP_128Bit |
+ NBCAP_MP| NBCAP_BIG_MP |
+ /* NBCAP_ECC | NBCAP_CHIPKILL_ECC | */
+ (NBCAP_MEMCLK_200MHZ << NBCAP_MEMCLK_SHIFT) |
+ NBCAP_MEMCTRL);
+
+ pci_write_config32(PCI_DEV(0, 0x19, 3), NORTHBRIDGE_CAP,
+ NBCAP_128Bit |
+ NBCAP_MP| NBCAP_BIG_MP |
+ /* NBCAP_ECC | NBCAP_CHIPKILL_ECC | */
+ (NBCAP_MEMCLK_200MHZ << NBCAP_MEMCLK_SHIFT) |
+ NBCAP_MEMCTRL);
+
+#if 0
+ pci_read_config32(PCI_DEV(0, 0x18, 3), NORTHBRIDGE_CAP);
+#endif
+}
+
+static void test1(void)
+{
+ reset_tests();
+
+ memcpy(&spd_data[0*256], spd_micron_512MB_DDR333, 256);
+ memcpy(&spd_data[1*256], spd_micron_512MB_DDR333, 256);
+#if 0
+ memcpy(&spd_data[2*256], spd_micron_512MB_DDR333, 256);
+ memcpy(&spd_data[3*256], spd_micron_512MB_DDR333, 256);
+
+ memcpy(&spd_data[8*256], spd_micron_512MB_DDR333, 256);
+ memcpy(&spd_data[9*256], spd_micron_512MB_DDR333, 256);
+ memcpy(&spd_data[10*256], spd_micron_512MB_DDR333, 256);
+ memcpy(&spd_data[11*256], spd_micron_512MB_DDR333, 256);
+#endif
+
+ raminit_main();
+
+#if 0
+ print_debug("spd_count: ");
+ print_debug_hex32(spd_count);
+ print_debug("\r\n");
+#endif
+
+}
+
+
+static void do_test2(int i)
+{
+ jmp_buf tmp_buf;
+ memcpy(&tmp_buf, &end_buf, sizeof(end_buf));
+ if (setjmp(end_buf) != 0) {
+ goto done;
+ }
+ reset_tests();
+ spd_fail_count = i;
+
+ print_debug("\r\nSPD will fail after: ");
+ print_debug_hex32(spd_fail_count);
+ print_debug(" accesses.\r\n");
+
+ memcpy(&spd_data[0*256], spd_micron_512MB_DDR333, 256);
+ memcpy(&spd_data[1*256], spd_micron_512MB_DDR333, 256);
+
+ raminit_main();
+
+ done:
+ memcpy(&end_buf, &tmp_buf, sizeof(end_buf));
+}
+
+static void test2(void)
+{
+ int i;
+ for(i = 0; i < 0x48; i++) {
+ do_test2(i);
+ }
+
+}
+
+int main(int argc, char **argv)
+{
+ if (setjmp(end_buf) != 0) {
+ return -1;
+ }
+ test1();
+ test2();
+ return 0;
+}
diff --git a/src/northbridge/amd/amdk8/reset_test.c b/src/northbridge/amd/amdk8/reset_test.c
index 9105324f33..7f4336ce5f 100644
--- a/src/northbridge/amd/amdk8/reset_test.c
+++ b/src/northbridge/amd/amdk8/reset_test.c
@@ -1,4 +1,5 @@
#include <stdint.h>
+#include <arch/smp/lapic.h>
#define NODE_ID 0x60
#define HT_INIT_CONTROL 0x6c
@@ -6,11 +7,13 @@
#define HTIC_BIOSR_Detect (1<<5)
#define HTIC_INIT_Detect (1<<6)
-
static int cpu_init_detected(void)
{
unsigned long htic;
- htic = pci_read_config32(PCI_DEV(0, 0x18, 0), HT_INIT_CONTROL);
+ device_t dev;
+
+ dev = PCI_DEV(0, 0x18 + lapicid(), 0);
+ htic = pci_read_config32(dev, HT_INIT_CONTROL);
return !!(htic & HTIC_INIT_Detect);
}
@@ -31,11 +34,11 @@ static int cold_reset_detected(void)
return !(htic & HTIC_ColdR_Detect);
}
-static void distinguish_cpu_resets(unsigned node_id)
+static void distinguish_cpu_resets(void)
{
uint32_t htic;
device_t device;
- device = PCI_DEV(0, 0x18 + node_id, 0);
+ device = PCI_DEV(0, 0x18 + lapicid(), 0);
htic = pci_read_config32(device, HT_INIT_CONTROL);
htic |= HTIC_ColdR_Detect | HTIC_BIOSR_Detect | HTIC_INIT_Detect;
pci_write_config32(device, HT_INIT_CONTROL, htic);
diff --git a/src/pc80/Config.lb b/src/pc80/Config.lb
index 0237fa96af..26d548b897 100644
--- a/src/pc80/Config.lb
+++ b/src/pc80/Config.lb
@@ -1,9 +1,8 @@
uses CONFIG_IDE_STREAM
-uses CONFIG_KEYBOARD
uses CONFIG_LEGACY_VGABIOS
object mc146818rtc.o
-#object isa-dma.o
+object isa-dma.o
#object i8259.o CONFIG_I8259
#object udelay_timer2.o CONFIG_UDELAY_TIMER2
#object beep.o CONFIG_BEEP
@@ -16,9 +15,7 @@ if CONFIG_IDE_STREAM
dir ide
end
-if CONFIG_KEYBOARD
- object keyboard.o
-end
+object keyboard.o
if CONFIG_LEGACY_VGABIOS
object vgabios.o
diff --git a/src/pc80/isa-dma.c b/src/pc80/isa-dma.c
new file mode 100644
index 0000000000..45cfb88a97
--- /dev/null
+++ b/src/pc80/isa-dma.c
@@ -0,0 +1,43 @@
+#include <arch/io.h>
+
+/* DMA controller registers */
+#define DMA1_CMD_REG 0x08 /* command register (w) */
+#define DMA1_STAT_REG 0x08 /* status register (r) */
+#define DMA1_REQ_REG 0x09 /* request register (w) */
+#define DMA1_MASK_REG 0x0A /* single-channel mask (w) */
+#define DMA1_MODE_REG 0x0B /* mode register (w) */
+#define DMA1_CLEAR_FF_REG 0x0C /* clear pointer flip-flop (w) */
+#define DMA1_TEMP_REG 0x0D /* Temporary Register (r) */
+#define DMA1_RESET_REG 0x0D /* Master Clear (w) */
+#define DMA1_CLR_MASK_REG 0x0E /* Clear Mask */
+#define DMA1_MASK_ALL_REG 0x0F /* all-channels mask (w) */
+
+#define DMA2_CMD_REG 0xD0 /* command register (w) */
+#define DMA2_STAT_REG 0xD0 /* status register (r) */
+#define DMA2_REQ_REG 0xD2 /* request register (w) */
+#define DMA2_MASK_REG 0xD4 /* single-channel mask (w) */
+#define DMA2_MODE_REG 0xD6 /* mode register (w) */
+#define DMA2_CLEAR_FF_REG 0xD8 /* clear pointer flip-flop (w) */
+#define DMA2_TEMP_REG 0xDA /* Temporary Register (r) */
+#define DMA2_RESET_REG 0xDA /* Master Clear (w) */
+#define DMA2_CLR_MASK_REG 0xDC /* Clear Mask */
+#define DMA2_MASK_ALL_REG 0xDE /* all-channels mask (w) */
+
+#define DMA_MODE_READ 0x44 /* I/O to memory, no autoinit, increment, single mode */
+#define DMA_MODE_WRITE 0x48 /* memory to I/O, no autoinit, increment, single mode */
+#define DMA_MODE_CASCADE 0xC0 /* pass thru DREQ->HRQ, DACK<-HLDA only */
+
+#define DMA_AUTOINIT 0x10
+
+
+void isa_dma_init(void)
+{
+ /* slave at 0x00 - 0x0f */
+ /* master at 0xc0 - 0xdf */
+ /* 0x80 - 0x8f DMA page registers */
+ /* DMA: 0x00, 0x02, 0x4, 0x06 base address for DMA channel */
+ outb(0, DMA1_RESET_REG);
+ outb(0, DMA2_RESET_REG);
+ outb(DMA_MODE_CASCADE, DMA2_MODE_REG);
+ outb(0, DMA2_MASK_REG);
+}
diff --git a/src/pc80/keyboard.c b/src/pc80/keyboard.c
index a7ecf8cbd3..d293f714de 100644
--- a/src/pc80/keyboard.c
+++ b/src/pc80/keyboard.c
@@ -1,8 +1,11 @@
+#include <console/console.h>
+#include <pc80/keyboard.h>
+#include <device/device.h>
#include <arch/io.h>
/* much better keyboard init courtesy ollie@sis.com.tw
TODO: Typematic Setting, the keyboard is too slow for me */
-void pc_keyboard_init()
+static void pc_keyboard_init(struct pc_keyboard *keyboard)
{
volatile unsigned char regval;
@@ -49,3 +52,9 @@ void pc_keyboard_init()
return;
}
+void init_pc_keyboard(unsigned port0, unsigned port1, struct pc_keyboard *kbd)
+{
+ if ((port0 == 0x60) && (port1 == 0x64)) {
+ pc_keyboard_init(kbd);
+ }
+}
diff --git a/src/pc80/mc146818rtc_early.c b/src/pc80/mc146818rtc_early.c
index 35f3f5910f..0c7d822718 100644
--- a/src/pc80/mc146818rtc_early.c
+++ b/src/pc80/mc146818rtc_early.c
@@ -97,3 +97,14 @@ static int do_normal_boot(void)
return (byte & (1<<1));
}
+
+static unsigned read_option(unsigned start, unsigned size, unsigned def)
+{
+#if USE_OPTION_TABLE == 1
+ unsigned byte;
+ byte = cmos_read(start/8);
+ return (byte >> (start & 7U)) & ((1U << size) - 1U);
+#else
+ return def;
+#endif
+}
diff --git a/src/pc80/serial.c b/src/pc80/serial.c
index c2788d6ec7..89ac425c56 100644
--- a/src/pc80/serial.c
+++ b/src/pc80/serial.c
@@ -77,8 +77,7 @@ static void uart_init(void)
#if USE_OPTION_TABLE == 1
static const unsigned char divisor[] = { 1,2,3,6,12,24,48,96 };
unsigned ttys0_div, ttys0_index;
- outb(RTC_BOOT_BYTE + 1, 0x70);
- ttys0_index = inb(0x71);
+ ttys0_index = read_option(CMOS_VSTART_baud_rate, CMOS_VLEN_baud_rate, 0);
ttys0_index &= 7;
ttys0_div = divisor[ttys0_index];
outb(ttys0_div & 0xff, TTYS0_BASE + UART_DLL);
diff --git a/src/pc80/serial.inc b/src/pc80/serial.inc
index b0f12699e1..7b80697c85 100644
--- a/src/pc80/serial.inc
+++ b/src/pc80/serial.inc
@@ -67,8 +67,7 @@ div:
mov %ah, %al ; \
outb %al, %dx
-
-serial0:
+serial_init:
/* Set 115.2Kbps,8n1 */
/* Set 8bit, 1 stop bit, no parity, DLAB */
mov $TTYS0_LCR, %dx
@@ -102,5 +101,7 @@ serial0:
mov $TTYS0_LCR, %dx
mov $(TTYS0_LCS & 0x7f), %al
out %al, %dx
+ RETSP
-
+serial0:
+ CALLSP(serial_init)
diff --git a/src/southbridge/amd/amd8111/Config.lb b/src/southbridge/amd/amd8111/Config.lb
index 904b0995b5..5bbbaba65e 100644
--- a/src/southbridge/amd/amd8111/Config.lb
+++ b/src/southbridge/amd/amd8111/Config.lb
@@ -5,5 +5,6 @@ driver amd8111_lpc.o
driver amd8111_ide.o
driver amd8111_acpi.o
driver amd8111_usb2.o
-#driver amd8111_ac97.o
-#driver amd8111_nic.o
+driver amd8111_ac97.o
+driver amd8111_nic.o
+driver amd8111_pci.o
diff --git a/src/southbridge/amd/amd8111/amd8111.c b/src/southbridge/amd/amd8111/amd8111.c
index 8dde5f13c6..d3fdf3b7ba 100644
--- a/src/southbridge/amd/amd8111/amd8111.c
+++ b/src/southbridge/amd/amd8111/amd8111.c
@@ -26,27 +26,24 @@ void amd8111_enable(device_t dev)
lpc_dev = dev_find_slot(dev->bus->secondary, devfn);
index = dev->path.u.pci.devfn & 7;
}
- if ((!lpc_dev) || (index >= 16) ||
- (lpc_dev->vendor != PCI_VENDOR_ID_AMD) ||
- (lpc_dev->device != PCI_DEVICE_ID_AMD_8111_ISA)) {
+ if ((!lpc_dev) || (index >= 16)) {
return;
}
-
+ if ((lpc_dev->vendor != PCI_VENDOR_ID_AMD) ||
+ (lpc_dev->device != PCI_DEVICE_ID_AMD_8111_ISA)) {
+ uint32_t id;
+ id = pci_read_config32(lpc_dev, PCI_VENDOR_ID);
+ if (id != (PCI_VENDOR_ID_AMD | (PCI_DEVICE_ID_AMD_8111_ISA << 16))) {
+ return;
+ }
+ }
reg = reg_old = pci_read_config16(lpc_dev, 0x48);
reg &= ~(1 << index);
if (dev->enable) {
reg |= (1 << index);
}
if (reg != reg_old) {
-#if 1
- printk_warning("amd8111_enable dev: %s", dev_path(dev));
- printk_warning(" lpc_dev: %s index: %d reg: %04x -> %04x ",
- dev_path(lpc_dev), index, reg_old, reg);
-#endif
pci_write_config16(lpc_dev, 0x48, reg);
-#if 1
- printk_warning("done\n");
-#endif
}
}
diff --git a/src/southbridge/amd/amd8111/amd8111_acpi.c b/src/southbridge/amd/amd8111/amd8111_acpi.c
index 3a5a594f57..e3b7038e46 100644
--- a/src/southbridge/amd/amd8111/amd8111_acpi.c
+++ b/src/southbridge/amd/amd8111/amd8111_acpi.c
@@ -4,11 +4,15 @@
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <pc80/mc146818rtc.h>
+#include <bitops.h>
+#include <arch/io.h>
#include "amd8111.h"
#define PREVIOUS_POWER_STATE 0x43
#define MAINBOARD_POWER_OFF 0
#define MAINBOARD_POWER_ON 1
+#define SLOW_CPU_OFF 0
+#define SLOW_CPU__ON 1
#ifndef MAINBOARD_POWER_ON_AFTER_POWER_FAIL
#define MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
@@ -19,6 +23,8 @@ static void acpi_init(struct device *dev)
{
uint8_t byte;
uint16_t word;
+ uint16_t pm10_bar;
+ uint32_t dword;
int on;
#if 0
@@ -57,10 +63,43 @@ static void acpi_init(struct device *dev)
pci_write_config8(dev, PREVIOUS_POWER_STATE, byte);
printk_info("set power %s after power fail\n", on?"on":"off");
+ /* Throttle the CPU speed down for testing */
+ on = SLOW_CPU_OFF;
+ get_option(&on, "slow_cpu");
+ if(on) {
+ pm10_bar = (pci_read_config16(dev, 0x58)&0xff00);
+ outl(((on<<1)+0x10) ,(pm10_bar + 0x10));
+ dword = inl(pm10_bar + 0x10);
+ on = 8-on;
+ printk_debug("Throttling CPU %2d.%1.1d percent.\n",
+ (on*12)+(on>>1),(on&1)*5);
+ }
+}
+
+static void acpi_read_resources(device_t dev)
+{
+ /* Handle the generic bars */
+ pci_dev_read_resources(dev);
+
+ if ((dev->resources + 1) < MAX_RESOURCES) {
+ struct resource *resource = &dev->resource[dev->resources];
+ dev->resources++;
+ resource->base = 0;
+ resource->size = 256;
+ resource->align = log2(256);
+ resource->gran = log2(256);
+ resource->limit = 65536;
+ resource->flags = IORESOURCE_IO;
+ resource->index = 0x58;
+ }
+ else {
+ printk_err("%s Unexpected resource shortage\n",
+ dev_path(dev));
+ }
}
static struct device_operations acpi_ops = {
- .read_resources = pci_dev_read_resources,
+ .read_resources = acpi_read_resources,
.set_resources = pci_dev_set_resources,
.enable_resources = pci_dev_enable_resources,
.init = acpi_init,
diff --git a/src/southbridge/amd/amd8111/amd8111_early_smbus.c b/src/southbridge/amd/amd8111/amd8111_early_smbus.c
index 4bc515c75d..5157609639 100644
--- a/src/southbridge/amd/amd8111/amd8111_early_smbus.c
+++ b/src/southbridge/amd/amd8111/amd8111_early_smbus.c
@@ -17,7 +17,7 @@ static void enable_smbus(void)
die("SMBUS controller not found\r\n");
}
uint8_t enable;
- print_debug("SMBus controller enabled\r\n");
+ print_spew("SMBus controller enabled\r\n");
pci_write_config32(dev, 0x58, SMBUS_IO_BASE | 1);
enable = pci_read_config8(dev, 0x41);
pci_write_config8(dev, 0x41, enable | (1 << 7));
@@ -134,6 +134,5 @@ static void smbus_write_byte(unsigned device, unsigned address, unsigned char va
/* poll for transaction completion */
smbus_wait_until_done();
-
return;
}
diff --git a/src/southbridge/amd/amd8111/amd8111_ide.c b/src/southbridge/amd/amd8111/amd8111_ide.c
index 4502bb3c45..6f8e018fe6 100644
--- a/src/southbridge/amd/amd8111/amd8111_ide.c
+++ b/src/southbridge/amd/amd8111/amd8111_ide.c
@@ -12,9 +12,6 @@ static void ide_init(struct device *dev)
uint16_t word;
int enable_a=1, enable_b=1;
-
- printk_debug("ide_init\n");
-
word = pci_read_config16(dev, 0x40);
/* Ensure prefetch is disabled */
word &= ~((1 << 15) | (1 << 13));
diff --git a/src/southbridge/amd/amd8111/amd8111_lpc.c b/src/southbridge/amd/amd8111/amd8111_lpc.c
index 535cbece66..b6e25d2c5e 100644
--- a/src/southbridge/amd/amd8111/amd8111_lpc.c
+++ b/src/southbridge/amd/amd8111/amd8111_lpc.c
@@ -7,8 +7,10 @@
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <device/chip.h>
+#include <pc80/mc146818rtc.h>
#include "amd8111.h"
+#define NMI_OFF 0
struct ioapicreg {
unsigned int reg;
@@ -100,8 +102,7 @@ static void lpc_init(struct device *dev)
{
uint8_t byte;
int pwr_on=-1;
-
- printk_debug("lpc_init\n");
+ int nmi_option;
/* IO APIC initialization */
byte = pci_read_config8(dev, 0x4B);
@@ -127,6 +128,31 @@ static void lpc_init(struct device *dev)
byte |= (1 << 5);
pci_write_config8(dev, 0x41, byte);
+ /* Enable Error reporting */
+ /* Set up sync flood detected */
+ byte = pci_read_config8(dev, 0x47);
+ byte |= (1 << 1);
+ pci_write_config8(dev, 0x47, byte);
+
+ /* Set up NMI on errors */
+ byte = pci_read_config8(dev, 0x40);
+ byte |= (1 << 1); /* clear PW2LPC error */
+ byte |= (1 << 6); /* clear LPCERR */
+ pci_write_config8(dev, 0x40, byte);
+ nmi_option = NMI_OFF;
+ get_option(&nmi_option, "nmi");
+ if(nmi_option) {
+ byte |= (1 << 7); /* set NMI */
+ pci_write_config8(dev, 0x40, byte);
+ }
+
+ /* Initialize the real time clock */
+ rtc_init(0);
+
+ /* Initialize isa dma */
+ isa_dma_init();
+
+ /* Initialize the High Precision Event Timers */
enable_hpet(dev);
}
@@ -146,7 +172,7 @@ static void amd8111_lpc_read_resources(device_t dev)
dev->resource[reg].align = 0;
dev->resource[reg].gran = 0;
dev->resource[reg].limit = 0;
- dev->resource[reg].flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_SET;
+ dev->resource[reg].flags = IORESOURCE_IO | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
dev->resource[reg].index = 0;
reg++;
@@ -155,7 +181,7 @@ static void amd8111_lpc_read_resources(device_t dev)
dev->resource[reg].align = 0;
dev->resource[reg].gran = 0;
dev->resource[reg].limit = 0;
- dev->resource[reg].flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_SET;
+ dev->resource[reg].flags = IORESOURCE_MEM | IORESOURCE_SUBTRACTIVE | IORESOURCE_ASSIGNED;
dev->resource[reg].index = 0;
reg++;
@@ -176,4 +202,3 @@ static struct pci_driver lpc_driver __pci_driver = {
.vendor = PCI_VENDOR_ID_AMD,
.device = PCI_DEVICE_ID_AMD_8111_ISA,
};
-
diff --git a/src/southbridge/amd/amd8111/amd8111_pci.c b/src/southbridge/amd/amd8111/amd8111_pci.c
new file mode 100644
index 0000000000..29d3fb88d8
--- /dev/null
+++ b/src/southbridge/amd/amd8111/amd8111_pci.c
@@ -0,0 +1,61 @@
+#include <console/console.h>
+#include <device/device.h>
+#include <device/pci.h>
+#include <device/pci_ids.h>
+#include <device/pci_ops.h>
+#include "amd8111.h"
+
+static void pci_init(struct device *dev)
+{
+
+ /* Enable pci error detecting */
+ uint32_t dword;
+
+ /* System error enable */
+ dword = pci_read_config32(dev, 0x04);
+ dword |= (1<<8); /* System error enable */
+ dword |= (7<<28); /* Clear possible errors */
+ pci_write_config32(dev, 0x04, dword);
+
+ /* System,Parity,timer,and abort error enable */
+ dword = pci_read_config32(dev, 0x3c);
+ dword |= (1<<16); /* Parity */
+ dword |= (1<<17); /* System */
+ dword |= (1<<21); /* Master abort */
+// dword &= ~(1<<21); /* Master abort */
+ dword |= (1<<27); /* Discard timer */
+ dword |= (1<<26); /* DTSTAT error clear */
+ pci_write_config32(dev, 0x3c, dword);
+
+ /* CRC flood enable */
+ dword = pci_read_config32(dev, 0xc4);
+ dword |= (1<<1); /* CRC Flood enable */
+ dword |= (1<<8); /* Clear any CRC errors */
+ dword |= (1<<4); /* Clear any LKFAIL errors */
+ pci_write_config32(dev, 0xc4, dword);
+
+ /* Clear possible errors */
+ dword = pci_read_config32(dev, 0x1c);
+ dword |= (1<<27); /* STA */
+ dword |= (1<<28); /* RTA */
+ dword |= (1<<29); /* RMA */
+ dword |= (1<<30); /* RSE */
+ dword |= (1<<31); /* DPE */
+ dword |= (1<<24); /* MDPE */
+ pci_write_config32(dev, 0x1c, dword);
+}
+
+static struct device_operations pci_ops = {
+ .read_resources = pci_bus_read_resources,
+ .set_resources = pci_dev_set_resources,
+ .enable_resources = pci_bus_enable_resources,
+ .init = pci_init,
+ .scan_bus = pci_scan_bridge,
+};
+
+static struct pci_driver pci_driver __pci_driver = {
+ .ops = &pci_ops,
+ .vendor = PCI_VENDOR_ID_AMD,
+ .device = PCI_DEVICE_ID_AMD_8111_PCI,
+};
+
diff --git a/src/southbridge/amd/amd8111/amd8111_usb.c b/src/southbridge/amd/amd8111/amd8111_usb.c
index 46cfabbcda..407729a381 100644
--- a/src/southbridge/amd/amd8111/amd8111_usb.c
+++ b/src/southbridge/amd/amd8111/amd8111_usb.c
@@ -9,6 +9,7 @@ static void usb_init(struct device *dev)
{
uint32_t cmd;
+#if 0
printk_debug("USB: Setting up controller.. ");
cmd = pci_read_config32(dev, PCI_COMMAND);
pci_write_config32(dev, PCI_COMMAND,
@@ -17,6 +18,7 @@ static void usb_init(struct device *dev)
printk_debug("done.\n");
+#endif
}
diff --git a/src/southbridge/amd/amd8111/amd8111_usb2.c b/src/southbridge/amd/amd8111/amd8111_usb2.c
index 15ed69b0f1..e6dd1e9da2 100644
--- a/src/southbridge/amd/amd8111/amd8111_usb2.c
+++ b/src/southbridge/amd/amd8111/amd8111_usb2.c
@@ -13,6 +13,7 @@ static void usb2_init(struct device *dev)
{
uint32_t cmd;
+#if 0
printk_debug("USB: Setting up controller.. ");
cmd = pci_read_config32(dev, PCI_COMMAND);
pci_write_config32(dev, PCI_COMMAND,
@@ -21,7 +22,7 @@ static void usb2_init(struct device *dev)
printk_debug("done.\n");
-
+#endif
}
static struct device_operations usb2_ops = {
diff --git a/src/southbridge/amd/amd8131/amd8131_bridge.c b/src/southbridge/amd/amd8131/amd8131_bridge.c
index e730997bbc..b96f46db45 100644
--- a/src/southbridge/amd/amd8131/amd8131_bridge.c
+++ b/src/southbridge/amd/amd8131/amd8131_bridge.c
@@ -6,11 +6,16 @@
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
+#include <pc80/mc146818rtc.h>
+
+#define NMI_OFF 0
static void pcix_init(device_t dev)
{
+ uint32_t dword;
uint16_t word;
uint8_t byte;
+ int nmi_option;
/* Enable memory write and invalidate ??? */
byte = pci_read_config8(dev, 0x04);
@@ -40,6 +45,37 @@ static void pcix_init(device_t dev)
pci_write_config16(dev, 0xaa, word);
word = pci_read_config16(dev, 0xac);
pci_write_config16(dev, 0xae, word);
+
+ /* Set up error reporting, enable all */
+ /* system error enable */
+ dword = pci_read_config32(dev, 0x04);
+ dword |= (1<<8);
+ pci_write_config32(dev, 0x04, dword);
+
+ /* system and error parity enable */
+ dword = pci_read_config32(dev, 0x3c);
+ dword |= (3<<16);
+ pci_write_config32(dev, 0x3c, dword);
+
+ /* NMI enable */
+ nmi_option = NMI_OFF;
+ get_option(&nmi_option, "nmi");
+ if(nmi_option) {
+ dword = pci_read_config32(dev, 0x44);
+ dword |= (1<<0);
+ pci_write_config32(dev, 0x44, dword);
+ }
+
+ /* Set up CRC flood enable */
+ dword = pci_read_config32(dev, 0xc0);
+ if(dword) { /* do device A only */
+ dword = pci_read_config32(dev, 0xc4);
+ dword |= (1<<1);
+ pci_write_config32(dev, 0xc4, dword);
+ dword = pci_read_config32(dev, 0xc8);
+ dword |= (1<<1);
+ pci_write_config32(dev, 0xc8, dword);
+ }
return;
}
@@ -69,13 +105,6 @@ static void ioapic_enable(device_t dev)
value &= ~((1 << 1) | (1 << 0));
}
pci_write_config32(dev, 0x44, value);
-
-//BY LYH
- value = pci_read_config32(dev, 0x4);
- value |= 6;
- pci_write_config32(dev, 0x4, value);
-//BY LYH END
-
}
static struct device_operations ioapic_ops = {
diff --git a/src/superio/NSC/pc87360/chip.h b/src/superio/NSC/pc87360/chip.h
index 55787566fc..9e0ef6f976 100644
--- a/src/superio/NSC/pc87360/chip.h
+++ b/src/superio/NSC/pc87360/chip.h
@@ -1,9 +1,3 @@
-#ifndef PNP_INDEX_REG
-#define PNP_INDEX_REG 0x15C
-#endif
-#ifndef PNP_DATA_REG
-#define PNP_DATA_REG 0x15D
-#endif
#ifndef SIO_COM1
#define SIO_COM1_BASE 0x3F8
#endif
@@ -13,8 +7,10 @@
extern struct chip_control superio_NSC_pc87360_control;
+#include <pc80/keyboard.h>
+#include <uart8250.h>
+
struct superio_NSC_pc87360_config {
- struct com_ports com1;
- struct lpt_ports lpt;
- int port;
+ struct uart8250 com1, com2;
+ struct pc_keyboard keyboard;
};
diff --git a/src/superio/NSC/pc87360/pc87360.h b/src/superio/NSC/pc87360/pc87360.h
new file mode 100644
index 0000000000..201da8eb6e
--- /dev/null
+++ b/src/superio/NSC/pc87360/pc87360.h
@@ -0,0 +1,11 @@
+#define PC87360_FDC 0x00 /* Floppy */
+#define PC87360_PP 0x01 /* Parallel port */
+#define PC87360_SP2 0x02 /* Com2 */
+#define PC87360_SP1 0x03 /* Com1 */
+#define PC87360_SWC 0x04
+#define PC87360_KBCM 0x05 /* Mouse */
+#define PC87360_KBCK 0x06 /* Keyboard */
+#define PC87360_GPIO 0x07
+#define PC87360_ACB 0x08
+#define PC87360_FSCM 0x09
+#define PC87360_WDT 0x0A
diff --git a/src/superio/NSC/pc87360/pc87360_early_serial.c b/src/superio/NSC/pc87360/pc87360_early_serial.c
new file mode 100644
index 0000000000..696d3a0570
--- /dev/null
+++ b/src/superio/NSC/pc87360/pc87360_early_serial.c
@@ -0,0 +1,11 @@
+#include <arch/romcc_io.h>
+#include "pc87360.h"
+
+
+static void pc87360_enable_serial(device_t dev, unsigned iobase)
+{
+ pnp_set_logical_device(dev);
+ pnp_set_enable(dev, 0);
+ pnp_set_iobase(dev, PNP_IDX_IO0, iobase);
+ pnp_set_enable(dev, 1);
+}
diff --git a/src/superio/NSC/pc87360/superio.c b/src/superio/NSC/pc87360/superio.c
index 8765eb35cc..50d71ea927 100644
--- a/src/superio/NSC/pc87360/superio.c
+++ b/src/superio/NSC/pc87360/superio.c
@@ -1,324 +1,77 @@
/* Copyright 2000 AG Electronics Ltd. */
+/* Copyright 2003-2004 Linux Networx */
/* This code is distributed without warranty under the GPL v2 (see COPYING) */
#include <arch/io.h>
#include <device/device.h>
+#include <device/pnp.h>
#include <device/chip.h>
#include <console/console.h>
#include <string.h>
#include <bitops.h>
+#include <uart8250.h>
+#include <pc80/keyboard.h>
#include "chip.h"
+#include "pc87360.h"
-void pnp_output(char address, char data)
+static void init(device_t dev)
{
- outb(address, PNP_INDEX_REG);
- outb(data, PNP_DATA_REG);
-}
-
-static void sio_enable(struct chip *chip, enum chip_pass pass)
-{
-
- struct superio_NSC_pc87360_config *conf = (struct superio_NSC_pc87360_config *)chip->chip_info;
-
- switch (pass) {
- case CONF_PASS_PRE_CONSOLE:
- /* Enable Super IO Chip */
- pnp_output(0x07, 6); /* LD 6 = UART1 */
- pnp_output(0x30, 0); /* Dectivate */
- pnp_output(0x60, conf->port >> 8); /* IO Base */
- pnp_output(0x61, conf->port & 0xFF); /* IO Base */
- pnp_output(0x30, 1); /* Activate */
- break;
- default:
- /* nothing yet */
- break;
- }
-}
-
-static void pnp_write_config(device_t dev, unsigned char value, unsigned char reg)
-{
- outb(reg, dev->path.u.pnp.port);
- outb(value, dev->path.u.pnp.port + 1);
-}
-
-static unsigned char pnp_read_config(device_t dev, unsigned char reg)
-{
- outb(reg, dev->path.u.pnp.port);
- return inb(dev->path.u.pnp.port + 1);
-}
-
-static void pnp_set_logical_device(device_t dev)
-{
- pnp_write_config(dev, dev->path.u.pnp.device, 0x07);
-}
-
-static void pnp_set_enable(device_t dev, int enable)
-{
- pnp_write_config(dev, enable?0x1:0x0, 0x30);
-}
-
-static int pnp_read_enable(device_t dev)
-{
- return !!pnp_read_config(dev, 0x30);
-}
-
-#define FLOPPY_DEVICE 0
-#define PARALLEL_DEVICE 1
-#define COM2_DEVICE 2
-#define COM1_DEVICE 3
-#define SWC_DEVICE 4
-#define MOUSE_DEVICE 5
-#define KBC_DEVICE 6
-#define GPIO_DEVICE 7
-#define ACB_DEVICE 8
-#define FSCM_DEVICE 9
-#define WDT_DEVICE 10
-
-struct io_info {
- unsigned mask, set;
-};
-struct pnp_info {
- unsigned flags;
-#define PNP_IO0 0x01
-#define PNP_IO1 0x02
-#define PNP_IRQ0 0x04
-#define PNP_IRQ1 0x08
-#define PNP_DRQ0 0x10
-#define PNP_DRQ1 0x20
- struct io_info io0, io1;
-};
-
-static struct pnp_info pnp_dev_info[] = {
- [ 0] = { PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x07fa, 0}, },
- [ 1] = { PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x04f8, 0}, },
- [ 2] = { PNP_IO0 | PNP_IRQ0 | PNP_DRQ0 | PNP_DRQ1, { 0x7f8, 0 }, },
- [ 3] = { PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, },
- [ 4] = { PNP_IO0 | PNP_IRQ0, { 0xfff0, 0 }, },
- [ 5] = { PNP_IRQ0 },
- [ 6] = { PNP_IO0 | PNP_IO1 | PNP_IRQ0, { 0x7f8, 0 }, { 0x7f8, 0x4}, },
- [ 7] = { PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } },
- [ 8] = { PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } },
- [ 9] = { PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } },
- [10] = { PNP_IO0 | PNP_IRQ0, { 0xfffc, 0 } },
-};
-
-static struct resource *get_resource(device_t dev, unsigned index)
-{
- struct resource *resource;
- int i;
- resource = 0;
- for(i = 0; i < dev->resources; i++) {
- resource = &dev->resource[i];
- if (resource->index == index) {
- break;
- }
- }
- if (!resource || (resource->index != index)) {
- resource = &dev->resource[dev->resources];
- memset(resource, 0, sizeof(*resource));
- dev->resources++;
- }
- /* Initialize the resource values */
- if (!(resource->flags & IORESOURCE_FIXED)) {
- resource->flags = 0;
- resource->base = 0;
- }
- resource->size = 0;
- resource->limit = 0;
- resource->flags = 0;
- resource->index = index;
- resource->align = 0;
- resource->gran = 0;
-
- return resource;
-}
-
-static void pnp_read_ioresource(device_t dev, unsigned index, struct io_info *info)
-{
- struct resource *resource;
- uint32_t size;
- resource = get_resource(dev, index);
-
- /* Initilize the resource */
- resource->limit = 0xffff;
- resource->flags |= IORESOURCE_IO;
-
- /* Set the resource size and alignment */
- size = (0xffff & info->mask);
- resource->size = (~(size | 0xfffff800) + 1);
- resource->align = log2(resource->size);
- resource->gran = resource->align;
-}
-
-
-static void pnp_read_resources(device_t dev)
-{
- struct pnp_info *info;
- struct resource *resource;
- pnp_set_logical_device(dev);
-
- info = &pnp_dev_info[dev->path.u.pnp.device];
-
- if (info->flags & PNP_IO0) {
- pnp_read_ioresource(dev, 0x60, &info->io0);
- }
- if (info->flags & PNP_IO1) {
- pnp_read_ioresource(dev, 0x62, &info->io1);
- }
- if (info->flags & PNP_IRQ0) {
- resource = get_resource(dev, 0x70);
- resource->size = 1;
- resource->flags |= IORESOURCE_IRQ;
- }
- if (info->flags & PNP_IRQ1) {
- resource = get_resource(dev, 0x72);
- resource->size = 1;
- resource->flags |= IORESOURCE_IRQ;
- }
- if (info->flags & PNP_DRQ0) {
- resource = get_resource(dev, 0x74);
- resource->size = 1;
- resource->flags |= IORESOURCE_DRQ;
- }
- if (info->flags & PNP_DRQ1) {
- resource = get_resource(dev, 0x75);
- resource->size = 1;
- resource->flags |= IORESOURCE_DRQ;
- }
-}
-
-static void pnp_set_iobase(device_t dev, unsigned iobase, unsigned index)
-{
- /* Index == 0x60 or 0x62 */
- pnp_write_config(dev, (iobase >> 8) & 0xff, index);
- pnp_write_config(dev, iobase & 0xff, index + 1);
-}
-
-static void pnp_set_irq(device_t dev, unsigned irq, unsigned index)
-{
- /* Index == 0x70 or 0x72 */
- pnp_write_config(dev, irq, index);
-}
-
-static void pnp_set_drq(device_t dev, unsigned drq, unsigned index)
-{
- /* Index == 0x74 */
- pnp_write_config(dev, drq & 0xff, index);
-}
-
-
-static void pnp_set_resource(device_t dev, struct resource *resource)
-{
- if (!(resource->flags & IORESOURCE_SET)) {
-#if 1
- printk_err("ERROR: %s %02x not allocated\n",
- dev_path(dev), resource->index);
-#endif
- return;
- }
- if (resource->flags & IORESOURCE_IO) {
- pnp_set_iobase(dev, resource->base, resource->index);
- }
- else if (resource->flags & IORESOURCE_DRQ) {
- pnp_set_drq(dev, resource->base, resource->index);
- }
- else if (resource->flags & IORESOURCE_IRQ) {
- pnp_set_irq(dev, resource->base, resource->index);
- }
- else {
- printk_err("ERROR: %s %02x unknown resource type\n",
- dev_path(dev), resource->index);
+ struct superio_NSC_pc87360_config *conf;
+ struct resource *res0, *res1;
+ /* Wishlist handle well known programming interfaces more
+ * generically.
+ */
+ if (!dev->enable) {
return;
}
- printk_debug(
- "%s %02x <- [0x%08lx - 0x%08lx %s\n",
- dev_path(dev),
- resource->index,
- resource->base, resource->base + resource->size - 1,
- (resource->flags & IORESOURCE_IO)? "io":
- (resource->flags & IORESOURCE_DRQ)? "drq":
- (resource->flags & IORESOURCE_IRQ)? "irq":
- (resource->flags & IORESOURCE_MEM)? "mem":
- "???");
-}
-
-static void pnp_set_resources(device_t dev)
-{
- int i;
- pnp_set_logical_device(dev);
- for(i = 0; i < dev->resources; i++) {
- pnp_set_resource(dev, &dev->resource[i]);
- }
-
-}
-static void pnp_enable_resources(device_t dev)
-{
- pnp_set_logical_device(dev);
- pnp_set_enable(dev, 1);
-
-}
-static void pnp_enable(device_t dev)
-{
- pnp_set_logical_device(dev);
- if (!dev->enable) {
- pnp_set_enable(dev, 0);
+ conf = dev->chip->chip_info;
+ switch(dev->path.u.pnp.device) {
+ case PC87360_SP1:
+ res0 = get_resource(dev, PNP_IDX_IO0);
+ init_uart8250(res0->base, &conf->com1);
+ break;
+ case PC87360_SP2:
+ res0 = get_resource(dev, PNP_IDX_IO0);
+ init_uart8250(res0->base, &conf->com2);
+ break;
+ case PC87360_KBCK:
+ res0 = get_resource(dev, PNP_IDX_IO0);
+ res1 = get_resource(dev, PNP_IDX_IO1);
+ init_pc_keyboard(res0->base, res1->base, &conf->keyboard);
+ break;
}
}
-static struct device_operations pnp_ops = {
+static struct device_operations ops = {
.read_resources = pnp_read_resources,
.set_resources = pnp_set_resources,
.enable_resources = pnp_enable_resources,
.enable = pnp_enable,
+ .init = init,
};
-#define MAX_FUNCTION 10
-static void enumerate(struct chip *chip)
-{
- struct superio_NSC_pc87360_config *conf = (struct superio_NSC_pc87360_config *)chip->chip_info;
- struct resource *resource;
- struct device_path path;
- device_t dev;
- int i;
-
- chip_enumerate(chip);
- path.type = DEVICE_PATH_PNP;
- path.u.pnp.port = chip->dev->path.u.pnp.port;
-
- /* Set the ops on the newly allocated devices */
- for(i = 0; i <= WDT_DEVICE; i++) {
- path.u.pnp.device = i;
- dev = alloc_find_dev(chip->bus, &path);
- dev->ops = &pnp_ops;
- }
+static struct pnp_info pnp_dev_info[] = {
+ { &ops, PC87360_FDC, PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x07fa, 0}, },
+ { &ops, PC87360_PP, PNP_IO0 | PNP_IRQ0 | PNP_DRQ0, { 0x04f8, 0}, },
+ { &ops, PC87360_SP2, PNP_IO0 | PNP_IRQ0 | PNP_DRQ0 | PNP_DRQ1, { 0x7f8, 0 }, },
+ { &ops, PC87360_SP1, PNP_IO0 | PNP_IRQ0, { 0x7f8, 0 }, },
+ { &ops, PC87360_SWC, PNP_IO0 | PNP_IRQ0, { 0xfff0, 0 }, },
+ { &ops, PC87360_KBCM, PNP_IRQ0 },
+ { &ops, PC87360_KBCK, PNP_IO0 | PNP_IO1 | PNP_IRQ0, { 0x7f8, 0 }, { 0x7f8, 0x4}, },
+ { &ops, PC87360_GPIO, PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } },
+ { &ops, PC87360_ACB, PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } },
+ { &ops, PC87360_FSCM, PNP_IO0 | PNP_IRQ0, { 0xfff8, 0 } },
+ { &ops, PC87360_WDT, PNP_IO0 | PNP_IRQ0, { 0xfffc, 0 } },
+};
- /* Processes the hard codes for com1 */
- path.u.pnp.device = COM1_DEVICE;
- dev = alloc_find_dev(chip->bus, &path);
- resource = get_resource(dev, 0x60);
- if (conf->com1.base) {
- resource->base = conf->com1.base;
- resource->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_SET;
- }
- resource = get_resource(dev, 0x70);
- if (conf->com1.irq) {
- resource->base = conf->com1.irq;
- resource->flags = IORESOURCE_IRQ | IORESOURCE_FIXED | IORESOURCE_SET;
- }
- /* Process the hard codes for the keyboard controller */
- path.u.pnp.device = KBC_DEVICE;
- dev = alloc_find_dev(dev, &path);
- resource = get_resource(dev, 0x60);
- resource->base = 0x60;
- resource->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_SET;
- resource = get_resource(dev, 0x62);
- resource->base = 0x64;
- resource->flags = IORESOURCE_IO | IORESOURCE_FIXED | IORESOURCE_SET;
+static void enumerate(struct chip *chip)
+{
+ pnp_enumerate(chip, sizeof(pnp_dev_info)/sizeof(pnp_dev_info[0]),
+ &pnp_ops, pnp_dev_info);
}
struct chip_control superio_NSC_pc87360_control = {
- .enable = sio_enable,
.enumerate = enumerate,
.name = "NSC 87360"
};