- Moved hlt() to it's own header.
authorEric Biederman <ebiederm@xmission.com>
Thu, 11 Mar 2004 15:01:31 +0000 (15:01 +0000)
committerEric Biederman <ebiederm@xmission.com>
Thu, 11 Mar 2004 15:01:31 +0000 (15:01 +0000)
- Reworked pnp superio device support.  Now complete superio support is less than 100 lines.
- Added support for hard coding resource assignments in Config.lb
- Minor bug fixes to romcc
- Initial support for catching the x86 processor BIST error codes.  I've only seen
  this trigger once in production during a very suspcious reset but...
- added raminit_test to test the code paths in raminit.c for the Opteron
- Removed the IORESOURCE_SET bit and added IORESOURCE_ASSIGNED and IORESOURCE_STORED
  so we can tell what we have really done.
- Added generic AGP/IOMMU setting code to x86
- Added an implementation of memmove and removed reserved identifiers from memcpy
- Added minimal support for booting on pre b3 stepping K8 cores
- Moved the checksum on amd8111 boards because our default location was on top of
  extended RTC registers
- On the Hdama added support for enabling i2c hub so we can get at the temperature
  sensors.  Not that i2c bus was implemented well enough to make that useful.
- Redid the Opteron port so we should only need one reset and most of memory initialization
  is done in cpu_fixup.  This is much, much faster.
- Attempted to make the VGA IO region assigment work.  The code seems to work now...
- Redid the error handling in amdk8/raminit.c to distinguish between a bad value
  and a smbus error, and moved memory clearing out to cpufixup.
- Removed CONFIG_KEYBOARD as it was useless.  See pc87360/superio.c for how to
  setup a legacy keyboard properly.
- Reworked the register values for standard hardware, moving the defintions from
  chip.h into the headers of the initialization routines.  This is much saner
  and is actually implemented.
- Made the hdama port an under clockers BIOS.  I debuged so many interesting problems.
- On amd8111_lpc added setup of architectural/legacy hardware
- Enabled PCI error reporting as much as possible.
- Enhanded build_opt_tbl to generate a header of the cmos option locations so
  that romcc compiled code can query the cmos options.
- In romcc gracefully handle function names that degenerate into function pointers
- Bumped the version to 1.1.6 as we are getting closer to 2.0

  TODO finish optimizing the HT links of non dual boards
  TODO make all Opteron board work again
  TODO convert all superio devices to use the new helpers
  TODO convert the via/epia to freebios2 conventions
  TODO cpu fixup/setup by cpu type

git-svn-id: svn://svn.coreboot.org/coreboot/trunk@1390 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1

101 files changed:
NEWS
src/arch/i386/include/arch/hlt.h [new file with mode: 0644]
src/arch/i386/include/arch/romcc_io.h
src/arch/i386/include/arch/smp/lapic.h [new file with mode: 0644]
src/arch/i386/lib/cpu.c
src/arch/i386/smp/start_stop.c
src/arch/ppc/boot/linuxbios_table.c
src/config/Config.lb
src/config/Options.lb
src/cpu/i386/bist32.inc [new file with mode: 0644]
src/cpu/i386/bist32_fail.inc [new file with mode: 0644]
src/cpu/i386/entry16.inc
src/cpu/i386/entry32.inc
src/cpu/k8/cpufixup.c
src/cpu/k8/earlymtrr.c
src/cpu/k8/earlymtrr.inc
src/cpu/k8/enable_mmx_sse.inc
src/cpu/p6/Config.lb
src/cpu/p6/boot_cpu.c
src/cpu/p6/earlymtrr.c
src/cpu/p6/mtrr.c
src/cpu/p6/pgtbl.c [new file with mode: 0644]
src/devices/Config.lb
src/devices/chip.c
src/devices/device.c
src/devices/device_util.c
src/devices/hypertransport.c
src/devices/pci_device.c
src/devices/pnp_device.c [new file with mode: 0644]
src/include/cpu/k8/mtrr.h
src/include/cpu/p6/mtrr.h
src/include/cpu/p6/pgtbl.h [new file with mode: 0644]
src/include/device/chip.h
src/include/device/device.h
src/include/device/hypertransport.h
src/include/device/hypertransport_def.h [new file with mode: 0644]
src/include/device/pci_def.h
src/include/device/pnp.h
src/include/device/pnp_def.h [new file with mode: 0644]
src/include/device/resource.h
src/include/pc80/keyboard.h [new file with mode: 0644]
src/include/pc80/mc146818rtc.h
src/include/string.h
src/include/uart8250.h
src/lib/Config.lb
src/lib/memcpy.c
src/lib/memmove.c [new file with mode: 0644]
src/lib/uart8250.c
src/mainboard/amd/quartet/Config.lb
src/mainboard/amd/solo/Config.lb
src/mainboard/amd/solo/auto.c
src/mainboard/amd/solo/cmos.layout
src/mainboard/amd/solo/failover.c
src/mainboard/amd/solo/mptable.c
src/mainboard/arima/hdama/Config.lb
src/mainboard/arima/hdama/auto.c
src/mainboard/arima/hdama/cmos.layout
src/mainboard/arima/hdama/failover.c
src/mainboard/arima/hdama/irq_tables.c
src/mainboard/arima/hdama/mainboard.c
src/mainboard/newisys/khepri/Config.lb
src/mainboard/newisys/khepri/auto.c
src/northbridge/amd/amdk8/Config.lb
src/northbridge/amd/amdk8/amdk8.h
src/northbridge/amd/amdk8/coherent_ht.c
src/northbridge/amd/amdk8/cpu_rev.c
src/northbridge/amd/amdk8/early_ht.c
src/northbridge/amd/amdk8/incoherent_ht.c [new file with mode: 0644]
src/northbridge/amd/amdk8/misc_control.c
src/northbridge/amd/amdk8/northbridge.c
src/northbridge/amd/amdk8/raminit.c
src/northbridge/amd/amdk8/raminit.h
src/northbridge/amd/amdk8/raminit_test.c [new file with mode: 0644]
src/northbridge/amd/amdk8/reset_test.c
src/pc80/Config.lb
src/pc80/isa-dma.c [new file with mode: 0644]
src/pc80/keyboard.c
src/pc80/mc146818rtc_early.c
src/pc80/serial.c
src/pc80/serial.inc
src/southbridge/amd/amd8111/Config.lb
src/southbridge/amd/amd8111/amd8111.c
src/southbridge/amd/amd8111/amd8111_acpi.c
src/southbridge/amd/amd8111/amd8111_early_smbus.c
src/southbridge/amd/amd8111/amd8111_ide.c
src/southbridge/amd/amd8111/amd8111_lpc.c
src/southbridge/amd/amd8111/amd8111_pci.c [new file with mode: 0644]
src/southbridge/amd/amd8111/amd8111_usb.c
src/southbridge/amd/amd8111/amd8111_usb2.c
src/southbridge/amd/amd8131/amd8131_bridge.c
src/superio/NSC/pc87360/chip.h
src/superio/NSC/pc87360/pc87360.h [new file with mode: 0644]
src/superio/NSC/pc87360/pc87360_early_serial.c [new file with mode: 0644]
src/superio/NSC/pc87360/superio.c
util/newconfig/config.g
util/options/build_opt_tbl.c
util/romcc/Makefile
util/romcc/romcc.c
util/romcc/tests/fail_test6.c [new file with mode: 0644]
util/romcc/tests/fail_test7.c [new file with mode: 0644]
util/romcc/tests/fail_test8.c [new file with mode: 0644]

diff --git a/NEWS b/NEWS
index d122514043e00115f36227e09962370bfed0a9c2..9bdaa1db630a3eb407e7fc4e6152ca70a5526ccb 100644 (file)
--- a/NEWS
+++ b/NEWS
@@ -1,3 +1,14 @@
+- 1.1.6
+  - pnp/superio devices are now handled cleanly with very little code
+  - Initial support for finding x86 BIST errors
+  - static resource assignments can now be specified in Config.lb
+  - special VGA I/O decode now should work
+  - added generic PCI error reporting enables
+  - build_opt_tbl now generates a header that allows cmos settings to
+    be read from romcc compiled code.
+  - split IORESOURCE_SET into IORESOURCE_ASSIGNED and IORESOURCE_STORED
+  - romcc now gracesfully handles function pointers instead of dying mysteriously
+  - First regression test in amdk8/raminit_test
 - 1.1.5
   - O2, enums, and switch statements work in romcc
   - Support for compiling romcc on non x86 platforms
diff --git a/src/arch/i386/include/arch/hlt.h b/src/arch/i386/include/arch/hlt.h
new file mode 100644 (file)
index 0000000..86ed7c8
--- /dev/null
@@ -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 */
index 1a646359a7acd4683c24a8ea11fbf5dcfd83b54c..c3a0ff76fabbbdbc37c2eea802b88e58b34e4ce5 100644 (file)
@@ -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 (file)
index 0000000..0ac87aa
--- /dev/null
@@ -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 */
index ad982dbc6cb91371aed3d3306f8edfcd7bbb314e..f459f3a8530f95fca3de5c968d2d1cab5d595e77 100644 (file)
@@ -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
index b40452403cca437d82b53869358b13bc94d076ee..bf26437984c7000363f18c1c504eb795f7e7e1d2 100644 (file)
@@ -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)
index 20264c202c8fa3602af8a176d8b3bb9291706505..f199615d5f4a2b6f36bc402fd29f3be335f6e3d4 100644 (file)
@@ -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;
index 4a99d07ffaee210c0407a3711e83fdaa94eb60db..636e5537c6cb8669736b58425defd08c495dec59 100644 (file)
@@ -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
index 936f9c3727fbfb6dc88a2a6d7c382a9874bce274..a175f358e814ea4632122a75c348d02660a5f2c9 100644 (file)
@@ -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
@@ -330,6 +336,29 @@ define USE_OPTION_TABLE
        comment "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 (file)
index 0000000..d2fb98c
--- /dev/null
@@ -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 (file)
index 0000000..f467b06
--- /dev/null
@@ -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
+
index 7ab3ff3bf068ff721af49afa3e5cbda5e92b6a5e..f9e921f2912e81a89de546bfb4adbd7f7bbd7b82 100644 (file)
@@ -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
 
index 6f55f0020314d38da3bb2fcf8e7a0bf9a5bd2032..3d30a3f85f2795d1a5ae0f03de689025af0f5ea4 100644 (file)
@@ -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
+
index 6aa6722579dc917b5b40558bd9f65c92a7024b96..2d347de829d0fddf2dc64ec646e4a778aa5d2568 100644 (file)
@@ -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
index 47ddd1234067b3c758b47dffea2bd9c98585aa13..5fb63d2e7d77888cef3abee04f9437cf70e7d11c 100644 (file)
@@ -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);
index d14afb1a312a6ad6d1ab97df7257d145ae4ebb28..acc917be7def8eccedafdfde0a9dfc7c56e13fb1 100644 (file)
@@ -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
index 5551525d68394865d45327c6cf1154e2dc4a268d..907e817325a968dc8ea2624d62895c392870448b 100644 (file)
@@ -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
index c9d483480aadde413aa30cefc2f56311be2e1986..f6e9777bcd581b93c316864bbd6f1b78f6de80e5 100644 (file)
@@ -3,4 +3,5 @@ uses INTEL_PPRO_MTRR
 dir /cpu/p5
 object cpufixup.o
 object mtrr.o
+object pgtbl.o
 #object l2_cache.o
index 803eecdd5d96b1557123b72c91acd0a6b5323e96..77b060b219bec2cc948a9f7af247869cae700684 100644 (file)
@@ -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);
index f352f3d79180e543264e77c08f845f6aca7a1710..df74f905c8d863b93ddec53b8aded5baed98d333 100644 (file)
@@ -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();
index ac6fd1db37415a113417ebfa2e5444e753f4ebee..7e2eb06e95646b977542d0cc4ec60af038f0422f 100644 (file)
@@ -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 (file)
index 0000000..e996dd0
--- /dev/null
@@ -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;
+}
index 6da04ee2e4b3fd82cbcb3a5228d0961a00545950..50d05579e56ca5787ddabec2bac173e4bb8450ae 100644 (file)
@@ -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
index c9e1ac564318394e975a225f1f41c2edf0bb6bb9..d8a59e30621b1276aa5f4c4eb378f5a070baf9bc 100644 (file)
@@ -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;
index 4f1cbb2c5dd56890614300045148ec43598db2b5..b54e7702947a3bd466f63226c5483176a7aa9949 100644 (file)
@@ -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");
 }
 
index c8067268537f2e6d5e53b78d8eced75c7b97a4cc..013501474cefa8a7ef80b3f4d16c40e9b549fb73 100644 (file)
@@ -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;
+}
+
index b65f518d3a76b231709658d8585937434f410054..e50ebf6f2047e81c5172f6313947c5ba6e30e130 100644 (file)
@@ -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;
index 734b982a6d48239c776acd249401fd6ab38ca257..c3f1f6ac8c5e6fc00655846bca41d734afd4ea7b 100644 (file)
  * @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 (file)
index 0000000..0bccd7d
--- /dev/null
@@ -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]);
+       }
+}
index 5a965eebb8500bb488d2f8eac433813f25c5ea97..890820b12f258c086b44733b23fb5d3cfe9c2041 100644 (file)
@@ -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 */
index 16af10b81b3afb1abe39070470659c436a92188b..92bf62e5c2d1e13860617a93d901dfb71c6bf6a3 100644 (file)
@@ -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 (file)
index 0000000..68e327c
--- /dev/null
@@ -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  */
index dc078a96b773a40cb869cbffc99401e2195c45a0..7dface868fbdee1c3772f12cfee0af284138ff7a 100644 (file)
@@ -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 
 #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;
index 1b2b0169dc05417411e190a37522ce6f5c1e35af..20d9c222983569815b9e443b8a7247aac45d9ec7 100644 (file)
@@ -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);
index e342aeb506a7a70784d5eb52e22ac216c2d88bdb..410495cdcb14fde9f420e604df6d2ff6811e23f4 100644 (file)
@@ -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 (file)
index 0000000..0b44109
--- /dev/null
@@ -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 */
index ad8f1e6b881936e34dea2c0ef0e7e51afe674cf1..46229a12f4c31a2dd0384b3410bcd80fbce7c844 100644 (file)
 #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) */
 
index 0d39fc16630b21d566de3cacc94d72fb45762a22..508fac68ed432ced2b89db36863442ba0abec7e6 100644 (file)
@@ -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 (file)
index 0000000..b077837
--- /dev/null
@@ -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 */
index f90aba19f43bb9ca288786d8919ae856e76744e8..73a3f6e0d523295e33bd5680cd092c3f4344a0bc 100644 (file)
@@ -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 (file)
index 0000000..775dbee
--- /dev/null
@@ -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 */
index 1daf39aa25b179c7d162f08569a8fda78bb7bca8..e7e13c85b7940bafb1aa5cacebe1e6b3466c9cbf 100644 (file)
@@ -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
 # 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
 
index cf9bbb14d245c46c2fea14f67711ce07360310b3..111e23bc15064f5a23d8319615ca289855177400 100644 (file)
@@ -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);
 
index ae45615758c06394c3750f6a0a439cc2fe4a0ec4..f6100266145b77957753b0d15ccdf535818934d7 100644 (file)
@@ -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 */
index a0de47c570e44dba2e0ce808c6267fa8f8c54a93..bd6a2a9090f2049e62538cccbfb79a5fa03c5669 100644 (file)
@@ -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
index ad8e8bd3f06f22d9c6e8cc33ac847818eb0ba848..16db67766dc0144ac0a1a0667309a69ec65f5076 100644 (file)
@@ -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 (file)
index 0000000..0a49083
--- /dev/null
@@ -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;
+}
index ceb4e4aa86d44002b5f955ebdec22aa50bebdd39..67b0a95cfb30f81a669a3733b3cce8fee5637f18 100644 (file)
@@ -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);
+}
index 1a2d8cd09f17714661abd2fcd6227c359206e058..d38ab96407fa2016e66c37eca4f3e36669a748b5 100644 (file)
@@ -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
index 1372e46005acd575a7a1ee15777a3b6382ef89e5..bb9044eb0aa67b515cd117418b1f496cfb95945a 100644 (file)
@@ -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
 
index 5963934fd510e71ee743b8bc55cd96320e1390d3..3a80e4c1bdd7087f0b9dca99dbfc4d16da0d5922 100644 (file)
@@ -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"
 #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
index 5ba4c032c188affa3b1bf89d35943a9cc88eead7..247715e6ac1adb21ec0ea0056717861e4e0b68ef 100644 (file)
@@ -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
 
 
index bd9c17020ec077595b157cc5275c6cff88a6b4f2..bd5869fead752749ee67435d2b9da73bf51978e9 100644 (file)
@@ -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
 }
index dfe432018169863086aa4eaaf7043654c58b6684..42c2e6b33cbcd92fff57dc73f91c59c2648f1b90 100644 (file)
@@ -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 */
index 60d74da0aba7188900ad39779281468e061aa86e..fbb1a2bbee5458f5fcbd0e73163d10fd84c98e61 100644 (file)
@@ -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
@@ -58,6 +64,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
 
index 689346e6f2cb4489f5ac3227f4843e963153c56f..e011809f49d99b2e4a385070a5290eafd0d285dc 100644 (file)
@@ -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"
 #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
 }
index 5ba4c032c188affa3b1bf89d35943a9cc88eead7..247715e6ac1adb21ec0ea0056717861e4e0b68ef 100644 (file)
@@ -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
 
 
index bd9c17020ec077595b157cc5275c6cff88a6b4f2..b22abfea06326c0487cec71978beac51e5da81d5 100644 (file)
@@ -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
 }
index 9be2d1cf140143f7691892ab451228b47b2936c9..c54d43bbd14ac6a30fb349bee05b1f774ce6e98a 100644 (file)
 
 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 ),
        }
 };
index 82041282f643b60e2b7ab1a403b6c33be95c396a..bbc6f537161c78b0c1e45c5e0d69a5d1ffe6a35a 100644 (file)
 #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,
 };
index 6deb3611ba71b8fc270fb381030ee531278e8cd1..f0ffeb4e768eeada6de2eed51be3e47cd3cf08f1 100644 (file)
@@ -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
index df6ad6c88c0b7ffdd2bfca4fabea11138c27bc84..44f128addcfe4e0ac2550bc2f3ec308f5b1ad0f0 100644 (file)
@@ -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"
 #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
 }
index 0110e218ce48b650513e57d04455af8913e91dd5..3b249161fdb04be49d14980f966e6ff7d3770278 100644 (file)
@@ -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
index c8ae95e3833d547a0810300aef7346bf93236138..ca8e8dc3d2974e660696ab43f1373e5648b4541f 100644 (file)
 #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
 #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
index 83fbd40bebf6dae680bc218ca289ca8ee63a1d33..5b6ea16e4ed5ddc8523a06c53427c1700707b280 100644 (file)
  */
 
 #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
 #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;
 }
index 51f235905e723f3b61b500d06fcbbf6dbfc6c37a..0c4c5f8fbdefd8bb9677d53b711fe086c3b26aaf 100644 (file)
@@ -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;
+}
index 4de8fa1075f02328b9b1312fb2e37c7cb892e99c..90f258e1bc4bd13526b96c29ab942acedfd2bcb9 100644 (file)
@@ -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 (file)
index 0000000..711100a
--- /dev/null
@@ -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;
+}
index fe797aa580e03ae6ed9d9d2ea18e99e217fb996d..df28bd033110b631c4a40a6c5b0ef374120f3378 100644 (file)
 #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,
 };
-
index e62aded451e4d3b6b29175308e4f5b47b4d93448..12d8f73c0b044c9055f7ca6ea38a143c0a7e620d 100644 (file)
@@ -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,
 };
-
index 006ab196dfff9ab71a6f139ce557caef28b69cab..bc73fcba1683c58e1591cdb5fb8b582660073f3b 100644 (file)
 #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");
 }
index 7622cb7621ecec37bc8a57dfbc103d2983b35d55..157dd13ee330281862d123513de12611485b2343 100644 (file)
@@ -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 (file)
index 0000000..8e323ea
--- /dev/null
@@ -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;
+}
index 9105324f33b5284d88db5021a65103adf2140709..7f4336ce5f241632b4c2076faf7c9c1d93ec4cce 100644 (file)
@@ -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);
index 0237fa96af31a4c223da4d91bcd4f2b5220097a1..26d548b897714d2bbb7365b5c827b38c54cc06fe 100644 (file)
@@ -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 (file)
index 0000000..45cfb88
--- /dev/null
@@ -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);
+}
index a7ecf8cbd3e6b642fc12ccd822f0123208ec035d..d293f714deb93b44144f8d133fa4ae02e458ef13 100644 (file)
@@ -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);
+       }
+}
index 35f3f5910f5f571e53853d18597edd673097e5b5..0c7d822718136e4c9a98073bf1d4830ac64a96ad 100644 (file)
@@ -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
+}
index c2788d6ec720f9e3319c0fb42755a203a755d90c..89ac425c56406c34013fef74ed4a3d254a030aec 100644 (file)
@@ -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);
index b0f12699e1ff4a80cf9cfd5eac064ea02238141c..7b80697c85dbb2694bdec555685f6c2ca8f874d4 100644 (file)
@@ -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)
index 904b0995b589238890fbd7d27637a8596847b170..5bbbaba65e43b430b0e41892502fd4bfcf3e0a64 100644 (file)
@@ -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
index 8dde5f13c64ebac5228cd0ba1b1cbf62ceaa0d83..d3fdf3b7ba5f5df3202a58654d8f7f7c30ff6689 100644 (file)
@@ -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
        }
 }
 
index 3a5a594f57694c3666d0774da642db51922177dd..e3b7038e46bd19666bbf94add163e62ab82a0f78 100644 (file)
@@ -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,
index 4bc515c75da1893aa4aaeb0f5504af21f0e65e76..5157609639b68bc8fd4139064f47b39d0546c4fc 100644 (file)
@@ -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;
 }
index 4502bb3c45c7108e4af77e7a592ae482cbac1c3b..6f8e018fe66e49000efdb0541d8a786c6fc2c268 100644 (file)
@@ -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));
index 535cbece66f1a937da564bc9d9261929b238c1a9..b6e25d2c5edc35906b2b2d1e801aac0b85a9eb1b 100644 (file)
@@ -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 (file)
index 0000000..29d3fb8
--- /dev/null
@@ -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,
+};
+
index 46cfabbcda2764245dac4893d98afe63f9ab9263..407729a381650dc62f96e3cebbd2045b947eeb77 100644 (file)
@@ -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
 
 }
 
index 15ed69b0f10708357bb94b00437eceee8bb8ccaf..e6dd1e9da2c1effd92717b66d2b523be7eb6fd6f 100644 (file)
@@ -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  = {
index e730997bbc6c869a5691e0c0bb30484886490ccd..b96f46db45059299e6b0eeadf66086344d4eeeae 100644 (file)
@@ -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 = {
index 55787566fc700f06b6d8c86885e035f9e816153f..9e0ef6f9763be665dd30f5a8fa7cdf893920ab39 100644 (file)
@@ -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 (file)
index 0000000..201da8e
--- /dev/null
@@ -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 (file)
index 0000000..696d3a0
--- /dev/null
@@ -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);
+}
index 8765eb35cc33cdd6f4680f92431d8dac4381d04d..50d71ea92756668b3116ec761a4a586ccc4a5677 100644 (file)
 /* 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"
 };
index 03cf941702600239910d6d0426af9b82b9501c72..b7f3d6fbf3f2cb8195f5f995c9ea456ea8396d3d 100644 (file)
@@ -740,6 +740,18 @@ class partobj:
                value = dequote(value)
                setdict(self.registercode, field, value)
 
+       def start_resources(self):
+               self.path = "%s, .resource={" % (self.path)
+
+       def end_resources(self):
+               self.path = "%s}}," % (self.path)
+
+       def add_resource(self, type, index, value):
+               """ Add a resource to a device """
+               self.path = "%s\n\t\t\t{ .flags=%s, .index=0x%x, .base=0x%x}," % (self.path, type, index, value)
+               
+               
+               
        def addpcipath(self, enable, bus, slot, function):
                """ Add a relative pci style path from our parent to this device """
                if ((bus < 0) or (bus > 255)):
@@ -748,7 +760,7 @@ class partobj:
                        fatal("Invalid device id")
                if ((function < 0) or (function > 7)):
                        fatal("Invalid function")
-               self.path = "%s\n\t\t{ .enable = %d, .path = {.type=DEVICE_PATH_PCI,.u={.pci={ .bus = 0x%x, .devfn = PCI_DEVFN(0x%x,%d) }}}}," % (self.path, enable, bus, slot, function)
+               self.path = "%s\n\t\t{ .enable = %d, .path = {.type=DEVICE_PATH_PCI,.u={.pci={ .bus = 0x%x, .devfn = PCI_DEVFN(0x%x,%d)}}}" % (self.path, enable, bus, slot, function)
 
        def addpnppath(self, enable, port, device):
                """ Add a relative path to a pnp device hanging off our parent """
@@ -756,13 +768,14 @@ class partobj:
                        fatal("Invalid port")
                if ((device < 0) or (device > 0xff)):
                        fatal("Invalid device")
-               self.path = "%s\n\t\t{ .enable = %d, .path={.type=DEVICE_PATH_PNP,.u={.pnp={ .port = 0x%x, .device = 0x%x }}}}," % (self.path, enable, port, device)
-
+               self.path = "%s\n\t\t{ .enable = %d, .path={.type=DEVICE_PATH_PNP,.u={.pnp={ .port = 0x%x, .device = 0x%x }}}" % (self.path, enable, port, device)
+               
        def addi2cpath(self, enable, device):
                """ Add a relative path to a i2c device hanging off our parent """
                if ((device < 0) or (device > 0x7f)):
                        fatal("Invalid device")
-               self.path = "%s\n\t\t{ .enable = %d, .path = {.type=DEVICE_PATH_I2C,.u={.i2c={ .device = 0x%x }}}}, " % (self.path, enable, device)
+               self.path = "%s\n\t\t{ .enable = %d, .path = {.type=DEVICE_PATH_I2C,.u={.i2c={ .device = 0x%x }}} " % (self.path, enable, device)
+
 
        def usesoption(self, name):
                """Declare option that can be used by this part"""
@@ -1111,7 +1124,7 @@ def endromimage():
 
 def mainboard(path):
        full_path = os.path.join(treetop, 'src', 'mainboard', path)
-        vendor = re.sub("/.*", "", path)
+       vendor = re.sub("/.*", "", path)
         part_number = re.sub("[^/]*/", "", path)
        setdefault('MAINBOARD', full_path, 1)
        setdefault('MAINBOARD_VENDOR', vendor, 1)
@@ -1278,7 +1291,7 @@ def dequote(str):
        return a
 
 def flatten_name(str):
-       a = re.sub("/", "_", str)
+       a = re.sub("[/-]", "_", str)
        return a
 
 def topify(path):
@@ -1316,6 +1329,7 @@ parser Config:
     token DEPENDS:             'depends'
     token DIR:                 'dir'
     token DRIVER:              'driver'
+    token DRQ:                 'drq'
     token ELSE:                        'else'
     token END:                 'end'
     token EOF:                 '$'
@@ -1326,12 +1340,15 @@ parser Config:
     token INIT:                        'init'
     token INITOBJECT:          'initobject'
     token INITINCLUDE:         'initinclude'
+    token IO:                  'io'
+    token IRQ:                 'irq'
     token LDSCRIPT:            'ldscript'
     token LOADOPTIONS:         'loadoptions'
     token MAINBOARD:           'mainboard'
     token MAINBOARDINIT:       'mainboardinit'
     token MAKEDEFINE:          'makedefine'
     token MAKERULE:            'makerule'
+    token MEM:                 'mem'
     token NEVER:               'never'
     token NONE:                        'none'
     token NORTHBRIDGE:         'northbridge'
@@ -1353,7 +1370,7 @@ parser Config:
     token HEX_PREFIX:          '0x'
     # Why is path separate? Because paths to resources have to at least
     # have a slash, we thinks
-    token PATH:                        r'[a-zA-Z0-9_.][a-zA-Z0-9/_.]+[a-zA-Z0-9_.]+'
+    token PATH:                        r'[-a-zA-Z0-9_.][-a-zA-Z0-9/_.]+[-a-zA-Z0-9_.]+'
     # Dir's on the other hand are abitrary
     # this may all be stupid.
     token DIRPATH:             r'[-a-zA-Z0-9_$()./]+'
@@ -1471,21 +1488,42 @@ parser Config:
                        [ ( ON                  {{ val = 1 }}
                        | OFF                   {{ val = 0 }}
                        ) ]                     {{ return val }}
+
+    rule resource<<C>>:                                {{ type = "" }}
+                       (  IO                   {{ type = "IORESOURCE_IO" }}
+                       |   MEM                 {{ type = "IORESOURCE_MEM" }}
+                       |   IRQ                 {{ type = "IORESOURCE_IRQ" }}
+                       |   DRQ                 {{ type = "IORESOURCE_DRQ" }}
+                       )
+                       term '='                {{ index = term }}
+                       term                    {{ value = term }}
+                                               {{ if (C): partstack.tos().add_resource(type, index, value) }}
+    
+                            
+    rule resources<<C>>:                       {{ if (C): partstack.tos().start_resources() }}
+                       ( resource<<C>> )*
+                                               {{ if (C): partstack.tos().end_resources() }}
+           
     
     rule pci<<C>>:     PCI HEX_NUM             {{ bus = int(HEX_NUM,16) }}
                        ':' HEX_NUM             {{ slot = int(HEX_NUM,16) }}
                        '.' HEX_NUM             {{ function = int(HEX_NUM, 16) }}
                        enable 
                                                {{ if (C): partstack.tos().addpcipath(enable, bus, slot, function) }}
+                       resources<<C>>
 
     rule pnp<<C>>:     PNP HEX_NUM             {{ port = int(HEX_NUM,16) }}
                        '.' HEX_NUM             {{ device = int(HEX_NUM, 16) }}
                        enable
                                                {{ if (C): partstack.tos().addpnppath(enable, port, device) }}
+                       resources<<C>>
+
 
     rule i2c<<C>>:     I2C HEX_NUM             {{ device = int(HEX_NUM, 16) }}
                        enable
                                                {{ if (C): partstatck.tos().addi2cpath(enable, device) }}
+                       resources<<C>>
+                       
                        
     rule prtval:       expr                    {{ return str(expr) }}
                |       STR                     {{ return STR }}
index 183aeab1bdd79055be5af9f09e56fc35c744f02b..a6b5cd306219f6f63f2ab72db7e589e009513661 100644 (file)
@@ -3,6 +3,7 @@
 #include <sys/io.h>
 #include <string.h>
 #include <ctype.h>
+#include <errno.h>
 #include "../../src/include/pc80/mc146818rtc.h"
 #include "../../src/include/boot/linuxbios_tables.h"
 
@@ -99,9 +100,11 @@ void display_usage(void)
 {
         printf("Usage build_opt_table [-b] [--option filename]\n");
         printf("                [--config filename]\n");
+        printf("                [--header filename]\n");
         printf("b = build option_table.c\n");
         printf("--option = name of option table output file\n");
         printf("--config = build the definitions table from the given file\n");
+       printf("--header = ouput a header file with the definitions\n");
         exit(1);
 }
 
@@ -131,6 +134,67 @@ static unsigned long get_number(char *line, char **ptr, int base)
        return value;
 }
 
+static int is_ident_digit(int c)
+{
+       int result;
+       switch(c) {
+       case '0':       case '1':       case '2':       case '3':
+       case '4':       case '5':       case '6':       case '7':
+       case '8':       case '9':
+               result = 1;
+               break;
+       default:
+               result = 0;
+               break;
+       }
+       return result;
+}
+
+static int is_ident_nondigit(int c)
+{
+       int result;
+       switch(c) {
+       case 'A':       case 'B':       case 'C':       case 'D':
+       case 'E':       case 'F':       case 'G':       case 'H':
+       case 'I':       case 'J':       case 'K':       case 'L':
+       case 'M':       case 'N':       case 'O':       case 'P':
+       case 'Q':       case 'R':       case 'S':       case 'T':
+       case 'U':       case 'V':       case 'W':       case 'X':
+       case 'Y':       case 'Z':
+       case 'a':       case 'b':       case 'c':       case 'd':
+       case 'e':       case 'f':       case 'g':       case 'h':
+       case 'i':       case 'j':       case 'k':       case 'l':
+       case 'm':       case 'n':       case 'o':       case 'p':
+       case 'q':       case 'r':       case 's':       case 't':
+       case 'u':       case 'v':       case 'w':       case 'x':
+       case 'y':       case 'z':
+       case '_':
+               result = 1;
+               break;
+       default:
+               result = 0;
+               break;
+       }
+       return result;
+}
+
+static int is_ident(char *str)
+{
+       int result;
+       int ch;
+       ch = *str;
+       result = 0;
+       if (is_ident_nondigit(ch)) {
+               do {
+                       str++;
+                       ch = *str;
+               } while(ch && (is_ident_nondigit(ch) || (is_ident_digit(ch))));
+               result = (ch == '\0');
+       }
+       return result;
+}
+
+
 /* This routine builds the cmos definition table from the cmos layout file
        input The input comes from the configuration file which contains two parts
                entries and enumerations. Each section is started with the key words
@@ -148,6 +212,7 @@ int main(int argc, char **argv)
        int i;
        char *config=0;
        char *option=0;
+       char *header=0;
        FILE *fp;
        struct cmos_option_table *ct;
        struct cmos_entries *ce;
@@ -188,11 +253,18 @@ int main(int argc, char **argv)
                                                 }
                                                 option=argv[++i];
                                                 break;
+                                       case 'h': /* Output a header file */
+                                               if (strcmp(&argv[i][2], "header") != 0) {
+                                                       display_usage();
+                                               }
+                                               header=argv[++i];
+                                               break;
                                         default:
                                                 display_usage();
                                                 break;
                                 }
                                 break;
+
                         default:
                                 display_usage();
                                 break;
@@ -203,13 +275,13 @@ int main(int argc, char **argv)
        /* Has the user specified a configuration file */
        if(config) {    /* if yes, open it */
                if((fp=fopen(config,"r"))==NULL){
-                       printf("Error - Can not open config file %s\n",config);
+                       fprintf(stderr, "Error - Can not open config file %s\n",config);
                        exit(1);  /* exit if it can not be opened */
                }
        }
        else {  /* no configuration file specified, so try the default */
                if((fp=fopen("cmos.layout","r"))==NULL){
-                       printf("Error - Can not open cmos.layout\n");
+                       fprintf(stderr, "Error - Can not open cmos.layout\n");
                        exit(1);  /* end of no configuration file is found */
                }
        }
@@ -254,11 +326,17 @@ int main(int argc, char **argv)
                ce->config=(int)uc;
                /* check bit and length ranges */
                if(ce->bit>(CMOS_IMAGE_BUFFER_SIZE*8)) {
-                        printf("Error - bit is to big in line \n%s\n",line);
+                        fprintf(stderr, "Error - bit is to big in line \n%s\n",line);
                         exit(1);
                 }
                if((ce->length>(MAX_VALUE_BYTE_LENGTH*8))&&(uc!='r')) {
-                       printf("Error - Length is to long in line \n%s\n",line);
+                       fprintf(stderr, "Error - Length is to long in line \n%s\n",line);
+                       exit(1);
+               }
+               if (!is_ident(ce->name)) {
+                       fprintf(stderr, 
+                               "Error - Name %s is an invalid identifier in line\n %s\n", 
+                               ce->name, line);
                        exit(1);
                }
                /* put in the record type */
@@ -353,43 +431,43 @@ int main(int argc, char **argv)
                skip_spaces(line, &ptr);
 
                if ((cs->range_start%8) != 0) {
-                       printf("Error - range start is not byte aligned in line\n%s\n", line);
+                       fprintf(stderr, "Error - range start is not byte aligned in line\n%s\n", line);
                        exit(1);
                }
                if (cs->range_start >= (CMOS_IMAGE_BUFFER_SIZE*8)) {
-                       printf("Error - range start is to big in line\n%s\n", line);
+                       fprintf(stderr, "Error - range start is to big in line\n%s\n", line);
                        exit(1);
                }
                if ((cs->range_end%8) != 7) {
-                       printf("Error - range end is not byte aligned in line\n%s\n", line);
+                       fprintf(stderr, "Error - range end is not byte aligned in line\n%s\n", line);
                        exit(1);
                }
                if ((cs->range_end) >= (CMOS_IMAGE_BUFFER_SIZE*8)) {
-                       printf("Error - range end is to long in line\n%s\n", line);
+                       fprintf(stderr, "Error - range end is to long in line\n%s\n", line);
                        exit(1);
                }
                if ((cs->location%8) != 0) {
-                       printf("Error - location is not byte aligned in line\n%s\n", line);
+                       fprintf(stderr, "Error - location is not byte aligned in line\n%s\n", line);
                        exit(1);
                }
                if ((cs->location >= (CMOS_IMAGE_BUFFER_SIZE*8)) ||
                        ((cs->location + 16) > (CMOS_IMAGE_BUFFER_SIZE*8))) 
                {
-                       printf("Error - location is to big in line\n%s\n", line);
+                       fprintf(stderr, "Error - location is to big in line\n%s\n", line);
                        exit(1);
                }
                /* And since we are not ready to be fully general purpose yet.. */
                if ((cs->range_start/8) != LB_CKS_RANGE_START) {
-                       printf("Error - Range start(%d) does not match define(%d) in line\n%s\n", 
+                       fprintf(stderr, "Error - Range start(%d) does not match define(%d) in line\n%s\n", 
                                cs->range_start/8, LB_CKS_RANGE_START, line);
                        exit(1);
                }
                if ((cs->range_end/8) != LB_CKS_RANGE_END) {
-                       printf("Error - Range end does not match define in line\n%s\n", line);
+                       fprintf(stderr, "Error - Range end does not match define in line\n%s\n", line);
                        exit(1);
                }
                if ((cs->location/8) != LB_CKS_LOC) {
-                       printf("Error - Location does not match define in line\n%s\n", line);
+                       fprintf(stderr, "Error - Location does not match define in line\n%s\n", line);
                        exit(1);
                }
 
@@ -407,19 +485,19 @@ int main(int argc, char **argv)
        /* test if an alternate file is to be created */
        if(option) {
                if((fp=fopen(option,"w"))==NULL){
-                        printf("Error - Can not open %s\n",option);
+                        fprintf(stderr, "Error - Can not open %s\n",option);
                         exit(1);
                }
        }
        else {  /* no, so use the default option_table.c */
                 if((fp=fopen("option_table.c","w"))==NULL){
-                        printf("Error - Can not open option_table.c\n");
+                        fprintf(stderr, "Error - Can not open option_table.c\n");
                         exit(1);
                }
        }
        /* write the header */
         if(!fwrite("unsigned char option_table[] = {",1,32,fp)) {
-                printf("Error - Could not write image file\n");
+                fprintf(stderr, "Error - Could not write image file\n");
                 fclose(fp);
                 exit(1);
         }
@@ -433,12 +511,48 @@ int main(int argc, char **argv)
        sprintf(buf,"0x%02x",cmos_table[i]);
        fwrite(buf,1,4,fp);
         if(!fwrite("};\n",1,3,fp)) {
-                printf("Error - Could not write image file\n");
+                fprintf(stderr, "Error - Could not write image file\n");
                 fclose(fp);
                 exit(1);
         }
 
         fclose(fp);
+
+       /* See if we also want to output a C header file */
+       if (header) {
+               struct cmos_option_table *hdr;
+               struct lb_record *ptr, *end;
+               fp = fopen(header, "w");
+               if (!fp) {
+                       fprintf(stderr, "Error Can not open %s: %s\n", 
+                               header, strerror(errno));
+                       exit(1);
+               }
+               /* Get the cmos table header */
+               hdr = (struct cmos_option_table *)cmos_table;
+               /* Walk through the entry records */
+               ptr = (struct lb_record *)(cmos_table + hdr->header_length);
+               end = (struct lb_record *)(cmos_table + hdr->size);
+               for(;ptr < end; ptr = (struct lb_record *)(((char *)ptr) + ptr->size)) {
+                       if (ptr->tag != LB_TAG_OPTION) {
+                               continue;
+                       }
+                       ce = (struct cmos_entries *)ptr;
+                       if (ce->config == 'r') {
+                               continue;
+                       }
+                       if (!is_ident(ce->name)) {
+                               fprintf(stderr, "Invalid identifier: %s\n",
+                                       ce->name);
+                               exit(1);
+                       }
+                       fprintf(fp, "#define CMOS_VSTART_%s %d\n",
+                               ce->name, ce->bit);
+                       fprintf(fp, "#define CMOS_VLEN_%s %d\n",
+                               ce->name, ce->length);
+               }
+               fclose(fp);
+       }
        return(0);
 }
 
index e8dd0a96792f5dd36153729dc0e6f47d7d50815f..75fb56c01f735bb079e9b085a369970019f34640 100644 (file)
@@ -1,5 +1,5 @@
-VERSION:=0.37
-RELEASE_DATE:=21 October 2003
+VERSION:=0.38
+RELEASE_DATE:=18 December 2003
 PACKAGE:=romcc
 
 
@@ -108,6 +108,9 @@ FAIL_TESTS = \
        fail_test3.c \
        fail_test4.c \
        fail_test5.c \
+       fail_test6.c \
+       fail_test7.c \
+       fail_test8.c \
 
 TEST_SRCS:=$(patsubst %, tests/%, $(TESTS))
 TEST_ASM:=$(patsubst %.c, tests/%.S, $(TESTS))
index d460cfb5486739e69e126371d01ce7ff2b24638a..ff7aee669b12c295d893b5a790d5839f42913b8f 100644 (file)
@@ -1579,7 +1579,7 @@ static unsigned short triple_sizes(struct compile_state *state,
                rhs = rhs_wanted;
                lhs = 0;
                if ((type->type & TYPE_MASK) == TYPE_STRUCT) {
-                       lhs = type->left->elements;
+                       lhs = type->elements;
                }
        }
        else if (op == OP_VAL_VEC) {
@@ -4822,7 +4822,8 @@ static int is_stable(struct compile_state *state, struct triple *def)
        if ((def->op == OP_ADECL) || 
                (def->op == OP_SDECL) || 
                (def->op == OP_DEREF) ||
-               (def->op == OP_BLOBCONST)) {
+               (def->op == OP_BLOBCONST) ||
+               (def->op == OP_LIST)) {
                ret = 1;
        }
        else if (def->op == OP_DOT) {
@@ -4930,6 +4931,9 @@ static struct triple *do_mk_addr_expr(struct compile_state *state,
                        RHS(expr, 0),
                        int_const(state, &ulong_type, offset));
        }
+       else if (expr->op == OP_LIST) {
+               error(state, 0, "Function addresses not supported");
+       }
        if (!result) {
                internal_error(state, expr, "cannot take address of expression");
        }
@@ -4951,8 +4955,9 @@ static struct triple *mk_deref_expr(
        return triple(state, OP_DEREF, base_type, expr, 0);
 }
 
-static struct triple *array_to_pointer(struct compile_state *state, struct triple *def)
+static struct triple *lvalue_conversion(struct compile_state *state, struct triple *def)
 {
+       /* Tranform an array to a pointer to the first element */
        if ((def->type->type & TYPE_MASK) == TYPE_ARRAY) {
                struct type *type;
                type = new_type(
@@ -4971,6 +4976,10 @@ static struct triple *array_to_pointer(struct compile_state *state, struct tripl
                        def = triple(state, OP_COPY, type, def, 0);
                }
        }
+       /* Transform a function to a pointer to it */
+       else if ((def->type->type & TYPE_MASK) == TYPE_FUNCTION) {
+               def = mk_addr_expr(state, def, 0);
+       }
        return def;
 }
 
@@ -5010,15 +5019,12 @@ static struct triple *read_expr(struct compile_state *state, struct triple *def)
        if  (!def) {
                return 0;
        }
+#warning "CHECK_ME is this the only place I need to do lvalue conversions?"
+       /* Transform lvalues into something we can read */
+       def = lvalue_conversion(state, def);
        if (!is_stable(state, def)) {
                return def;
        }
-       /* Tranform an array to a pointer to the first element */
-       
-#warning "CHECK_ME is this the right place to transform arrays to pointers?"
-       if ((def->type->type & TYPE_MASK) == TYPE_ARRAY) {
-               return array_to_pointer(state, def);
-       }
        if (is_in_reg(state, def)) {
                op = OP_READ;
        } else {
@@ -8268,7 +8274,11 @@ static struct triple *expr(struct compile_state *state)
 static void expr_statement(struct compile_state *state, struct triple *first)
 {
        if (peek(state) != TOK_SEMI) {
-               flatten(state, first, expr(state));
+               /* lvalue conversions always apply except when certaion operators
+                * are applied so the values so apply them here as I know no more
+                * operators will be applied.
+                */
+               flatten(state, first, lvalue_conversion(state, expr(state)));
        }
        eat(state, TOK_SEMI);
 }
@@ -9650,7 +9660,7 @@ static struct triple *initializer(
                        ((result->type->type & TYPE_MASK) == TYPE_ARRAY) &&
                        (type->type & TYPE_MASK) != TYPE_ARRAY)
                {
-                       result = array_to_pointer(state, result);
+                       result = lvalue_conversion(state, result);
                }
                if (!is_init_compatible(state, type, result->type)) {
                        error(state, 0, "Incompatible types in initializer");
@@ -18548,6 +18558,7 @@ static void print_const(struct compile_state *state,
                case TYPE_UINT:
                case TYPE_LONG:
                case TYPE_ULONG:
+               case TYPE_POINTER:
                        fprintf(fp, ".int %lu\n", 
                                (unsigned long)(ins->u.cval));
                        break;
diff --git a/util/romcc/tests/fail_test6.c b/util/romcc/tests/fail_test6.c
new file mode 100644 (file)
index 0000000..cc7bcf5
--- /dev/null
@@ -0,0 +1,11 @@
+
+
+static void hlt(void)
+{
+}
+
+static void main(void)
+{
+       void *foo;
+       foo = hlt;
+}
diff --git a/util/romcc/tests/fail_test7.c b/util/romcc/tests/fail_test7.c
new file mode 100644 (file)
index 0000000..e7a0db9
--- /dev/null
@@ -0,0 +1,10 @@
+
+
+static void hlt(void)
+{
+}
+
+static void main(void)
+{
+       &hlt;
+}
diff --git a/util/romcc/tests/fail_test8.c b/util/romcc/tests/fail_test8.c
new file mode 100644 (file)
index 0000000..10ade55
--- /dev/null
@@ -0,0 +1,10 @@
+
+
+static void hlt(void)
+{
+}
+
+static void main(void)
+{
+       hlt;
+}