- 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
This commit is contained in:
Eric Biederman
2003-07-21 20:13:45 +00:00
parent 6d4512cdf9
commit 2c018fba95
33 changed files with 1512 additions and 268 deletions

View File

@ -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 */

View File

@ -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 */

View File

@ -1,6 +1,6 @@
#include <arch/asm.h> #include <arch/asm.h>
#include <arch/intel.h> #include <arch/intel.h>
#ifdef SMP #ifdef CONFIG_SMP
#include <cpu/p6/apic.h> #include <cpu/p6/apic.h>
#endif #endif
.section ".text" .section ".text"
@ -39,7 +39,7 @@ _start:
/* set new stack */ /* set new stack */
movl $_estack, %esp movl $_estack, %esp
#ifdef SMP #ifdef CONFIG_SMP
/* Get the cpu id */ /* Get the cpu id */
movl $APIC_DEFAULT_BASE, %edi movl $APIC_DEFAULT_BASE, %edi
movl APIC_ID(%edi), %eax movl APIC_ID(%edi), %eax

View File

@ -68,8 +68,11 @@ static struct mem_range *get_ramsize(void)
mem = sizeram(); mem = sizeram();
} }
if (!mem) { if (!mem) {
printk_err("No memory size information!\n"); printk_emerg("No memory size information!\n");
for(;;); for(;;) {
/* Ensure this loop is not optimized away */
asm volatile("":/* outputs */:/*inputs */ :"memory");
}
} }
return mem; return mem;
} }
@ -120,9 +123,9 @@ static void wait_for_other_cpus(void)
printk_debug("All AP CPUs stopped\n"); printk_debug("All AP CPUs stopped\n");
} }
#else /* SMP */ #else /* CONIFG_SMP */
#define wait_for_other_cpus() do {} while(0) #define wait_for_other_cpus() do {} while(0)
#endif /* SMP */ #endif /* CONFIG_SMP */
void hardwaremain(int boot_complete) void hardwaremain(int boot_complete)
{ {

View File

@ -380,11 +380,6 @@ define CONFIG_SMP
export always export always
comment "Define if we support SMP" comment "Define if we support SMP"
end end
define SMP
default none
export always
comment "Define if we support SMP"
end
define MAX_CPUS define MAX_CPUS
default 1 default 1
export always export always

View File

@ -2,60 +2,52 @@
#include <console/console.h> #include <console/console.h>
#include <mem.h> #include <mem.h>
#include <cpu/p6/msr.h> #include <cpu/p6/msr.h>
#include <cpu/k8/mtrr.h>
#define TOP_MEM 0xc001001A #include <device/device.h>
#define TOP_MEM2 0xc001001D
#define IORR_FIRST 0xC0010016
#define IORR_LAST 0xC0010019
#define SYSCFG 0xC0010010
#define MTRRVARDRAMEN (1 << 20)
void k8_cpufixup(struct mem_range *mem) void k8_cpufixup(struct mem_range *mem)
{ {
msr_t msr; unsigned long mmio_basek, tomk;
unsigned long i; unsigned long i;
unsigned long ram_megabytes; msr_t msr;
/* Except for the PCI MMIO hold just before 4GB there are no
/* For now no Athlon board has significant holes in it's * significant holes in the address space, so just account
* address space so just find the last memory region * for those two and move on.
* and compute the end of memory from that.
*/ */
for(i = 0; mem[i].sizek; i++) mmio_basek = tomk = 0;
; for(i = 0; mem[i].sizek; i++) {
if (i == 0) unsigned long topk;
return; topk = mem[i].basek + mem[i].sizek;
ram_megabytes = (mem[i-1].basek + mem[i-1].sizek) *1024; if (tomk < topk) {
tomk = topk;
}
if ((topk < 4*1024*1024) && (mmio_basek < topk)) {
mmio_basek = topk;
}
}
if (mmio_basek > tomk) {
mmio_basek = tomk;
}
/* Setup TOP_MEM */
#warning "FIXME handle > 4GB of ram" msr.hi = mmio_basek >> 22;
// 8 MB alignment please msr.lo = mmio_basek << 10;
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;
wrmsr(TOP_MEM, msr); 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); wrmsr(TOP_MEM2, msr);
/* zero the IORR's before we enable to prevent /* zero the IORR's before we enable to prevent
* undefined side effects * undefined side effects.
*/ */
msr.lo = msr.hi = 0; msr.lo = msr.hi = 0;
for (i = IORR_FIRST; i <= IORR_LAST; i++) for(i = IORR_FIRST; i <= IORR_LAST; i++) {
wrmsr(i, msr); wrmsr(i, msr);
msr = rdmsr(SYSCFG);
printk_spew("SYSCFG was 0x%x:0x%x\n", msr.hi, msr.lo);
msr.lo |= MTRRVARDRAMEN;
wrmsr(SYSCFG, msr);
msr = rdmsr(SYSCFG);
printk_spew("SYSCFG IS NOW 0x%x:0x%x\n", msr.hi, msr.lo);
} }
msr = rdmsr(SYSCFG);
msr.lo |= SYSCFG_MSR_MtrrVarDramEn | SYSCFG_MSR_TOM2En;
wrmsr(SYSCFG, msr);
}

View File

@ -33,9 +33,6 @@ static struct device **last_dev_p = &all_devices;
#define DEVICE_IO_START 0x1000 #define DEVICE_IO_START 0x1000
unsigned long device_memory_base;
/* Append a new device to the global device chain. /* Append a new device to the global device chain.
* The chain is used to find devices once everything is set up. * The chain is used to find devices once everything is set up.
*/ */
@ -379,7 +376,6 @@ void dev_configure(void)
root->resource[1].base = root->resource[1].base =
round_down(DEVICE_MEM_HIGH - root->resource[1].size, round_down(DEVICE_MEM_HIGH - root->resource[1].size,
1UL << root->resource[1].align); 1UL << root->resource[1].align);
device_memory_base = root->resource[1].base;
root->resource[1].flags |= IORESOURCE_SET; root->resource[1].flags |= IORESOURCE_SET;
// now just set things into registers ... we hope ... // now just set things into registers ... we hope ...
root->ops->set_resources(root); root->ops->set_resources(root);

View File

@ -1,9 +1,8 @@
#ifndef CPU_K8_MTRR_H #ifndef CPU_K8_MTRR_H
#define CPU_K8_MTRR_H #define CPU_K8_MTRR_H
#include <cpu/k7/mtrr.h> #include <cpu/p6/mtrr.h>
#if 0
#define IORR_FIRST 0xC0010016 #define IORR_FIRST 0xC0010016
#define IORR_LAST 0xC0010019 #define IORR_LAST 0xC0010019
#define SYSCFG 0xC0010010 #define SYSCFG 0xC0010010
@ -12,17 +11,12 @@
#define MTRR_WRITE_MEM (1 << 3) #define MTRR_WRITE_MEM (1 << 3)
#define SYSCFG_MSR 0xC0010010 #define SYSCFG_MSR 0xC0010010
#define SYSCFG_MSR_EvictEn (1 << 22)
#define SYSCFG_MSR_TOM2En (1 << 21) #define SYSCFG_MSR_TOM2En (1 << 21)
#define SYSCFG_MSR_MtrrVarDramEn (1 << 20) #define SYSCFG_MSR_MtrrVarDramEn (1 << 20)
#define SYSCFG_MSR_MtrrFixDramModEn (1 << 19) #define SYSCFG_MSR_MtrrFixDramModEn (1 << 19)
#define SYSCFG_MSR_MtrrFixDramEn (1 << 18) #define SYSCFG_MSR_MtrrFixDramEn (1 << 18)
#define SYSCFG_MSR_UcLockEn (1 << 17) #define SYSCFG_MSR_UcLockEn (1 << 17)
#define SYSCFG_MSR_ChxToDirtyDis (1 << 16) #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_ClVicBlkEn (1 << 11)
#define SYSCFG_MSR_SetDirtyEnO (1 << 10) #define SYSCFG_MSR_SetDirtyEnO (1 << 10)
#define SYSCFG_MSR_SetDirtyEnS (1 << 9) #define SYSCFG_MSR_SetDirtyEnS (1 << 9)
@ -40,6 +34,4 @@
#define TOP_MEM2 0xC001001D #define TOP_MEM2 0xC001001D
#define HWCR_MSR 0xC0010015 #define HWCR_MSR 0xC0010015
#endif
#endif /* CPU_K8_MTRR_H */ #endif /* CPU_K8_MTRR_H */

View File

@ -17,7 +17,7 @@ struct device_operations {
#define MAX_RESOURCES 6 #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: * combination:
*/ */
@ -75,8 +75,6 @@ void compute_allocate_resource(device_t bus, struct resource *bridge,
unsigned long type_mask, unsigned long type); unsigned long type_mask, unsigned long type);
void assign_resources(device_t bus); void assign_resources(device_t bus);
void enumerate_static_device(void); void enumerate_static_device(void);
unsigned long device_memory_base;
/* Helper functions */ /* Helper functions */
device_t dev_find_device (unsigned int vendor, unsigned int device, device_t from); device_t dev_find_device (unsigned int vendor, unsigned int device, device_t from);

View File

@ -1,7 +1,7 @@
#ifndef SMP_ATOMIC_H #ifndef SMP_ATOMIC_H
#define SMP_ATOMIC_H #define SMP_ATOMIC_H
#ifdef SMP #ifdef CONFIG_SMP
#include <arch/smp/atomic.h> #include <arch/smp/atomic.h>
#else #else
@ -48,6 +48,6 @@ typedef struct { int counter; } atomic_t;
#define atomic_dec(v) (((v)->counter)--) #define atomic_dec(v) (((v)->counter)--)
#endif /* SMP */ #endif /* CONFIG_SMP */
#endif /* SMP_ATOMIC_H */ #endif /* SMP_ATOMIC_H */

View File

@ -1,9 +1,9 @@
#ifndef SMP_SPINLOCK_H #ifndef SMP_SPINLOCK_H
#define SMP_SPINLOCK_H #define SMP_SPINLOCK_H
#ifdef SMP #ifdef CONFIG_SMP
#include <arch/smp/spinlock.h> #include <arch/smp/spinlock.h>
#else /* !SMP */ #else /* !CONFIG_SMP */
/* Most GCC versions have a nasty bug with empty initializers */ /* Most GCC versions have a nasty bug with empty initializers */
#if (__GNUC__ > 2) #if (__GNUC__ > 2)

View File

@ -16,7 +16,7 @@ void boot_successful(void)
byte = inb(RTC_PORT(1)); byte = inb(RTC_PORT(1));
byte &= 0xfe; byte &= 0xfe;
byte |= (byte & 2) >> 1; byte |= (byte & (1 << 1)) >> 1;
/* If we are in normal mode set the boot count to 0 */ /* If we are in normal mode set the boot count to 0 */
if(byte & 1) if(byte & 1)

View File

@ -86,6 +86,11 @@ static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes)
return ret; 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 "northbridge/amd/amdk8/cpu_ldtstop.c"
#include "southbridge/amd/amd8111/amd8111_ldtstop.c" #include "southbridge/amd/amd8111/amd8111_ldtstop.c"

View File

@ -25,6 +25,12 @@ static unsigned int generate_row(uint8_t node, uint8_t row, uint8_t maxnodes)
return 0x00010101; /* default row entry */ 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/raminit.c"
#include "northbridge/amd/amdk8/coherent_ht.c" #include "northbridge/amd/amdk8/coherent_ht.c"
#include "sdram/generic_sdram.c" #include "sdram/generic_sdram.c"

View File

@ -17,7 +17,7 @@
#include "northbridge/amd/amdk8/reset_test.c" #include "northbridge/amd/amdk8/reset_test.c"
#include "debug.c" #include "debug.c"
static void memreset_setup(const struct mem_controller *ctrl) static void memreset_setup(void)
{ {
/* Set the memreset low */ /* Set the memreset low */
outb((0 << 7)|(0 << 6)|(0<<5)|(0<<4)|(1<<2)|(0<<0), SMBUS_IO_BASE + 0xc0 + 28); 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); 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); udelay(800);
/* Set memreset_high */ /* Set memreset_high */
outb((0<<7)|(0<<6)|(0<<5)|(0<<4)|(1<<2)|(1<<0), SMBUS_IO_BASE + 0xc0 + 28); 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) 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; 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 "northbridge/amd/amdk8/cpu_ldtstop.c"
#include "southbridge/amd/amd8111/amd8111_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); 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) static void main(void)
{ {
/* /*
* GPIO28 of 8111 will control H0_MEMRESET_L * GPIO28 of 8111 will control H0_MEMRESET_L
* GPIO29 of 8111 will control H1_MEMRESET_L * GPIO29 of 8111 will control H1_MEMRESET_L
*/ */
static const struct mem_controller cpu[] = {
static const struct mem_controller cpu0 = { #if FIRST_CPU
{
.node_id = 0,
.f0 = PCI_DEV(0, 0x18, 0), .f0 = PCI_DEV(0, 0x18, 0),
.f1 = PCI_DEV(0, 0x18, 1), .f1 = PCI_DEV(0, 0x18, 1),
.f2 = PCI_DEV(0, 0x18, 2), .f2 = PCI_DEV(0, 0x18, 2),
.f3 = PCI_DEV(0, 0x18, 3), .f3 = PCI_DEV(0, 0x18, 3),
.channel0 = { (0xa<<3)|0, (0xa<<3)|2, 0, 0 }, .channel0 = { (0xa<<3)|0, (0xa<<3)|2, 0, 0 },
.channel1 = { (0xa<<3)|1, (0xa<<3)|3, 0, 0 }, .channel1 = { (0xa<<3)|1, (0xa<<3)|3, 0, 0 },
}; },
static const struct mem_controller cpu1 = { #endif
#if SECOND_CPU
{
.node_id = 1,
.f0 = PCI_DEV(0, 0x19, 0), .f0 = PCI_DEV(0, 0x19, 0),
.f1 = PCI_DEV(0, 0x19, 1), .f1 = PCI_DEV(0, 0x19, 1),
.f2 = PCI_DEV(0, 0x19, 2), .f2 = PCI_DEV(0, 0x19, 2),
.f3 = PCI_DEV(0, 0x19, 3), .f3 = PCI_DEV(0, 0x19, 3),
.channel0 = { (0xa<<3)|4, (0xa<<3)|6, 0, 0 }, .channel0 = { (0xa<<3)|4, (0xa<<3)|6, 0, 0 },
.channel1 = { (0xa<<3)|5, (0xa<<3)|7, 0, 0 }, .channel1 = { (0xa<<3)|5, (0xa<<3)|7, 0, 0 },
},
#endif
}; };
if (cpu_init_detected()) { if (cpu_init_detected()) {
asm("jmp __cpu_reset"); asm("jmp __cpu_reset");
} }
pc87360_enable_serial();
uart_init();
console_init();
enable_lapic(); enable_lapic();
init_timer();
if (!boot_cpu()) { if (!boot_cpu()) {
stop_this_cpu(); stop_this_cpu();
} }
init_timer(); pc87360_enable_serial();
uart_init();
console_init();
setup_default_resource_map(); setup_default_resource_map();
setup_coherent_ht_domain(); setup_coherent_ht_domain();
enumerate_ht_chain(0); enumerate_ht_chain(0);
distinguish_cpu_resets(); distinguish_cpu_resets(0);
#if 1 #if 0
print_pci_devices(); print_pci_devices();
#endif #endif
enable_smbus(); enable_smbus();
#if 0 #if 0
dump_spd_registers(&cpu0); dump_spd_registers(&cpu[0]);
#endif #endif
sdram_initialize(&cpu0); memreset_setup();
sdram_initialize(sizeof(cpu)/sizeof(cpu[0]), cpu);
#if 1 #if 1
dump_pci_devices(); dump_pci_devices();
@ -204,7 +220,12 @@ static void main(void)
#if 0 #if 0
ram_check(0x00000000, msr.lo); ram_check(0x00000000, msr.lo);
#else #else
/* Check 16MB of memory */ #if TOTAL_CPUS < 2
/* Check 16MB of memory @ 0*/
ram_check(0x00000000, 0x01000000); ram_check(0x00000000, 0x01000000);
#else
/* Check 16MB of memory @ 2GB */
ram_check(0x80000000, 0x81000000);
#endif
#endif #endif
} }

View File

@ -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

View File

@ -0,0 +1 @@
2.0

View File

@ -0,0 +1,437 @@
#define ASSEMBLY 1
#include <stdint.h>
#include <device/pci_def.h>
#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");
}
}
}

View File

@ -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

View File

@ -0,0 +1,26 @@
#define ASSEMBLY 1
#include <stdint.h>
#include <device/pci_def.h>
#include <device/pci_ids.h>
#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");
}
}

View File

@ -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 <arch/pirq_routing.h>
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},
}
};

View File

@ -0,0 +1,120 @@
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
#include <part/mainboard.h>
//#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
}

View File

@ -0,0 +1,99 @@
#include <console/console.h>
#include <arch/smp/mpspec.h>
#include <device/pci.h>
#include <string.h>
#include <stdint.h>
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);
}

View File

@ -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("Enabling routing table for node ");
print_debug_hex32(node); print_debug_hex32(node);
val=pci_read_config32(NODE_HT(node), 0x6c); 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); pci_write_config32(NODE_HT(node), 0x6c, val);
print_debug(" done.\r\n"); print_debug(" done.\r\n");

View File

@ -2,22 +2,91 @@
#include <stdint.h> #include <stdint.h>
#include <mem.h> #include <mem.h>
#include <part/sizeram.h> #include <part/sizeram.h>
#include <device/device.h>
#include <device/pci.h>
#include <console/console.h>
struct mem_range *sizeram(void) struct mem_range *sizeram(void)
{ {
static struct mem_range mem[3]; unsigned long mmio_basek;
uint32_t size; static struct mem_range mem[10];
/* Convert size in bytes to size in K */ device_t dev;
#warning "FINISH sizeram" int i, idx;
/* FIXME hardcoded for now */
size = 512*1024;
mem[0].basek = 0; #warning "FIXME handle interleaved nodes"
mem[0].sizek = 640; dev = dev_find_slot(0, PCI_DEVFN(0x18, 1));
mem[1].basek = 960; if (!dev) {
mem[1].sizek = size - mem[1].basek; return 0;
mem[2].basek = 0; }
mem[2].sizek = 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; return mem;
} }

View File

@ -922,10 +922,9 @@ static void sdram_set_registers(const struct mem_controller *ctrl)
}; };
int i; int i;
int max; int max;
#if 1 print_debug("setting up CPU");
memreset_setup(ctrl); print_debug_hex8(ctrl->node_id);
#endif print_debug(" northbridge registers\r\n");
print_debug("setting up CPU0 northbridge registers\r\n");
max = sizeof(register_values)/sizeof(register_values[0]); max = sizeof(register_values)/sizeof(register_values[0]);
for(i = 0; i < max; i += 3) { for(i = 0; i < max; i += 3) {
device_t dev; 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 * a multiple of 4MB. The way we do it now we can size both
* sides of an assymetric dimm. * sides of an assymetric dimm.
*/ */
value = smbus_read_byte(device, 3); /* rows */ value = spd_read_byte(device, 3); /* rows */
if (value < 0) goto out; if (value < 0) goto out;
sz.side1 += value & 0xf; sz.side1 += value & 0xf;
value = smbus_read_byte(device, 4); /* columns */ value = spd_read_byte(device, 4); /* columns */
if (value < 0) goto out; if (value < 0) goto out;
sz.side1 += value & 0xf; sz.side1 += value & 0xf;
value = smbus_read_byte(device, 17); /* banks */ value = spd_read_byte(device, 17); /* banks */
if (value < 0) goto out; if (value < 0) goto out;
sz.side1 += log2(value & 0xff); sz.side1 += log2(value & 0xff);
/* Get the module data width and convert it to a power of two */ /* 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; if (value < 0) goto out;
value &= 0xff; value &= 0xff;
value <<= 8; value <<= 8;
low = smbus_read_byte(device, 6); /* (low byte) */ low = spd_read_byte(device, 6); /* (low byte) */
if (low < 0) goto out; if (low < 0) goto out;
value = value | (low & 0xff); value = value | (low & 0xff);
sz.side1 += log2(value); sz.side1 += log2(value);
/* side 2 */ /* 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; if (value <= 1) goto out;
/* Start with the symmetrical case */ /* Start with the symmetrical case */
sz.side2 = sz.side1; 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 < 0) goto out;
if ((value & 0xf0) == 0) goto out; /* If symmetrical we are done */ if ((value & 0xf0) == 0) goto out; /* If symmetrical we are done */
sz.side2 -= (value & 0x0f); /* Subtract out rows on side 1 */ sz.side2 -= (value & 0x0f); /* Subtract out rows on side 1 */
sz.side2 += ((value >> 4) & 0x0f); /* Add in rows on side 2 */ 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; if (value < 0) goto out;
sz.side2 -= (value & 0x0f); /* Subtract out columns on side 1 */ sz.side2 -= (value & 0x0f); /* Subtract out columns on side 1 */
sz.side2 += ((value >> 4) & 0x0f); /* Add in columsn on side 2 */ 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, static void route_dram_accesses(const struct mem_controller *ctrl,
unsigned long base_k, unsigned long limit_k) 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 node_id;
unsigned limit; unsigned limit;
unsigned base; unsigned base;
node_id = 0; unsigned index;
/* Route the addresses to node 0 */ unsigned limit_reg, base_reg;
device_t device;
node_id = ctrl->node_id;
index = (node_id << 3);
limit = (limit_k << 2); limit = (limit_k << 2);
limit &= 0xffff0000; limit &= 0xffff0000;
limit -= 0x00010000; limit -= 0x00010000;
limit |= ( 0 << 8) | (node_id << 0);
base = (base_k << 2); base = (base_k << 2);
base &= 0xffff0000; base &= 0xffff0000;
pci_write_config32(ctrl->f1, 0x44, limit | (0 << 8) | (node_id << 0)); base |= (0 << 8) | (1<<1) | (1<<0);
pci_write_config32(ctrl->f1, 0x40, base | (0 << 8) | (1<<1) | (1<<0));
#if 1 limit_reg = 0x44 + index;
pci_write_config32(PCI_DEV(0, 0x19, 1), 0x44, limit | (0 << 8) | (1 << 4) | (node_id << 0)); base_reg = 0x40 + index;
pci_write_config32(PCI_DEV(0, 0x19, 1), 0x40, base | (0 << 8) | (1<<1) | (1<<0)); for(device = PCI_DEV(0, 0x18, 1); device <= PCI_DEV(0, 0x1f, 1); device += PCI_DEV(0, 1, 0)) {
#endif pci_write_config32(device, limit_reg, limit);
pci_write_config32(device, base_reg, base);
}
} }
static void set_top_mem(unsigned tom_k) static void set_top_mem(unsigned tom_k)
@ -1148,6 +1152,13 @@ static void set_top_mem(unsigned tom_k)
die("No memory"); 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 */ /* Now set top of memory */
msr_t msr; msr_t msr;
msr.lo = (tom_k & 0x003fffff) << 10; 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.lo = (tom_k & 0x003fffff) << 10;
msr.hi = (tom_k & 0xffc00000) >> 22; msr.hi = (tom_k & 0xffc00000) >> 22;
wrmsr(TOP_MEM, msr); 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) 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 */ /* Remember which registers we have used in the high 8 bits of tom */
tom = 0; tom = base_k >> 15;
for(;;) { for(;;) {
/* Find the largest remaining canidate */ /* Find the largest remaining canidate */
unsigned index, canidate; unsigned index, canidate;
@ -1212,12 +1230,24 @@ static void order_dimms(const struct mem_controller *ctrl)
break; break;
} }
/* Remember I have used this register */
tom |= (1 << (canidate + 24));
/* Remember the dimm size */ /* Remember the dimm size */
size = csbase >> 21; 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 */ /* Recompute the cs base register value */
csbase = (tom << 21) | 1; csbase = (tom << 21) | 1;
@ -1239,11 +1269,13 @@ static void order_dimms(const struct mem_controller *ctrl)
#if 0 #if 0
print_debug("tom: "); print_debug("tom: ");
print_debug_hex32(tom); print_debug_hex32(tom);
print_debug(" base_k: ");
print_debug_hex32(base_k);
print_debug(" tom_k: "); print_debug(" tom_k: ");
print_debug_hex32(tom_k); print_debug_hex32(tom_k);
print_debug("\r\n"); print_debug("\r\n");
#endif #endif
route_dram_accesses(ctrl, 0, tom_k); route_dram_accesses(ctrl, base_k, tom_k);
set_top_mem(tom_k); set_top_mem(tom_k);
} }
@ -1267,7 +1299,7 @@ static void spd_handle_unbuffered_dimms(const struct mem_controller *ctrl)
registered = 0; registered = 0;
for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) { for(i = 0; (i < 4) && (ctrl->channel0[i]); i++) {
int value; int value;
value = smbus_read_byte(ctrl->channel0[i], 21); value = spd_read_byte(ctrl->channel0[i], 21);
if (value < 0) { if (value < 0) {
disable_dimm(ctrl, i); disable_dimm(ctrl, i);
continue; continue;
@ -1307,31 +1339,30 @@ static void spd_enable_2channels(const struct mem_controller *ctrl)
{ {
int i; int i;
uint32_t nbcap; 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" #warning "FINISHME review and see if these are the bytes I need"
/* 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[] = { static const unsigned addresses[] = {
2, /* Type should be DDR SDRAM */ 2, /* Type should be DDR SDRAM */
3, /* Row addresses */ 3, /* *Row addresses */
4, /* Column addresses */ 4, /* *Column addresses */
5, /* Physical Banks */ 5, /* *Physical Banks */
6, /* Module Data Width low */ 6, /* *Module Data Width low */
7, /* Module Data Width high */ 7, /* *Module Data Width high */
9, /* Cycle time at highest CAS Latency CL=X */ 9, /* *Cycle time at highest CAS Latency CL=X */
11, /* SDRAM Type */ 11, /* *SDRAM Type */
12, /* Refresh Interval */ 13, /* *SDRAM Width */
13, /* SDRAM Width */ 17, /* *Logical Banks */
15, /* Back-to-Back Random Column Access */ 18, /* *Supported CAS Latencies */
16, /* Burst Lengths */ 21, /* *SDRAM Module Attributes */
17, /* Logical Banks */ 23, /* *Cycle time at CAS Latnecy (CLX - 0.5) */
18, /* Supported CAS Latencies */ 26, /* *Cycle time at CAS Latnecy (CLX - 1.0) */
23, /* Cycle time at CAS Latnecy (CLX - 0.5) */ 27, /* *tRP Row precharge time */
26, /* Cycle time at CAS Latnecy (CLX - 1.0) */ 28, /* *Minimum Row Active to Row Active Delay (tRRD) */
27, /* tRP Row precharge time */ 29, /* *tRCD RAS to CAS */
29, /* tRCD RAS to CAS */ 30, /* *tRAS Activate to Precharge */
30, /* tRAS Activate to Precharge */ 41, /* *Minimum Active to Active/Auto Refresh Time(Trc) */
31, /* Module Bank Density */ 42, /* *Minimum Auto Refresh Command Time(Trfc) */
33, /* Address and Command Hold Time After Clock */
}; };
nbcap = pci_read_config32(ctrl->f3, NORTHBRIDGE_CAP); nbcap = pci_read_config32(ctrl->f3, NORTHBRIDGE_CAP);
if (!(nbcap & NBCAP_128Bit)) { 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++) { for(j = 0; j < sizeof(addresses)/sizeof(addresses[0]); j++) {
unsigned addr; unsigned addr;
addr = addresses[j]; addr = addresses[j];
value0 = smbus_read_byte(device0, addr); value0 = spd_read_byte(device0, addr);
if (value0 < 0) { if (value0 < 0) {
break; break;
} }
value1 = smbus_read_byte(device1, addr); value1 = spd_read_byte(device1, addr);
if (value1 < 0) { if (value1 < 0) {
return; return;
} }
@ -1498,7 +1529,7 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
new_cycle_time = 0xa0; new_cycle_time = 0xa0;
new_latency = 5; new_latency = 5;
latencies = smbus_read_byte(ctrl->channel0[i], 18); latencies = spd_read_byte(ctrl->channel0[i], 18);
if (latencies <= 0) continue; if (latencies <= 0) continue;
/* Compute the lowest cas latency supported */ /* 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)))) { (!(latencies & (1 << latency)))) {
continue; continue;
} }
value = smbus_read_byte(ctrl->channel0[i], latency_indicies[index]); value = spd_read_byte(ctrl->channel0[i], latency_indicies[index]);
if (value < 0) { if (value < 0) {
continue; continue;
} }
@ -1553,7 +1584,7 @@ static const struct mem_param *spd_set_memclk(const struct mem_controller *ctrl)
int index; int index;
int value; int value;
int dimm; int dimm;
latencies = smbus_read_byte(ctrl->channel0[i], 18); latencies = spd_read_byte(ctrl->channel0[i], 18);
if (latencies <= 0) { if (latencies <= 0) {
goto dimm_err; 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 */ /* 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 /* All is good if the selected clock speed
* is what I need or slower. * 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; unsigned clocks, old_clocks;
uint32_t dtl; uint32_t dtl;
int value; 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) return -1;
if ((value == 0) || (value == 0xff)) { if ((value == 0) || (value == 0xff)) {
value = param->tRC; value = param->tRC;
@ -1648,7 +1679,7 @@ static int update_dimm_Trfc(const struct mem_controller *ctrl, const struct mem_
unsigned clocks, old_clocks; unsigned clocks, old_clocks;
uint32_t dtl; uint32_t dtl;
int value; 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) return -1;
if ((value == 0) || (value == 0xff)) { if ((value == 0) || (value == 0xff)) {
value = param->tRFC; value = param->tRFC;
@ -1677,7 +1708,7 @@ static int update_dimm_Trcd(const struct mem_controller *ctrl, const struct mem_
unsigned clocks, old_clocks; unsigned clocks, old_clocks;
uint32_t dtl; uint32_t dtl;
int value; int value;
value = smbus_read_byte(ctrl->channel0[i], 29); value = spd_read_byte(ctrl->channel0[i], 29);
if (value < 0) return -1; if (value < 0) return -1;
#if 0 #if 0
clocks = (value + (param->divisor << 1) -1)/(param->divisor << 1); 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; unsigned clocks, old_clocks;
uint32_t dtl; uint32_t dtl;
int value; int value;
value = smbus_read_byte(ctrl->channel0[i], 28); value = spd_read_byte(ctrl->channel0[i], 28);
if (value < 0) return -1; if (value < 0) return -1;
clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1); clocks = (value + ((param->divisor & 0xff) << 1) -1)/((param->divisor & 0xff) << 1);
if (clocks < DTL_TRRD_MIN) { 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; unsigned clocks, old_clocks;
uint32_t dtl; uint32_t dtl;
int value; int value;
value = smbus_read_byte(ctrl->channel0[i], 30); value = spd_read_byte(ctrl->channel0[i], 30);
if (value < 0) return -1; if (value < 0) return -1;
clocks = ((value << 1) + param->divisor - 1)/param->divisor; clocks = ((value << 1) + param->divisor - 1)/param->divisor;
if (clocks < DTL_TRAS_MIN) { 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; unsigned clocks, old_clocks;
uint32_t dtl; uint32_t dtl;
int value; int value;
value = smbus_read_byte(ctrl->channel0[i], 27); value = spd_read_byte(ctrl->channel0[i], 27);
if (value < 0) return -1; if (value < 0) return -1;
#if 0 #if 0
clocks = (value + (param->divisor << 1) - 1)/(param->divisor << 1); 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; uint32_t dth;
int value; int value;
unsigned tref, old_tref; 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; if (value < 0) return -1;
value &= 0xf; value &= 0xf;
@ -1841,7 +1872,7 @@ static int update_dimm_x4(const struct mem_controller *ctrl, const struct mem_pa
uint32_t dcl; uint32_t dcl;
int value; int value;
int dimm; int dimm;
value = smbus_read_byte(ctrl->channel0[i], 13); value = spd_read_byte(ctrl->channel0[i], 13);
if (value < 0) { if (value < 0) {
return -1; return -1;
} }
@ -1860,7 +1891,7 @@ static int update_dimm_ecc(const struct mem_controller *ctrl, const struct mem_p
{ {
uint32_t dcl; uint32_t dcl;
int value; int value;
value = smbus_read_byte(ctrl->channel0[i], 11); value = spd_read_byte(ctrl->channel0[i], 11);
if (value < 0) { if (value < 0) {
return -1; return -1;
} }
@ -2169,24 +2200,33 @@ static void sdram_set_spd_registers(const struct mem_controller *ctrl)
} }
#define TIMEOUT_LOOPS 300000 #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 */ /* Before enabling memory start the memory clocks */
dch = pci_read_config32(ctrl->f2, DRAM_CONFIG_HIGH); for(i = 0; i < controllers; i++) {
uint32_t dch;
dch = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_HIGH);
dch |= DCH_MEMCLK_VALID; dch |= DCH_MEMCLK_VALID;
pci_write_config32(ctrl->f2, DRAM_CONFIG_HIGH, dch); pci_write_config32(ctrl[i].f2, DRAM_CONFIG_HIGH, dch);
}
/* And if necessary toggle the the reset on the dimms by hand */ /* And if necessary toggle the the reset on the dimms by hand */
memreset(ctrl); memreset(controllers, ctrl);
for(i = 0; i < controllers; i++) {
uint32_t dcl;
/* Toggle DisDqsHys to get it working */ /* Toggle DisDqsHys to get it working */
dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
#if 0
print_debug("dcl: "); print_debug("dcl: ");
print_debug_hex32(dcl); print_debug_hex32(dcl);
print_debug("\r\n"); print_debug("\r\n");
#endif
#if 1
dcl &= ~DCL_DimmEccEn;
#endif
#warning "FIXME set the ECC type to perform" #warning "FIXME set the ECC type to perform"
#warning "FIXME initialize the scrub registers" #warning "FIXME initialize the scrub registers"
#if 0 #if 0
@ -2195,18 +2235,21 @@ static void sdram_enable(const struct mem_controller *ctrl)
} }
#endif #endif
dcl |= DCL_DisDqsHys; dcl |= DCL_DisDqsHys;
pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl); pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
dcl &= ~DCL_DisDqsHys; dcl &= ~DCL_DisDqsHys;
dcl &= ~DCL_DLL_Disable; dcl &= ~DCL_DLL_Disable;
dcl &= ~DCL_D_DRV; dcl &= ~DCL_D_DRV;
dcl &= ~DCL_QFC_EN; dcl &= ~DCL_QFC_EN;
dcl |= DCL_DramInit; dcl |= DCL_DramInit;
pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl); pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
}
for(i = 0; i < controllers; i++) {
uint32_t dcl;
print_debug("Initializing memory: "); print_debug("Initializing memory: ");
int loops = 0; int loops = 0;
do { do {
dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
loops += 1; loops += 1;
if ((loops & 1023) == 0) { if ((loops & 1023) == 0) {
print_debug("."); print_debug(".");
@ -2217,17 +2260,15 @@ static void sdram_enable(const struct mem_controller *ctrl)
} else { } else {
print_debug(" done\r\n"); print_debug(" done\r\n");
} }
#if 0 #if 0
if (dcl & DCL_DimmEccEn) { if (dcl & DCL_DimmEccEn) {
print_debug("Clearing memory: "); print_debug("Clearing memory: ");
loops = 0; loops = 0;
dcl &= ~DCL_MemClrStatus; dcl &= ~DCL_MemClrStatus;
pci_write_config32(ctrl->f2, DRAM_CONFIG_LOW, dcl); pci_write_config32(ctrl[i].f2, DRAM_CONFIG_LOW, dcl);
do { do {
dcl = pci_read_config32(ctrl->f2, DRAM_CONFIG_LOW); dcl = pci_read_config32(ctrl[i].f2, DRAM_CONFIG_LOW);
loops += 1; loops += 1;
if ((loops & 1023) == 0) { if ((loops & 1023) == 0) {
print_debug(" "); print_debug(" ");
@ -2239,8 +2280,9 @@ static void sdram_enable(const struct mem_controller *ctrl)
} else { } else {
print_debug("done\r\n"); print_debug("done\r\n");
} }
pci_write_config32(ctrl->f3, SCRUB_ADDR_LOW, 0); pci_write_config32(ctrl[i].f3, SCRUB_ADDR_LOW, 0);
pci_write_config32(ctrl->f3, SCRUB_ADDR_HIGH, 0); pci_write_config32(ctrl[i].f3, SCRUB_ADDR_HIGH, 0);
} }
#endif #endif
} }
}

View File

@ -2,6 +2,7 @@
#define RAMINIT_H #define RAMINIT_H
struct mem_controller { struct mem_controller {
unsigned node_id;
device_t f0, f1, f2, f3; device_t f0, f1, f2, f3;
uint8_t channel0[4]; uint8_t channel0[4];
uint8_t channel1[4]; uint8_t channel1[4];

View File

@ -34,10 +34,12 @@ static int cpu_init_detected(void)
return cpu_init; return cpu_init;
} }
static void distinguish_cpu_resets(void) static void distinguish_cpu_resets(unsigned node_id)
{ {
uint32_t htic; 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; 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);
} }

View File

@ -4,7 +4,7 @@
#ifndef MAX_REBOOT_CNT #ifndef MAX_REBOOT_CNT
#error "MAX_REBOOT_CNT not defined" #error "MAX_REBOOT_CNT not defined"
#endif #endif
#if MAX_REBOOT_CNT > 14 #if MAX_REBOOT_CNT > 15
#error "MAX_REBOOT_CNT too high" #error "MAX_REBOOT_CNT too high"
#endif #endif
@ -78,6 +78,12 @@ static int do_normal_boot(void)
byte &= 0x0f; /* yes, clear the boot count */ 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? */ /* Are we already at the max count? */
if ((byte >> 4) < MAX_REBOOT_CNT) { if ((byte >> 4) < MAX_REBOOT_CNT) {
byte += 1 << 4; /* No, add 1 to the count */ 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 */ 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 */ /* Save the boot byte */
cmos_write(byte, RTC_BOOT_BYTE); cmos_write(byte, RTC_BOOT_BYTE);
return ((byte >> 4) < MAX_REBOOT_CNT); return (byte & (1<<1));
} }

View File

@ -7,22 +7,31 @@ void sdram_no_memory(void)
} }
/* Setup SDRAM */ /* 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 */ /* 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 */ /* 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. /* Now that everything is setup enable the SDRAM.
* Some chipsets do the work for use while on others * Some chipsets do the work for use while on others
* we need to it by hand. * we need to it by hand.
*/ */
sdram_enable(ctrl); print_debug("Ram3\r\n");
sdram_enable(controllers, ctrl);
print_debug("Ram4\r\n"); print_debug("Ram4\r\n");
} }

View File

@ -87,6 +87,7 @@ static void setup_ioapic(void)
static void lpc_init(struct device *dev) static void lpc_init(struct device *dev)
{ {
uint8_t byte; uint8_t byte;
uint16_t word;
int pwr_on=-1; int pwr_on=-1;
printk_debug("lpc_init\n"); printk_debug("lpc_init\n");
@ -101,6 +102,13 @@ static void lpc_init(struct device *dev)
byte = pci_read_config8(dev, 0x46); byte = pci_read_config8(dev, 0x46);
pci_write_config8(dev, 0x46, byte | (1<<0)); 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 */ /* power after power fail */
byte = pci_read_config8(dev, 0x43); byte = pci_read_config8(dev, 0x43);
if (pwr_on) { if (pwr_on) {

View File

@ -0,0 +1,38 @@
//2003 Copywright Tyan
//BY LYH
#include <console/console.h>
#include <device/device.h>
#include <device/pci.h>
#include <device/pci_ids.h>
#include <device/pci_ops.h>
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,
};

View File

@ -14,7 +14,7 @@
#define DEBUG_ERROR_MESSAGES 0 #define DEBUG_ERROR_MESSAGES 0
#define DEBUG_COLOR_GRAPH 0 #define DEBUG_COLOR_GRAPH 0
#define DEBUG_SCC 0 #define DEBUG_SCC 0
#define DEBUG_CONSISTENCY 2 #define DEBUG_CONSISTENCY 1
#define DEBUG_RANGE_CONFLICTS 0 #define DEBUG_RANGE_CONFLICTS 0
#define DEBUG_COALESCING 0 #define DEBUG_COALESCING 0
#define DEBUG_SDP_BLOCKS 0 #define DEBUG_SDP_BLOCKS 0
@ -12952,6 +12952,23 @@ static void verify_graph_ins(
return; 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( static void print_interference_ins(
struct compile_state *state, struct compile_state *state,
@ -13765,6 +13782,7 @@ static int color_graph(struct compile_state *state, struct reg_state *rstate)
return colored; return colored;
} }
#if DEBUG_CONSISTENCY
static void verify_colors(struct compile_state *state, struct reg_state *rstate) static void verify_colors(struct compile_state *state, struct reg_state *rstate)
{ {
struct live_range *lr; struct live_range *lr;
@ -13801,6 +13819,9 @@ static void verify_colors(struct compile_state *state, struct reg_state *rstate)
ins = ins->next; ins = ins->next;
} while(ins != first); } 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) 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 #endif
} while(coalesced); } while(coalesced);
#if DEBUG_CONSISTENCY > 1
# if 0
fprintf(stderr, "verify_graph_ins...\n");
# endif
/* Verify the interference graph */ /* Verify the interference graph */
walk_variable_lifetimes( verify_interference_graph(state, &rstate);
state, rstate.blocks, verify_graph_ins, &rstate);
# if 0
fprintf(stderr, "verify_graph_ins done\n");
#endif
#endif
/* Build the groups low and high. But with the nodes /* Build the groups low and high. But with the nodes
* first sorted by degree order. * first sorted by degree order.