From 2c018fba95a5f40c4eaaa20421e8c893dffdb62e Mon Sep 17 00:00:00 2001 From: Eric Biederman Date: Mon, 21 Jul 2003 20:13:45 +0000 Subject: [PATCH] - First pass at s2880 support. - SMP cleanups (remove SMP only use CONFIG_SMP) - Minor tweaks to romcc to keep it from taking forever compiling - failover fixes - Get a good implementation of k8_cpufixup and sizeram for the opteron git-svn-id: svn://svn.coreboot.org/coreboot/trunk@998 2b7e53f0-3cfb-0310-b3e9-8179ed1497e1 --- src/arch/i386/include/arch/smp/atomic.h | 69 ++++ src/arch/i386/include/arch/smp/spinlock.h | 57 +++ src/arch/i386/lib/c_start.S | 4 +- src/boot/hardwaremain.c | 11 +- src/config/Options.lb | 5 - src/cpu/k8/cpufixup.c | 72 ++-- src/devices/device.c | 4 - src/include/cpu/k8/mtrr.h | 10 +- src/include/device/device.h | 4 +- src/include/smp/atomic.h | 4 +- src/include/smp/spinlock.h | 4 +- src/lib/fallback_boot.c | 2 +- src/mainboard/amd/quartet/auto.c | 5 + src/mainboard/amd/solo/auto.c | 6 + src/mainboard/arima/hdama/auto.c | 77 ++-- src/mainboard/tyan/s2880/Config.lb | 134 +++++++ src/mainboard/tyan/s2880/VERSION | 1 + src/mainboard/tyan/s2880/auto.c | 437 +++++++++++++++++++++ src/mainboard/tyan/s2880/cmos.layout | 74 ++++ src/mainboard/tyan/s2880/failover.c | 26 ++ src/mainboard/tyan/s2880/irq_tables.c | 37 ++ src/mainboard/tyan/s2880/mainboard.c | 120 ++++++ src/mainboard/tyan/s2880/mptable.c | 99 +++++ src/northbridge/amd/amdk8/coherent_ht.c | 4 +- src/northbridge/amd/amdk8/northbridge.c | 93 ++++- src/northbridge/amd/amdk8/raminit.c | 294 ++++++++------ src/northbridge/amd/amdk8/raminit.h | 1 + src/northbridge/amd/amdk8/reset_test.c | 8 +- src/pc80/mc146818rtc_early.c | 15 +- src/sdram/generic_sdram.c | 23 +- src/southbridge/amd/amd8111/amd8111_lpc.c | 8 + src/southbridge/amd/amd8111/amd8111_usb2.c | 38 ++ util/romcc/romcc.c | 34 +- 33 files changed, 1512 insertions(+), 268 deletions(-) create mode 100644 src/arch/i386/include/arch/smp/atomic.h create mode 100644 src/arch/i386/include/arch/smp/spinlock.h create mode 100644 src/mainboard/tyan/s2880/Config.lb create mode 100644 src/mainboard/tyan/s2880/VERSION create mode 100644 src/mainboard/tyan/s2880/auto.c create mode 100644 src/mainboard/tyan/s2880/cmos.layout create mode 100644 src/mainboard/tyan/s2880/failover.c create mode 100644 src/mainboard/tyan/s2880/irq_tables.c create mode 100644 src/mainboard/tyan/s2880/mainboard.c create mode 100644 src/mainboard/tyan/s2880/mptable.c create mode 100644 src/southbridge/amd/amd8111/amd8111_usb2.c diff --git a/src/arch/i386/include/arch/smp/atomic.h b/src/arch/i386/include/arch/smp/atomic.h new file mode 100644 index 0000000000..7b68377c22 --- /dev/null +++ b/src/arch/i386/include/arch/smp/atomic.h @@ -0,0 +1,69 @@ +#ifndef ARCH_SMP_ATOMIC_H +#define ARCH_SMP_ATOMIC_H + +/* + * Make sure gcc doesn't try to be clever and move things around + * on us. We need to use _exactly_ the address the user gave us, + * not some alias that contains the same information. + */ +typedef struct { volatile int counter; } atomic_t; + +#define ATOMIC_INIT(i) { (i) } + +/* + * Atomic operations that C can't guarantee us. Useful for + * resource counting etc.. + */ + +/** + * atomic_read - read atomic variable + * @v: pointer of type atomic_t + * + * Atomically reads the value of @v. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_read(v) ((v)->counter) + +/** + * atomic_set - set atomic variable + * @v: pointer of type atomic_t + * @i: required value + * + * Atomically sets the value of @v to @i. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +#define atomic_set(v,i) (((v)->counter) = (i)) + +/** + * atomic_inc - increment atomic variable + * @v: pointer of type atomic_t + * + * Atomically increments @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ void atomic_inc(atomic_t *v) +{ + __asm__ __volatile__( + "lock ; incl %0" + :"=m" (v->counter) + :"m" (v->counter)); +} + +/** + * atomic_dec - decrement atomic variable + * @v: pointer of type atomic_t + * + * Atomically decrements @v by 1. Note that the guaranteed + * useful range of an atomic_t is only 24 bits. + */ +static __inline__ void atomic_dec(atomic_t *v) +{ + __asm__ __volatile__( + "lock ; decl %0" + :"=m" (v->counter) + :"m" (v->counter)); +} + + + +#endif /* ARCH_SMP_ATOMIC_H */ diff --git a/src/arch/i386/include/arch/smp/spinlock.h b/src/arch/i386/include/arch/smp/spinlock.h new file mode 100644 index 0000000000..d0cc11c6a7 --- /dev/null +++ b/src/arch/i386/include/arch/smp/spinlock.h @@ -0,0 +1,57 @@ +#ifndef ARCH_SMP_SPINLOCK_H +#define ARCH_SMP_SPINLOCK_H + +/* + * Your basic SMP spinlocks, allowing only a single CPU anywhere + */ + +typedef struct { + volatile unsigned int lock; +} spinlock_t; + + +#define SPIN_LOCK_UNLOCKED (spinlock_t) { 1 } + +/* + * Simple spin lock operations. There are two variants, one clears IRQ's + * on the local processor, one does not. + * + * We make no fairness assumptions. They have a cost. + */ +#define barrier() __asm__ __volatile__("": : :"memory") +#define spin_is_locked(x) (*(volatile char *)(&(x)->lock) <= 0) +#define spin_unlock_wait(x) do { barrier(); } while(spin_is_locked(x)) + +#define spin_lock_string \ + "\n1:\t" \ + "lock ; decb %0\n\t" \ + "js 2f\n" \ + ".section .text.lock,\"ax\"\n" \ + "2:\t" \ + "cmpb $0,%0\n\t" \ + "rep;nop\n\t" \ + "jle 2b\n\t" \ + "jmp 1b\n" \ + ".previous" + +/* + * This works. Despite all the confusion. + */ +#define spin_unlock_string \ + "movb $1,%0" + +static inline void spin_lock(spinlock_t *lock) +{ + __asm__ __volatile__( + spin_lock_string + :"=m" (lock->lock) : : "memory"); +} + +static inline void spin_unlock(spinlock_t *lock) +{ + __asm__ __volatile__( + spin_unlock_string + :"=m" (lock->lock) : : "memory"); +} + +#endif /* ARCH_SMP_SPINLOCK_H */ diff --git a/src/arch/i386/lib/c_start.S b/src/arch/i386/lib/c_start.S index 48c1514a1e..dfe57dd7f0 100644 --- a/src/arch/i386/lib/c_start.S +++ b/src/arch/i386/lib/c_start.S @@ -1,6 +1,6 @@ #include #include -#ifdef SMP +#ifdef CONFIG_SMP #include #endif .section ".text" @@ -39,7 +39,7 @@ _start: /* set new stack */ movl $_estack, %esp -#ifdef SMP +#ifdef CONFIG_SMP /* Get the cpu id */ movl $APIC_DEFAULT_BASE, %edi movl APIC_ID(%edi), %eax diff --git a/src/boot/hardwaremain.c b/src/boot/hardwaremain.c index 1443727948..0477253ec4 100644 --- a/src/boot/hardwaremain.c +++ b/src/boot/hardwaremain.c @@ -68,8 +68,11 @@ static struct mem_range *get_ramsize(void) mem = sizeram(); } if (!mem) { - printk_err("No memory size information!\n"); - for(;;); + printk_emerg("No memory size information!\n"); + for(;;) { + /* Ensure this loop is not optimized away */ + asm volatile("":/* outputs */:/*inputs */ :"memory"); + } } return mem; } @@ -120,9 +123,9 @@ static void wait_for_other_cpus(void) printk_debug("All AP CPUs stopped\n"); } -#else /* SMP */ +#else /* CONIFG_SMP */ #define wait_for_other_cpus() do {} while(0) -#endif /* SMP */ +#endif /* CONFIG_SMP */ void hardwaremain(int boot_complete) { diff --git a/src/config/Options.lb b/src/config/Options.lb index e56e664194..eb3c4e16ab 100644 --- a/src/config/Options.lb +++ b/src/config/Options.lb @@ -380,11 +380,6 @@ define CONFIG_SMP export always comment "Define if we support SMP" end -define SMP - default none - export always - comment "Define if we support SMP" -end define MAX_CPUS default 1 export always diff --git a/src/cpu/k8/cpufixup.c b/src/cpu/k8/cpufixup.c index 8e7ad95d5d..573064071d 100644 --- a/src/cpu/k8/cpufixup.c +++ b/src/cpu/k8/cpufixup.c @@ -2,60 +2,52 @@ #include #include #include - -#define TOP_MEM 0xc001001A -#define TOP_MEM2 0xc001001D -#define IORR_FIRST 0xC0010016 -#define IORR_LAST 0xC0010019 -#define SYSCFG 0xC0010010 - -#define MTRRVARDRAMEN (1 << 20) +#include +#include void k8_cpufixup(struct mem_range *mem) { - msr_t msr; + unsigned long mmio_basek, tomk; unsigned long i; - unsigned long ram_megabytes; - - /* For now no Athlon board has significant holes in it's - * address space so just find the last memory region - * and compute the end of memory from that. + msr_t msr; + /* Except for the PCI MMIO hold just before 4GB there are no + * significant holes in the address space, so just account + * for those two and move on. */ - for(i = 0; mem[i].sizek; i++) - ; - if (i == 0) - return; - ram_megabytes = (mem[i-1].basek + mem[i-1].sizek) *1024; - + mmio_basek = tomk = 0; + for(i = 0; mem[i].sizek; i++) { + unsigned long topk; + topk = mem[i].basek + mem[i].sizek; + if (tomk < topk) { + tomk = topk; + } + if ((topk < 4*1024*1024) && (mmio_basek < topk)) { + mmio_basek = topk; + } + } + if (mmio_basek > tomk) { + mmio_basek = tomk; + } -#warning "FIXME handle > 4GB of ram" - // 8 MB alignment please - ram_megabytes += 0x7fffff; - ram_megabytes &= (~0x7fffff); - - // set top_mem registers to ram size - printk_spew("Setting top_mem to 0x%x\n", ram_megabytes); - msr = rdmsr(TOP_MEM); - printk_spew("TOPMEM was 0x%02x:0x%02x\n", msr.hi, msr.lo); - msr.hi = 0; - msr.lo = ram_megabytes; + /* Setup TOP_MEM */ + msr.hi = mmio_basek >> 22; + msr.lo = mmio_basek << 10; wrmsr(TOP_MEM, msr); - // I am setting this even though I won't enable it + /* Setup TOP_MEM2 */ + msr.hi = tomk >> 22; + msr.lo = tomk << 12; wrmsr(TOP_MEM2, msr); /* zero the IORR's before we enable to prevent - * undefined side effects + * undefined side effects. */ msr.lo = msr.hi = 0; - for (i = IORR_FIRST; i <= IORR_LAST; i++) + for(i = IORR_FIRST; i <= IORR_LAST; i++) { wrmsr(i, msr); - + } + msr = rdmsr(SYSCFG); - printk_spew("SYSCFG was 0x%x:0x%x\n", msr.hi, msr.lo); - msr.lo |= MTRRVARDRAMEN; + msr.lo |= SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_TOM2En; wrmsr(SYSCFG, msr); - msr = rdmsr(SYSCFG); - printk_spew("SYSCFG IS NOW 0x%x:0x%x\n", msr.hi, msr.lo); } - diff --git a/src/devices/device.c b/src/devices/device.c index 291c10cde2..9e5e24580c 100644 --- a/src/devices/device.c +++ b/src/devices/device.c @@ -33,9 +33,6 @@ static struct device **last_dev_p = &all_devices; #define DEVICE_IO_START 0x1000 -unsigned long device_memory_base; - - /* Append a new device to the global device chain. * The chain is used to find devices once everything is set up. */ @@ -379,7 +376,6 @@ void dev_configure(void) root->resource[1].base = round_down(DEVICE_MEM_HIGH - root->resource[1].size, 1UL << root->resource[1].align); - device_memory_base = root->resource[1].base; root->resource[1].flags |= IORESOURCE_SET; // now just set things into registers ... we hope ... root->ops->set_resources(root); diff --git a/src/include/cpu/k8/mtrr.h b/src/include/cpu/k8/mtrr.h index ce9e6d4d04..832df3b8d3 100644 --- a/src/include/cpu/k8/mtrr.h +++ b/src/include/cpu/k8/mtrr.h @@ -1,9 +1,8 @@ #ifndef CPU_K8_MTRR_H #define CPU_K8_MTRR_H -#include +#include -#if 0 #define IORR_FIRST 0xC0010016 #define IORR_LAST 0xC0010019 #define SYSCFG 0xC0010010 @@ -12,17 +11,12 @@ #define MTRR_WRITE_MEM (1 << 3) #define SYSCFG_MSR 0xC0010010 -#define SYSCFG_MSR_EvictEn (1 << 22) #define SYSCFG_MSR_TOM2En (1 << 21) #define SYSCFG_MSR_MtrrVarDramEn (1 << 20) #define SYSCFG_MSR_MtrrFixDramModEn (1 << 19) #define SYSCFG_MSR_MtrrFixDramEn (1 << 18) #define SYSCFG_MSR_UcLockEn (1 << 17) #define SYSCFG_MSR_ChxToDirtyDis (1 << 16) -#define SYSCFG_MSR_SysEccEn (1 << 15) -#define SYSCFG_MSR_RdBlkL2WayEn (1 << 14) -#define SYSCFG_MSR_SysFillValIsD1 (1 << 13) -#define SYSCFG_MSR_IcInclusive (1 << 12) #define SYSCFG_MSR_ClVicBlkEn (1 << 11) #define SYSCFG_MSR_SetDirtyEnO (1 << 10) #define SYSCFG_MSR_SetDirtyEnS (1 << 9) @@ -40,6 +34,4 @@ #define TOP_MEM2 0xC001001D #define HWCR_MSR 0xC0010015 -#endif - #endif /* CPU_K8_MTRR_H */ diff --git a/src/include/device/device.h b/src/include/device/device.h index 4ad776ffc9..d5013f15da 100644 --- a/src/include/device/device.h +++ b/src/include/device/device.h @@ -17,7 +17,7 @@ struct device_operations { #define MAX_RESOURCES 6 /* - * There is one pci_dev structure for each slot-number/function-number + * There is one device structure for each slot-number/function-number * combination: */ @@ -75,8 +75,6 @@ void compute_allocate_resource(device_t bus, struct resource *bridge, unsigned long type_mask, unsigned long type); void assign_resources(device_t bus); void enumerate_static_device(void); -unsigned long device_memory_base; - /* Helper functions */ device_t dev_find_device (unsigned int vendor, unsigned int device, device_t from); diff --git a/src/include/smp/atomic.h b/src/include/smp/atomic.h index b36e0e2051..4748990f12 100644 --- a/src/include/smp/atomic.h +++ b/src/include/smp/atomic.h @@ -1,7 +1,7 @@ #ifndef SMP_ATOMIC_H #define SMP_ATOMIC_H -#ifdef SMP +#ifdef CONFIG_SMP #include #else @@ -48,6 +48,6 @@ typedef struct { int counter; } atomic_t; #define atomic_dec(v) (((v)->counter)--) -#endif /* SMP */ +#endif /* CONFIG_SMP */ #endif /* SMP_ATOMIC_H */ diff --git a/src/include/smp/spinlock.h b/src/include/smp/spinlock.h index 9e0f8af0a9..77a0e51682 100644 --- a/src/include/smp/spinlock.h +++ b/src/include/smp/spinlock.h @@ -1,9 +1,9 @@ #ifndef SMP_SPINLOCK_H #define SMP_SPINLOCK_H -#ifdef SMP +#ifdef CONFIG_SMP #include -#else /* !SMP */ +#else /* !CONFIG_SMP */ /* Most GCC versions have a nasty bug with empty initializers */ #if (__GNUC__ > 2) diff --git a/src/lib/fallback_boot.c b/src/lib/fallback_boot.c index 1bddd0a169..fe34e081fb 100644 --- a/src/lib/fallback_boot.c +++ b/src/lib/fallback_boot.c @@ -16,7 +16,7 @@ void boot_successful(void) byte = inb(RTC_PORT(1)); byte &= 0xfe; - byte |= (byte & 2) >> 1; + byte |= (byte & (1 << 1)) >> 1; /* If we are in normal mode set the boot count to 0 */ if(byte & 1) diff --git a/src/mainboard/amd/quartet/auto.c b/src/mainboard/amd/quartet/auto.c index b773379dc6..8ba6a0d6e9 100644 --- a/src/mainboard/amd/quartet/auto.c +++ b/src/mainboard/amd/quartet/auto.c @@ -86,6 +86,11 @@ static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes) return ret; } +static inline int spd_read_byte(unsigned device, unsigned address) +{ + return smbus_read_byte(device, address); +} + #include "northbridge/amd/amdk8/cpu_ldtstop.c" #include "southbridge/amd/amd8111/amd8111_ldtstop.c" diff --git a/src/mainboard/amd/solo/auto.c b/src/mainboard/amd/solo/auto.c index 848cddfc5b..bb1cd753fe 100644 --- a/src/mainboard/amd/solo/auto.c +++ b/src/mainboard/amd/solo/auto.c @@ -25,6 +25,12 @@ static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes) return 0x00010101; /* default row entry */ } +static inline int spd_read_byte(unsigned device, unsigned address) +{ + return smbus_read_byte(device, address); +} + + #include "northbridge/amd/amdk8/raminit.c" #include "northbridge/amd/amdk8/coherent_ht.c" #include "sdram/generic_sdram.c" diff --git a/src/mainboard/arima/hdama/auto.c b/src/mainboard/arima/hdama/auto.c index 9ae459b136..ba0d7e0408 100644 --- a/src/mainboard/arima/hdama/auto.c +++ b/src/mainboard/arima/hdama/auto.c @@ -17,7 +17,7 @@ #include "northbridge/amd/amdk8/reset_test.c" #include "debug.c" -static void memreset_setup(const struct mem_controller *ctrl) +static void memreset_setup(void) { /* Set the memreset low */ outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 28); @@ -25,12 +25,12 @@ static void memreset_setup(const struct mem_controller *ctrl) outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 29); } -static void memreset(const struct mem_controller *ctrl) +static void memreset(int controllers, const struct mem_controller *ctrl) { udelay(800); /* Set memreset_high */ outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), SMBUS_IO_BASE + 0xc0 + 28); - udelay(50); + udelay(90); } static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes) @@ -77,6 +77,11 @@ static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes) return ret; } +static inline int spd_read_byte(unsigned device, unsigned address) +{ + return smbus_read_byte(device, address); +} + #include "northbridge/amd/amdk8/cpu_ldtstop.c" #include "southbridge/amd/amd8111/amd8111_ldtstop.c" @@ -137,53 +142,64 @@ static void pc87360_enable_serial(void) pnp_set_iobase0(SIO_BASE, 0x3f8); } +#define FIRST_CPU 1 +#define SECOND_CPU 0 +#define TOTAL_CPUS (FIRST_CPU + SECOND_CPU) static void main(void) { /* * GPIO28 of 8111 will control H0_MEMRESET_L * GPIO29 of 8111 will control H1_MEMRESET_L */ - - static const struct mem_controller cpu0 = { - .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 = { (0xa<<3)|0, (0xa<<3)|2, 0, 0 }, - .channel1 = { (0xa<<3)|1, (0xa<<3)|3, 0, 0 }, - }; - static const struct mem_controller cpu1 = { - .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 = { (0xa<<3)|4, (0xa<<3)|6, 0, 0 }, - .channel1 = { (0xa<<3)|5, (0xa<<3)|7, 0, 0 }, + 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 = { (0xa<<3)|0, (0xa<<3)|2, 0, 0 }, + .channel1 = { (0xa<<3)|1, (0xa<<3)|3, 0, 0 }, + }, +#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 = { (0xa<<3)|4, (0xa<<3)|6, 0, 0 }, + .channel1 = { (0xa<<3)|5, (0xa<<3)|7, 0, 0 }, + }, +#endif }; if (cpu_init_detected()) { asm("jmp __cpu_reset"); } - pc87360_enable_serial(); - uart_init(); - console_init(); enable_lapic(); + init_timer(); if (!boot_cpu()) { stop_this_cpu(); } - init_timer(); + pc87360_enable_serial(); + uart_init(); + console_init(); setup_default_resource_map(); setup_coherent_ht_domain(); enumerate_ht_chain(0); - distinguish_cpu_resets(); + distinguish_cpu_resets(0); -#if 1 +#if 0 print_pci_devices(); #endif enable_smbus(); #if 0 - dump_spd_registers(&cpu0); + dump_spd_registers(&cpu[0]); #endif - sdram_initialize(&cpu0); + memreset_setup(); + sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu); #if 1 dump_pci_devices(); @@ -204,7 +220,12 @@ static void main(void) #if 0 ram_check(0x00000000, msr.lo); #else - /* Check 16MB of memory */ +#if TOTAL_CPUS < 2 + /* Check 16MB of memory @ 0*/ ram_check(0x00000000, 0x01000000); +#else + /* Check 16MB of memory @ 2GB */ + ram_check(0x80000000, 0x81000000); +#endif #endif } diff --git a/src/mainboard/tyan/s2880/Config.lb b/src/mainboard/tyan/s2880/Config.lb new file mode 100644 index 0000000000..59e5b90f03 --- /dev/null +++ b/src/mainboard/tyan/s2880/Config.lb @@ -0,0 +1,134 @@ +uses HAVE_MP_TABLE +uses HAVE_PIRQ_TABLE +uses USE_FALLBACK_IMAGE +uses USE_NORMAL_IMAGE +uses AMD8111_DEV +# +# +### +### Set all of the defaults for an x86 architecture +### +# +# +### +### 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 +# +arch i386 end +cpu k8 end +# +### +### Build our 16 bit and 32 bit linuxBIOS entry code +### +mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc +ldscript /cpu/i386/entry16.lds +ldscript /cpu/i386/entry32.lds +# +### +### Build our reset vector (This is where linuxBIOS is entered) +### +if USE_FALLBACK_IMAGE + print "Use fallback!" + mainboardinit cpu/i386/reset16.inc + ldscript /cpu/i386/reset16.lds +end + +if USE_NORMAL_IMAGE + mainboardinit cpu/i386/reset32.inc + ldscript /cpu/i386/reset32.lds +end +# +#### Should this be in the northbridge code? +mainboardinit arch/i386/lib/cpu_reset.inc +# +### +### Include an id string (For safe flashing) +### +mainboardinit arch/i386/lib/id.inc +ldscript /arch/i386/lib/id.lds +# +#### +#### This is the early phase of linuxBIOS startup +#### Things are delicate and we test to see if we should +#### failover to another image. +#### +#option MAX_REBOOT_CNT=2 +##ldscript arch/i386/lib/failover.lds USE_FALLBACK_IMAGE +# +### +### Setup our mtrrs +### +mainboardinit cpu/k8/earlymtrr.inc +# +# +### +### Only the bootstrap cpu makes it here. +### Failover if we need to +### +# +if USE_FALLBACK_IMAGE + mainboardinit southbridge/amd/amd8111/cmos_boot_failover.inc +end +# +#### +#### O.k. We aren't just an intermediary anymore! +#### +# +### +### When debugging disable the watchdog timer +### +##option MAXIMUM_CONSOLE_LOGLEVEL=7 +#default MAXIMUM_CONSOLE_LOGLEVEL=7 +#option DISABLE_WATCHDOG= (MAXIMUM_CONSOLE_LOGLEVEL >= 8) +#if DISABLE_WATCHDOG +# mainboardinit southbridgeamd/amd8111/disable_watchdog.inc +#end +# +### +### Setup the serial port +### +#mainboardinit superiowinbond/w83627hf/setup_serial.inc +mainboardinit pc80/serial.inc +mainboardinit arch/i386/lib/console.inc +if USE_FALLBACK_IMAGE mainboardinit arch/i386/lib/noop_failover.inc end +# +### +### Romcc output +### +#makerule ./failover.E dep "$(MAINBOARD)/failover.c" act "$(CPP) -I$(TOP)/src $(CPPFLAGS) $(MAINBOARD)/failover.c > ./failever.E" +#makerule ./failover.inc dep "./romcc ./failover.E" act "./romcc -O ./failover.E > failover.inc" +#mainboardinit .failover.inc +makerule ./auto.E dep "$(MAINBOARD)/auto.c" act "$(CPP) -I$(TOP)/src -$(ROMCCPPFLAGS) $(CPPFLAGS) $(MAINBOARD)/auto.c > ./auto.E" +makerule ./auto.inc dep "./romcc ./auto.E" act "./romcc -O ./auto.E > auto.inc" +mainboardinit ./auto.inc +# +### +### Setup RAM +### +mainboardinit ram/ramtest.inc +mainboardinit southbridge/amd/amd8111/smbus.inc +mainboardinit sdram/generic_dump_spd.inc +# +### +### Include the secondary Configuration files +### +northbridge amd/amdk8 +end +southbridge amd/amd8111 +end +#mainboardinit archi386/smp/secondary.inc +superio NSC/pc87360 + register "com1={1} com2={0} floppy=1 lpt=1 keyboard=1" +end +dir /pc80 +##dir /src/superio/winbond/w83627hf +cpu p5 end +cpu p6 end +cpu k7 end +cpu k8 end diff --git a/src/mainboard/tyan/s2880/VERSION b/src/mainboard/tyan/s2880/VERSION new file mode 100644 index 0000000000..cd5ac039d6 --- /dev/null +++ b/src/mainboard/tyan/s2880/VERSION @@ -0,0 +1 @@ +2.0 diff --git a/src/mainboard/tyan/s2880/auto.c b/src/mainboard/tyan/s2880/auto.c new file mode 100644 index 0000000000..0612989337 --- /dev/null +++ b/src/mainboard/tyan/s2880/auto.c @@ -0,0 +1,437 @@ +#define ASSEMBLY 1 +#include +#include +#include "arch/romcc_io.h" +#include "pc80/serial.c" +#include "arch/i386/lib/console.c" +#include "ram/ramtest.c" +#include "northbridge/amd/amdk8/early_ht.c" +#include "southbridge/amd/amd8111/amd8111_early_smbus.c" +#include "northbridge/amd/amdk8/raminit.h" +/* +#warning "FIXME move these delay functions somewhere more appropriate" +#warning "FIXME use the apic timer instead it needs no calibration on an Opteron it runs at 200Mhz" +static void print_clock_multiplier(void) +{ + msr_t msr; + print_debug("clock multipler: 0x"); + msr = rdmsr(0xc0010042); + print_debug_hex32(msr.lo & 0x3f); + print_debug(" = 0x"); + print_debug_hex32(((msr.lo & 0x3f) + 8) * 100); + print_debug("Mhz\r\n"); +} + +static unsigned usecs_to_ticks(unsigned usecs) +{ +#warning "FIXME make usecs_to_ticks work properly" +#if 1 + return usecs *2000; +#else + // This can only be done if cpuid says fid changing is supported + // I need to look up the base frequency another way for other + // cpus. Is it worth dedicating a global register to this? + // Are the PET timers useable for this purpose? + + msr_t msr; + msr = rdmsr(0xc0010042); + return ((msr.lo & 0x3f) + 8) * 100 *usecs; +#endif +} + +static void init_apic_timer(void) +{ + volatile uint32_t *apic_reg = (volatile uint32_t *)0xfee00000; + uint32_t start, end; + // Set the apic timer to no interrupts and periodic mode + apic_reg[0x320 >> 2] = (1 << 17)|(1<< 16)|(0 << 12)|(0 << 0); + // Set the divider to 1, no divider + apic_reg[0x3e0 >> 2] = (1 << 3) | 3; + // Set the initial counter to 0xffffffff + apic_reg[0x380 >> 2] = 0xffffffff; +} + +static void udelay(unsigned usecs) +{ +#if 1 + uint32_t start, ticks; + tsc_t tsc; + // Calculate the number of ticks to run for + ticks = usecs_to_ticks(usecs); + // Find the current time + tsc = rdtsc(); + start = tsc.lo; + do { + tsc = rdtsc(); + } while((tsc.lo - start) < ticks); +#else + volatile uint32_t *apic_reg = (volatile uint32_t *)0xfee00000; + uint32_t start, value, ticks; + // Calculate the number of ticks to run for + ticks = usecs * 200; + start = apic_reg[0x390 >> 2]; + do { + value = apic_reg[0x390 >> 2]; + } while((start - value) < ticks); +#endif +} + +static void mdelay(unsigned msecs) +{ + int i; + for(i = 0; i < msecs; i++) { + udelay(1000); + } +} + +static void delay(unsigned secs) +{ + int i; + for(i = 0; i < secs; i++) { + mdelay(1000); + } +} + +static void memreset_setup(const struct mem_controller *ctrl) +{ + // Set the memreset low + outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 28); + // Ensure the BIOS has control of the memory lines + outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 29); + print_debug("memreset lo\r\n"); +} + +static void memreset(const struct mem_controller *ctrl) +{ + udelay(800); + // Set memreset_high + outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), SMBUS_IO_BASE + 0xc0 + 28); + print_debug("memreset hi\r\n"); + udelay(50); +} +*/ + +#include "northbridge/amd/amdk8/raminit.c" +#include "northbridge/amd/amdk8/coherent_ht.c" +#include "sdram/generic_sdram.c" + +#define NODE_ID 0x60 +#define HT_INIT_CONTROL 0x6c + +#define HTIC_ColdR_Detect (1<<4) +#define HTIC_BIOSR_Detect (1<<5) +#define HTIC_INIT_Detect (1<<6) + +#define APIC_DEFAULT_BASE 0xfee00000 + +#define APIC_ID 0x020 + +static int boot_cpu(void) +{ + volatile unsigned long *local_apic; + unsigned long apic_id; + int bsp; + int apicEn; + msr_t msr; + msr = rdmsr(0x1b); + bsp = !!(msr.lo & (1 << 8)); + apicEn = !!(msr.lo & (1<<11)); + if(apicEn) { + print_debug("apic enabled\r\n"); + } else { + msr.lo |= (1<<11); + wrmsr(0x1b,msr); + } + apic_id = *((volatile unsigned long *)(APIC_DEFAULT_BASE+APIC_ID)); + print_debug("apic_id: "); + print_debug_hex32(apic_id>>24); + print_debug("\r\n"); + + if (bsp) { + print_debug("Bootstrap cpu\r\n"); + } else { + print_debug("Application processor\r\n"); + // asm("hlt"); // move to end before halt should notify BSP + // if you start AP in coherent.c you can just stop it here + } + + return bsp; +} + +static int cpu_init_detected(void) +{ + unsigned long dcl; + int cpu_init; + + unsigned long htic; + + htic = pci_read_config32(PCI_DEV(0, 0x18, 0), HT_INIT_CONTROL); +#if 0 + print_debug("htic: "); + print_debug_hex32(htic); + print_debug("\r\n"); + + if (!(htic & HTIC_ColdR_Detect)) { + print_debug("Cold Reset.\r\n"); + } + if ((htic & HTIC_ColdR_Detect) && !(htic & HTIC_BIOSR_Detect)) { + print_debug("BIOS generated Reset.\r\n"); + } + if (htic & HTIC_INIT_Detect) { + print_debug("Init event.\r\n"); + } +#endif + cpu_init = (htic & HTIC_INIT_Detect); + if (cpu_init) { + print_debug("CPU INIT Detected.\r\n"); + } + return cpu_init; +} +/* +static void print_debug_pci_dev(unsigned dev) +{ + print_debug("PCI: "); + print_debug_hex8((dev >> 16) & 0xff); + print_debug_char(':'); + print_debug_hex8((dev >> 11) & 0x1f); + print_debug_char('.'); + print_debug_hex8((dev >> 8) & 7); +} + + +static void print_pci_devices(void) +{ + device_t dev; + for(dev = PCI_DEV(0, 0, 0); + dev <= PCI_DEV(0, 0x1f, 0x7); + dev += PCI_DEV(0,0,1)) { + uint32_t id; + id = pci_read_config32(dev, PCI_VENDOR_ID); + if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0x0000)) { + continue; + } + print_debug_pci_dev(dev); + print_debug("\r\n"); + } +} +*/ +/* +static void dump_pci_device(unsigned dev) +{ + int i; + print_debug_pci_dev(dev); + print_debug("\r\n"); + + for(i = 0; i <= 255; i++) { + unsigned char val; + if ((i & 0x0f) == 0) { + print_debug_hex8(i); + print_debug_char(':'); + } + val = pci_read_config8(dev, i); + print_debug_char(' '); + print_debug_hex8(val); + if ((i & 0x0f) == 0x0f) { + print_debug("\r\n"); + } + } +} +static void dump_pci_devices(void) +{ + device_t dev; + for(dev = PCI_DEV(0, 0, 0); + dev <= PCI_DEV(0, 0x1f, 0x7); + dev += PCI_DEV(0,0,1)) { + uint32_t id; + id = pci_read_config32(dev, PCI_VENDOR_ID); + if (((id & 0xffff) == 0x0000) || ((id & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0xffff) || + (((id >> 16) & 0xffff) == 0x0000)) { + continue; + } + dump_pci_device(dev); + } +} + + + +static void dump_spd_registers(const struct mem_controller *ctrl) +{ + int i; + print_debug("\r\n"); + for(i = 0; i < 4; i++) { + unsigned device; + device = ctrl->channel0[i]; + if (device) { + int j; + print_debug("dimm: "); + print_debug_hex8(i); + print_debug(".0: "); + print_debug_hex8(device); + for(j = 0; j < 256; j++) { + int status; + unsigned char byte; + if ((j & 0xf) == 0) { + print_debug("\r\n"); + print_debug_hex8(j); + print_debug(": "); + } + status = smbus_read_byte(device, j); + if (status < 0) { + print_debug("bad device\r\n"); + + break; + } + byte = status & 0xff; + print_debug_hex8(byte); + print_debug_char(' '); + } + print_debug("\r\n"); + } + device = ctrl->channel1[i]; + if (device) { + int j; + print_debug("dimm: "); + print_debug_hex8(i); + print_debug(".1: "); + print_debug_hex8(device); + for(j = 0; j < 256; j++) { + int status; + unsigned char byte; + if ((j & 0xf) == 0) { + print_debug("\r\n"); + print_debug_hex8(j); + print_debug(": "); + } + status = smbus_read_byte(device, j); + + if (status < 0) { + print_debug("bad device\r\n"); + break; + } + byte = status & 0xff; + print_debug_hex8(byte); + print_debug_char(' '); + } + print_debug("\r\n"); + } + } +} + +*/ + + + +static void main(void) +{ + static const struct mem_controller cpu0 = { + .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 = { (0xa<<3)|0, (0xa<<3)|2, 0, 0 }, + .channel1 = { (0xa<<3)|1, (0xa<<3)|3, 0, 0 }, + }; + static const struct mem_controller cpu1 = { + .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 = { (0xa<<3)|4, (0xa<<3)|6, 0, 0 }, + .channel1 = { (0xa<<3)|5, (0xa<<3)|7, 0, 0 }, + }; + + // device_t dev; + // unsigned where; + unsigned long reg; +// dev = PCI_ADDR(0, 0x19, 0, 0x6C) & ~0xff; +// where = PCI_ADDR(0, 0x19, 0, 0x6C) & 0xff; +#if 0 + init_apic_timer(); +#endif + + uart_init(); + console_init(); + if (boot_cpu() && !cpu_init_detected()) { + setup_default_resource_map(); + setup_coherent_ht_domain(); + enumerate_ht_chain(); +// print_pci_devices(); + enable_smbus(); +// sdram_initialize(); + // dump_spd_registers(&cpu0); + sdram_initialize(&cpu0); + // dump_spd_registers(&cpu1); +// sdram_initialize(&cpu1); + +// dump_pci_device(PCI_DEV(0, 0x18, 2)); +#if 0 + ram_fill( 0x00100000, 0x00180000); + ram_verify(0x00100000, 0x00180000); +#endif +//#ifdef MEMORY_1024MB +// ram_fill( 0x00000000, 0x00001000); +// ram_verify(0x00000000, 0x00001000); +//#endif +//#ifdef MEMROY_512MB +// ram_fill( 0x00000000, 0x01ffffff); +// ram_verify(0x00000000, 0x01ffffff); +//#endif + /* Check the first 512M */ +/* 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"); + ram_check(0x00000000, msr.lo); + */ +/* + reg = *((volatile unsigned long *)(APIC_DEFAULT_BASE+APIC_ID)); + print_debug("bootstrap cpu apic_id: "); + print_debug_hex32(reg>>24); + print_debug("\r\n"); +*/ + + // Start AP now + reg = pci_read_config32(PCI_DEV(0, 0x19, 0), 0x6C); + reg &= 0xffffff8c; + reg |= 0x00000070; + pci_write_config32(PCI_DEV(0, 0x19, 0), 0x6C, reg); //start AP + for(;;) { + reg = pci_read_config32(PCI_DEV(0, 0x19, 0), 0x6C); + if((reg & (1<<4))==0) break; // wait until AP stop + } + reg |= 1<<4; + pci_write_config32(PCI_DEV(0, 0x19, 0), 0x6C, reg); + + } + else { + // Need to init second cpu's APIC id + // It's AP + +// apic_write(APIC_ID,(1<<24)); + reg = *((volatile unsigned long *)(APIC_DEFAULT_BASE+APIC_ID)); +/* print_debug("applicaton cpu apic_id: "); + print_debug_hex32(reg>>24); + print_debug("\r\n"); + if((reg>>24)==7){ // FIXME: Need to read NodeID at first. + *((volatile unsigned long *)(APIC_DEFAULT_BASE+APIC_ID))=1<<24; + }*/ + if((reg>>24)!=0) { +// before hlt clear the ColdResetbit + + //notify BSP that AP is stopped + reg = pci_read_config32(PCI_DEV(0, 0x19, 0), 0x6C); + reg &= ~(1<<4); + pci_write_config32(PCI_DEV(0, 0x19, 0), 0x6C, reg); + + asm("hlt"); + } + + + } + +} diff --git a/src/mainboard/tyan/s2880/cmos.layout b/src/mainboard/tyan/s2880/cmos.layout new file mode 100644 index 0000000000..5ba4c032c1 --- /dev/null +++ b/src/mainboard/tyan/s2880/cmos.layout @@ -0,0 +1,74 @@ +entries + +#start-bit length config config-ID name +#0 8 r 0 seconds +#8 8 r 0 alarm_seconds +#16 8 r 0 minutes +#24 8 r 0 alarm_minutes +#32 8 r 0 hours +#40 8 r 0 alarm_hours +#48 8 r 0 day_of_week +#56 8 r 0 day_of_month +#64 8 r 0 month +#72 8 r 0 year +#80 4 r 0 rate_select +#84 3 r 0 REF_Clock +#87 1 r 0 UIP +#88 1 r 0 auto_switch_DST +#89 1 r 0 24_hour_mode +#90 1 r 0 binary_values_enable +#91 1 r 0 square-wave_out_enable +#92 1 r 0 update_finished_enable +#93 1 r 0 alarm_interrupt_enable +#94 1 r 0 periodic_interrupt_enable +#95 1 r 0 disable_clock_updates +#96 288 r 0 temporary_filler +0 384 r 0 reserved_memory +384 1 e 4 boot_option +385 1 e 4 last_boot +386 1 e 1 ECC_memory +388 4 r 0 reboot_bits +392 3 e 5 baud_rate +400 1 e 1 power_on_after_fail +412 4 e 6 debug_level +416 4 e 7 boot_first +420 4 e 7 boot_second +424 4 e 7 boot_third +428 4 h 0 boot_index +432 8 h 0 boot_countdown +1008 16 h 0 check_sum + +enumerations + +#ID value text +1 0 Disable +1 1 Enable +2 0 Enable +2 1 Disable +4 0 Fallback +4 1 Normal +5 0 115200 +5 1 57600 +5 2 38400 +5 3 19200 +5 4 9600 +5 5 4800 +5 6 2400 +5 7 1200 +6 6 Notice +6 7 Info +6 8 Debug +6 9 Spew +7 0 Network +7 1 HDD +7 2 Floppy +7 8 Fallback_Network +7 9 Fallback_HDD +7 10 Fallback_Floppy +#7 3 ROM + +checksums + +checksum 392 1007 1008 + + diff --git a/src/mainboard/tyan/s2880/failover.c b/src/mainboard/tyan/s2880/failover.c new file mode 100644 index 0000000000..cda8ea8076 --- /dev/null +++ b/src/mainboard/tyan/s2880/failover.c @@ -0,0 +1,26 @@ +#define ASSEMBLY 1 +#include +#include +#include +#include "arch/romcc_io.h" +#include "pc80/mc146818rtc_early.c" +#include "southbridge/amd/amd8111/amd8111_enable_rom.c" +#include "northbridge/amd/amdk8/early_ht.c" + + + +static void main(void) +{ + if (do_normal_boot()) { + /* 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(); + + /* Jump to the normal image */ + asm("jmp __normal_image"); + } +} diff --git a/src/mainboard/tyan/s2880/irq_tables.c b/src/mainboard/tyan/s2880/irq_tables.c new file mode 100644 index 0000000000..cbaf7b8ded --- /dev/null +++ b/src/mainboard/tyan/s2880/irq_tables.c @@ -0,0 +1,37 @@ +/* This file was generated by getpir.c, do not modify! + (but if you do, please run checkpir on it to verify) + Contains the IRQ Routing Table dumped directly from your memory , wich BIOS sets up + + Documentation at : http://www.microsoft.com/hwdev/busbios/PCIIRQ.HTM +*/ + +#include + +const struct irq_routing_table intel_irq_routing_table = { + PIRQ_SIGNATURE, /* u32 signature */ + PIRQ_VERSION, /* u16 version */ + 32+16*13, /* there can be total 13 devices on the bus */ + 0, /* Where the interrupt router lies (bus) */ + 0x3b, /* Where the interrupt router lies (dev) */ + 0, /* IRQs devoted exclusively to PCI usage */ + 0x1022, /* Vendor */ + 0x746b, /* Device */ + 0, /* Crap (miniport) */ + { 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */ + 0xe8, /* u8 checksum , this hase to set to some value that would give 0 after the sum of all bytes for this structure (including checksum) */ + { + {0,0x38, {{0x1, 0xdef8}, {0x2, 0xdef8}, {0x3, 0xdef8}, {0x4, 0xdef8}}, 0, 0}, + {0x3,0, {{0, 0}, {0, 0}, {0, 0}, {0x4, 0xdef8}}, 0, 0}, + {0x2,0x18, {{0x1, 0xdef8}, {0x2, 0xdef8}, {0x3, 0xdef8}, {0x4, 0xdef8}}, 0x1, 0}, + {0x2,0x30, {{0x2, 0xdef8}, {0x3, 0xdef8}, {0x4, 0xdef8}, {0x1, 0xdef8}}, 0x2, 0}, + {0x2,0x20, {{0x2, 0xdef8}, {0x3, 0xdef8}, {0x4, 0xdef8}, {0x1, 0xdef8}}, 0x6, 0}, + {0x1,0x40, {{0x4, 0xdef8}, {0x1, 0xdef8}, {0x2, 0xdef8}, {0x3, 0xdef8}}, 0x3, 0}, + {0x1,0x38, {{0x3, 0xdef8}, {0x4, 0xdef8}, {0x1, 0xdef8}, {0x2, 0xdef8}}, 0x4, 0}, + {0x3,0x8, {{0x1, 0xdef8}, {0, 0}, {0, 0}, {0, 0}}, 0, 0}, + {0x3,0x30, {{0x3, 0xdef8}, {0, 0}, {0, 0}, {0, 0}}, 0, 0}, + {0x3,0x20, {{0x1, 0xdef8}, {0x2, 0xdef8}, {0x3, 0xdef8}, {0x4, 0xdef8}}, 0x5, 0}, + {0x1,0x48, {{0x1, 0xdef8}, {0x2, 0xdef8}, {0, 0}, {0, 0}}, 0, 0}, + {0x3,0x28, {{0x2, 0xdef8}, {0, 0}, {0, 0}, {0, 0}}, 0, 0}, + {0x1,0x50, {{0x1, 0xdef8}, {0x2, 0xdef8}, {0, 0}, {0, 0}}, 0, 0}, + } +}; diff --git a/src/mainboard/tyan/s2880/mainboard.c b/src/mainboard/tyan/s2880/mainboard.c new file mode 100644 index 0000000000..c4f7cf8015 --- /dev/null +++ b/src/mainboard/tyan/s2880/mainboard.c @@ -0,0 +1,120 @@ +#include +#include +#include +#include +#include +#include +//#include "lsi_scsi.c" +unsigned long initial_apicid[MAX_CPUS] = +{ + 0,1 +}; +/* +static void fixup_lsi_53c1030(struct device *pdev) +{ +// uint8_t byte; + uint16_t word; + + byte = 1; + pci_write_config8(pdev, 0xff, byte); + // Set the device id +// pci_write_config_word(pdev, PCI_DEVICE_ID, PCI_DEVICE_ID_LSILOGIC_53C1030); + // Set the subsytem vendor id +// pci_write_config16(pdev, PCI_SUBSYSTEM_VENDOR_ID, PCI_VENDOR_ID_TYAN); + word = 0x10f1; + pci_write_config16(pdev, PCI_SUBSYSTEM_VENDOR_ID, word); + // Set the subsytem id + word = 0x2880; + pci_write_config16(pdev, PCI_SUBSYSTEM_ID, word); + // Disable writes to the device id + byte = 0; + pci_write_config8(pdev, 0xff, byte); + +// lsi_scsi_init(pdev); + +} +//extern static void lsi_scsi_init(struct device *dev); +static void print_pci_regs(struct device *dev) +{ + uint8_t byte; + int i; + + for(i=0;i<256;i++) { + byte = pci_read_config8(dev, i); + + if((i%16)==0) printk_info("\n %02x:",i); + printk_debug(" %02x ",byte); + } + printk_debug("\r\n"); + +// pci_write_config8(dev, 0x4, byte); + +} +*/ +static void onboard_scsi_fixup(void) +{ + struct device *dev; +/* + // Set the scsi device id's + printk_debug("%2d:%2d:%2d\n",0,1,0); + dev = dev_find_slot(0, PCI_DEVFN(0x1, 0)); + if (dev) { + } + // Set the scsi device id's + printk_debug("%2d:%2d:%2d\n",0,2,0); + dev = dev_find_slot(0, PCI_DEVFN(0x2, 0)); + if (dev) { + print_pci_regs(dev); + } + + // Set the scsi device id's + printk_debug("%2d:%2d:%2d\n",1,0xa,0); + dev = dev_find_slot(1, PCI_DEVFN(0xa, 0)); + if (dev) { + print_pci_regs(dev); + } + // Set the scsi device id's + printk_debug("%2d:%2d:%2d\n",1,0xa,1); + dev = dev_find_slot(1, PCI_DEVFN(0xa, 1)); + if (dev) { + print_pci_regs(dev); + } + printk_debug("%2d:%2d:%2d\n",1,9,0); + dev = dev_find_slot(1, PCI_DEVFN(0x9, 0)); + if (dev) { + print_pci_regs(dev); + } + // Set the scsi device id's + printk_debug("%2d:%2d:%2d\n",1,9,1); + dev = dev_find_slot(1, PCI_DEVFN(0x9, 1)); + if (dev) { + print_pci_regs(dev); + } +*/ + +/* + dev = dev_find_device(PCI_VENDOR_ID_LSI_LOGIC, PCI_DEVICE_ID_LSI_53C1030,0); + if(!dev) { + printk_info("LSI_SCSI_FW_FIXUP: No Device Found!"); + return; + } + + lsi_scsi_init(dev); +*/ +} + +void mainboard_fixup(void) +{ + printk_debug("Enter mainboard_fixup\r\n"); +// onboard_device_fixup + onboard_scsi_fixup(); + printk_debug("mainboard fixup done\r\n"); + +} +void final_mainboard_fixup(void) +{ +#if 0 + enable_ide_devices(); +#endif +} + diff --git a/src/mainboard/tyan/s2880/mptable.c b/src/mainboard/tyan/s2880/mptable.c new file mode 100644 index 0000000000..c4687b1197 --- /dev/null +++ b/src/mainboard/tyan/s2880/mptable.c @@ -0,0 +1,99 @@ +#include +#include +#include +#include +#include + +void *smp_write_config_table(void *v, unsigned long * processor_map) +{ + static const char sig[4] = "PCMP"; + static const char oem[8] = "TYAN "; + static const char productid[12] = "S2880 "; + struct mp_config_table *mc; + + mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN); + memset(mc, 0, sizeof(*mc)); + + memcpy(mc->mpc_signature, sig, sizeof(sig)); + mc->mpc_length = sizeof(*mc); /* initially just the header */ + mc->mpc_spec = 0x04; + mc->mpc_checksum = 0; /* not yet computed */ + memcpy(mc->mpc_oem, oem, sizeof(oem)); + memcpy(mc->mpc_productid, productid, sizeof(productid)); + mc->mpc_oemptr = 0; + mc->mpc_oemsize = 0; + mc->mpc_entry_count = 0; /* No entries yet... */ + mc->mpc_lapic = LAPIC_ADDR; + mc->mpe_length = 0; + mc->mpe_checksum = 0; + mc->reserved = 0; + + smp_write_processors(mc, processor_map); + + +/*Bus: Bus ID Type*/ + smp_write_bus(mc, 0, "PCI "); + smp_write_bus(mc, 1, "PCI "); + smp_write_bus(mc, 2, "PCI "); + smp_write_bus(mc, 3, "PCI "); + smp_write_bus(mc, 4, "ISA "); +/*I/O APICs: APIC ID Version State Address*/ + smp_write_ioapic(mc, 2, 0x11, 0xfec00000); + { + struct pci_dev *dev; + uint32_t base; + dev = dev_find_slot(0, PCI_DEVFN(0x1,1)); + if (dev) { + base = pci_read_config32(dev, PCI_BASE_ADDRESS_0); + base &= PCI_BASE_ADDRESS_MEM_MASK; + smp_write_ioapic(mc, 3, 0x11, base); + } + dev = dev_find_slot(0, PCI_DEVFN(0x2,1)); + if (dev) { + base = pci_read_config32(dev, PCI_BASE_ADDRESS_0); + base &= PCI_BASE_ADDRESS_MEM_MASK; + smp_write_ioapic(mc, 4, 0x11, base); + } + } + +/*I/O Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN# +*/ smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x4, 0x0, 0x2, 0x0); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x4, 0x1, 0x2, 0x1); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x4, 0x0, 0x2, 0x2); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x4, 0x3, 0x2, 0x3); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x4, 0x4, 0x2, 0x4); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x4, 0x6, 0x2, 0x6); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x4, 0x7, 0x2, 0x7); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x4, 0x8, 0x2, 0x8); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x4, 0xc, 0x2, 0xc); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x4, 0xd, 0x2, 0xd); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x4, 0xe, 0x2, 0xe); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x4, 0xf, 0x2, 0xf); + + + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x3, 0x3, 0x2, 0x13); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x3, 0x18, 0x2, 0x12); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x3, 0x14, 0x2, 0x11); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x1, 0x24, 0x3, 0x0); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x1, 0x25, 0x3, 0x1); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x1, 0x28, 0x3, 0x0); + smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW, 0x1, 0x29, 0x3, 0x1); +/*Local Ints: Type Polarity Trigger Bus ID IRQ APIC ID PIN#*/ + smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x0, 0x0, MP_APIC_ALL, 0x0); + smp_write_intsrc(mc, mp_NMI, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH, 0x0, 0x0, MP_APIC_ALL, 0x1); + /* There is no extension information... */ + + /* Compute the checksums */ + mc->mpe_checksum = smp_compute_checksum(smp_next_mpc_entry(mc), mc->mpe_length); + mc->mpc_checksum = smp_compute_checksum(mc, mc->mpc_length); + printk_debug("Wrote the mp table end at: %p - %p\n", + mc, smp_next_mpe_entry(mc)); + return smp_next_mpe_entry(mc); +} + +unsigned long write_smp_table(unsigned long addr, unsigned long *processor_map) +{ + void *v; + v = smp_write_floating_table(addr); + return (unsigned long)smp_write_config_table(v, processor_map); +} diff --git a/src/northbridge/amd/amdk8/coherent_ht.c b/src/northbridge/amd/amdk8/coherent_ht.c index 471af5a415..6828294ead 100644 --- a/src/northbridge/amd/amdk8/coherent_ht.c +++ b/src/northbridge/amd/amdk8/coherent_ht.c @@ -104,12 +104,12 @@ static void enable_routing(u8 node) * */ - /* Enable routing table for BSP */ + /* Enable routing table */ print_debug("Enabling routing table for node "); print_debug_hex32(node); val=pci_read_config32(NODE_HT(node), 0x6c); - val &= ~((1<<1)|(1<<0)); + val &= ~((1<<6)|(1<<5)|(1<<4)|(1<<1)|(1<<0)); pci_write_config32(NODE_HT(node), 0x6c, val); print_debug(" done.\r\n"); diff --git a/src/northbridge/amd/amdk8/northbridge.c b/src/northbridge/amd/amdk8/northbridge.c index 8c2dbf1d16..4d1e6987af 100644 --- a/src/northbridge/amd/amdk8/northbridge.c +++ b/src/northbridge/amd/amdk8/northbridge.c @@ -2,22 +2,91 @@ #include #include #include +#include +#include +#include struct mem_range *sizeram(void) { - static struct mem_range mem[3]; - uint32_t size; - /* Convert size in bytes to size in K */ -#warning "FINISH sizeram" - /* FIXME hardcoded for now */ - size = 512*1024; + unsigned long mmio_basek; + static struct mem_range mem[10]; + device_t dev; + int i, idx; - mem[0].basek = 0; - mem[0].sizek = 640; - mem[1].basek = 960; - mem[1].sizek = size - mem[1].basek; - mem[2].basek = 0; - mem[2].sizek = 0; +#warning "FIXME handle interleaved nodes" + dev = dev_find_slot(0, PCI_DEVFN(0x18, 1)); + if (!dev) { + return 0; + } + mmio_basek = (dev_root.resource[1].base >> 10); + /* Round mmio_basek to something the processor can support */ + mmio_basek &= ~((1 << 6) -1); + +#if 1 +#warning "FIXME improve mtrr.c so we don't use up all of the mtrrs with a 64M MMIO hole" + /* Round the mmio hold to 256M */ + mmio_basek &= ~((256*1024) - 1); +#endif + + /* Temporary hack to get mmio handling working */ + for(i = 0; i < 8; i++) { +#warning "FIXME handle multiple Hypertransport chains in device.c" + device_t node; + node = dev_find_slot(0, PCI_DEVFN(0x18 + i, 1)); + pci_write_config32(node, 0xB8, ((mmio_basek >> 6) << 8) | (1<<1) | (1 << 0)); + pci_write_config32(node, 0xBC, 0x00ffff00); + } + for(idx = i = 0; i < 8; i++) { + uint32_t base, limit; + unsigned basek, limitk, sizek; + base = pci_read_config32(dev, 0x40 + (i<<3)); + limit = pci_read_config32(dev, 0x44 + (i<<3)); + if ((base & ((1<<1)|(1<<0))) != ((1<<1)|(1<<0))) { + continue; + } + basek = (base & 0xffff0000) >> 2; + limitk = ((limit + 0x00010000) & 0xffff0000) >> 2; + sizek = limitk - basek; + if ((idx > 0) && + ((mem[idx -1].basek + mem[idx - 1].sizek) == basek)) { + mem[idx -1].sizek += sizek; + } + else { + mem[idx].basek = basek; + mem[idx].sizek = sizek; + idx++; + } + /* See if I need to split the region to accomodate pci memory space */ + if ((mem[idx - 1].basek <= mmio_basek) && + ((mem[idx - 1].basek + mem[idx - 1].sizek) > mmio_basek)) { + if (mem[idx - 1].basek < mmio_basek) { + unsigned pre_sizek; + pre_sizek = mmio_basek - mem[idx - 1].basek; + mem[idx].basek = mmio_basek; + mem[idx].sizek = mem[idx - 1].sizek - pre_sizek; + mem[idx - 1].sizek = pre_sizek; + idx++; + } + if ((mem[idx - 1].basek + mem[idx - 1].sizek) <= 4*1024*1024) { + idx -= 1; + } + else { + mem[idx - 1].basek = 4*1024*1024; + mem[idx - 1].sizek -= (4*1024*1024 - mmio_basek); + } + } + } +#if 0 + for(i = 0; i < idx; i++) { + printk_debug("mem[%d].basek = %08x mem[%d].sizek = %08x\n", + i, mem[i].basek, i, mem[i].sizek); + } +#endif + while(idx < sizeof(mem)/sizeof(mem[0])) { + mem[idx].basek = 0; + mem[idx].sizek = 0; + idx++; + } return mem; } diff --git a/src/northbridge/amd/amdk8/raminit.c b/src/northbridge/amd/amdk8/raminit.c index 41a93b51e9..1b258c62ce 100644 --- a/src/northbridge/amd/amdk8/raminit.c +++ b/src/northbridge/amd/amdk8/raminit.c @@ -922,10 +922,9 @@ static void sdram_set_registers(const struct mem_controller *ctrl) }; int i; int max; -#if 1 - memreset_setup(ctrl); -#endif - print_debug("setting up CPU0 northbridge registers\r\n"); + print_debug("setting up CPU"); + print_debug_hex8(ctrl->node_id); + print_debug(" northbridge registers\r\n"); max = sizeof(register_values)/sizeof(register_values[0]); for(i = 0; i < max; i += 3) { device_t dev; @@ -1001,43 +1000,43 @@ static struct dimm_size spd_get_dimm_size(unsigned device) * a multiple of 4MB. The way we do it now we can size both * sides of an assymetric dimm. */ - value = smbus_read_byte(device, 3); /* rows */ + value = spd_read_byte(device, 3); /* rows */ if (value < 0) goto out; sz.side1 += value & 0xf; - value = smbus_read_byte(device, 4); /* columns */ + value = spd_read_byte(device, 4); /* columns */ if (value < 0) goto out; sz.side1 += value & 0xf; - value = smbus_read_byte(device, 17); /* banks */ + value = spd_read_byte(device, 17); /* banks */ if (value < 0) goto out; sz.side1 += log2(value & 0xff); /* Get the module data width and convert it to a power of two */ - value = smbus_read_byte(device, 7); /* (high byte) */ + value = spd_read_byte(device, 7); /* (high byte) */ if (value < 0) goto out; value &= 0xff; value <<= 8; - low = smbus_read_byte(device, 6); /* (low byte) */ + low = spd_read_byte(device, 6); /* (low byte) */ if (low < 0) goto out; value = value | (low & 0xff); sz.side1 += log2(value); /* side 2 */ - value = smbus_read_byte(device, 5); /* number of physical banks */ + value = spd_read_byte(device, 5); /* number of physical banks */ if (value <= 1) goto out; /* Start with the symmetrical case */ sz.side2 = sz.side1; - value = smbus_read_byte(device, 3); /* rows */ + value = spd_read_byte(device, 3); /* rows */ if (value < 0) goto out; if ((value & 0xf0) == 0) goto out; /* If symmetrical we are done */ sz.side2 -= (value & 0x0f); /* Subtract out rows on side 1 */ sz.side2 += ((value >> 4) & 0x0f); /* Add in rows on side 2 */ - value = smbus_read_byte(device, 4); /* columns */ + value = spd_read_byte(device, 4); /* columns */ if (value < 0) goto out; sz.side2 -= (value & 0x0f); /* Subtract out columns on side 1 */ sz.side2 += ((value >> 4) & 0x0f); /* Add in columsn on side 2 */ @@ -1121,24 +1120,29 @@ static void spd_set_ram_size(const struct mem_controller *ctrl) static void route_dram_accesses(const struct mem_controller *ctrl, unsigned long base_k, unsigned long limit_k) { -#warning "FIXME this is hardcoded for one cpu" + /* Route the addresses to the controller node */ unsigned node_id; unsigned limit; unsigned base; - node_id = 0; - /* Route the addresses to node 0 */ + unsigned index; + unsigned limit_reg, base_reg; + device_t device; + node_id = ctrl->node_id; + index = (node_id << 3); limit = (limit_k << 2); limit &= 0xffff0000; limit -= 0x00010000; + limit |= ( 0 << 8) | (node_id << 0); base = (base_k << 2); base &= 0xffff0000; - pci_write_config32(ctrl->f1, 0x44, limit | (0 << 8) | (node_id << 0)); - pci_write_config32(ctrl->f1, 0x40, base | (0 << 8) | (1<<1) | (1<<0)); + base |= (0 << 8) | (1<<1) | (1<<0); -#if 1 - pci_write_config32(PCI_DEV(0, 0x19, 1), 0x44, limit | (0 << 8) | (1 << 4) | (node_id << 0)); - pci_write_config32(PCI_DEV(0, 0x19, 1), 0x40, base | (0 << 8) | (1<<1) | (1<<0)); -#endif + limit_reg = 0x44 + index; + base_reg = 0x40 + index; + for(device = PCI_DEV(0, 0x18, 1); device <= PCI_DEV(0, 0x1f, 1); device += PCI_DEV(0, 1, 0)) { + pci_write_config32(device, limit_reg, limit); + pci_write_config32(device, base_reg, base); + } } static void set_top_mem(unsigned tom_k) @@ -1148,6 +1152,13 @@ static void set_top_mem(unsigned tom_k) die("No memory"); } +#if 1 + /* Report the amount of memory. */ + print_debug("RAM: 0x"); + print_debug_hex32(tom_k); + print_debug(" KB\r\n"); +#endif + /* Now set top of memory */ msr_t msr; msr.lo = (tom_k & 0x003fffff) << 10; @@ -1163,21 +1174,28 @@ static void set_top_mem(unsigned tom_k) msr.lo = (tom_k & 0x003fffff) << 10; msr.hi = (tom_k & 0xffc00000) >> 22; wrmsr(TOP_MEM, msr); - -#if 1 - /* And report the amount of memory. */ - print_debug("RAM: 0x"); - print_debug_hex32(tom_k); - print_debug(" KB\r\n"); -#endif } static void order_dimms(const struct mem_controller *ctrl) { - unsigned long tom, tom_k; + unsigned long tom, tom_k, base_k; + unsigned node_id; + /* Compute the memory base address address */ + base_k = 0; + for(node_id = 0; node_id < ctrl->node_id; node_id++) { + uint32_t limit, base; + unsigned index; + index = node_id << 3; + base = pci_read_config32(ctrl->f1, 0x40 + index); + /* Only look at the limit if the base is enabled */ + if ((base & 3) == 3) { + limit = pci_read_config32(ctrl->f1, 0x44 + index); + base_k = ((limit + 0x00010000) & 0xffff0000) >> 2; + } + } /* Remember which registers we have used in the high 8 bits of tom */ - tom = 0; + tom = base_k >> 15; for(;;) { /* Find the largest remaining canidate */ unsigned index, canidate; @@ -1212,12 +1230,24 @@ static void order_dimms(const struct mem_controller *ctrl) break; } - /* Remember I have used this register */ - tom |= (1 << (canidate + 24)); - /* Remember the dimm size */ size = csbase >> 21; + /* If this is the first chip select, round base_k to + * be a multiple of it's size. Then set tom to equal + * base_k. + * I assume that size is a power of two. + */ + if ((tom & 0xff000000) == 0) { + unsigned size_k; + size_k = size << 15; + base_k = (base_k + size_k -1) & ~(size_k -1); + tom = base_k >> 15; + } + + /* Remember I have used this register */ + tom |= (1 << (canidate + 24)); + /* Recompute the cs base register value */ csbase = (tom << 21) | 1; @@ -1239,11 +1269,13 @@ static void order_dimms(const struct mem_controller *ctrl) #if 0 print_debug("tom: "); print_debug_hex32(tom); + print_debug(" base_k: "); + print_debug_hex32(base_k); print_debug(" tom_k: "); print_debug_hex32(tom_k); print_debug("\r\n"); #endif - route_dram_accesses(ctrl, 0, tom_k); + route_dram_accesses(ctrl, base_k, tom_k); set_top_mem(tom_k); } @@ -1267,7 +1299,7 @@ static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl) registered = 0; for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) { int value; - value = smbus_read_byte(ctrl->channel0[i], 21); + value = spd_read_byte(ctrl->channel0[i], 21); if (value < 0) { disable_dimm(ctrl, i); continue; @@ -1307,31 +1339,30 @@ static void spd_enable_2channels(const struct mem_controller *ctrl) { int i; uint32_t nbcap; - /* SMBUS addresses to verify are identical */ + /* SPD addresses to verify are identical */ #warning "FINISHME review and see if these are the bytes I need" /* FINISHME review and see if these are the bytes I need */ static const unsigned addresses[] = { 2, /* Type should be DDR SDRAM */ - 3, /* Row addresses */ - 4, /* Column addresses */ - 5, /* Physical Banks */ - 6, /* Module Data Width low */ - 7, /* Module Data Width high */ - 9, /* Cycle time at highest CAS Latency CL=X */ - 11, /* SDRAM Type */ - 12, /* Refresh Interval */ - 13, /* SDRAM Width */ - 15, /* Back-to-Back Random Column Access */ - 16, /* Burst Lengths */ - 17, /* Logical Banks */ - 18, /* Supported CAS Latencies */ - 23, /* Cycle time at CAS Latnecy (CLX - 0.5) */ - 26, /* Cycle time at CAS Latnecy (CLX - 1.0) */ - 27, /* tRP Row precharge time */ - 29, /* tRCD RAS to CAS */ - 30, /* tRAS Activate to Precharge */ - 31, /* Module Bank Density */ - 33, /* Address and Command Hold Time After Clock */ + 3, /* *Row addresses */ + 4, /* *Column addresses */ + 5, /* *Physical Banks */ + 6, /* *Module Data Width low */ + 7, /* *Module Data Width high */ + 9, /* *Cycle time at highest CAS Latency CL=X */ + 11, /* *SDRAM Type */ + 13, /* *SDRAM Width */ + 17, /* *Logical Banks */ + 18, /* *Supported CAS Latencies */ + 21, /* *SDRAM Module Attributes */ + 23, /* *Cycle time at CAS Latnecy (CLX - 0.5) */ + 26, /* *Cycle time at CAS Latnecy (CLX - 1.0) */ + 27, /* *tRP Row precharge time */ + 28, /* *Minimum Row Active to Row Active Delay (tRRD) */ + 29, /* *tRCD RAS to CAS */ + 30, /* *tRAS Activate to Precharge */ + 41, /* *Minimum Active to Active/Auto Refresh Time(Trc) */ + 42, /* *Minimum Auto Refresh Command Time(Trfc) */ }; nbcap = pci_read_config32(ctrl->f3, NORTHBRIDGE_CAP); if (!(nbcap & NBCAP_128Bit)) { @@ -1348,11 +1379,11 @@ static void spd_enable_2channels(const struct mem_controller *ctrl) for(j = 0; j < sizeof(addresses)/sizeof(addresses[0]); j++) { unsigned addr; addr = addresses[j]; - value0 = smbus_read_byte(device0, addr); + value0 = spd_read_byte(device0, addr); if (value0 < 0) { break; } - value1 = smbus_read_byte(device1, addr); + value1 = spd_read_byte(device1, addr); if (value1 < 0) { return; } @@ -1498,7 +1529,7 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl) new_cycle_time = 0xa0; new_latency = 5; - latencies = smbus_read_byte(ctrl->channel0[i], 18); + latencies = spd_read_byte(ctrl->channel0[i], 18); if (latencies <= 0) continue; /* Compute the lowest cas latency supported */ @@ -1511,7 +1542,7 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl) (!(latencies & (1 << latency)))) { continue; } - value = smbus_read_byte(ctrl->channel0[i], latency_indicies[index]); + value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]); if (value < 0) { continue; } @@ -1553,7 +1584,7 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl) int index; int value; int dimm; - latencies = smbus_read_byte(ctrl->channel0[i], 18); + latencies = spd_read_byte(ctrl->channel0[i], 18); if (latencies <= 0) { goto dimm_err; } @@ -1575,7 +1606,7 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl) } /* Read the min_cycle_time for this latency */ - value = smbus_read_byte(ctrl->channel0[i], latency_indicies[index]); + value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]); /* All is good if the selected clock speed * is what I need or slower. @@ -1619,7 +1650,7 @@ static int update_dimm_Trc(const struct mem_controller *ctrl, const struct mem_p unsigned clocks, old_clocks; uint32_t dtl; int value; - value = smbus_read_byte(ctrl->channel0[i], 41); + value = spd_read_byte(ctrl->channel0[i], 41); if (value < 0) return -1; if ((value == 0) || (value == 0xff)) { value = param->tRC; @@ -1648,7 +1679,7 @@ static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_ unsigned clocks, old_clocks; uint32_t dtl; int value; - value = smbus_read_byte(ctrl->channel0[i], 42); + value = spd_read_byte(ctrl->channel0[i], 42); if (value < 0) return -1; if ((value == 0) || (value == 0xff)) { value = param->tRFC; @@ -1677,7 +1708,7 @@ static int update_dimm_Trcd(const struct mem_controller *ctrl, const struct mem_ unsigned clocks, old_clocks; uint32_t dtl; int value; - value = smbus_read_byte(ctrl->channel0[i], 29); + value = spd_read_byte(ctrl->channel0[i], 29); if (value < 0) return -1; #if 0 clocks = (value + (param->divisor << 1) -1)/(param->divisor << 1); @@ -1706,7 +1737,7 @@ static int update_dimm_Trrd(const struct mem_controller *ctrl, const struct mem_ unsigned clocks, old_clocks; uint32_t dtl; int value; - value = smbus_read_byte(ctrl->channel0[i], 28); + value = spd_read_byte(ctrl->channel0[i], 28); if (value < 0) return -1; clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1); if (clocks < DTL_TRRD_MIN) { @@ -1731,7 +1762,7 @@ static int update_dimm_Tras(const struct mem_controller *ctrl, const struct mem_ unsigned clocks, old_clocks; uint32_t dtl; int value; - value = smbus_read_byte(ctrl->channel0[i], 30); + value = spd_read_byte(ctrl->channel0[i], 30); if (value < 0) return -1; clocks = ((value << 1) + param->divisor - 1)/param->divisor; if (clocks < DTL_TRAS_MIN) { @@ -1756,7 +1787,7 @@ static int update_dimm_Trp(const struct mem_controller *ctrl, const struct mem_p unsigned clocks, old_clocks; uint32_t dtl; int value; - value = smbus_read_byte(ctrl->channel0[i], 27); + value = spd_read_byte(ctrl->channel0[i], 27); if (value < 0) return -1; #if 0 clocks = (value + (param->divisor << 1) - 1)/(param->divisor << 1); @@ -1813,7 +1844,7 @@ static int update_dimm_Tref(const struct mem_controller *ctrl, const struct mem_ uint32_t dth; int value; unsigned tref, old_tref; - value = smbus_read_byte(ctrl->channel0[i], 3); + value = spd_read_byte(ctrl->channel0[i], 3); if (value < 0) return -1; value &= 0xf; @@ -1841,7 +1872,7 @@ static int update_dimm_x4(const struct mem_controller *ctrl, const struct mem_pa uint32_t dcl; int value; int dimm; - value = smbus_read_byte(ctrl->channel0[i], 13); + value = spd_read_byte(ctrl->channel0[i], 13); if (value < 0) { return -1; } @@ -1860,7 +1891,7 @@ static int update_dimm_ecc(const struct mem_controller *ctrl, const struct mem_p { uint32_t dcl; int value; - value = smbus_read_byte(ctrl->channel0[i], 11); + value = spd_read_byte(ctrl->channel0[i], 11); if (value < 0) { return -1; } @@ -2169,78 +2200,89 @@ static void sdram_set_spd_registers(const struct mem_controller *ctrl) } #define TIMEOUT_LOOPS 300000 -static void sdram_enable(const struct mem_controller *ctrl) +static void sdram_enable(int controllers, const struct mem_controller *ctrl) { - uint32_t dcl, dch; + int i; /* Before enabling memory start the memory clocks */ - dch = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH); - dch |= DCH_MEMCLK_VALID; - pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, dch); + for(i = 0; i < controllers; i++) { + uint32_t dch; + dch = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_HIGH); + dch |= DCH_MEMCLK_VALID; + pci_write_config32(ctrl[i].f2, DRAM_CONFIG_HIGH, dch); + } /* And if necessary toggle the the reset on the dimms by hand */ - memreset(ctrl); - - /* Toggle DisDqsHys to get it working */ - dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); - print_debug("dcl: "); - print_debug_hex32(dcl); - print_debug("\r\n"); + memreset(controllers, ctrl); + for(i = 0; i < controllers; i++) { + uint32_t dcl; + /* Toggle DisDqsHys to get it working */ + dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW); +#if 0 + print_debug("dcl: "); + print_debug_hex32(dcl); + print_debug("\r\n"); +#endif +#if 1 + dcl &= ~DCL_DimmEccEn; +#endif #warning "FIXME set the ECC type to perform" #warning "FIXME initialize the scrub registers" #if 0 - if (dcl & DCL_DimmEccEn) { - print_debug("ECC enabled\r\n"); - } -#endif - dcl |= DCL_DisDqsHys; - pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl); - dcl &= ~DCL_DisDqsHys; - dcl &= ~DCL_DLL_Disable; - dcl &= ~DCL_D_DRV; - dcl &= ~DCL_QFC_EN; - dcl |= DCL_DramInit; - pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl); - - print_debug("Initializing memory: "); - int loops = 0; - do { - dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); - loops += 1; - if ((loops & 1023) == 0) { - print_debug("."); + if (dcl & DCL_DimmEccEn) { + print_debug("ECC enabled\r\n"); } - } while(((dcl & DCL_DramInit) != 0) && (loops < TIMEOUT_LOOPS)); - if (loops >= TIMEOUT_LOOPS) { - print_debug(" failed\r\n"); - } else { - print_debug(" done\r\n"); +#endif + dcl |= DCL_DisDqsHys; + pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl); + dcl &= ~DCL_DisDqsHys; + dcl &= ~DCL_DLL_Disable; + dcl &= ~DCL_D_DRV; + dcl &= ~DCL_QFC_EN; + dcl |= DCL_DramInit; + pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl); + } - -#if 0 - - if (dcl & DCL_DimmEccEn) { - print_debug("Clearing memory: "); - loops = 0; - dcl &= ~DCL_MemClrStatus; - pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl); - + for(i = 0; i < controllers; i++) { + uint32_t dcl; + print_debug("Initializing memory: "); + int loops = 0; do { - dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); + dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW); loops += 1; if ((loops & 1023) == 0) { - print_debug(" "); - print_debug_hex32(loops); + print_debug("."); } - } while(((dcl & DCL_MemClrStatus) == 0) && (loops < TIMEOUT_LOOPS)); + } while(((dcl & DCL_DramInit) != 0) && (loops < TIMEOUT_LOOPS)); if (loops >= TIMEOUT_LOOPS) { - print_debug("failed\r\n"); + print_debug(" failed\r\n"); } else { - print_debug("done\r\n"); + print_debug(" done\r\n"); + } +#if 0 + if (dcl & DCL_DimmEccEn) { + print_debug("Clearing memory: "); + loops = 0; + dcl &= ~DCL_MemClrStatus; + pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl); + + do { + dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW); + loops += 1; + if ((loops & 1023) == 0) { + print_debug(" "); + print_debug_hex32(loops); + } + } while(((dcl & DCL_MemClrStatus) == 0) && (loops < TIMEOUT_LOOPS)); + if (loops >= TIMEOUT_LOOPS) { + print_debug("failed\r\n"); + } else { + print_debug("done\r\n"); + } + pci_write_config32(ctrl[i].f3, SCRUB_ADDR_LOW, 0); + pci_write_config32(ctrl[i].f3, SCRUB_ADDR_HIGH, 0); } - pci_write_config32(ctrl->f3, SCRUB_ADDR_LOW, 0); - pci_write_config32(ctrl->f3, SCRUB_ADDR_HIGH, 0); - } #endif + } } diff --git a/src/northbridge/amd/amdk8/raminit.h b/src/northbridge/amd/amdk8/raminit.h index 6778243706..44c9b7575c 100644 --- a/src/northbridge/amd/amdk8/raminit.h +++ b/src/northbridge/amd/amdk8/raminit.h @@ -2,6 +2,7 @@ #define RAMINIT_H struct mem_controller { + unsigned node_id; device_t f0, f1, f2, f3; uint8_t channel0[4]; uint8_t channel1[4]; diff --git a/src/northbridge/amd/amdk8/reset_test.c b/src/northbridge/amd/amdk8/reset_test.c index 949bd7cc15..ab48f9830e 100644 --- a/src/northbridge/amd/amdk8/reset_test.c +++ b/src/northbridge/amd/amdk8/reset_test.c @@ -34,10 +34,12 @@ static int cpu_init_detected(void) return cpu_init; } -static void distinguish_cpu_resets(void) +static void distinguish_cpu_resets(unsigned node_id) { uint32_t htic; - htic = pci_read_config32(PCI_DEV(0, 0x18, 0), HT_INIT_CONTROL); + device_t device; + device = PCI_DEV(0, 0x18 + node_id, 0); + htic = pci_read_config32(device, HT_INIT_CONTROL); htic |= HTIC_ColdR_Detect | HTIC_BIOSR_Detect | HTIC_INIT_Detect; - pci_write_config32(PCI_DEV(0, 0x18, 0), HT_INIT_CONTROL, htic); + pci_write_config32(device, HT_INIT_CONTROL, htic); } diff --git a/src/pc80/mc146818rtc_early.c b/src/pc80/mc146818rtc_early.c index 30369455fe..35f3f5910f 100644 --- a/src/pc80/mc146818rtc_early.c +++ b/src/pc80/mc146818rtc_early.c @@ -4,7 +4,7 @@ #ifndef MAX_REBOOT_CNT #error "MAX_REBOOT_CNT not defined" #endif -#if MAX_REBOOT_CNT > 14 +#if MAX_REBOOT_CNT > 15 #error "MAX_REBOOT_CNT too high" #endif @@ -78,6 +78,12 @@ static int do_normal_boot(void) byte &= 0x0f; /* yes, clear the boot count */ } + /* Properly set the last boot flag */ + byte &= 0xfc; + if ((byte >> 4) < MAX_REBOOT_CNT) { + byte |= (1<<1); + } + /* Are we already at the max count? */ if ((byte >> 4) < MAX_REBOOT_CNT) { byte += 1 << 4; /* No, add 1 to the count */ @@ -86,13 +92,8 @@ static int do_normal_boot(void) byte &= 0xfc; /* Yes, put in fallback mode */ } - /* Is this the first boot? */ - if ((byte >> 4) <= 1) { - byte = (byte & 0xfc) | ((byte & 1) << 1); /* yes, shift the boot bits */ - } - /* Save the boot byte */ cmos_write(byte, RTC_BOOT_BYTE); - return ((byte >> 4) < MAX_REBOOT_CNT); + return (byte & (1<<1)); } diff --git a/src/sdram/generic_sdram.c b/src/sdram/generic_sdram.c index 7bd801a926..9ec8122afe 100644 --- a/src/sdram/generic_sdram.c +++ b/src/sdram/generic_sdram.c @@ -7,22 +7,31 @@ void sdram_no_memory(void) } /* Setup SDRAM */ -void sdram_initialize(const struct mem_controller *ctrl) +void sdram_initialize(int controllers, const struct mem_controller *ctrl) { - print_debug("Ram1\r\n"); + int i; /* Set the registers we can set once to reasonable values */ - sdram_set_registers(ctrl); + for(i = 0; i < controllers; i++) { + print_debug("Ram1."); + print_debug_hex8(i); + print_debug("\r\n"); + sdram_set_registers(ctrl + i); + } - print_debug("Ram2\r\n"); /* Now setup those things we can auto detect */ - sdram_set_spd_registers(ctrl); + for(i = 0; i < controllers; i++) { + print_debug("Ram2."); + print_debug_hex8(i); + print_debug("\r\n"); + sdram_set_spd_registers(ctrl + i); + } - print_debug("Ram3\r\n"); /* Now that everything is setup enable the SDRAM. * Some chipsets do the work for use while on others * we need to it by hand. */ - sdram_enable(ctrl); + print_debug("Ram3\r\n"); + sdram_enable(controllers, ctrl); print_debug("Ram4\r\n"); } diff --git a/src/southbridge/amd/amd8111/amd8111_lpc.c b/src/southbridge/amd/amd8111/amd8111_lpc.c index 643b84cad9..b78b55bc88 100644 --- a/src/southbridge/amd/amd8111/amd8111_lpc.c +++ b/src/southbridge/amd/amd8111/amd8111_lpc.c @@ -87,6 +87,7 @@ static void setup_ioapic(void) static void lpc_init(struct device *dev) { uint8_t byte; + uint16_t word; int pwr_on=-1; printk_debug("lpc_init\n"); @@ -101,6 +102,13 @@ static void lpc_init(struct device *dev) byte = pci_read_config8(dev, 0x46); pci_write_config8(dev, 0x46, byte | (1<<0)); +//BY LYH + /* Disable AC97 and Ethernet */ + word = pci_read_config16(dev, 0x48); + pci_write_config16(dev, 0x48, word & ~((1<<5)|(1<<6)|(1<<9))); +//BY LYH END + + /* power after power fail */ byte = pci_read_config8(dev, 0x43); if (pwr_on) { diff --git a/src/southbridge/amd/amd8111/amd8111_usb2.c b/src/southbridge/amd/amd8111/amd8111_usb2.c new file mode 100644 index 0000000000..5c680ba0ad --- /dev/null +++ b/src/southbridge/amd/amd8111/amd8111_usb2.c @@ -0,0 +1,38 @@ +//2003 Copywright Tyan +//BY LYH + + +#include +#include +#include +#include +#include + +static void usb2_init(struct device *dev) +{ + uint32_t cmd; + + printk_debug("USB: Setting up controller.. "); + cmd = pci_read_config32(dev, PCI_COMMAND); + pci_write_config32(dev, PCI_COMMAND, + cmd | PCI_COMMAND_IO | PCI_COMMAND_MEMORY | + PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE); + + + printk_debug("done.\n"); + +} + +static struct device_operations usb_ops = { + .read_resources = pci_dev_read_resources, + .set_resources = pci_dev_set_resources, + .init = usb2_init, + .scan_bus = 0, +}; + +static struct pci_driver usb2_driver __pci_driver = { + .ops = &usb_ops, + .vendor = PCI_VENDOR_ID_AMD, + .device = PCI_DEVICE_ID_AMD_8111_USB2, +}; + diff --git a/util/romcc/romcc.c b/util/romcc/romcc.c index 386d86a238..c721a21002 100644 --- a/util/romcc/romcc.c +++ b/util/romcc/romcc.c @@ -14,7 +14,7 @@ #define DEBUG_ERROR_MESSAGES 0 #define DEBUG_COLOR_GRAPH 0 #define DEBUG_SCC 0 -#define DEBUG_CONSISTENCY 2 +#define DEBUG_CONSISTENCY 1 #define DEBUG_RANGE_CONFLICTS 0 #define DEBUG_COALESCING 0 #define DEBUG_SDP_BLOCKS 0 @@ -12952,6 +12952,23 @@ static void verify_graph_ins( return; } +#if DEBUG_CONSISTENCY > 1 +static void verify_interference_graph( + struct compile_state *state, struct reg_state *rstate) +{ +#if 0 + fprintf(stderr, "verify_interference_graph...\n"); +#endif + + walk_variable_lifetimes(state, rstate->blocks, verify_graph_ins, rstate); +#if 0 + fprintf(stderr, "verify_interference_graph done\n"); +#endif +} +#else +static inline void verify_interference_graph( + struct compile_state *state, struct reg_state *rstate) {} +#endif static void print_interference_ins( struct compile_state *state, @@ -13765,6 +13782,7 @@ static int color_graph(struct compile_state *state, struct reg_state *rstate) return colored; } +#if DEBUG_CONSISTENCY static void verify_colors(struct compile_state *state, struct reg_state *rstate) { struct live_range *lr; @@ -13801,6 +13819,9 @@ static void verify_colors(struct compile_state *state, struct reg_state *rstate) ins = ins->next; } while(ins != first); } +#else +static inline void verify_colors(struct compile_state *state, struct reg_state *rstate) {} +#endif static void color_triples(struct compile_state *state, struct reg_state *rstate) { @@ -14005,17 +14026,8 @@ static void allocate_registers(struct compile_state *state) #endif } while(coalesced); -#if DEBUG_CONSISTENCY > 1 -# if 0 - fprintf(stderr, "verify_graph_ins...\n"); -# endif /* Verify the interference graph */ - walk_variable_lifetimes( - state, rstate.blocks, verify_graph_ins, &rstate); -# if 0 - fprintf(stderr, "verify_graph_ins done\n"); -#endif -#endif + verify_interference_graph(state, &rstate); /* Build the groups low and high. But with the nodes * first sorted by degree order.