Massive resync of my tree and freebios-cvs including.

- Motherboard identification in the linuxbios table.
- Better SMP startup code.
- Support for the tyan s2462, the supermicro p4dc6, the supermicro p4dc6+, and the beginnings of supermicro p4dpr support
- Remove of no longer needed USE_AMD_NDA option
This commit is contained in:
Eric W. Biederman 2002-06-20 00:11:56 +00:00
commit 9e334b9ec3
105 changed files with 6483 additions and 1703 deletions

View file

@ -71,6 +71,30 @@ struct lb_memory *lb_memory(struct lb_header *header)
return mem;
}
struct lb_mainboard *lb_mainboard(struct lb_header *header)
{
#define __STR(X) #X
#define STR(X) __STR(X)
static const char vendor[] = STR(MAINBOARD_VENDOR);
static const char part_number[] = STR(MAINBOARD_PART_NUMBER);
struct lb_record *rec;
struct lb_mainboard *mainboard;
rec = lb_new_record(header);
mainboard = (struct lb_mainboard *)rec;
mainboard->tag = LB_TAG_MAINBOARD;
mainboard->size = sizeof(*mainboard) +
sizeof(vendor) + sizeof(part_number);
mainboard->vendor_idx = 0;
mainboard->part_number_idx = sizeof(vendor);
memcpy(mainboard->strings + mainboard->vendor_idx,
vendor, sizeof(vendor));
memcpy(mainboard->strings + mainboard->part_number_idx,
part_number, sizeof(part_number));
#undef STR
#undef __STR
return mainboard;
}
/* Some version of gcc have problems with 64 bit types so
* take an unsigned long instead of a uint64_t for now.
*/
@ -117,6 +141,7 @@ static void lb_reserve_table_memory(struct lb_header *head)
}
}
unsigned long lb_table_fini(struct lb_header *head)
{
struct lb_record *rec, *first_rec;
@ -129,8 +154,8 @@ unsigned long lb_table_fini(struct lb_header *head)
head->table_checksum = compute_ip_checksum(first_rec, head->table_bytes);
head->header_checksum = 0;
head->header_checksum = compute_ip_checksum(head, sizeof(*head));
printk_debug("Wrote linuxbios table at: %p - %p\n",
head, rec);
printk_debug("Wrote linuxbios table at: %p - %p checksum %lx\n",
head, rec, head->table_checksum);
return (unsigned long)rec;
}
@ -176,6 +201,9 @@ unsigned long write_linuxbios_table(
/* Now show all of memory */
lb_memory_range(mem, LB_MEM_RAM, 0x00100000, (totalram - 1024) << 10);
/* Record our motheboard */
lb_mainboard(head);
low_table_end = lb_table_fini(head);
/* Remember where my valid memory ranges are */

View file

@ -1,89 +1,6 @@
jmp cpu_reset_out
#include <cpu/p6/mtrr.h>
#include <cpu/p6/apic.h>
#include <loglevel.h>
.section ".rom.data"
#if ASM_CONSOLE_LOGLEVEL >= BIOS_SPEW
cpu_reset_str: .string "cpu_reset\r\n";
cpu_apic_str: .string "apic: ";
cpu_size_set_str: .string "cpu memory size set\r\n";
#endif
.previous
__cpu_reset:
CONSOLE_SPEW_TX_STRING($cpu_reset_str)
#ifdef SMP
/* Enable the local apic, and map it where we expext it */
movl $APIC_BASE_MSR, %ecx
rdmsr
orl $APIC_BASE_MSR_ENABLE, %eax
andl $(~APIC_BASE_MSR_ADDR_MASK), %eax
orl $APIC_DEFAULT_BASE, %eax
/* xorl %edx, %edx */
wrmsr
/* Get the apic_id */
movl (APIC_ID + APIC_DEFAULT_BASE), %edi
shrl $24, %edi
CONSOLE_SPEW_TX_STRING($cpu_apic_str)
CONSOLE_SPEW_TX_HEX32(%edi)
CONSOLE_SPEW_TX_CHAR($'\r')
CONSOLE_SPEW_TX_CHAR($'\n')
#endif
CALLSP(set_memory_size)
CONSOLE_SPEW_TX_STRING($cpu_size_set_str);
#ifdef SMP
/* Test to see if we are the boot strap processor.
* If so the boot must be complete.
*/
movl $APIC_BASE_MSR, %ecx
rdmsr
testl $APIC_BASE_MSR_BOOTSTRAP_PROCESSOR, %eax
jnz __reboot
/* Fixed mtrrs are enabled by the C code so if they
* aren't enabled yet we must be a secondary
* processor initializing in an SMP system.
*/
mov $MTRRdefType_MSR, %ecx
rdmsr
testl $0x400, %eax
jnz __reboot
/* Get the apic_id */
movl (APIC_ID + APIC_DEFAULT_BASE), %edi
shrl $24, %edi
/* Get the cpu index (MAX_CPUS on error) */
movl $-4, %ebx
1: addl $4, %ebx
cmpl $(MAX_CPUS << 2), %ebx
je 2
cmpl %edi, EXT(initial_apicid)(%ebx)
jne 1b
2: shrl $2, %ebx
/* set the stack pointer */
movl $_estack, %esp
movl %ebx, %eax
movl $STACK_SIZE, %ebx
mull %ebx
subl %eax, %esp
call EXT(secondary_cpu_init)
/* Fall through in case we somehow return */
#endif /* SMP */
__reboot:
movl $0xffffffff, %ebp
jmp __main

View file

@ -32,6 +32,10 @@ it with the version available from LANL.
static char rcsid[] = "$Id$";
#endif
#ifndef MAX_PHYSICAL_CPUS
#define MAX_PHYSICAL_CPUS MAX_CPUS
#endif
#include <arch/io.h>
#include <arch/intel.h>
#include <pciconf.h>
@ -58,6 +62,7 @@ static char rcsid[] = "$Id$";
#include <smp/atomic.h>
#include <arch/smp/mpspec.h>
#include <boot/linuxbios_table.h>
#include <pc80/mc146818rtc.h>
/* The processor map.
@ -138,6 +143,7 @@ static void wait_for_other_cpus(void)
int old_active_count, active_count;
int i;
old_active_count = 1;
active_count = atomic_read(&active_cpus);
while (active_count > 1) {
@ -150,20 +156,40 @@ static void wait_for_other_cpus(void)
for (i = 0; i < MAX_CPUS; i++) {
if (!(processor_map[i] & CPU_ENABLED)) {
printk_err("CPU %d/%u did not initialize!\n",
i, initial_apicid);
i, initial_apicid[i]);
}
}
printk_debug("All AP CPUs stopped\n");
}
static void remove_logical_cpus(void)
{
/* To turn off hyperthreading just remove the logical
* cpus from the processor map.
*/
int cnt;
cnt=0;
if (get_option(&cnt,"logical_cpus")==0) {
if (cnt) {
/* disable logical cpus */
for(cnt=MAX_PHYSICAL_CPUS;cnt<MAX_CPUS;cnt++)
processor_map[cnt]=0;
printk_debug("logical cpus disabled\n");
}
}
}
#else /* SMP */
#define wait_for_other_cpus() do {} while(0)
#define remove_logical_cpus() do {} while(0)
#endif /* SMP */
void write_tables(unsigned long totalram)
{
unsigned long low_table_start, low_table_end;
unsigned long rom_table_start, rom_table_end;
rom_table_start = 0xf0000;
rom_table_end = 0xf0000;
/* Start low addr at 16 bytes instead of 0 because of a buglet
@ -180,6 +206,7 @@ void write_tables(unsigned long totalram)
/* copy the smp block to address 0 */
post_code(0x96);
/* The smp table must be in 0-1K, 639K-640K, or 960K-1M */
remove_logical_cpus();
low_table_end = write_smp_table(low_table_end, processor_map);
/* Don't write anything in the traditional x86 BIOS data segment */
@ -328,6 +355,20 @@ void hardwaremain(int boot_complete)
printk_debug("INSTALL REAL-MODE IDT\n");
setup_realmode_idt();
#endif
#if CONFIG_VGABIOS == 1
printk_debug("DO THE VGA BIOS\n");
do_vgabios();
post_code(0x93);
#endif
// we do this right here because:
// - all the hardware is working, and some VGA bioses seem to need
// that
// - we need page 0 below for linuxbios tables.
#if CONFIG_REALMODE_IDT == 1
printk_debug("INSTALL REAL-MODE IDT\n");
setup_realmode_idt();
#endif
#if CONFIG_VGABIOS == 1
printk_debug("DO THE VGA BIOS\n");
do_vgabios();
@ -352,3 +393,6 @@ void hardwaremain(int boot_complete)

21
src/arch/i386/lib/id.inc Normal file
View file

@ -0,0 +1,21 @@
.section ".id", "a", @progbits
#define __STR(X) #X
#define STR(X) __STR(X)
.globl __id_start
__id_start:
vendor:
.asciz STR(MAINBOARD_VENDOR)
part:
.asciz STR(MAINBOARD_PART_NUMBER)
.long __id_end + 0x10 - vendor /* Reverse offset to the vendor id */
.long __id_end + 0x10 - part /* Reverse offset to the part number */
.long PAYLOAD_SIZE + ROM_IMAGE_SIZE /* Size of this romimage */
.globl __id_end
#undef __STR
#undef STR
__id_end:
.previous

6
src/arch/i386/lib/id.lds Normal file
View file

@ -0,0 +1,6 @@
SECTIONS {
. = (_ROMBASE + ROM_IMAGE_SIZE - 0x10) - (__id_end - __id_start);
.id (.): {
*(.id)
}
}

View file

@ -74,18 +74,23 @@ void stop_cpu(unsigned long apicid)
while(1) {
hlt();
}
}
// This is a lot more paranoid now, since Linux can NOT handle
// being told there is a CPU when none exists. So any errors
// will return 0, meaning no CPU.
/* This is a lot more paranoid now, since Linux can NOT handle
* being told there is a CPU when none exists. So any errors
* will return 0, meaning no CPU.
*
* We actually handling that case by noting which cpus startup
* and not telling anyone about the ones that dont.
*/
int start_cpu(unsigned long apicid)
{
int timeout;
unsigned long send_status, accept_status, start_eip;
int j, num_starts, maxlvt;
extern char _start[], _estart[];
extern char reboot_halt[];
extern char _secondary_start[];
/*
* Starting actual IPI sequence...
@ -101,6 +106,7 @@ int start_cpu(unsigned long apicid)
/*
* Send IPI
*/
apic_write_around(APIC_ICR, APIC_INT_LEVELTRIG | APIC_INT_ASSERT
| APIC_DM_INIT);
@ -147,12 +153,7 @@ int start_cpu(unsigned long apicid)
return 0;
}
start_eip = START_CPU_SEG + (((unsigned long)_start) & 0xf000);
if ((((unsigned long)_start) & 0xfff) != 0) {
printk_err("_start is not 4K aligned!\n");
return 0;
}
memcpy((void *)start_eip, _start, _estart - _start);
start_eip = (unsigned long)_secondary_start;
printk_spew("start_eip=0x%08lx\n", start_eip);
num_starts = 2;

View file

@ -1,9 +1,15 @@
#if defined(CACHE_RAM_BASE) && defined(CACHE_RAM_SIZE)
jmp 1f
start_cacheram: .string "Start cache ram\r\n"
/* Disable the cache while we set up the cache ram MTRR */
movl %cr0, %eax
1: movl %cr0, %eax
orl $0x40000000, %eax
movl %eax, %cr0
CONSOLE_INFO_TX_STRING($start_cacheram)
/* Set up an mtrr in write-back mode over some arbitrary
* location. As long as we do not get a capacity miss,
* or a multiprocessor conflict miss this should allow us to
@ -20,10 +26,15 @@
movl $(~(CACHE_RAM_SIZE - 1) | 0x800), %eax
wrmsr
/* Disable 3rd level cache */
movl $0x1a0, %ecx
rdmsr
andl $0xffffffbf, %eax
wrmsr
/* Reenable the cache now that the mtrr is set up */
movl %cr0, %eax
andl $0x9fffffff, %eax
movl %eax, %cr0
movl %eax, %cr0
/* Force cache ram area into cache
* Note: Some versions of the P4 don't allocate a cache
@ -33,15 +44,21 @@
*/
movl $CACHE_RAM_BASE, %esi
movl $(CACHE_RAM_BASE + CACHE_RAM_SIZE), %edi
jmp 1f
/* Loop to use cache and allocate it for stack usage
The loop must be cache block aligned to work. */
.balign 128
1: movl (%esi), %eax
addl $4, %esi
movl %eax, -4(%esi)
cmpl %esi, %edi
jnz 1b
intel_chip_post_macro(0x02)
/* Load a different set of data segments */
movw $0x08, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
#endif

View file

@ -1,5 +1,6 @@
#include <arch/cache_ram.h>
/* copy data segment from FLASH ROM to CACHE */
movl $_clrodata, %esi
movl $_rodata, %edi

View file

@ -0,0 +1,123 @@
#include <arch/cache_ram.h>
#define MINI_DATA_SIZE 0x00008000
#define MINI_STACK_SIZE 0x00000400
#define MINI_DATA_BASE (_edata)
#define MINI_DATA_END (MINI_DATA_BASE + MINI_DATA_SIZE)
#define MINI_STACK_BASE MINI_DATA_END
#define MINI_STACK_END (MINI_STACK_BASE + MINI_STACK_SIZE)
debug_loop:
CONSOLE_DEBUG_INLINE_TX_CHAR($'a')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\r')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\n')
/* Load my normal data segments */
movw $0x18, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
CONSOLE_DEBUG_INLINE_TX_CHAR($'b')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\r')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\n')
movl $0x20, %ecx
movl $(CACHE_RAM_BASE), %eax
movl $(CACHE_RAM_BASE + CACHE_RAM_SIZE), %ebx
CALLSP(ramtest)
CONSOLE_DEBUG_INLINE_TX_CHAR($'c')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\r')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\n')
/* Load a different set of data segments */
movw $0x08, %ax
movw %ax, %ds
movw %ax, %es
movw %ax, %ss
movl $(_stack + STACK_SIZE), %esp
CONSOLE_DEBUG_INLINE_TX_CHAR($'d')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\r')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\n')
call debug2
CONSOLE_DEBUG_INLINE_TX_CHAR($'e')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\r')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\n')
call debug3
CONSOLE_DEBUG_INLINE_TX_CHAR($'f')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\r')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\n')
#if 0
jmp debug_loop
#else
jmp debug_loop_out
#endif
debug2:
CONSOLE_DEBUG_INLINE_TX_CHAR($'g')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\r')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\n')
ret
debug3:
CONSOLE_DEBUG_INLINE_TX_CHAR($'h')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\r')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\n')
#if 1
movl $(MINI_DATA_BASE + (MINI_DATA_SIZE/2)), %esi
movl $MINI_DATA_BASE, %edi
movl $((MINI_DATA_SIZE)/8), %ecx
rep movsl
#endif
#if 1
push %ebp
mov %esp,%ebp
push %esi
push %ebx
mov $0x3f8,%ecx
mov $0x3f9,%ebx
xor %eax,%eax
mov %ebx,%edx
out %al,(%dx)
mov $0x1,%al
mov $0x3fa,%edx
out %al,(%dx)
mov $0x3fb,%esi
mov $0x83,%al
mov %esi,%edx
out %al,(%dx)
mov $0xc,%al
mov %ecx,%edx
out %al,(%dx)
xor %eax,%eax
mov %ebx,%edx
out %al,(%dx)
mov $0x3,%al
mov %esi,%edx
out %al,(%dx)
lea 0xfffffff8(%ebp),%esp
pop %ebx
pop %esi
leave
#endif
ret
debug_loop_out:
CONSOLE_DEBUG_INLINE_TX_CHAR($'i')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\r')
CONSOLE_DEBUG_INLINE_TX_CHAR($'\n')

View file

@ -7,7 +7,7 @@ void ndelay(unsigned long ns)
unsigned long long ticks;
/* FIXME calibrate this... don't just estimage 2Ghz */
ticks = ns << 1;
ticks = (ns << 1) + ns; /* times 3 for up to 3Ghz */
rdtscll(count);
stop = ticks + count;
while(stop > count) {

View file

@ -1,5 +1,6 @@
#include <cpu/p6/mtrr.h>
/* The fixed and variable MTRRs are powered-up with random values, clear them to
* MTRR_TYPE_UNCACHABLE for safty reason
*/

View file

@ -0,0 +1,99 @@
/*
Test if this is the main cpu BSP
*/
logical_cpu_start:
movl $0x1B , %ecx
rdmsr
testl $(1 << 8) , %eax
jnz logical_cpu_end
/* This is the 2nd virtual cpu, so enable cache and sleep */
movl %cr0, %eax
andl $0x9fffffff, %eax
movl %eax, %cr0
/* Signal the BSP */
movl $0x20f, %ecx /* mtrr[7] physical mask register */
xorl %edx, %edx
movl $0x01000, %eax
wrmsr
1: hlt
jmp 1b
logical_cpu_end:
/* Test if this physical cpu has virtual cpu's.
If it does start the second virtual cpu so that it can
enable cache in cr0. Wait for it to finish, then
continue. */
movl $0x20f, %ecx /* mtrr[7] physical mask register */
xorl %eax,%eax /* clear out the mttr used as a flag */
xorl %edx, %edx
wrmsr
/* test if this cpu has hyper-threading, & the # of virtual cpus */
movl $1, %eax
cpuid
andl $(1 << 28), %edx
jz enable_cache_cr0_end /* no hyper threading, so jump */
shr $16, %ebx
andl $0x0ff, %ebx
cmpl $1, %ebx
jle enable_cache_cr0_end /* only 1 logical cpu, so jump */
subl $1, %ebx
cache_enable_logical_cpus:
/* start logical cpu */
movl (APIC_ID + APIC_DEFAULT_BASE ), %edi
movl %ebx, %eax
shl $24, %eax /* add the logical cpu # for the apic addr */
addl %eax, %edi
movl %edi,( APIC_ICR2 + APIC_DEFAULT_BASE )
movl $_start, %edi
shrl $12, %edi
andl $0x0ff, %edi
orl $(APIC_DM_STARTUP | APIC_INT_ASSERT), %edi
movl %edi,( APIC_ICR + APIC_DEFAULT_BASE )
/* wait for message to be received */
1: movl ( APIC_ICR + APIC_DEFAULT_BASE ), %edi
andl $APIC_ICR_BUSY, %edi
jnz 1b
/* delay waiting for virtual cpu to enable cache */
2: rep; nop
movl $0x20f, %ecx /* mtrr[7] physical mask register */
rdmsr
andl %eax,%eax
jz 2b
xorl %eax,%eax /* clear out the mttr used as a flag */
xorl %edx, %edx
wrmsr
subl $1, %ebx
jnz cache_enable_logical_cpus
enable_cache_cr0_end:
/* delay loop to give logical cpu time to halt */
/* test showed 400 cycles needed, so use 1000 to be safe*/
xorl %ecx, %ecx
1: rdtsc
movl %eax, %ebx
2: rep; nop
rdtsc
movl %eax, %edx
subl %ebx, %eax
jc 1b
addl %eax, %ecx
movl %edx, %ebx
cmpl $1000, %ecx
jc 2b

View file

@ -1,3 +1,3 @@
option k7
option CPU_FIXUP
option k7=1
option CPU_FIXUP=1
object cpufixup.o

View file

@ -4,7 +4,6 @@
* MTRR_TYPE_UNCACHABLE for safty reason
*/
earlymtrr_start:
xorl %eax, %eax # clear %eax and %edx
xorl %edx, %edx #
@ -22,6 +21,11 @@ clear_fixed_var_mtrr:
jmp clear_fixed_var_mtrr
clear_fixed_var_mtrr_out:
/* enable memory access for 0 - 8MB using top_mem */
movl $TOP_MEM, %ecx
xorl %edx, %edx
movl $0x0800000, %eax
wrmsr
set_var_mtrr:
/* enable caching for 0 - 128MB using variable mtrr */
@ -65,8 +69,10 @@ enable_mtrr:
wrmsr
/* Enable the MTRRs in SYSCFG */
#if USE_AMD_NDA_CODE
#endif /* USE_AMD_NDA_CODE */
movl $SYSCFG_MSR, %ecx
rdmsr
orl $(SYSCFG_MSR_MtrrVarDramEn), %eax
wrmsr
/* enable cache */
movl %cr0, %eax
@ -85,7 +91,9 @@ var_mtrr_msr:
.long 0x204, 0x205, 0x206, 0x207
.long 0x208, 0x209, 0x20A, 0x20B
.long 0x20C, 0x20D, 0x20E, 0x20F
#if USE_AMD_NDA_CODE
#endif /* USE_AMD_NDA_CODE */
var_iorr_msr:
.long 0xC0010016, 0xC0010017, 0xC0010018, 0xC0010019
mem_top:
.long 0xC001001A, 0xC001001D
.long 0x000 /* NULL, end of table */
earlymtrr_end:

100
src/cpu/p5/delay_tsc.c Normal file
View file

@ -0,0 +1,100 @@
#include <printk.h>
#include <arch/io.h>
#include <cpu/p6/msr.h>
static unsigned long clocks_per_usec;
#define CLOCK_TICK_RATE 1193180U /* Underlying HZ */
/* ------ Calibrate the TSC -------
* Too much 64-bit arithmetic here to do this cleanly in C, and for
* accuracy's sake we want to keep the overhead on the CTC speaker (channel 2)
* output busy loop as low as possible. We avoid reading the CTC registers
* directly because of the awkward 8-bit access mechanism of the 82C54
* device.
*/
#define CALIBRATE_INTERVAL ((20*CLOCK_TICK_RATE)/1000) /* 20ms */
#define CALIBRATE_DIVISOR (20*1000) /* 20ms / 20000 == 1usec */
static unsigned long long calibrate_tsc(void)
{
/* Set the Gate high, disable speaker */
outb((inb(0x61) & ~0x02) | 0x01, 0x61);
/*
* Now let's take care of CTC channel 2
*
* Set the Gate high, program CTC channel 2 for mode 0,
* (interrupt on terminal count mode), binary count,
* load 5 * LATCH count, (LSB and MSB) to begin countdown.
*/
outb(0xb0, 0x43); /* binary, mode 0, LSB/MSB, Ch 2 */
outb(CALIBRATE_INTERVAL & 0xff, 0x42); /* LSB of count */
outb(CALIBRATE_INTERVAL >> 8, 0x42); /* MSB of count */
{
unsigned long startlow, starthigh;
unsigned long endlow, endhigh;
unsigned long count;
rdtsc(startlow,starthigh);
count = 0;
do {
count++;
} while ((inb(0x61) & 0x20) == 0);
rdtsc(endlow,endhigh);
/* Error: ECTCNEVERSET */
if (count <= 1)
goto bad_ctc;
/* 64-bit subtract - gcc just messes up with long longs */
__asm__("subl %2,%0\n\t"
"sbbl %3,%1"
:"=a" (endlow), "=d" (endhigh)
:"g" (startlow), "g" (starthigh),
"0" (endlow), "1" (endhigh));
/* Error: ECPUTOOFAST */
if (endhigh)
goto bad_ctc;
/* Error: ECPUTOOSLOW */
if (endlow <= CALIBRATE_DIVISOR)
goto bad_ctc;
return (endlow + CALIBRATE_DIVISOR -1)/CALIBRATE_DIVISOR;
}
/*
* The CTC wasn't reliable: we got a hit on the very first read,
* or the CPU was so fast/slow that the quotient wouldn't fit in
* 32 bits..
*/
bad_ctc:
printk_err("bad_ctc\n");
return 0;
}
void udelay(unsigned long us)
{
unsigned long long count;
unsigned long long stop;
unsigned long long clocks;
if (!clocks_per_usec) {
clocks_per_usec = calibrate_tsc();
printk_info("clocks_per_usec: %u\n", clocks_per_usec);
}
clocks = us;
clocks *= clocks_per_usec;
rdtscll(count);
stop = clocks + count;
while(stop > count) {
rdtscll(count);
}
}

View file

@ -18,6 +18,7 @@ struct lb_record *lb_new_record(struct lb_header *header);
struct lb_memory *lb_memory(struct lb_header *header);
void lb_memory_range(struct lb_memory *mem,
uint32_t type, unsigned long start, unsigned long size);
struct lb_mainboard *lb_mainboard(struct lb_header *header);
unsigned long lb_table_fini(struct lb_header *header);
/* Routines to extract part so the linuxBIOS table or information

View file

@ -79,6 +79,15 @@ struct lb_hwrpb {
uint64_t hwrpb;
};
#define LB_TAG_MAINBOARD 0x0003
struct lb_mainboard {
uint32_t tag;
uint32_t size;
uint8_t vendor_idx;
uint8_t part_number_idx;
uint8_t strings[0];
};
/* The following structures are for the cmos definitions table */

View file

@ -0,0 +1,3 @@
#define THERMAL_MONITORING_OFF 0
#define THERMAL_MONITORING_SET 0x00000008
#define MISC_ENABLE 0x01a0

View file

@ -3,10 +3,26 @@
#include <cpu/p6/mtrr.h>
#define TOP_MEM 0xc001001A
#define TOP_MEM2 0xc001001D
#define IORR_FIRST 0xC0010016
#define IORR_LAST 0xC0010019
#define SYSCFG 0xC0010010
#define MTRR_READ_MEM (1 << 4)
#define MTRR_WRITE_MEM (1 << 3)
#define SYSCFG_MSR 0xC0010010
#define SYSCFG_MSR_MtrrFixDramEn (1 << 18)
#define SYSCFG_MSR_MtrrFixDramModEn (1 << 19)
#define SYSCFG_MSR_MtrrVarDramEn (1 << 20)
#define IORR0_BASE 0xC0010016
#define IORR0_MASK 0xC0010017
#define IORR1_BASE 0xC0010018
#define IORR1_MASK 0xC0010019
#define TOP_MEM 0xC001001A
#define TOP_MEM2 0xC001001D
#define HWCR_MSR 0xC0010015
#endif /* CPU_K7_MTRR_H */

View file

@ -88,6 +88,10 @@
#define PC_CKS_RANGE_END 45
#define PC_CKS_LOC 46
#define LB_CKS_RANGE_START 49
#define LB_CKS_RANGE_END 125
#define LB_CKS_LOC 126
#if !defined(ASSEMBLY)
void rtc_init(int invalid);
#if USE_OPTION_TABLE == 1

View file

@ -1226,6 +1226,17 @@
#define PCI_DEVICE_ID_INTEL_82801BA_1F4 0x2444
#define PCI_DEVICE_ID_INTEL_82801BA_1F5 0x2445
#define PCI_DEVICE_ID_INTEL_82801CA_1E0 0x244e
#define PCI_DEVICE_ID_INTEL_82801CA_1F0 0x2480
#define PCI_DEVICE_ID_INTEL_82801CA_1F1 0x248b
#define PCI_DEVICE_ID_INTEL_82801CA_1D2 0x2482
#define PCI_DEVICE_ID_INTEL_82801CA_1F3 0x2483
#define PCI_DEVICE_ID_INTEL_82801CA_1D1 0x2484
#define PCI_DEVICE_ID_INTEL_82801CA_1F5 0x2485
#define PCI_DEVICE_ID_INTEL_82801CA_1D2 0x2487
#define PCI_DEVICE_ID_INTEL_82870_1F0 0x1461
#define PCI_DEVICE_ID_INTEL_82820FW_0 0x2440
#define PCI_DEVICE_ID_INTEL_82820FW_1 0x2442
#define PCI_DEVICE_ID_INTEL_82820FW_2 0x2443

View file

@ -0,0 +1,19 @@
#ifndef AMD766_H
#define AMD766_H
void amd766_disable_watchdog(void);
void amd766_enable_ioapic(void);
void amd766_enable_port92_reset(void);
void amd766_mouse_sends_irq12(void);
void amd766_enable_serial_irqs(int continuous, unsigned frames, unsigned startclocks);
void amd766_cpu_reset_sends_init(void);
#define DECODE_STPGNT_ADDR 0
#define DECODE_STPGNT_DATA 1
void amd766_decode_stop_grant(unsigned how);
void amd766_set_pm_classcode(void);
void amd766_usb_setup(void);
void amd766_power_after_power_fail(int on);
void amd766_posted_memory_write_enable(void);
void amd766_hard_reset(void);
void amd766_enable_ide(int enable_a, int enable_b);
#endif /* AMD766_H */

View file

@ -6,11 +6,27 @@ unsigned long compute_ip_checksum(void *addr, unsigned long length)
uint16_t *ptr;
unsigned long sum;
unsigned long len;
/* FIXME this assumes addr is 2 byte aligned.
* This isn't fatal on x86 but it can be on other platforms..
*/
unsigned long laddr;
/* compute an ip style checksum */
laddr = (unsigned long )addr;
sum = 0;
if (laddr & 1) {
uint16_t buffer;
unsigned char *ptr;
/* copy the first byte into a 2 byte buffer.
* This way automatically handles the endian question
* of which byte (low or high) the last byte goes in.
*/
buffer = 0;
ptr = addr;
memcpy(&buffer, ptr, 1);
sum += buffer;
if (sum > 0xFFFF)
sum -= 0xFFFF;
length -= 1;
addr = ptr +1;
}
len = length >> 1;
ptr = addr;
while (len--) {
@ -18,6 +34,7 @@ unsigned long compute_ip_checksum(void *addr, unsigned long length)
if (sum > 0xFFFF)
sum -= 0xFFFF;
}
addr = ptr;
if (length & 1) {
uint16_t buffer;
unsigned char *ptr;
@ -27,7 +44,6 @@ unsigned long compute_ip_checksum(void *addr, unsigned long length)
*/
buffer = 0;
ptr = addr;
ptr += length - 1;
memcpy(&buffer, ptr, 1);
sum += buffer;
if (sum > 0xFFFF)

View file

@ -30,7 +30,8 @@ static char rcsid[] = "$Id$";
// initialize the display
void displayinit(void)
{
get_option(&console_loglevel, "debug_level");
if(get_option(&console_loglevel, "debug_level"))
console_loglevel=DEFAULT_CONSOLE_LOGLEVEL;
#ifdef VIDEO_CONSOLE
video_init();

View file

@ -34,7 +34,6 @@ option SMBUS_MEM_DEVICE_END=(SMBUS_MEM_DEVICE_START +3)
option SMBUS_MEM_DEVICE_INC=1
#option SIO_BASE=0x2e
#option IOAPIC=1
option USE_AMD_NDA_CODE=1
option SUPERIO_DEVFN=0x20
option PM_DEVFN=0x2400
cpu p5

View file

@ -19,6 +19,17 @@ ldscript cpu/i386/reset16.lds USE_FALLBACK_IMAGE
mainboardinit cpu/i386/reset32.inc USE_NORMAL_IMAGE
ldscript cpu/i386/reset32.lds USE_NORMAL_IMAGE
##
## Include an id string (For safe flashing)
##
mainboardinit arch/i386/lib/id.inc
ldscript arch/i386/lib/id.lds
##
## Startup code for secondary CPUS
##
mainboardinit arch/i386/smp/secondary.inc
## This is the early phase of linuxBIOS startup
## Things are delicate and we test to see if we should
## failover to another image.
@ -204,6 +215,12 @@ option STACK_SIZE=0x2000
##
option HEAP_SIZE=0x2000
##
## Clean up the motherboard id strings
##
option MAINBOARD_PART_NUMBER=P4DC6
option MAINBOARD_VENDOR=Supermicro
##
## Only use the option table in a normal image
##
@ -211,7 +228,7 @@ expr USE_OPTION_TABLE=!USE_FALLBACK_IMAGE
##
## Compute the location and size of where this firmware image
## (linuxBIOS plus bootloader) will linv in the boot rom chip.
## (linuxBIOS plus bootloader) will live in the boot rom chip.
##
expr ROM_SECTION_SIZE =(USE_FALLBACK_IMAGE*65536)+(USE_NORMAL_IMAGE*(ROM_SIZE - 65536))
expr ROM_SECTION_OFFSET=(USE_FALLBACK_IMAGE*(ROM_SIZE-65536))+(USE_NORMAL_IMAGE*0)

File diff suppressed because it is too large Load diff

View file

@ -1,10 +0,0 @@
#define MCH_RICM 0x94
#define RICM_DONE (1 << 27)
/* If I have already booted once skip a bunch of initialization */
/* To see if I have already booted I check to see if memory
* has been enabled.
*/
movl $MCH_RICM, %eax
PCI_READ_CONFIG_DWORD
testl $RICM_DONE, %eax
jnz __cpu_reset

View file

@ -29,8 +29,8 @@ unsigned long initial_apicid[MAX_CPUS] =
#define CPU_CLOCK_MULTIPLIER XEON_X17
#endif
#define MAINBOARD_POWER_OFF 0
#define MAINBOARD_POWER_ON 1
#define MAINBOARD_POWER_OFF 2
#ifndef MAINBOARD_POWER_ON_AFTER_POWER_FAIL
#define MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
@ -67,7 +67,7 @@ void mainboard_fixup(void)
ich2_set_cpu_multiplier(cpu_clock_multiplier);
power_on_after_power_fail = MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
get_option(&power_on_after_power_fail, "power_on_after_power_fail");
get_option(&power_on_after_power_fail, "power_on_after_fail");
set_power_on_after_power_fail(power_on_after_power_fail);
return;
}
@ -99,7 +99,6 @@ void cache_ram_start(void)
/* displayinit MUST PRECEDE ALL PRINTK! */
displayinit();
printk_info("printk: Testing %d %s\n", 123, "testing!!!");
printk_info("Finding PCI configuration type.\n");
pci_set_method();
printk_info("Setting up smbus controller\n");
@ -107,8 +106,9 @@ void cache_ram_start(void)
ich2_rtc_init();
printk_info("Selecting rdram i2c bus\n");
select_rdram_i2c();
#if 0
display_smbus_spd();
#endif
init_memory();

View file

@ -2,13 +2,17 @@
#include <string.h>
#include <printk.h>
#define __STR(X) #X
#define STR(X) __STR(X)
void *smp_write_config_table(void *v, unsigned long * processor_map)
{
int ioapicid = 0;
static const char sig[4] = "PCMP";
static const char oem[8] = "LNXI ";
static const char productid[12] = "P4DC6 ";
static const char oem[] = STR(MAINBOARD_VENDOR);
static const char productid[12] = STR(MAINBOARD_PART_NUMBER);
struct mp_config_table *mc;
int len;
mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
memset(mc, 0, sizeof(*mc));
@ -17,8 +21,12 @@ void *smp_write_config_table(void *v, unsigned long * processor_map)
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));
memset(mc->mpc_oem, ' ', sizeof(mc->mpc_oem));
len = strnlen(oem, sizeof(mc->mpc_oem));
memcpy(mc->mpc_oem, oem, len);
memset(mc->mpc_productid, ' ', sizeof(mc->mpc_productid));
len = strnlen(productid, sizeof(mc->mpc_productid));
memcpy(mc->mpc_productid, productid, len);
mc->mpc_oemptr = 0;
mc->mpc_oemsize = 0;
mc->mpc_entry_count = 0; /* No entries yet... */

View file

@ -0,0 +1,265 @@
##
## Set all of the defaults for an x86 architecture
##
arch i386
##
## 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
##
## Test for logical cpu thats not BSP
##
mainboardinit cpu/i786/logical_cpu.inc USE_FALLBACK_IMAGE
##
## Build our reset vector (This is where linuxBIOS is entered)
##
mainboardinit cpu/i386/reset16.inc USE_FALLBACK_IMAGE
ldscript cpu/i386/reset16.lds USE_FALLBACK_IMAGE
mainboardinit cpu/i386/reset32.inc USE_NORMAL_IMAGE
ldscript cpu/i386/reset32.lds USE_NORMAL_IMAGE
##
## Include an id string (For safe flashing)
##
mainboardinit arch/i386/lib/id.inc
ldscript arch/i386/lib/id.lds
##
## Startup code for secondary CPUS
##
mainboardinit arch/i386/smp/secondary.inc
## This is the early phase of linuxBIOS startup
## Things are delicate and we test to see if we should
## failover to another image.
mainboardinit northbridge/intel/82860/reset_test.inc
mainboardinit arch/i386/lib/noop_failover.inc USE_NORMAL_IMAGE
mainboardinit southbridge/intel/82801/cmos_failover.inc USE_FALLBACK_IMAGE
ldscript arch/i386/lib/failover.lds USE_FALLBACK_IMAGE
###
### O.k. We aren't just an intermediary anymore!
###
##
## Setup our mtrrs
##
mainboardinit cpu/i786/earlymtrr.inc
##
## Setup the serial port
##
mainboardinit superio/winbond/w83627hf/setup_serial.inc
mainboardinit pc80/serial.inc
mainboardinit arch/i386/lib/console.inc
##
## Switch temporarily into C code to setup RAM
##
mainboardinit cpu/i786/cache_ram_init.inc
## mainboardinit cpu/i786/cache_ram_test.inc
mainboardinit cpu/i786/cache_ram_start.inc
mainboardinit cpu/i786/cache_ram_fini.inc
ldscript cpu/i786/cache_ram.lds
## mainboardinit ram/ramtest.inc
option RAMTEST=1
##
## Include the secondary Configuration files
##
northbridge intel/82860
southbridge intel/82801
southbridge intel/82806
nsuperio winbond/w83627hf com1={1} com2={1} floppy=1 lpt=1 keyboard=1
dir /src/pc80
dir /src/superio/winbond/w83627hf
cpu p5
cpu p6
cpu i786
##
## Build the objects we have code for in this directory.
##
object mainboard.o
object mtrr_values.o
object mptable.o HAVE_MP_TABLE
object irq_tables.o HAVE_PIRQ_TABLE
###
### Build options
###
##
## Location of the DIMM EEPROMS on the SMBUS
## This is fixed into a narrow range by the DIMM package standard.
##
option SMBUS_MEM_DEVICE_START=(0xa << 3)
option SMBUS_MEM_DEVICE_END=(SMBUS_MEM_DEVICE_START +3)
option SMBUS_MEM_DEVICE_INC=1
##
## Customize our winbond superio chip for this motherboard
##
option SIO_BASE=0x2e
option SIO_SYSTEM_CLK_INPUT=SIO_SYSTEM_CLK_INPUT_48MHZ
##
## Build code for the fallback boot
##
option HAVE_FALLBACK_BOOT=1
##
## Build code for using cache as RAM
##
option USE_CACHE_RAM=1
##
## Build code to reset the motherboard from linuxBIOS
##
option HAVE_HARD_RESET=1
##
## Build code to export a programmable irq routing table
##
option HAVE_PIRQ_TABLE=1
##
## Do not build special code to the keyboard
##
option NO_KEYBOARD=1
##
## Build code to export an x86 MP table
## Useful for specifying IRQ routing values
##
option HAVE_MP_TABLE=1
##
## Build code to export a CMOS option tabe table
##
option HAVE_OPTION_TABLE=1
##
## Build code for SMP support
## Only worry about 2 micro processors
##
option SMP=1
option MAX_CPUS=4
option MAX_PHYSICAL_CPUS=2
##
## Build code to setup a generic IOAPIC
##
option IOAPIC=1
##
## MEMORY_HOLE instructs earlymtrr.inc to
## enable caching from 0-640KB and to disable
## caching from 640KB-1MB using fixed MTRRs
##
## Enabling this option breaks SMP because secondary
## CPU identification depends on only variable MTRRs
## being enabled.
##
nooption MEMORY_HOLE
##
## Don't do a generic MTRR setup
## Instead use values from the fixed_mtrr_values array
##
option HAVE_MTRR_TABLE=1
##
## Enable both fixed and variable MTRRS
## When we setup MTRRs in mtrr.c
##
## We must setup the fixed mtrrs or we confuse SMP secondary
## processor identification
##
option ENABLE_FIXED_AND_VARIABLE_MTRRS=1
##
## Figure out which type of linuxBIOS image to build
## If we aren't a fallback image we must be a normal image
## This is useful for optional includes
##
option USE_FALLBACK_IMAGE=0
expr USE_NORMAL_IMAGE=!USE_FALLBACK_IMAGE
###
### LinuxBIOS layout values
###
## ROM_SIZE is the size of boot ROM that this board will use.
option ROM_SIZE=524288
## ROM_IMAGE_SIZE is the amount of space to allow linuxBIOS to occupy.
option ROM_IMAGE_SIZE=49152
## LinuxBIOS C code runs at this location in RAM
option _RAMBASE=0x00008000
## For the trick of using cache as ram
## put the fake ram location at this address
option CACHE_RAM_BASE=0xfff70000
option CACHE_RAM_SIZE=0x00010000
##
## Use a small 8K stack
##
option STACK_SIZE=0x2000
##
## Use a small 8K heap
##
option HEAP_SIZE=0x2000
##
## Clean up the motherboard id strings
##
option MAINBOARD_PART_NUMBER=P4DC6
option MAINBOARD_VENDOR=Supermicro
##
## Only use the option table in a normal image
##
expr USE_OPTION_TABLE=!USE_FALLBACK_IMAGE
##
## Compute the location and size of where this firmware image
## (linuxBIOS plus bootloader) will live in the boot rom chip.
##
expr ROM_SECTION_SIZE =(USE_FALLBACK_IMAGE*65536)+(USE_NORMAL_IMAGE*(ROM_SIZE - 65536))
expr ROM_SECTION_OFFSET=(USE_FALLBACK_IMAGE*(ROM_SIZE-65536))+(USE_NORMAL_IMAGE*0)
##
## Compute the start location and size size of
## The linuxBIOS bootloader.
##
expr ZKERNEL_START =(0xffffffff - ROM_SIZE + ROM_SECTION_OFFSET + 1)
expr PAYLOAD_SIZE =ROM_SECTION_SIZE - ROM_IMAGE_SIZE
##
## Compute where this copy of linuxBIOS will start in the boot rom
##
expr _ROMBASE =ZKERNEL_START + PAYLOAD_SIZE
##
## Compute a range of ROM that can cached to speed of linuxBIOS,
## execution speed.
##
expr XIP_ROM_SIZE = 65536
expr XIP_ROM_BASE = _ROMBASE + ROM_IMAGE_SIZE - XIP_ROM_SIZE

View file

@ -0,0 +1,104 @@
## This will make a target directory of ./fallback
## This is relative to where the configuration file resides in the filesystem
target ./fallback
mainboard supermicro/p4dc6
## Build a fallback not a normal image.
option USE_FALLBACK_IMAGE=1
## Build an image for a 512KB rom
## ./fallback/romimage is just the last 64KB which we reserve for the fallback image.
option ROM_SIZE=524288
#option ROM_SIZE=1048576
## Select the maximum size the linuxBIOS code can compile to.
## Allow linuxBIOS to be up to 48KB in size
option ROM_IMAGE_SIZE=49152
##
### The Serial Console
##
## Hardware flow control is currently ignored.
## Enable the Serial Console
option SERIAL_CONSOLE=1
## Select the serial console baud rate.
option TTYS0_BAUD=115200
#option TTYS0_BAUD=57600
#option TTYS0_BAUD=38400
#option TTYS0_BAUD=19200
#option TTYS0_BAUD=9600
#option TTYS0_BAUD=4800
#option TTYS0_BAUD=2400
#option TTYS0_BAUD=1200
# Select the serial console base port
option TTYS0_BASE=0x3f8
# Select the serial protocol
# This defaults to 8 data bits, 1 stop bit, and no parity
option TTYS0_LCS=0x3
##
### Select the linuxBIOS loglevel
##
## EMERG 1 system is unusable
## ALERT 2 action must be taken immediately
## CRIT 3 critical conditions
## ERR 4 error conditions
## WARNING 5 warning conditions
## NOTICE 6 normal but significant condition
## INFO 7 informational
## DEBUG 8 debug-level messages
## SPEW 9 Way too many details
## Request this level of debugging output
option DEFAULT_CONSOLE_LOGLEVEL=9
## At a maximum only compile in this level of debugging
option MAXIMUM_CONSOLE_LOGLEVEL=6
## Use the elf bootloader
option USE_ELF_BOOT=1
## Select the boot device
option USE_GENERIC_ROM=1
#option BOOT_FLOPPY=1
#option USE_SERIAL_FILL_INBUF=1
#option BOOT_IDE=1
# Load etherboot with the elf bootloader
# The payload command is relative the build directory
# So .. is the directory this config file resides in
payload ../eepro100.ebi
##
## Cpu Speed
##
option CPU_CLOCK_MULTIPLIER=XEON_X8
#option CPU_CLOCK_MULTIPLIER=XEON_X9
#option CPU_CLOCK_MULTIPLIER=XEON_X10
#option CPU_CLOCK_MULTIPLIER=XEON_X11
#option CPU_CLOCK_MULTIPLIER=XEON_X12
#option CPU_CLOCK_MULTIPLIER=XEON_X13
#option CPU_CLOCK_MULTIPLIER=XEON_X14
#option CPU_CLOCK_MULTIPLIER=XEON_X15
#option CPU_CLOCK_MULTIPLIER=XEON_X16
#option CPU_CLOCK_MULTIPLIER=XEON_X17
#option CPU_CLOCK_MULTIPLIER=XEON_X18
#option CPU_CLOCK_MULTIPLIER=XEON_X19
#option CPU_CLOCK_MULTIPLIER=XEON_X19
#option CPU_CLOCK_MULTIPLIER=XEON_X20
#option CPU_CLOCK_MULTIPLIER=XEON_X21
#option CPU_CLOCK_MULTIPLIER=XEON_X22
#option CPU_CLOCK_MULTIPLIER=XEON_X23
##
## Select power on after power fail setting
option MAINBOARD_POWER_ON_AFTER_POWER_FAIL=MAINBOARD_POWER_ON
#option MAINBOARD_POWER_ON_AFTER_POWER_FAIL=MAINBOARD_POWER_ON

View file

@ -0,0 +1,105 @@
## This will make a target directory of ./normal
## This is relative to where the configuration file resides in the filesystem
target ./normal
mainboard supermicro/p4dc6
## Build a normal not a fallback image.
option USE_FALLBACK_IMAGE=0
## Build an image for a 512KB rom
## ./normal/romimage is the entire rom image except for the last 64KB
## which are reserved for the fallback image.
option ROM_SIZE=524288
#option ROM_SIZE=1048576
## Select the maximum size the linuxBIOS code can compile to.
## Allow linuxBIOS to be up to 48KB in size
option ROM_IMAGE_SIZE=49152
##
### The Serial Console
##
## Hardware flow control is currently ignored.
## Enable the Serial Console
option SERIAL_CONSOLE=1
## Select the serial console baud rate.
option TTYS0_BAUD=115200
#option TTYS0_BAUD=57600
#option TTYS0_BAUD=38400
#option TTYS0_BAUD=19200
#option TTYS0_BAUD=9600
#option TTYS0_BAUD=4800
#option TTYS0_BAUD=2400
#option TTYS0_BAUD=1200
# Select the serial console base port
option TTYS0_BASE=0x3f8
# Select the serial protocol
# This defaults to 8 data bits, 1 stop bit, and no parity
option TTYS0_LCS=0x3
##
### Select the linuxBIOS loglevel
##
## EMERG 1 system is unusable
## ALERT 2 action must be taken immediately
## CRIT 3 critical conditions
## ERR 4 error conditions
## WARNING 5 warning conditions
## NOTICE 6 normal but significant condition
## INFO 7 informational
## DEBUG 8 debug-level messages
## SPEW 9 Way too many details
## Request this level of debugging output
option DEFAULT_CONSOLE_LOGLEVEL=9
## At a maximum only compile in this level of debugging
option MAXIMUM_CONSOLE_LOGLEVEL=8
## Use the elf bootloader
option USE_ELF_BOOT=1
## Select the boot device
option USE_GENERIC_ROM=1
#option BOOT_FLOPPY=1
#option USE_SERIAL_FILL_INBUF=1
#option BOOT_IDE=1
# Load etherboot with the elf bootloader
# The payload command is relative the build directory
# So .. is the directory this config file resides in
payload ../eepro100.ebi
##
## Cpu Speed
##
#option CPU_CLOCK_MULTIPLIER=XEON_X8
#option CPU_CLOCK_MULTIPLIER=XEON_X9
#option CPU_CLOCK_MULTIPLIER=XEON_X10
#option CPU_CLOCK_MULTIPLIER=XEON_X11
#option CPU_CLOCK_MULTIPLIER=XEON_X12
#option CPU_CLOCK_MULTIPLIER=XEON_X13
#option CPU_CLOCK_MULTIPLIER=XEON_X14
#option CPU_CLOCK_MULTIPLIER=XEON_X15
#option CPU_CLOCK_MULTIPLIER=XEON_X16
option CPU_CLOCK_MULTIPLIER=XEON_X17
#option CPU_CLOCK_MULTIPLIER=XEON_X18
#option CPU_CLOCK_MULTIPLIER=XEON_X19
#option CPU_CLOCK_MULTIPLIER=XEON_X19
#option CPU_CLOCK_MULTIPLIER=XEON_X20
#option CPU_CLOCK_MULTIPLIER=XEON_X21
#option CPU_CLOCK_MULTIPLIER=XEON_X22
#option CPU_CLOCK_MULTIPLIER=XEON_X23
##
## Select power on after power fail setting
option MAINBOARD_POWER_ON_AFTER_POWER_FAIL=MAINBOARD_POWER_ON
#option MAINBOARD_POWER_ON_AFTER_POWER_FAIL=MAINBOARD_POWER_ON

View file

@ -0,0 +1,29 @@
/* PCI: Interrupt Routing Table found at 0x4011ced0 size = 176 */
#include <arch/pirq_routing.h>
const struct irq_routing_table intel_irq_routing_table = {
0x52495024, /* u32 signature */
0x0100, /* u16 version */
192, /* u16 Table size 32+(16*devices) */
0x00, /* u8 Bus 0 */
0xf8, /* u8 Device 1, Function 0 */
0x1e20, /* u16 reserve IRQ for PCI */
0x8086, /* u16 Vendor */
0x7000, /* Device ID */
0x00000000, /* u32 miniport_data */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
0x67, /* u8 checksum - mod 256 checksum must give zero */
{ /* bus, devfn, {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */
{0x00, 0x10, {{0x62, 0xdeb8}, {0x62, 0xdeb8}, {0x62, 0xdeb8}, {0x62, 0xdeb8}}, 0x01, 0x00},
{0x04, 0x40, {{0x68, 0xdeb8}, {0x69, 0xdeb8}, {0x6a, 0xdeb8}, {0x6b, 0xdeb8}}, 0x02, 0x00},
{0x04, 0x38, {{0x60, 0xdeb8}, {0x61, 0xdeb8}, {0x62, 0xdeb8}, {0x63, 0xdeb8}}, 0x03, 0x00},
{0x04, 0x08, {{0x61, 0xdeb8}, {0x62, 0xdeb8}, {0x63, 0xdeb8}, {0x60, 0xdeb8}}, 0x04, 0x00},
{0x04, 0x10, {{0x62, 0xdeb8}, {0x63, 0xdeb8}, {0x60, 0xdeb8}, {0x61, 0xdeb8}}, 0x05, 0x00},
{0x04, 0x18, {{0x63, 0xdeb8}, {0x60, 0xdeb8}, {0x61, 0xdeb8}, {0x62, 0xdeb8}}, 0x06, 0x00},
{0x04, 0x20, {{0x60, 0xdeb8}, {0x61, 0xdeb8}, {0x62, 0xdeb8}, {0x63, 0xdeb8}}, 0x07, 0x00},
{0x03, 0x20, {{0x60, 0xdeb8}, {0x61, 0xdeb8}, {0x62, 0xdeb8}, {0x63, 0xdeb8}}, 0x07, 0x00},
{0x00, 0xf8, {{0x60, 0xdeb8}, {0x61, 0xdeb8}, {0x6b, 0xdeb8}, {0x63, 0xdeb8}}, 0x00, 0x00},
{0x00, 0x08, {{0x6a, 0xdeb8}, {0x6b, 0xdeb8}, {0x60, 0xdeb8}, {0x61, 0xdeb8}}, 0x00, 0x00}
}
};

View file

@ -0,0 +1,202 @@
#include <arch/io.h>
#include <part/mainboard.h>
#include <printk.h>
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/intel/82801.h>
#include <arch/smp/mpspec.h>
#include <pc80/isa_dma.h>
#include <cpu/i786/multiplier.h>
#include <cpu/i786/thermal_monitoring.h>
#include <cpu/p6/msr.h>
#include <superio/w83627hf.h>
#include <superio/generic.h>
#include <subr.h>
#include <smbus.h>
#include <ramtest.h>
#include <northbridge/intel/82860/rdram.h>
#include <pc80/mc146818rtc.h>
#define SMBUS_MEM_DEVICE_0 (0xa << 3)
extern int rdram_chips; /* number of ram chips on the rimms */
unsigned long initial_apicid[MAX_CPUS] =
{
0, 6, 1, 7
};
#ifndef CPU_CLOCK_MULTIPLIER
#define CPU_CLOCK_MULTIPLIER XEON_X17
#endif
#define MAINBOARD_POWER_ON 1
#define MAINBOARD_POWER_OFF 2
#ifndef MAINBOARD_POWER_ON_AFTER_POWER_FAIL
#define MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
#endif
static void set_power_on_after_power_fail(int setting)
{
switch(setting) {
case MAINBOARD_POWER_ON:
default:
ich2_power_after_power_fail(1);
w832627hf_power_after_power_fail(POWER_ON);
break;
case MAINBOARD_POWER_OFF:
ich2_power_after_power_fail(0);
w832627hf_power_after_power_fail(POWER_OFF);
break;
}
}
static void set_thermal_monitoring(int thermal_monitoring)
{
int tm_high,tm_low;
rdmsr(MISC_ENABLE,tm_low,tm_high);
if(thermal_monitoring != THERMAL_MONITORING_OFF) {
tm_low |= THERMAL_MONITORING_SET;
}
else {
tm_low &= ~THERMAL_MONITORING_SET;
}
wrmsr(MISC_ENABLE,tm_low,tm_high);
return;
}
void mainboard_fixup(void)
{
int cpu_clock_multiplier;
int power_on_after_power_fail;
int thermal_monitoring;
ich2_enable_ioapic();
ich2_enable_serial_irqs();
ich2_enable_ide(1,1);
ich2_rtc_init();
ich2_lpc_route_dma(0xff);
isa_dma_init();
cpu_clock_multiplier = CPU_CLOCK_MULTIPLIER;
if(get_option(&cpu_clock_multiplier, "CPU_clock_speed"))
cpu_clock_multiplier = CPU_CLOCK_MULTIPLIER;
ich2_set_cpu_multiplier(cpu_clock_multiplier);
power_on_after_power_fail = MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
if(get_option(&power_on_after_power_fail, "power_on_after_power_fail"))
power_on_after_power_fail = MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
set_power_on_after_power_fail(power_on_after_power_fail);
thermal_monitoring = THERMAL_MONITORING_OFF;
if(get_option(&thermal_monitoring, "thermal_monitoring"))
thermal_monitoring = THERMAL_MONITORING_OFF;
set_thermal_monitoring(thermal_monitoring);
return;
}
void hard_reset(void)
{
ich2_hard_reset();
}
static void select_rdram_i2c(void)
{
unsigned char byte;
w83627hf_enter_pnp(SIO_BASE);
byte = pnp_read_config(SIO_BASE, 0x2b);
byte |= 0x30;
pnp_write_config(SIO_BASE, byte, 0x2b);
pnp_set_logical_device(SIO_BASE, GPIO_PORT2_DEVICE);
pnp_set_enable(SIO_BASE, 1);
byte = pnp_read_config(SIO_BASE, 0xf0);
byte &= ~(1 << 3);
pnp_write_config(SIO_BASE, byte, 0xf0);
w83627hf_exit_pnp(SIO_BASE);
}
void cache_ram_start(void)
{
int error;
error = 0;
/* displayinit MUST PRECEDE ALL PRINTK! */
#if 1
displayinit();
#endif
printk_info("Finding PCI configuration type.\n");
pci_set_method();
printk_info("Setting up smbus controller\n");
smbus_setup();
ich2_rtc_init();
printk_info("Selecting rdram i2c bus\n");
select_rdram_i2c();
#if 1
display_smbus_spd();
#endif
init_memory();
#if 0
{
unsigned long addr;
for(addr = 0; addr < 0x20000000; addr += 0x02000000) {
ram_fill(addr, addr + 0x400);
}
/* Do some dummy writes to flush a write cache, in the
* processor.
*/
ram_fill(0xc0000000, 0xc0000400);
for(addr = 0; addr < 0x20000000; addr += 0x02000000) {
ram_verify(addr, addr + 0x400, 1);
}
}
#endif
#if 0
error |= ramcheck(0x00000000, 0x00080000, 20);
error |= ramcheck(0x02000000, 0x02080000, 20);
error |= ramcheck(0x04000000, 0x04080000, 20);
error |= ramcheck(0x06000000, 0x06080000, 20);
error |= ramcheck(0x08000000, 0x08080000, 20);
error |= ramcheck(0x0a000000, 0x0a080000, 20);
error |= ramcheck(0x0c000000, 0x0c080000, 20);
error |= ramcheck(0x0e000000, 0x0e080000, 20);
error |= ramcheck(0x10000000, 0x10080000, 20);
error |= ramcheck(0x12000000, 0x12080000, 20);
error |= ramcheck(0x14000000, 0x14080000, 20);
error |= ramcheck(0x16000000, 0x16080000, 20);
error |= ramcheck(0x18000000, 0x18080000, 20);
error |= ramcheck(0x1a000000, 0x1a080000, 20);
error |= ramcheck(0x1c000000, 0x1c080000, 20);
error |= ramcheck(0x1e000000, 0x1e080000, 20);
#endif
#if 0
error |= ramcheck(0x00000000, 0x00080000, 20);
#endif
#if 0
display_rdram_regs(rdram_chips );
#endif
#if 0
display_mch_regs();
#endif
if (error) {
printk_err("Something isn't working!!!\n");
while(1);
} else {
printk_info("Leaving cacheram...\n");
}
}

View file

@ -0,0 +1,138 @@
#include <arch/smp/mpspec.h>
#include <string.h>
#include <printk.h>
void *smp_write_config_table(void *v, unsigned long * processor_map)
{
int ioapicid = 0;
static const char sig[4] = "PCMP";
static const char oem[8] = "LNXI ";
static const char productid[12] = "P4DC6P ";
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);
ioapicid = 2;
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, "PCI ");
smp_write_bus(mc, 5, "ISA ");
smp_write_ioapic(mc, 2, 0x11, 0xfec00000);
/* Onboard ich2 soutbhridge */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x00, (0x1f << 2)|3, 0x02, 0x13);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x00, (0x1f << 2)|2, 0x02, 0x17);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x00, (0x1f << 2)|1, 0x02, 0x11);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x00, (0x1f << 2)|0, 0x02, 0x10);
/* agp slot */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x01, 0x00, 0x02, 0x16);
/* Onboard PCI NIC */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (4 <<2)|0, 0x02, 0x10);
/* Four standard PCI slots */
/* Slot 1 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (7 <<2)|0, 0x02, 0x10);
/* Slot 2 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (1 <<2)|0, 0x02, 0x11);
/* Slot 3 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (2 <<2)|0, 0x02, 0x12);
/* Slot 4 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (3 <<2)|0, 0x02, 0x13);
/* Two 64 bit PCI slots */
/* Slot 1 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x03, (1 <<2)|0, 0x02, 0x12);
/* Slot 2 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x03, (2 <<2)|0, 0x02, 0x12);
/* Two SCSI */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x03, (4 <<2)|0, 0x02, 0x12);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x03, (4 <<2)|1, 0x02, 0x12);
/* ISA backward compatibility interrupts */
smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x00, 0x02, 0x00);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x01, 0x02, 0x01);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x00, 0x02, 0x02);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x03, 0x02, 0x03);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x04, 0x02, 0x04);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x06, 0x02, 0x06);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x07, 0x02, 0x07);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x08, 0x02, 0x08);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x0d, 0x02, 0x0d);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x0e, 0x02, 0x0e);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x0f, 0x02, 0x0f);
/* Standard local interrupt assignments */
smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x00, 0x00, MP_APIC_ALL, 0x00);
smp_write_lintsrc(mc, mp_NMI, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x00, 0x00, MP_APIC_ALL, 0x01);
/* 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

@ -0,0 +1,49 @@
#include <cpu/p6/mtrr.h>
/* We want to cache memory as efficiently as possible.
*/
#define RAM MTRR_TYPE_WRBACK
/* We can't use Write Combining on a legacy frame buffer because
* it is incompatible with EGA 16 color video modes...
*/
#define FB MTRR_TYPE_UNCACHABLE
/* For areas that are supposed to cover roms it makes no
* sense to cache writes.
*/
#define ROM MTRR_TYPE_WRPROT
unsigned char fixed_mtrr_values[][4] = {
/* MTRRfix64K_00000_MSR, defines memory range from 0KB to 512 KB, each byte cover 64KB area */
{RAM, RAM, RAM, RAM}, {RAM, RAM, RAM, RAM},
/* MTRRfix16K_80000_MSR, defines memory range from 512KB to 640KB, each byte cover 16KB area */
{RAM, RAM, RAM, RAM}, {RAM, RAM, RAM, RAM},
/* MTRRfix16K_A0000_MSR, defines memory range from A0000 to C0000, each byte cover 16KB area */
{FB, FB, FB, FB}, {FB, FB, FB, FB},
/* MTRRfix4K_C0000_MSR, defines memory range from C0000 to C8000, each byte cover 4KB area */
{RAM, RAM, RAM, RAM}, {RAM, RAM, RAM, RAM},
/* MTRRfix4K_C8000_MSR, defines memory range from C8000 to D0000, each byte cover 4KB area */
{RAM, RAM, RAM, RAM}, {RAM, RAM, RAM, RAM},
/* MTRRfix4K_D0000_MSR, defines memory range from D0000 to D8000, each byte cover 4KB area */
{RAM, RAM, RAM, RAM}, {RAM, RAM, RAM, RAM},
/* MTRRfix4K_D8000_MSR, defines memory range from D8000 to E0000, each byte cover 4KB area */
{RAM, RAM, RAM, RAM}, {RAM, RAM, RAM, RAM},
/* MTRRfix4K_E0000_MSR, defines memory range from E0000 to E8000, each byte cover 4KB area */
{RAM, RAM, RAM, RAM}, {RAM, RAM, RAM, RAM},
/* MTRRfix4K_E8000_MSR, defines memory range from E8000 to F0000, each byte cover 4KB area */
{RAM, RAM, RAM, RAM}, {RAM, RAM, RAM, RAM},
/* MTRRfix4K_F0000_MSR, defines memory range from F0000 to F8000, each byte cover 4KB area */
{RAM, RAM, RAM, RAM}, {RAM, RAM, RAM, RAM},
/* MTRRfix4K_F8000_MSR, defines memory range from F8000 to 100000, each byte cover 4KB area */
{RAM, RAM, RAM, RAM}, {RAM, RAM, RAM, RAM},
};

View file

@ -0,0 +1,273 @@
## Set all of the defaults for an x86 architecture
##
arch i386
##
## 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
##
## Test for logical cpu thats not BSP
##
mainboardinit cpu/i786/logical_cpu.inc USE_FALLBACK_IMAGE
##
## Build our reset vector (This is where linuxBIOS is entered)
##
mainboardinit cpu/i386/reset16.inc USE_FALLBACK_IMAGE
ldscript cpu/i386/reset16.lds USE_FALLBACK_IMAGE
mainboardinit cpu/i386/reset32.inc USE_NORMAL_IMAGE
ldscript cpu/i386/reset32.lds USE_NORMAL_IMAGE
##
## Include an id string (For safe flashing)
##
mainboardinit arch/i386/lib/id.inc
ldscript arch/i386/lib/id.lds
##
## Startup code for secondary CPUS
##
mainboardinit arch/i386/smp/secondary.inc
## This is the early phase of linuxBIOS startup
## Things are delicate and we test to see if we should
## failover to another image.
mainboardinit northbridge/intel/82860/reset_test.inc
mainboardinit arch/i386/lib/noop_failover.inc USE_NORMAL_IMAGE
mainboardinit southbridge/intel/82801/cmos_failover.inc USE_FALLBACK_IMAGE
ldscript arch/i386/lib/failover.lds USE_FALLBACK_IMAGE
###
### O.k. We aren't just an intermediary anymore!
###
##
## Setup our mtrrs
##
mainboardinit cpu/i786/earlymtrr.inc
##
## Setup the serial port
##
mainboardinit superio/winbond/w83627hf/setup_serial.inc
mainboardinit pc80/serial.inc
mainboardinit arch/i386/lib/console.inc
##
## Switch temporarily into C code to setup RAM
##
#mainboardinit cpu/i786/cache_ram_init.inc
## mainboardinit cpu/i786/cache_ram_test.inc
#mainboardinit cpu/i786/cache_ram_start.inc
#mainboardinit cpu/i786/cache_ram_fini.inc
#ldscript cpu/i786/cache_ram.lds
mainboardinit ram/ramtest.inc
option RAMTEST=1
mainboardinit ram/dump_northbridge.inc
##
## Setup RAM
##
#mainboardinit southbridge/intel/82801/smbus.inc
#mainboardinit sdram/generic_dump_spd.inc
mainboardinit mainboard/supermicro/p4dpr/mainboard_raminit.inc
##
## Include the secondary Configuration files
##
northbridge intel/E7500
southbridge intel/82801ca
southbridge intel/82870
nsuperio winbond/w83627hf com1={1} com2={1} floppy=1 lpt=1 keyboard=1
dir /src/pc80
dir /src/superio/winbond/w83627hf
dir /src/ram/
cpu p5
cpu p6
cpu i786
##
## Build the objects we have code for in this directory.
##
object mainboard.o
object mtrr_values.o
object mptable.o HAVE_MP_TABLE
object irq_tables.o HAVE_PIRQ_TABLE
###
### Build options
###
##
## Location of the DIMM EEPROMS on the SMBUS
## This is fixed into a narrow range by the DIMM package standard.
##
option SMBUS_MEM_DEVICE_START=(0xa << 3)
option SMBUS_MEM_DEVICE_END=(SMBUS_MEM_DEVICE_START +3)
option SMBUS_MEM_DEVICE_INC=1
##
## Customize our winbond superio chip for this motherboard
##
option SIO_BASE=0x2e
option SIO_SYSTEM_CLK_INPUT=SIO_SYSTEM_CLK_INPUT_48MHZ
##
## Build code for the fallback boot
##
option HAVE_FALLBACK_BOOT=1
##
## Build code for using cache as RAM
##
option USE_CACHE_RAM=1
##
## Build code to reset the motherboard from linuxBIOS
##
option HAVE_HARD_RESET=1
##
## Build code to export a programmable irq routing table
##
option HAVE_PIRQ_TABLE=1
##
## Do not build special code to the keyboard
##
option NO_KEYBOARD=1
##
## Build code to export an x86 MP table
## Useful for specifying IRQ routing values
##
option HAVE_MP_TABLE=1
##
## Build code to export a CMOS option tabe table
##
option HAVE_OPTION_TABLE=1
##
## Build code for SMP support
## Only worry about 2 micro processors
##
option SMP=1
option MAX_CPUS=4
option MAX_PHYSICAL_CPUS=2
##
## Build code to setup a generic IOAPIC
##
option IOAPIC=1
##
## MEMORY_HOLE instructs earlymtrr.inc to
## enable caching from 0-640KB and to disable
## caching from 640KB-1MB using fixed MTRRs
##
## Enabling this option breaks SMP because secondary
## CPU identification depends on only variable MTRRs
## being enabled.
##
nooption MEMORY_HOLE
##
## Don't do a generic MTRR setup
## Instead use values from the fixed_mtrr_values array
##
option HAVE_MTRR_TABLE=1
##
## Enable both fixed and variable MTRRS
## When we setup MTRRs in mtrr.c
##
## We must setup the fixed mtrrs or we confuse SMP secondary
## processor identification
##
option ENABLE_FIXED_AND_VARIABLE_MTRRS=1
##
## Figure out which type of linuxBIOS image to build
## If we aren't a fallback image we must be a normal image
## This is useful for optional includes
##
option USE_FALLBACK_IMAGE=0
expr USE_NORMAL_IMAGE=!USE_FALLBACK_IMAGE
###
### LinuxBIOS layout values
###
## ROM_SIZE is the size of boot ROM that this board will use.
option ROM_SIZE=524288
## ROM_IMAGE_SIZE is the amount of space to allow linuxBIOS to occupy.
option ROM_IMAGE_SIZE=49152
## LinuxBIOS C code runs at this location in RAM
option _RAMBASE=0x00008000
## For the trick of using cache as ram
## put the fake ram location at this address
option CACHE_RAM_BASE=0xfff70000
option CACHE_RAM_SIZE=0x00010000
##
## Use a small 8K stack
##
option STACK_SIZE=0x2000
##
## Use a small 8K heap
##
option HEAP_SIZE=0x2000
##
## Clean up the motherboard id strings
##
option MAINBOARD_PART_NUMBER=P4DPR
option MAINBOARD_VENDOR=Supermicro
##
## Only use the option table in a normal image
##
expr USE_OPTION_TABLE=!USE_FALLBACK_IMAGE
##
## Compute the location and size of where this firmware image
## (linuxBIOS plus bootloader) will live in the boot rom chip.
##
expr ROM_SECTION_SIZE =(USE_FALLBACK_IMAGE*65536)+(USE_NORMAL_IMAGE*(ROM_SIZE - 65536))
expr ROM_SECTION_OFFSET=(USE_FALLBACK_IMAGE*(ROM_SIZE-65536))+(USE_NORMAL_IMAGE*0)
##
## Compute the start location and size size of
## The linuxBIOS bootloader.
##
expr ZKERNEL_START =(0xffffffff - ROM_SIZE + ROM_SECTION_OFFSET + 1)
expr PAYLOAD_SIZE =ROM_SECTION_SIZE - ROM_IMAGE_SIZE
##
## Compute where this copy of linuxBIOS will start in the boot rom
##
expr _ROMBASE =ZKERNEL_START + PAYLOAD_SIZE
##
## Compute a range of ROM that can cached to speed of linuxBIOS,
## execution speed.
##
expr XIP_ROM_SIZE = 65536
expr XIP_ROM_BASE = _ROMBASE + ROM_IMAGE_SIZE - XIP_ROM_SIZE

View file

@ -0,0 +1,104 @@
## This will make a target directory of ./fallback
## This is relative to where the configuration file resides in the filesystem
target ./fallback
mainboard supermicro/p4dc6
## Build a fallback not a normal image.
option USE_FALLBACK_IMAGE=1
## Build an image for a 512KB rom
## ./fallback/romimage is just the last 64KB which we reserve for the fallback image.
option ROM_SIZE=524288
#option ROM_SIZE=1048576
## Select the maximum size the linuxBIOS code can compile to.
## Allow linuxBIOS to be up to 48KB in size
option ROM_IMAGE_SIZE=49152
##
### The Serial Console
##
## Hardware flow control is currently ignored.
## Enable the Serial Console
option SERIAL_CONSOLE=1
## Select the serial console baud rate.
option TTYS0_BAUD=115200
#option TTYS0_BAUD=57600
#option TTYS0_BAUD=38400
#option TTYS0_BAUD=19200
#option TTYS0_BAUD=9600
#option TTYS0_BAUD=4800
#option TTYS0_BAUD=2400
#option TTYS0_BAUD=1200
# Select the serial console base port
option TTYS0_BASE=0x3f8
# Select the serial protocol
# This defaults to 8 data bits, 1 stop bit, and no parity
option TTYS0_LCS=0x3
##
### Select the linuxBIOS loglevel
##
## EMERG 1 system is unusable
## ALERT 2 action must be taken immediately
## CRIT 3 critical conditions
## ERR 4 error conditions
## WARNING 5 warning conditions
## NOTICE 6 normal but significant condition
## INFO 7 informational
## DEBUG 8 debug-level messages
## SPEW 9 Way too many details
## Request this level of debugging output
option DEFAULT_CONSOLE_LOGLEVEL=9
## At a maximum only compile in this level of debugging
option MAXIMUM_CONSOLE_LOGLEVEL=6
## Use the elf bootloader
option USE_ELF_BOOT=1
## Select the boot device
option USE_GENERIC_ROM=1
#option BOOT_FLOPPY=1
#option USE_SERIAL_FILL_INBUF=1
#option BOOT_IDE=1
# Load etherboot with the elf bootloader
# The payload command is relative the build directory
# So .. is the directory this config file resides in
payload ../eepro100.ebi
##
## Cpu Speed
##
option CPU_CLOCK_MULTIPLIER=XEON_X8
#option CPU_CLOCK_MULTIPLIER=XEON_X9
#option CPU_CLOCK_MULTIPLIER=XEON_X10
#option CPU_CLOCK_MULTIPLIER=XEON_X11
#option CPU_CLOCK_MULTIPLIER=XEON_X12
#option CPU_CLOCK_MULTIPLIER=XEON_X13
#option CPU_CLOCK_MULTIPLIER=XEON_X14
#option CPU_CLOCK_MULTIPLIER=XEON_X15
#option CPU_CLOCK_MULTIPLIER=XEON_X16
#option CPU_CLOCK_MULTIPLIER=XEON_X17
#option CPU_CLOCK_MULTIPLIER=XEON_X18
#option CPU_CLOCK_MULTIPLIER=XEON_X19
#option CPU_CLOCK_MULTIPLIER=XEON_X19
#option CPU_CLOCK_MULTIPLIER=XEON_X20
#option CPU_CLOCK_MULTIPLIER=XEON_X21
#option CPU_CLOCK_MULTIPLIER=XEON_X22
#option CPU_CLOCK_MULTIPLIER=XEON_X23
##
## Select power on after power fail setting
option MAINBOARD_POWER_ON_AFTER_POWER_FAIL=MAINBOARD_POWER_ON
#option MAINBOARD_POWER_ON_AFTER_POWER_FAIL=MAINBOARD_POWER_ON

View file

@ -0,0 +1,105 @@
## This will make a target directory of ./normal
## This is relative to where the configuration file resides in the filesystem
target ./normal
mainboard supermicro/p4dc6
## Build a normal not a fallback image.
option USE_FALLBACK_IMAGE=0
## Build an image for a 512KB rom
## ./normal/romimage is the entire rom image except for the last 64KB
## which are reserved for the fallback image.
option ROM_SIZE=524288
#option ROM_SIZE=1048576
## Select the maximum size the linuxBIOS code can compile to.
## Allow linuxBIOS to be up to 48KB in size
option ROM_IMAGE_SIZE=49152
##
### The Serial Console
##
## Hardware flow control is currently ignored.
## Enable the Serial Console
option SERIAL_CONSOLE=1
## Select the serial console baud rate.
option TTYS0_BAUD=115200
#option TTYS0_BAUD=57600
#option TTYS0_BAUD=38400
#option TTYS0_BAUD=19200
#option TTYS0_BAUD=9600
#option TTYS0_BAUD=4800
#option TTYS0_BAUD=2400
#option TTYS0_BAUD=1200
# Select the serial console base port
option TTYS0_BASE=0x3f8
# Select the serial protocol
# This defaults to 8 data bits, 1 stop bit, and no parity
option TTYS0_LCS=0x3
##
### Select the linuxBIOS loglevel
##
## EMERG 1 system is unusable
## ALERT 2 action must be taken immediately
## CRIT 3 critical conditions
## ERR 4 error conditions
## WARNING 5 warning conditions
## NOTICE 6 normal but significant condition
## INFO 7 informational
## DEBUG 8 debug-level messages
## SPEW 9 Way too many details
## Request this level of debugging output
option DEFAULT_CONSOLE_LOGLEVEL=9
## At a maximum only compile in this level of debugging
option MAXIMUM_CONSOLE_LOGLEVEL=8
## Use the elf bootloader
option USE_ELF_BOOT=1
## Select the boot device
option USE_GENERIC_ROM=1
#option BOOT_FLOPPY=1
#option USE_SERIAL_FILL_INBUF=1
#option BOOT_IDE=1
# Load etherboot with the elf bootloader
# The payload command is relative the build directory
# So .. is the directory this config file resides in
payload ../eepro100.ebi
##
## Cpu Speed
##
#option CPU_CLOCK_MULTIPLIER=XEON_X8
#option CPU_CLOCK_MULTIPLIER=XEON_X9
#option CPU_CLOCK_MULTIPLIER=XEON_X10
#option CPU_CLOCK_MULTIPLIER=XEON_X11
#option CPU_CLOCK_MULTIPLIER=XEON_X12
#option CPU_CLOCK_MULTIPLIER=XEON_X13
#option CPU_CLOCK_MULTIPLIER=XEON_X14
#option CPU_CLOCK_MULTIPLIER=XEON_X15
#option CPU_CLOCK_MULTIPLIER=XEON_X16
option CPU_CLOCK_MULTIPLIER=XEON_X17
#option CPU_CLOCK_MULTIPLIER=XEON_X18
#option CPU_CLOCK_MULTIPLIER=XEON_X19
#option CPU_CLOCK_MULTIPLIER=XEON_X19
#option CPU_CLOCK_MULTIPLIER=XEON_X20
#option CPU_CLOCK_MULTIPLIER=XEON_X21
#option CPU_CLOCK_MULTIPLIER=XEON_X22
#option CPU_CLOCK_MULTIPLIER=XEON_X23
##
## Select power on after power fail setting
option MAINBOARD_POWER_ON_AFTER_POWER_FAIL=MAINBOARD_POWER_ON
#option MAINBOARD_POWER_ON_AFTER_POWER_FAIL=MAINBOARD_POWER_ON

View file

@ -0,0 +1,43 @@
/* PCI: Interrupt Routing Table found at 0x4011ce40 size = 416 */
#include <arch/pirq_routing.h>
const struct irq_routing_table intel_irq_routing_table = {
0x52495024, /* u32 signature */
0x0100, /* u16 version */
416, /* u16 Table size 32+(16*devices) */
0x00, /* u8 Bus 0 */
0xf8, /* u8 Device 1, Function 0 */
0x0000, /* u16 reserve IRQ for PCI */
0x8086, /* u16 Vendor */
0x122e, /* Device ID */
0x00000000, /* u32 miniport_data */
{ 0, 0, 0, 0, 0, 0, 0, 0, 0, 0, 0 }, /* u8 rfu[11] */
0x94, /* u8 checksum - mod 256 checksum must give zero */
{ /* bus, devfn, {link, bitmap}, {link, bitmap}, {link, bitmap}, {link, bitmap}, slot, rfu */
{0x00, 0x00, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00},
{0x00, 0x10, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00},
{0x01, 0xe8, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00},
{0x02, 0x08, {{0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}}, 0x01, 0x00},
{0x02, 0x18, {{0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}}, 0x0a, 0x00},
{0x02, 0x10, {{0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}}, 0x03, 0x00},
{0x01, 0xf8, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00},
{0x03, 0x08, {{0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}}, 0x02, 0x00},
{0x03, 0x10, {{0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}}, 0x05, 0x00},
{0x03, 0x18, {{0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}}, 0x06, 0x00},
{0x03, 0x20, {{0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}, {0x68, 0xdcb8}}, 0x0b, 0x00},
{0x00, 0x20, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00},
{0x10, 0xe8, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00},
{0x11, 0x08, {{0x63, 0xdcb8}, {0x63, 0xdcb8}, {0x63, 0xdcb8}, {0x63, 0xdcb8}}, 0x03, 0x00},
{0x10, 0xf8, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00},
{0x12, 0x08, {{0x63, 0xdcb8}, {0x63, 0xdcb8}, {0x63, 0xdcb8}, {0x63, 0xdcb8}}, 0x04, 0x00},
{0x00, 0xf0, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00},
{0x04, 0x08, {{0x60, 0xdcb8}, {0x60, 0xdcb8}, {0x60, 0xdcb8}, {0x60, 0xdcb8}}, 0x07, 0x00},
{0x04, 0x10, {{0x61, 0xdcb8}, {0x61, 0xdcb8}, {0x61, 0xdcb8}, {0x61, 0xdcb8}}, 0x08, 0x00},
{0x04, 0x18, {{0x62, 0xdcb8}, {0x62, 0xdcb8}, {0x62, 0xdcb8}, {0x62, 0xdcb8}}, 0x09, 0x00},
{0x00, 0xe8, {{0x60, 0xdcb8}, {0x00, 0xdef8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00},
{0x00, 0xe9, {{0x00, 0xdef8}, {0x63, 0xdcb8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00},
{0x00, 0xea, {{0x00, 0xdef8}, {0x00, 0xdef8}, {0x62, 0xdcb8}, {0x00, 0xdef8}}, 0x00, 0x00},
{0x00, 0xf8, {{0x62, 0xdcb8}, {0x61, 0xdcb8}, {0x00, 0xdef8}, {0x00, 0xdef8}}, 0x00, 0x00}
}
};

View file

@ -0,0 +1,209 @@
#include <arch/io.h>
#include <part/mainboard.h>
#include <printk.h>
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/intel/82801.h>
#include <arch/smp/mpspec.h>
#include <pc80/isa_dma.h>
#include <cpu/i786/multiplier.h>
#include <cpu/i786/thermal_monitoring.h>
#include <cpu/p6/msr.h>
#include <superio/w83627hf.h>
#include <superio/generic.h>
#include <subr.h>
#include <smbus.h>
#include <ramtest.h>
#include <northbridge/intel/82860/rdram.h>
#include <pc80/mc146818rtc.h>
#define SMBUS_MEM_DEVICE_0 (0xa << 3)
extern int rdram_chips; /* number of ram chips on the rimms */
unsigned long initial_apicid[MAX_CPUS] =
{
0, 6, 1, 7
};
#ifndef CPU_CLOCK_MULTIPLIER
#define CPU_CLOCK_MULTIPLIER XEON_X17
#endif
#define MAINBOARD_POWER_ON 1
#define MAINBOARD_POWER_OFF 2
#ifndef MAINBOARD_POWER_ON_AFTER_POWER_FAIL
#define MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
#endif
static void set_power_on_after_power_fail(int setting)
{
switch(setting) {
case MAINBOARD_POWER_ON:
default:
ich3_power_after_power_fail(1);
w832627hf_power_after_power_fail(POWER_ON);
break;
case MAINBOARD_POWER_OFF:
ich3_power_after_power_fail(0);
w832627hf_power_after_power_fail(POWER_OFF);
break;
}
}
static void set_thermal_monitoring(int thermal_monitoring)
{
int tm_high,tm_low;
rdmsr(MISC_ENABLE,tm_low,tm_high);
if(thermal_monitoring != THERMAL_MONITORING_OFF) {
tm_low |= THERMAL_MONITORING_SET;
}
else {
tm_low &= ~THERMAL_MONITORING_SET;
}
wrmsr(MISC_ENABLE,tm_low,tm_high);
return;
}
void mainboard_fixup(void)
{
int cpu_clock_multiplier;
int power_on_after_power_fail;
int thermal_monitoring;
ich3_enable_ioapic();
p64h2_enable_ioapic();
ich3_enable_serial_irqs();
ich3_enable_ide(1,1);
ich3_rtc_init();
ich3_lpc_route_dma(0xff);
isa_dma_init();
ich3_1e0_misc();
ich3_1f0_misc();
cpu_clock_multiplier = CPU_CLOCK_MULTIPLIER;
if(get_option(&cpu_clock_multiplier, "CPU_clock_speed"))
cpu_clock_multiplier = CPU_CLOCK_MULTIPLIER;
ich3_set_cpu_multiplier(cpu_clock_multiplier);
power_on_after_power_fail = MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
if(get_option(&power_on_after_power_fail, "power_on_after_power_fail"))
power_on_after_power_fail = MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
set_power_on_after_power_fail(power_on_after_power_fail);
thermal_monitoring = THERMAL_MONITORING_OFF;
if(get_option(&thermal_monitoring, "thermal_monitoring"))
thermal_monitoring = THERMAL_MONITORING_OFF;
set_thermal_monitoring(thermal_monitoring);
return;
}
void hard_reset(void)
{
ich3_hard_reset();
}
static void select_rdram_i2c(void)
{
unsigned char byte;
w83627hf_enter_pnp(SIO_BASE);
byte = pnp_read_config(SIO_BASE, 0x2b);
byte |= 0x30;
pnp_write_config(SIO_BASE, byte, 0x2b);
pnp_set_logical_device(SIO_BASE, GPIO_PORT2_DEVICE);
pnp_set_enable(SIO_BASE, 1);
byte = pnp_read_config(SIO_BASE, 0xf0);
byte &= ~(1 << 3);
pnp_write_config(SIO_BASE, byte, 0xf0);
w83627hf_exit_pnp(SIO_BASE);
}
#if 0
void cache_ram_start(void)
{
int error;
error = 0;
/* displayinit MUST PRECEDE ALL PRINTK! */
#if 1
displayinit();
#endif
printk_info("Finding PCI configuration type.\n");
pci_set_method();
printk_info("Setting up smbus controller\n");
smbus_setup();
ich3_rtc_init();
printk_info("Selecting rdram i2c bus\n");
select_rdram_i2c();
#if 0
display_smbus_spd();
#endif
init_memory();
#if 0
{
unsigned long addr;
for(addr = 0; addr < 0x20000000; addr += 0x02000000) {
ram_fill(addr, addr + 0x400);
}
/* Do some dummy writes to flush a write cache, in the
* processor.
*/
ram_fill(0xc0000000, 0xc0000400);
for(addr = 0; addr < 0x20000000; addr += 0x02000000) {
ram_verify(addr, addr + 0x400, 1);
}
}
#endif
#if 1
printk_debug("starting ramcheck\n");
error |= ramcheck(0x00000000, 0x00080000, 40);
error |= ramcheck(0x02000000, 0x02080000, 40);
error |= ramcheck(0x04000000, 0x04080000, 40);
error |= ramcheck(0x06000000, 0x06080000, 40);
error |= ramcheck(0x08000000, 0x08080000, 40);
error |= ramcheck(0x0a000000, 0x0a080000, 40);
error |= ramcheck(0x0c000000, 0x0c080000, 40);
error |= ramcheck(0x0e000000, 0x0e080000, 40);
error |= ramcheck(0x1a000000, 0x1a080000, 40);
#if 0
error |= ramcheck(0x10000000, 0x10080000, 20);
error |= ramcheck(0x12000000, 0x12080000, 20);
error |= ramcheck(0x14000000, 0x14080000, 20);
error |= ramcheck(0x16000000, 0x16080000, 20);
error |= ramcheck(0x18000000, 0x18080000, 20);
error |= ramcheck(0x1a000000, 0x1a080000, 20);
error |= ramcheck(0x1c000000, 0x1c080000, 20);
error |= ramcheck(0x1e000000, 0x1e080000, 20);
#endif
#endif
#if 0
error |= ramcheck(0x00000000, 0x00080000, 20);
#endif
#if 0
display_rdram_regs(rdram_chips );
#endif
#if 0
display_mch_regs();
#endif
if (error) {
printk_err("Something isn't working!!!\n");
while(1);
} else {
printk_info("Leaving cacheram...\n");
}
}
#endif

View file

@ -0,0 +1 @@

View file

@ -0,0 +1,197 @@
#include <arch/smp/mpspec.h>
#include <string.h>
#include <printk.h>
void *smp_write_config_table(void *v, unsigned long * processor_map)
{
int ioapicid = 0;
static const char sig[4] = "PCMP";
static const char oem[8] = "LNXI ";
static const char productid[12] = "P4DPR ";
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;
#if 1
smp_write_processor(mc, 0x00, 0x14, CPU_BOOTPROCESSOR | CPU_ENABLED,
0x00000f24, 0x3febfbff);
smp_write_processor(mc, 0x06, 0x14, CPU_ENABLED, 0x00000f24, 0x3febfbff);
smp_write_processor(mc, 0x01, 0x14, CPU_ENABLED, 0x00000f24, 0x3febfbff);
smp_write_processor(mc, 0x07, 0x14, CPU_ENABLED, 0x00000f24, 0x3febfbff);
#else
smp_write_processors(mc, processor_map);
#endif
ioapicid = 2;
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, "PCI ");
smp_write_bus(mc, 5, "ISA ");
#if 1
smp_write_ioapic(mc, 2, 0x20, 0xfec00000);
smp_write_ioapic(mc, 3, 0x20, 0xfec80000);
smp_write_ioapic(mc, 4, 0x20, 0xfec80400);
#else
smp_write_ioapic(mc, 4, 0x20, 0xfec00000);
smp_write_ioapic(mc, 5, 0x20, 0xfec80000);
smp_write_ioapic(mc, 8, 0x20, 0xfec80400);
#endif
smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x00, 0x02, 0x00);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x01, 0x02, 0x01);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x00, 0x02, 0x02);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x03, 0x02, 0x03);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x04, 0x02, 0x04);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x05, 0x02, 0x05);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x06, 0x02, 0x06);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x00, 0x76, 0x02, 0x12);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x08, 0x02, 0x08);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x09, 0x02, 0x09);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x00, 0x75, 0x02, 0x13);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x00, 0x74, 0x02, 0x10);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, 0x08, 0x02, 0x11);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x0d, 0x02, 0x0d);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x0e, 0x02, 0x0e);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x0f, 0x02, 0x0f);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x03, 0x04, 0x03, 0x00);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x03, 0x10, 0x03, 0x07);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, 0x04, 0x02, 0x10);
smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x00, MP_APIC_ALL, 0x00);
smp_write_lintsrc(mc, mp_NMI, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x00, MP_APIC_ALL, 0x01);
#if 0
/* Onboard ich2 soutbhridge */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x00, (0x1f << 2)|3, 0x02, 0x13);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x00, (0x1f << 2)|2, 0x02, 0x17);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x00, (0x1f << 2)|1, 0x02, 0x11);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x00, (0x1f << 2)|0, 0x02, 0x10);
/* agp slot */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x01, 0x00, 0x02, 0x16);
/* Onboard PCI NIC */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (4 <<2)|0, 0x02, 0x10);
/* Four standard PCI slots */
/* Slot 1 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (7 <<2)|0, 0x02, 0x10);
/* Slot 2 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (1 <<2)|0, 0x02, 0x11);
/* Slot 3 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (2 <<2)|0, 0x02, 0x12);
/* Slot 4 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x04, (3 <<2)|0, 0x02, 0x13);
/* Two 64 bit PCI slots */
/* Slot 1 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x03, (1 <<2)|0, 0x02, 0x12);
/* Slot 2 */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x03, (2 <<2)|0, 0x02, 0x12);
/* Two SCSI */
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x03, (4 <<2)|0, 0x02, 0x12);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_LEVEL|MP_IRQ_POLARITY_LOW,
0x03, (4 <<2)|1, 0x02, 0x12);
/* ISA backward compatibility interrupts */
smp_write_intsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x00, 0x02, 0x00);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x01, 0x02, 0x01);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x00, 0x02, 0x02);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x03, 0x02, 0x03);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x04, 0x02, 0x04);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x06, 0x02, 0x06);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x07, 0x02, 0x07);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_EDGE|MP_IRQ_POLARITY_HIGH,
0x05, 0x08, 0x02, 0x08);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x0d, 0x02, 0x0d);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x0e, 0x02, 0x0e);
smp_write_intsrc(mc, mp_INT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x05, 0x0f, 0x02, 0x0f);
/* Standard local interrupt assignments */
smp_write_lintsrc(mc, mp_ExtINT, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x00, 0x00, MP_APIC_ALL, 0x00);
smp_write_lintsrc(mc, mp_NMI, MP_IRQ_TRIGGER_DEFAULT|MP_IRQ_POLARITY_DEFAULT,
0x00, 0x00, MP_APIC_ALL, 0x01);
#endif
/* 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

@ -1,63 +1,277 @@
##
## Set all of the defaults for an x86 architecture
##
arch i386
##
## 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
mainboardinit cpu/i386/reset16.inc
ldscript cpu/i386/reset16.lds
mainboardinit northbridge/amd/amd76x/reset_test.inc
##
## Build our reset vector (This is where linuxBIOS is entered)
##
mainboardinit cpu/i386/reset16.inc USE_FALLBACK_IMAGE
ldscript cpu/i386/reset16.lds USE_FALLBACK_IMAGE
mainboardinit cpu/i386/reset32.inc USE_NORMAL_IMAGE
ldscript cpu/i386/reset32.lds USE_NORMAL_IMAGE
##
## 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.
###
#mainboardinit northbridge/amd/amd76x/reset_test.inc
#mainboardinit arch/i386/lib/noop_failover.inc
#mainboardinit arch/i386/lib/noop_failover.inc USE_NORMAL_IMAGE
#mainboardinit southbridge/amd/amd766/cmos_reset_failover.inc USE_FALLBACK_IMAGE
ldscript arch/i386/lib/failover.lds USE_FALLBACK_IMAGE
##
## We aren't a reset so shutdown the second cpu if present.
##
##
## Setup our mtrrs
##
mainboardinit cpu/k7/earlymtrr.inc
mainboardinit northbridge/amd/amd76x/mpinit.inc
#mainboardinit southbridge/amd/amd766/disable_watchdog.inc
##
## Initialize the processor busses
##
mainboardinit northbridge/amd/amd76x/mpinit.inc USE_FALLBACK_IMAGE
##
## Only the bootstrap cpu makes it here.
## Failover if we need to
##
mainboardinit southbridge/amd/amd766/cmos_boot_failover.inc USE_FALLBACK_IMAGE
###
### O.k. We aren't just an intermediary anymore!
###
##
## When debugging disable the watchdog timer
##
option MAXIMUM_CONSOLE_LOGLEVEL=7
expr DISABLE_WATCHDOG= MAXIMUM_CONSOLE_LOGLEVEL >= 8
mainboardinit southbridge/amd/amd766/disable_watchdog.inc DISABLE_WATCHDOG
##
## Setup the serial port
##
mainboardinit southbridge/amd/amd766/lpc_com1.inc
mainboardinit superio/winbond/w83627hf/setup_serial.inc
mainboardinit pc80/serial.inc
mainboardinit arch/i386/lib/console.inc
##
## Setup RAM
##
#mainboardinit ram/ramtest.inc
#mainboardinit mainboard/tyan/guiness/do_ramtest.inc
mainboardinit southbridge/amd/amd766/smbus.inc
#mainboardinit sdram/generic_dump_spd.inc
mainboardinit mainboard/tyan/guiness/mainboard_raminit.inc
##
## Include the secondary Configuration files
##
northbridge amd/amd76x
#mainboardinit mainboard/tyan/guiness/do_ramtest.inc
#mainboardinit cpu/k7/earlymtrr.inc
southbridge amd/amd766
nsuperio winbond/w83627hf com1={1} com2={0} floppy=1 lpt=1
option RAMTEST=1
option NO_KEYBOARD
option ENABLE_FIXED_AND_VARIABLE_MTRRS
#option FINAL_MAINBOARD_FIXUP
object mainboard.o
object mptable.o HAVE_MP_TABLE
#object irq_tables.o
#keyboard pc80
mainboardinit arch/i386/smp/secondary.inc
nsuperio winbond/w83627hf com1={1} com2={0} floppy=1 lpt=1 keyboard=1
dir ../../../pc80
option AMD766_DEV=0x3800
# FIXME are the SMBUS DIMM locations documented anywhere?
option SMBUS_MEM_DEVICE_START=(0xa << 3)
option SMBUS_MEM_DEVICE_END=(SMBUS_MEM_DEVICE_START +3)
option SMBUS_MEM_DEVICE_INC=1
option SIO_BASE=0x2e
option SMP=1
option IOAPIC=1
option MAX_CPUS=2
option HAVE_MP_TABLE=1
option USE_AMD_NDA_CODE=1
option FINAL_MAINBOARD_FIXUP=1
option HAVE_HARD_RESET=1
option STACK_SIZE=0x10000
option XIP_ROM_SIZE=0x8000
option XIP_ROM_BASE=0xffff8000
nooption MEMORY_HOLE
dir /src/superio/winbond/w83627hf
cpu p5
cpu p6
cpu k7
##
## Build the objects we have code for in this directory.
##
object mainboard.o
object mptable.o HAVE_MP_TABLE
#object irq_tables.o HAVE_PIRQ_TABLE
###
### Build options
###
##
## Location of the DIMM EEPROMS on the SMBUS
## This is fixed into a narrow range by the DIMM package standard.
##
option SMBUS_MEM_DEVICE_START=(0xa << 3)
option SMBUS_MEM_DEVICE_END=(SMBUS_MEM_DEVICE_START +3)
option SMBUS_MEM_DEVICE_INC=1
##
## Customize our winbond superio chip for this motherboard
##
option SIO_BASE=0x2e
nooption SIO_SYSTEM_CLK_INPUT
##
## Build code for the fallback boot
##
option HAVE_FALLBACK_BOOT=1
##
## Build code to reset the motherboard from linuxBIOS
##
option HAVE_HARD_RESET=1
##
## Build code to export a programmable irq routing table
##
#option HAVE_PIRQ_TABLE=1
##
## Build code to export an x86 MP table
## Useful for specifying IRQ routing values
##
option HAVE_MP_TABLE=1
##
## Do not build special code for the keyboard
##
option NO_KEYBOARD=1
##
## Build code to export a CMOS option table
##
option HAVE_OPTION_TABLE=1
##
## Build code for SMP support
## Only worry about 2 micro processors
##
option SMP=1
option MAX_CPUS=2
##
## Build code to setup a generic IOAPIC
##
option IOAPIC=1
##
## MEMORY_HOLE instructs earlymtrr.inc to
## enable caching from 0-640KB and to disable
## caching from 640KB-1MB using fixed MTRRs
##
## Enabling this option breaks SMP because secondary
## CPU identification depends on only variable MTRRs
## being enabled.
##
nooption MEMORY_HOLE
##
## Enable both fixed and variable MTRRS
## When we setup MTRRs in mtrr.c
##
## We must setup the fixed mtrrs or we confuse SMP secondary
## processor identification
##
option ENABLE_FIXED_AND_VARIABLE_MTRRS=1
##
## Clean up the motherboard id strings
##
option MAINBOARD_PART_NUMBER=THUNDER K7
option MAINBOARD_VENDOR=Tyan
##
## Let Assembly code know where on the pci bus the AMD southbridge is
##
option AMD766_DEV=0x3800
##
## Call the final_mainboard_fixup function
##
option FINAL_MAINBOARD_FIXUP=1
##
## Figure out which type of linuxBIOS image to build
## If we aren't a fallback image we must be a normal image
## This is useful for optional includes
##
option USE_FALLBACK_IMAGE=0
expr USE_NORMAL_IMAGE=!USE_FALLBACK_IMAGE
###
### LinuxBIOS layout values
###
## ROM_SIZE is the size of boot ROM that this board will use.
option ROM_SIZE=524288
## ROM_IMAGE_SIZE is the amount of space to allow linuxBIOS to occupy.
option ROM_IMAGE_SIZE=49152
##
## Use a small 8K stack
##
option STACK_SIZE=0x2000
##
## Use a small 8K heap
##
option HEAP_SIZE=0x2000
##
## Only use the option table in a normal image
##
expr USE_OPTION_TABLE=!USE_FALLBACK_IMAGE
##
## Compute the location and size of where this firmware image
## (linuxBIOS plus bootloader) will live in the boot rom chip.
##
expr ROM_SECTION_SIZE =(USE_FALLBACK_IMAGE*65536)+(USE_NORMAL_IMAGE*(ROM_SIZE - 65536))
expr ROM_SECTION_OFFSET=(USE_FALLBACK_IMAGE*(ROM_SIZE-65536))+(USE_NORMAL_IMAGE*0)
##
## Compute the start location and size size of
## The linuxBIOS bootloader.
##
expr ZKERNEL_START =(0xffffffff - ROM_SIZE + ROM_SECTION_OFFSET + 1)
expr PAYLOAD_SIZE =ROM_SECTION_SIZE - ROM_IMAGE_SIZE
##
## Compute where this copy of linuxBIOS will start in the boot rom
##
expr _ROMBASE =ZKERNEL_START + PAYLOAD_SIZE
##
## Compute a range of ROM that can cached to speed up linuxBIOS,
## execution speed.
##
#expr XIP_ROM_SIZE = 65536
#expr XIP_ROM_BASE = _ROMBASE + ROM_IMAGE_SIZE - XIP_ROM_SIZE
#option XIP_ROM_SIZE=65536
#option XIP_ROM_BASE=0xffff0000
# XIP_ROM_SIZE && XIP_ROM_BASE values that work.
#option XIP_ROM_SIZE=0x8000
#option XIP_ROM_BASE=0xffff8000
##
## Compute where the SMP startup code needs to live
## FIXME I don't see how to make this work for the normal image....
##
option START_CPU_SEG=0xf0000

View file

@ -7,6 +7,11 @@
#include <part/hard_reset.h>
#include <arch/smp/mpspec.h>
#include <pc80/mc146818rtc.h>
#include <pc80/isa_dma.h>
#include <superio/w83627hf.h>
#include <superio/generic.h>
#include <southbridge/amd/amd766.h>
#include <northbridge/amd/amd76x.h>
unsigned long initial_apicid[MAX_CPUS] =
{
@ -51,51 +56,6 @@ static void lpc_routing_fixup(void)
}
static void enable_ioapic(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410,0);
if (dev != NULL) {
/* Enable the ioapic */
pci_write_config_byte(dev, 0x4b, (0 << 3)|(0 <<2)|(0 << 1)|(1<< 0));
}
}
static void serial_irq_fixup(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
if (dev != NULL) {
/* Setup serial irq's for the LPC bus. */
pci_write_config_byte(dev, 0x4a, (1<<6)|(0<<2)|(0<<0));
}
}
static void mouse_sends_irq12(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
if (dev != NULL) {
unsigned short word;
/* Setup so irq12 is sent by the ps2 mouse port. */
pci_read_config_word(dev, 0x46, &word);
pci_write_config_word(dev, 0x46, word | (1<<9));
}
}
static void disable_watchdog(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
if (dev != NULL) {
unsigned char byte;
/* Disable the watchdog timer */
pci_read_config_byte(dev, 0x41, &byte);
pci_write_config_byte(dev, 0x41, byte | (1<<6)|(1<<2));
}
}
static void enable_reset_port_0xcf9(void)
{
/* FIXME this code is correct but the bit isn't getting set on my test machine. */
@ -109,17 +69,6 @@ static void enable_reset_port_0xcf9(void)
}
}
static void enable_port92_reset(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
if (dev != NULL) {
unsigned char byte;
/* Enable reset using port 0x92 */
pci_read_config_byte(dev, 0x41, &byte);
pci_write_config_byte(dev, 0x41, byte | (1<<5));
}
}
static void print_whami(void)
{
@ -136,193 +85,6 @@ static void print_whami(void)
}
#define IDE_ERR_ICRC 0x80 /* ATA Ultra DMA bad CRC */
#define IDE_ERR_BBK 0x80 /* ATA bad block */
#define IDE_ERR_UNC 0x40 /* ATA uncorrected error */
#define IDE_ERR_MC 0x20 /* ATA media change */
#define IDE_ERR_IDNF 0x10 /* ATA id not found */
#define IDE_ERR_MCR 0x08 /* ATA media change request */
#define IDE_ERR_ABRT 0x04 /* ATA command aborted */
#define IDE_ERR_NTK0 0x02 /* ATA track 0 not found */
#define IDE_ERR_NDAM 0x01 /* ATA address mark not found */
#define IDE_STATUS_BSY 0x80 /* busy */
#define IDE_STATUS_RDY 0x40 /* ready */
#define IDE_STATUS_DF 0x20 /* device fault */
#define IDE_STATUS_WFT 0x20 /* write fault (old name) */
#define IDE_STATUS_SKC 0x10 /* seek complete */
#define IDE_STATUS_DRQ 0x08 /* data request */
#define IDE_STATUS_CORR 0x04 /* corrected */
#define IDE_STATUS_IDX 0x02 /* index */
#define IDE_STATUS_ERR 0x01 /* error (ATA) */
#define IDE_STATUS_CHK 0x01 /* check (ATAPI) */
#define IDE_CTRL_HD15 0x08 /* bit should always be set to one */
#define IDE_CTRL_SRST 0x04 /* soft reset */
#define IDE_CTRL_NIEN 0x02 /* disable interrupts */
/* Most mandtory and optional ATA commands (from ATA-3), */
#define IDE_CMD_CFA_ERASE_SECTORS 0xC0
#define IDE_CMD_CFA_REQUEST_EXT_ERR_CODE 0x03
#define IDE_CMD_CFA_TRANSLATE_SECTOR 0x87
#define IDE_CMD_CFA_WRITE_MULTIPLE_WO_ERASE 0xCD
#define IDE_CMD_CFA_WRITE_SECTORS_WO_ERASE 0x38
#define IDE_CMD_CHECK_POWER_MODE1 0xE5
#define IDE_CMD_CHECK_POWER_MODE2 0x98
#define IDE_CMD_DEVICE_RESET 0x08
#define IDE_CMD_EXECUTE_DEVICE_DIAGNOSTIC 0x90
#define IDE_CMD_FLUSH_CACHE 0xE7
#define IDE_CMD_FORMAT_TRACK 0x50
#define IDE_CMD_IDENTIFY_DEVICE 0xEC
#define IDE_CMD_IDENTIFY_DEVICE_PACKET 0xA1
#define IDE_CMD_IDENTIFY_PACKET_DEVICE 0xA1
#define IDE_CMD_IDLE1 0xE3
#define IDE_CMD_IDLE2 0x97
#define IDE_CMD_IDLE_IMMEDIATE1 0xE1
#define IDE_CMD_IDLE_IMMEDIATE2 0x95
#define IDE_CMD_INITIALIZE_DRIVE_PARAMETERS 0x91
#define IDE_CMD_INITIALIZE_DEVICE_PARAMETERS 0x91
#define IDE_CMD_NOP 0x00
#define IDE_CMD_PACKET 0xA0
#define IDE_CMD_READ_BUFFER 0xE4
#define IDE_CMD_READ_DMA 0xC8
#define IDE_CMD_READ_DMA_QUEUED 0xC7
#define IDE_CMD_READ_MULTIPLE 0xC4
#define IDE_CMD_READ_SECTORS 0x20
#define IDE_CMD_READ_VERIFY_SECTORS 0x40
#define IDE_CMD_RECALIBRATE 0x10
#define IDE_CMD_SEEK 0x70
#define IDE_CMD_SET_FEATURES 0xEF
#define IDE_CMD_SET_MULTIPLE_MODE 0xC6
#define IDE_CMD_SLEEP1 0xE6
#define IDE_CMD_SLEEP2 0x99
#define IDE_CMD_STANDBY1 0xE2
#define IDE_CMD_STANDBY2 0x96
#define IDE_CMD_STANDBY_IMMEDIATE1 0xE0
#define IDE_CMD_STANDBY_IMMEDIATE2 0x94
#define IDE_CMD_WRITE_BUFFER 0xE8
#define IDE_CMD_WRITE_DMA 0xCA
#define IDE_CMD_WRITE_DMA_QUEUED 0xCC
#define IDE_CMD_WRITE_MULTIPLE 0xC5
#define IDE_CMD_WRITE_SECTORS 0x30
#define IDE_CMD_WRITE_VERIFY 0x3C
static void reset_ide_controller(unsigned ide_ctl, unsigned ide_data)
{
unsigned char status, error;
printk_spew("resetting ide controller at 0x%04x\n", ide_ctl);
outb(IDE_CTRL_HD15 | IDE_CTRL_SRST | IDE_CTRL_NIEN, ide_ctl);
printk_spew("1\n");
udelay(25);
printk_spew("2\n");
outb(IDE_CTRL_HD15 | IDE_CTRL_NIEN, ide_ctl);
printk_spew("3\n");
do {
mdelay(2);
printk_spew("4\n");
error = inb_p(ide_data+1);
status = inb_p(ide_data+7);
printk_spew("error = 0x%02x status = 0x%02x\n", error, status);
} while(status & IDE_STATUS_BSY);
printk_spew("reset ide controller at 0x%04x\n", ide_ctl);
}
static void setup_ide_devices(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, 0);
if (dev != NULL) {
/* Enable ide devices so the linux ide driver will work */
u16 word;
pci_read_config_word(dev, 0x40, &word);
/* enable:
* both devices
* both devices posted write buffers
*/
pci_write_config_word(dev, 0x40, word |(1<<14)|(1<<12)|(1<<1)|(1<<0));
#if 1
/* Setup the appropriate ide timing */
pci_write_config_dword(dev, 0x48, 0x5e5e5e5e);
pci_write_config_byte(dev, 0x4c, 0xaa);
#endif
#if 0
/* Enable native ide native mode, at the legacy addresses */
/* This would be cool if I could receive an interrupt from
* the ide controller.
*/
{
u32 class_revision;
pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_revision);
pci_write_config_dword(dev, PCI_CLASS_REVISION,
class_revision | ( 1 << 8) | (1 << 10));
pci_write_config_dword(dev, PCI_BASE_ADDRESS_0,
0x1f0 | PCI_BASE_ADDRESS_SPACE_IO);
pci_write_config_dword(dev, PCI_BASE_ADDRESS_1,
0x3f6 | PCI_BASE_ADDRESS_SPACE_IO);
pci_write_config_dword(dev, PCI_BASE_ADDRESS_2,
0x170 | PCI_BASE_ADDRESS_SPACE_IO);
pci_write_config_dword(dev, PCI_BASE_ADDRESS_3,
0x376 | PCI_BASE_ADDRESS_SPACE_IO);
}
#endif
}
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
if (dev != NULL) {
unsigned char byte;
/* optimize ide dma acknowledge */
pci_read_config_byte(dev, 0x4a, &byte);
pci_write_config_byte(dev, 0x4a, byte & ~(1<<7));
}
}
static void enable_ide_devices(void)
{
u32 ide0_data = 0, ide0_ctl = 0, ide1_data = 0, ide1_ctl = 0, dma_base = 0;
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, 0);
if (dev != NULL) {
ide0_data = 0x1f0;
ide0_ctl = 0x3f6;
ide1_data = 0x170;
ide1_ctl = 0x376;
pci_read_config_dword(dev, PCI_BASE_ADDRESS_4, &dma_base);
if (dma_base & PCI_BASE_ADDRESS_SPACE_IO) {
dma_base &= ~PCI_BASE_ADDRESS_SPACE_IO;
} else {
dma_base = 0;
}
}
#if 0
/* IDE resets take forever, plus my reset code looks broken... */
if (ide0_data && ide0_ctl) {
reset_ide_controller(ide0_ctl,ide0_data + 7);
}
if (ide0_data && ide1_ctl) {
reset_ide_controller(ide1_ctl, ide1_data + 7);
}
#endif
if (dma_base) {
printk_debug("ide dma_base = 0x%08lx\n", dma_base);
#if 1
/* Disable DMA */
outb_p(inb_p(dma_base + 2) & ~((1<<5)|(1<<6)), dma_base +2);
outb_p(inb_p(dma_base+8 + 2) & ~((1<<5)|(1<<6)), dma_base+8 +2);
#endif
#if 0
/* Enable DMA */
outb_p(inb_p(dma_base + 2) | ((1<<5)|(1<<6)), dma_base +2);
outb_p(inb_p(dma_base+8 + 2) | ((1<<5)|(1<<6)), dma_base+8 +2);
#endif
}
}
static void fixup_adaptec_7899P(struct pci_dev *pdev)
{
@ -355,72 +117,27 @@ static void onboard_scsi_fixup(void)
}
static void cpu_reset_sends_init(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
if (dev != NULL) {
unsigned char byte;
pci_read_config_byte(dev, 0x47, &byte);
pci_write_config_byte(dev, 0x47, byte | (1<<7));
}
#define MAINBOARD_POWER_OFF 0
#define MAINBOARD_POWER_ON 1
}
static void decode_stop_grant_fixup(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
if (dev != NULL) {
unsigned char byte;
pci_read_config_byte(dev, 0x41, &byte);
pci_write_config_byte(dev, 0x41, byte | (1<<1));
}
}
static void pm_controller_classcode_fixup(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
if (dev != NULL) {
pci_write_config_dword(dev, 0x60, 0x06800000);
}
}
#if 0
static void set_power_on_after_power_fail(int enable)
{
/* FIXME: This may be part of the picture but it isn't
* the whole story :(
*/
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
if (dev != NULL) {
unsigned char byte;
pci_read_config_byte(dev, 0x43, &byte);
if (enable) {
byte &= ~(1<<6);
}
else {
byte |= (1<<6);
}
pci_write_config_byte(dev, 0x43, byte);
}
}
#ifndef MAINBOARD_POWER_ON_AFTER_POWER_FAIL
#define MAINBOARD_POWER_ON_AFTER_POWER_FAIL MAINBOARD_POWER_ON
#endif
static void posted_memory_write_enable(void)
static void set_power_on_after_power_fail(int setting)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
if (dev != NULL) {
unsigned char byte;
pci_read_config_byte(dev, 0x46, &byte);
pci_write_config_byte(dev, 0x46, byte | (1<<0));
}
switch(setting) {
case MAINBOARD_POWER_ON:
default:
amd766_power_after_power_fail(1);
w832627hf_power_after_power_fail(POWER_ON);
break;
case MAINBOARD_POWER_OFF:
amd766_power_after_power_fail(0);
w832627hf_power_after_power_fail(POWER_OFF);
break;
}
}
static void setup_pci_irq_to_isa_routing(void)
@ -438,48 +155,6 @@ static void setup_pci_irq_to_isa_routing(void)
}
}
static void setup_pci_arbiter(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, 0);
if (dev) {
/* Enable:
* PCI parking
* memory prefetching
* EV6 mode
* Enable power management registers
* The southbridge lock
* Read data error disable
* PCI retries
* AGP retries
* AGP chaining
* PCI chaining
*/
pci_write_config_dword(dev, 0x84,
(0<<24)
|(1<<23)
|(1<<17)|(1<<16)
|(0<<15)|(1<<14)|(1<<13)|(1<<12)
|(0<<11)|(0<<10)|(0<<9)|(0<<8)
|(1<<7)|(0<<6)|(0<<5)|(1<<4)
|(0<<3)|(1<<2)|(1<<1)|(1<<0));
}
}
static void usb_setup(void)
{
/* FIXME this is untested incomplete implementation. */
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7414, 0);
if (dev) {
u32 cmd;
pci_read_config_dword(dev, PCI_COMMAND, &cmd);
pci_write_config_dword(dev, PCI_COMMAND,
cmd | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
}
}
static void hide_devices(void)
{
struct pci_dev *dev;
@ -504,30 +179,34 @@ static void hide_devices(void)
void mainboard_fixup(void)
{
disable_watchdog();
int power_on_after_power_fail;
amd766_disable_watchdog();
lpc_routing_fixup();
enable_ioapic();
serial_irq_fixup();
amd766_enable_ioapic();
amd766_enable_serial_irqs(1, 0, 0);
enable_reset_port_0xcf9();
enable_port92_reset();
amd766_enable_port92_reset();
#if 0
print_whami();
#endif
setup_ide_devices();
amd766_enable_ide(1,1);
onboard_scsi_fixup();
cpu_reset_sends_init();
amd766_cpu_reset_sends_init();
rtc_init(0);
decode_stop_grant_fixup();
posted_memory_write_enable();
pm_controller_classcode_fixup();
#if 1
mouse_sends_irq12();
#endif
amd766_decode_stop_grant(DECODE_STPGNT_DATA);
amd766_posted_memory_write_enable();
amd766_set_pm_classcode();
amd766_mouse_sends_irq12();
setup_pci_irq_to_isa_routing();
setup_pci_arbiter();
amd76x_setup_pci_arbiter();
isa_dma_init();
power_on_after_power_fail = MAINBOARD_POWER_ON_AFTER_POWER_FAIL;
get_option(&power_on_after_power_fail, "power_on_after_fail");
set_power_on_after_power_fail(power_on_after_power_fail);
#if 0
usb_setup();
amd766_usb_setup();
#endif
#if 0
hide_devices();
@ -537,17 +216,12 @@ void mainboard_fixup(void)
void final_mainboard_fixup(void)
{
#if 1
#if 0
enable_ide_devices();
#endif
}
void hard_reset(void)
{
pci_set_method();
/* Allow the watchdog timer to reboot us, and enable 0xcf9 */
pcibios_write_config_byte(0, (AMD766_DEV >> 8) | 3, 0x41, (1<<5)|(1<<1));
/* Try rebooting though port 0xcf9 */
outb((0<<3)|(1<<2)|(1<<1), 0xcf9);
return;
amd766_hard_reset();
}

View file

@ -3,12 +3,16 @@
#include <printk.h>
#include <cpu/p6/apic.h>
#define __STR(X) #X
#define STR(X) __STR(X)
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] = "GUINESS ";
static const char oem[] = STR(MAINBOARD_VENDOR);
static const char productid[12] = STR(MAINBOARD_PART_NUMBER);
struct mp_config_table *mc;
int len;
mc = (void *)(((char *)v) + SMP_FLOATING_TABLE_LEN);
memset(mc, 0, sizeof(*mc));
@ -17,8 +21,12 @@ void *smp_write_config_table(void *v, unsigned long * processor_map)
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));
memset(mc->mpc_oem, ' ', sizeof(mc->mpc_oem));
len = strnlen(oem, sizeof(mc->mpc_oem));
memcpy(mc->mpc_oem, oem, len);
memset(mc->mpc_productid, ' ', sizeof(mc->mpc_productid));
len = strnlen(productid, sizeof(mc->mpc_productid));
memcpy(mc->mpc_productid, productid, len);
mc->mpc_oemptr = 0;
mc->mpc_oemsize = 0;
mc->mpc_entry_count = 0; /* No entries yet... */

View file

@ -4,4 +4,5 @@ mainboardinit sdram/generic_sdram.inc
mainboardinit sdram/generic_zero_ecc_sdram.inc
mainboardinit arch/i386/lib/cpu_reset.inc
object northbridge.o
object northbridge.o
object amd76x_pci.o

View file

@ -0,0 +1,34 @@
#include <pci.h>
#include <pci_ids.h>
#include <northbridge/amd/amd76x.h>
/* FIXME add support for 66Mhz pci */
void amd76x_setup_pci_arbiter(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_FE_GATE_700C, 0);
if (dev) {
/* Enable:
* PCI parking
* memory prefetching
* EV6 mode
* Enable power management registers
* The southbridge lock
* Read data error disable
* PCI retries
* AGP retries
* AGP chaining
* PCI chaining
*/
pci_write_config_dword(dev, 0x84,
(0<<24)
|(1<<23)
|(1<<17)|(1<<16)
|(0<<15)|(1<<14)|(1<<13)|(1<<12)
|(0<<11)|(0<<10)|(0<<9)|(0<<8)
|(1<<7)|(0<<6)|(0<<5)|(1<<4)
|(0<<3)|(1<<2)|(1<<1)|(1<<0));
}
}

View file

@ -106,8 +106,20 @@
movl %eax, %esi
andl $0xf, %esi
#if defined(USE_AMD_NDA_CODE)
#endif
/* Set the processor id. */
movl $HWCR_MSR, %ecx
rdmsr
andl $0x0FFFFFFF, %eax
shll $28, %esi
orl %esi, %eax
shrl $28, %esi
/* Enable SSE detection */
andl $(~(1<<15)), %eax
/* Set PFER */
orl $(1<<12), %eax
/* Say the page tables live in cachable memory */
orl $(1<< 3), %eax
wrmsr
/* Figure out how many unacknowledged acks
@ -132,8 +144,12 @@
/* Tell the processor how many unacknoledged probes the AMD762 can
* support
*/
#if defined(USE_AMD_NDA_CODE)
#endif /* USE_AMD_NDA_CODE */
movl $SYSCFG_MSR, %ecx
rdmsr
andl $(~(0x1f<< 0)), %eax
andl $0x1f, %ebp
orl %ebp, %eax
wrmsr
/* Enable the local apic, and map it where we expect it. */
movl $APIC_BASE_MSR, %ecx

View file

@ -4,7 +4,7 @@
unsigned long sizeram(void)
{
unsigned long size;
u32 size;
/* Use the PCI top memory register */
pcibios_read_config_dword(0, 0, 0x9c, &size);
/* Convert size in bytes to size in K */

View file

@ -217,11 +217,7 @@ constant_register_values:
* [01:01] 1 == PCI Ordering Rules Compliance Enable
* [00:00] 1 == Function 1 Enable
*/
#if 0
.long 0x4C, (1 << 2)|(1 << 1)|(1 << 0)
#else
.long 0x4C, (0 << 2)|(0 << 1)|(1 << 0)
#endif
#if 0 /* Calculated via SPD */
/* DRAM Timing
* 0x54

View file

@ -5,4 +5,4 @@
movl $0x58, %eax
PCI_READ_CONFIG_DWORD
testl $(1<<25), %eax
jnz __cpu_reset
jnz __cpu_reset

View file

@ -6,9 +6,25 @@ set_memory_size:
movl $0x9c, %eax
PCI_READ_CONFIG_DWORD
#if USE_AMD_NDA_CODE
#endif /* USE_AMD_NDA_CODE */
/* Set the Athlon Top of memory MSR */
xorl %edx, %edx
movl $TOP_MEM, %ecx
wrmsr
movl $TOP_MEM2, %ecx
wrmsr
/* Clear the IOrr's */
xorl %edx, %edx
xorl %eax, %eax
movl $IORR0_BASE, %ecx
wrmsr
movl $IORR0_MASK, %ecx
wrmsr
movl $IORR1_BASE, %ecx
wrmsr
movl $IORR1_MASK, %ecx
wrmsr
set_memory_size_end:
RETSP
set_memory_size_out:
set_memory_size_out:

View file

@ -269,7 +269,7 @@ void display_smbus_spd(void)
unsigned char byte;
status = smbus_read_byte(j, i, &byte);
if (status != 0) {
printk_debug("bad device\n");
printk_debug("ram slot empty or bad device\n");
continue;
}
printk_debug("0x%02x ", byte);
@ -279,6 +279,7 @@ void display_smbus_spd(void)
}
}
printk_debug("\n");
}
void display_mch_regs(void)

View file

@ -16,6 +16,8 @@
#include <superio/w83627hf.h>
#include <northbridge/intel/82860/rdram.h>
#include <pc80/mc146818rtc.h>
#include <part/fallback_boot.h>
#define LPC_BUS 0
#define LPC_DEVFN ((0x1f << 3) + 0)
@ -37,6 +39,7 @@
#define TSCYCLE_SLOW 1000 /* ns */
#define TSCYCLE_FAST 10 /* ns */
void ndelay(unsigned long);
void delay(unsigned long);
#define I860_MCH_BUS 0
#define I860_MCH_DEVFN 0
@ -343,7 +346,7 @@ static void set_init_bits(int rdram_devices)
}
}
static void rdram_read_domain_initialization(int rdram_devices)
static int rdram_read_domain_initialization(int rdram_devices)
{
u8 rdt=0x8d;
int i,j,k;
@ -371,6 +374,14 @@ static void rdram_read_domain_initialization(int rdram_devices)
mem[k]=data;
}
printk_debug("Device = %d, %x, %x\n",j,mem[0],mem[4]);
if((mem[0]==0)||(mem[0]>8)){
printk_err("ERROR - Invalid memory read device %d, channel A\n",j);
return(j);
}
if((mem[4]==0)||(mem[4]>8)){
printk_err("ERROR - Invalid memory read device %d, channel B\n",j);
return(j+(1<<8));
}
adj_a[j]=(mem[0]&0x0ff)-1;
adj_b[j]=(mem[4]&0x0ff)-1;
if(adj_a[j]<l) l=adj_a[j];
@ -409,7 +420,8 @@ static void rdram_read_domain_initialization(int rdram_devices)
rdram_run_command(0, 0, CMD_MCH_RAC_LOAD_RACA_CONFIG);
rdram_run_command(0, 0, CMD_MCH_RAC_LOAD_RACB_CONFIG);
#endif
return(0);
}
static void rdram_set_clear_reset(void)
@ -425,10 +437,12 @@ static void rdram_set_clear_reset(void)
tcycle=(999+spd_mhz_min[0])/spd_mhz_min[0];
delay=tcycle*2816;
}
if(delay>(16*TSCYCLE_SLOW))
if(delay>(16*TSCYCLE_SLOW)) {
ndelay(delay);
else
}
else {
ndelay(16*TSCYCLE_SLOW);
}
rdram_run_command(0, BCAST, CMD_RDRAM_CLEAR_RESET);
rdram_write_reg(0, BCAST, REG_TEST34, 0, 0);
rdram_write_reg(0, BCAST, REG_TEST78, 0, 0);
@ -771,13 +785,52 @@ static void ram_zap(unsigned long start, unsigned long stop)
}
void init_memory(void)
void rdram_calibrate(void)
{
int i,j;
/* 5. Rdram Current Control */
/* You can disable the final memory initialized bit
* to see if this is working and it isn't!
* It is close though.
* FIXME manual current calibration.
*/
rdram_run_command(0, 0, CMD_MCH_RAC_CURRENT_CALIBRATION);
/* Do not do the following command. It will cause a lock up */
/* rdram_run_command(0, 0, CMD_MANUAL_CURRENT_CALIBRATION); */
for(i = 0; i < 128; i++) {
for(j=0;j<rdram_chips;j++) {
rdram_run_command(0, j, CMD_RDRAM_CURRENT_CALIBRATION);
}
}
rdram_run_command(0, BCAST, CMD_TEMP_CALIBRATE_ENABLE);
rdram_run_command(0, BCAST, CMD_TEMP_CALIBRATE);
#if 0
display_rdram_regs( rdram_chips );
#endif
/* 6.1 RDRAM Core Initialization */
for(i = 0; i < 192; i++) {
rdram_run_command(0, BCAST, CMD_RDRAM_REFRESH);
}
}
void init_memory(void)
{
int i,j,k;
int status;
int ecc=1;
int rdram_devices=0;
u32 ricm;
u16 word;
unsigned char byte;
char manufact[8];
unsigned char m_year, m_week, m_location;
load_spd_vars();
display_spd_dev_row_col_bank(spd_devices, spd_row_col, spd_banks);
@ -788,7 +841,7 @@ void init_memory(void)
rdram_devices+=spd_devices[i];
}
if(rdram_devices==0){
printk_debug("ERROR - Memory Rimms are not matched.\n");
printk_err("ERROR - Invalid Rimm configuration.\n");
for(;;) i=1; /* Freeze the system error */
}
else {
@ -808,38 +861,67 @@ void init_memory(void)
/* 4. Initialize Memory Controller */
mch_init();
/* 6.1 RDRAM Core Initialization */
for(i = 0; i < 192; i++) {
rdram_run_command(0, BCAST, CMD_RDRAM_REFRESH);
}
/* do steps 5. through 6.1 to calibrate
current, temperature, refresh */
rdram_calibrate();
/* set up additional timing for each device */
if(rdram_read_domain_initialization(rdram_devices)) {
/* memory devices could not be read, so re-initialize
and calibrate, then try again */
printk_err("Re-initializing and calibrating ram\n");
rdram_init(rdram_devices);
rdram_calibrate();
if(k=rdram_read_domain_initialization(rdram_devices)) {
/* failed the second time, so halt and
and display ram spd info. */
printk_err("ERROR - Ram failed to write and read\n");
i=k&0x0ff;
j=SMBUS_MEM_DEVICE_0;
if(i<spd_devices[0]){
if((k&0x0f00)==0) {
printk_err("Ram bank 0, channel A, device %d\n",i);
}
else {
printk_err("Ram bank 0, channel B, device %d\n",i);
j+=2;
}
}
else {
i-=spd_devices[0];
if((k&0x0f00)==0) {
printk_err("Ram bank 1, channel A, device %d\n",i);
j++;
}
else {
printk_err("Ram bank 1, channel B, device %d\n",i);
j+=3;
}
}
status = smbus_read_byte(j, 93, &byte);
if (status == 0) {
m_year=byte;
}
status = smbus_read_byte(j, 94, &byte);
if (status == 0) {
m_week=byte;
}
status = smbus_read_byte(j, 72, &byte);
if (status == 0) {
m_location=byte;
}
for(i=65;i<72;i++) {
smbus_read_byte(j, i, &manufact[i-65]);
}
manufact[7]=0;
printk_err("Manufacturer %s year %d week %d location %d\n",
manufact,m_year,m_week,m_location);
/* 5. Rdram Current Control */
/* You can disable the final memory initialized bit
* to see if this is working and it isn't!
* It is close though.
* FIXME manual current calibration.
*/
rdram_run_command(0, 0, CMD_MCH_RAC_CURRENT_CALIBRATION);
/* Do not do the following command. It will cause a lock up */
/* rdram_run_command(0, 0, CMD_MANUAL_CURRENT_CALIBRATION); */
for(i = 0; i < 128; i++) {
for(j=0;j<rdram_chips;j++) {
rdram_run_command(0, j, CMD_RDRAM_CURRENT_CALIBRATION);
for(;;) i=1; /* Freeze the system error */
}
}
#if 0
display_rdram_regs( rdram_chips );
#endif
rdram_run_command(0, BCAST, CMD_TEMP_CALIBRATE_ENABLE);
rdram_run_command(0, BCAST, CMD_TEMP_CALIBRATE);
/* 6.2 RDRAM Read Domain Initialization */
rdram_read_domain_initialization(rdram_devices);
/* 7.0 Remaining init bits (LSR, NSR, PSR) */
set_init_bits(rdram_devices);
@ -851,8 +933,13 @@ void init_memory(void)
MCH_RICM, ricm);
/* Memory Controller Hub Configuration Enable ECC */
get_option(&ecc,"ECC_memory");
if((ecc)&&(spd_data_width[0]==18)) { /* ECC is enables, so turn it on */
if(get_option(&ecc,"ECC_memory"))
ecc=0;
if((ecc)&&(spd_data_width[0]==18)&&
((spd_data_width[1]==18)||(spd_data_width[1]==0))&&
((spd_data_width[2]==18)||(spd_data_width[2]==0))&&
((spd_data_width[3]==18)||(spd_data_width[3]==0))) {
/* ECC is enables, so turn it on */
pcibios_read_config_word(I860_MCH_BUS,I860_MCH_DEVFN,MCH_MCHCFG, &word);
word |= (1 << 8);
pcibios_write_config_word(I860_MCH_BUS,I860_MCH_DEVFN,MCH_MCHCFG,word);

View file

@ -0,0 +1,9 @@
mainboardinit arch/i386/lib/set_memory_size_noop.inc
mainboardinit arch/i386/lib/cpu_reset.inc
mainboardinit northbridge/intel/E7500/raminit.inc
mainboardinit northbridge/intel/E7500/sdram_enable.inc
mainboardinit sdram/generic_sdram.inc
object northbridge.o
#object rdram_setup.o
#object rdram_debug.o

View file

@ -0,0 +1,18 @@
#include <pci.h>
#include <arch/io.h>
#include <part/sizeram.h>
#include <printk.h>
unsigned long sizeram(void)
{
unsigned long size;
unsigned short word;
/* Read TOLM */
/* How should we handle > 4GB of ram? */
pcibios_read_config_word(0, 0, 0xc4, &word);
/* Convert size in 128K bytes to size in K bytes */
size = word << 5;
return size;
}

File diff suppressed because it is too large Load diff

View file

@ -0,0 +1,10 @@
#define MCH_RICM 0x94
#define RICM_DONE (1 << 27)
/* If I have already booted once skip a bunch of initialization */
/* To see if I have already booted I check to see if memory
* has been enabled.
*/
movl $MCH_RICM, %eax
PCI_READ_CONFIG_DWORD
testl $RICM_DONE, %eax
setnz %al

View file

@ -0,0 +1,118 @@
jmp sdram_enable_out
ram_enable_1: .string "Ram Enable 1\r\n"
ram_enable_2: .string "Ram Enable 2\r\n"
ram_enable_3: .string "Ram Enable 3\r\n"
ram_enable_4: .string "Ram Enable 4\r\n"
ram_enable_5: .string "Ram Enable 5\r\n"
/* Estimate that SLOW_DOWN_IO takes about 50&76us*/
/* delay for 200us */
#define DO_DELAY \
movl $16, %edi ; \
1: SLOW_DOWN_IO ; \
decl %edi ; \
jnz 1b
enable_sdram:
/* now the fun begins.
turn on the dram and wait a while (this from the intel book)
turn power on and set the nop bit too
*/
CONSOLE_DEBUG_TX_STRING($ram_enable_1)
/* 1 & 2 Power up and start clocks */
DO_DELAY
DO_DELAY
/* Apply NOP */
SET_RAM_COMMAND(RAM_COMMAND_NOP)
ASSERT_RAM_COMMAND() /* nop command */
DO_DELAY
/* 4 Precharge all */
SET_RAM_COMMAND(RAM_COMMAND_PRECHARGE)
ASSERT_RAM_COMMAND()
/* wait until the all banks idle state... */
CONSOLE_DEBUG_TX_STRING($ram_enable_2)
DO_DELAY
/* 5. Issue EMRS to enable DLL */
SET_RAM_COMMAND(RAM_COMMAND_EMRS)
movl (0x0000<<MD_SHIFT), %eax
DO_DELAY
/* 6. Reset DLL */
SET_RAM_COMMAND(RAM_COMMAND_MRS)
#if 1
movl (((1<<8)|(0<<7)|(5<<4)|(1<<3)|(2<<0))<<MD_SHIFT), %eax
#else
movl (((1<<8)|(0<<7)|(2<<4)|(1<<3)|(3<<0))<<MD_SHIFT), %eax
#endif
DO_DELAY
/* 7 Precharge all */
SET_RAM_COMMAND(RAM_COMMAND_PRECHARGE)
ASSERT_RAM_COMMAND()
DO_DELAY
/* 8 Now we need 8 AUTO REFRESH / CBR cycles to be performed */
#if 0
SET_RAM_COMMAND(RAM_COMMAND_CBR)
ASSERT_RAM_COMMAND()
ASSERT_RAM_COMMAND()
ASSERT_RAM_COMMAND()
ASSERT_RAM_COMMAND()
ASSERT_RAM_COMMAND()
ASSERT_RAM_COMMAND()
ASSERT_RAM_COMMAND()
ASSERT_RAM_COMMAND()
#else
SET_RAM_COMMAND(RAM_COMMAND_CBR)
ASSERT_RAM_COMMAND()
DO_DELAY
SET_RAM_COMMAND(RAM_COMMAND_CBR)
ASSERT_RAM_COMMAND()
DO_DELAY
#endif
CONSOLE_DEBUG_TX_STRING($ram_enable_3)
/* 9 mode register set */
SET_RAM_COMMAND(RAM_COMMAND_MRS)
#if 1
movl (((0<<8)|(0<<7)|(5<<4)|(1<<3)|(2<<0))<<MD_SHIFT), %eax
#else
movl (((0<<8)|(0<<7)|(2<<4)|(1<<3)|(3<<0))<<MD_SHIFT), %eax
#endif
DO_DELAY
/* MAx[14:0] lines,
* MAx[2:0 ] 010 == burst mode of 4
* MAx[3:3 ] 1 == interleave wrap type
* MAx[6:4 ] 110 == CAS# latency bits
* MAx[7:7 ] 0 == mode normal
* MAx[8:8 ] 0 == DLL reset no
* MAx[13:13 ] 0 == MRS
* MAx[others] 0 == reserved
*/
CONSOLE_DEBUG_TX_STRING($ram_enable_4)
/* normal operation */
SET_RAM_COMMAND(RAM_COMMAND_NORMAL)
CONSOLE_DEBUG_TX_STRING($ram_enable_5)
#if 0
1: nop
jmp 1b
#endif
RET_LABEL(enable_sdram)
sdram_enable_out:

View file

@ -1 +1,3 @@
object ide.o
#object ide_probe.o

View file

@ -6,13 +6,13 @@
#include <string.h>
#define CMOS_READ(addr) ({ \
outb_p((addr),RTC_PORT(0)); \
inb_p(RTC_PORT(1)); \
outb((addr),RTC_PORT(0)); \
inb(RTC_PORT(1)); \
})
#define CMOS_WRITE(val, addr) ({ \
outb_p((addr),RTC_PORT(0)); \
outb_p((val),RTC_PORT(1)); \
outb((addr),RTC_PORT(0)); \
outb((val),RTC_PORT(1)); \
})
/* control registers - Moto names
@ -86,30 +86,30 @@ outb_p((val),RTC_PORT(1)); \
static int rtc_checksum_valid(void)
static int rtc_checksum_valid(int range_start, int range_end, int cks_loc)
{
int i;
unsigned sum, old_sum;
sum = 0;
for(i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; i++) {
for(i = range_start; i <= range_end; i++) {
sum += CMOS_READ(i);
}
sum &= 0xffff;
old_sum = (CMOS_READ(PC_CKS_LOC) << 8) | CMOS_READ(PC_CKS_LOC+1);
sum = (~sum)&0x0ffff;
old_sum = ((CMOS_READ(cks_loc)<<8) | CMOS_READ(cks_loc+1))&0x0ffff;
return sum == old_sum;
}
static void rtc_set_checksum(void)
static void rtc_set_checksum(int range_start, int range_end, int cks_loc)
{
int i;
unsigned sum;
sum = 0;
for(i = PC_CKS_RANGE_START; i <= PC_CKS_RANGE_END; i++) {
for(i = range_start; i <= range_end; i++) {
sum += CMOS_READ(i);
}
sum &= 0xffff;
CMOS_WRITE(((sum >> 8) & 0xff), PC_CKS_LOC);
CMOS_WRITE(((sum >> 0) & 0xff), PC_CKS_LOC+1);
sum = ~(sum & 0x0ffff);
CMOS_WRITE(((sum >> 8) & 0x0ff), cks_loc);
CMOS_WRITE(((sum >> 0) & 0x0ff), cks_loc+1);
}
#define RTC_CONTROL_DEFAULT (RTC_24H)
@ -125,12 +125,15 @@ void rtc_init(int invalid)
{
unsigned char x;
int cmos_invalid, checksum_invalid;
printk_debug("RTC Init\n");
/* See if there has been a CMOS power problem. */
x = CMOS_READ(RTC_VALID);
cmos_invalid = !(x & RTC_VRT);
/* See if there is a CMOS checksum error */
checksum_invalid = !rtc_checksum_valid();
checksum_invalid = !rtc_checksum_valid(PC_CKS_RANGE_START,
PC_CKS_RANGE_END,PC_CKS_LOC);
if (invalid || cmos_invalid || checksum_invalid) {
int i;
@ -138,10 +141,11 @@ void rtc_init(int invalid)
invalid?" Clear requested":"",
cmos_invalid?" Power Problem":"",
checksum_invalid?" Checksum invalid":"");
#if 0
CMOS_WRITE(0, 0x01);
CMOS_WRITE(0, 0x03);
CMOS_WRITE(0, 0x05);
for(i = 10; i < 128; i++) {
for(i = 10; i < 48; i++) {
CMOS_WRITE(0, i);
}
@ -155,13 +159,21 @@ void rtc_init(int invalid)
CMOS_WRITE(1, 0x08); /* month */
CMOS_WRITE(0, 0x09); /* year */
}
#endif
}
/* See if there is a LB CMOS checksum error */
checksum_invalid = !rtc_checksum_valid(LB_CKS_RANGE_START,
LB_CKS_RANGE_END,LB_CKS_LOC);
if(checksum_invalid)
printk_debug("Invalid CMOS LB checksum\n");
/* Setup the real time clock */
CMOS_WRITE(RTC_CONTROL_DEFAULT, RTC_CONTROL);
/* Setup the frequency it operates at */
CMOS_WRITE(RTC_FREQ_SELECT_DEFAULT, RTC_FREQ_SELECT);
/* Make certain we have a valid checksum */
rtc_set_checksum();
rtc_set_checksum(PC_CKS_RANGE_START,
PC_CKS_RANGE_END,PC_CKS_LOC);
/* Clear any pending interrupts */
(void) CMOS_READ(RTC_INTR_FLAGS);
}
@ -182,7 +194,8 @@ static int get_cmos_value(unsigned long bit, unsigned long length, void *vret)
unsigned long i;
unsigned char uchar;
/* The table is checked when it is built to ensure all values are valid. */
/* The table is checked when it is built to ensure all
values are valid. */
ret = vret;
byte=bit/8; /* find the byte where the data starts */
byte_bit=bit%8; /* find the bit in the byte where the data starts */
@ -201,7 +214,6 @@ static int get_cmos_value(unsigned long bit, unsigned long length, void *vret)
return 0;
}
int get_option(void *dest, char *name)
{
extern struct cmos_option_table option_table;
@ -223,10 +235,16 @@ int get_option(void *dest, char *name)
break;
}
}
if(!found) return(-2);
if(!found) {
printk_err("ERR: No cmos option '%s'\n", name);
return(-2);
}
if(get_cmos_value(ce->bit, ce->length, dest))
return(-3);
if(!rtc_checksum_valid(LB_CKS_RANGE_START,
LB_CKS_RANGE_END,LB_CKS_LOC))
return(-4);
return(0);
}
#endif /* USE_OPTION_TABLE */

View file

@ -49,7 +49,7 @@
.type div,@object
.size div,8
div:
.byte 1,2,3,5,12,24,48,96
.byte 1,2,3,6,12,24,48,96
.previous
#endif
@ -77,11 +77,11 @@ serial0:
/* set Baud Rate Divisor to 1 ==> 115200 Buad */
#if USE_OPTION_TABLE == 1
movb $RTC_BOOT_BYTE, %al
movb $(RTC_BOOT_BYTE+1), %al
outb %al, $0x70
xorl %edx,%edx
inb $0x71, %al
sarb $2,%al
andb $7,%al
movb %al,%dl
movb div(%edx),%al

View file

@ -1 +1,2 @@
object ramtest.o USE_RAMTEST
#object ramtest.o USE_RAMTEST
object ramtest.o

View file

@ -22,7 +22,23 @@ dn_after: .string "After setting values: \r\n"
movl %ecx, %eax
PCI_READ_CONFIG_DWORD
#if 0
CONSOLE_INFO_TX_HEX32(%eax)
#else
CONSOLE_INFO_TX_HEX8(%al)
movl %ecx, %eax
PCI_READ_CONFIG_DWORD
shrl $8,%eax
CONSOLE_INFO_TX_HEX8(%al)
movl %ecx, %eax
PCI_READ_CONFIG_DWORD
shrl $16,%eax
CONSOLE_INFO_TX_HEX8(%al)
movl %ecx, %eax
PCI_READ_CONFIG_DWORD
shrl $24,%eax
CONSOLE_INFO_TX_HEX8(%al)
#endif
CONSOLE_INFO_TX_CHAR($'\r')
CONSOLE_INFO_TX_CHAR($'\n')
addl $0x4, %ecx

View file

@ -25,6 +25,7 @@ int ram_verify(unsigned long start, unsigned long stop, int max_errors)
{
unsigned long addr;
int errors = 0;
int correct = 0;
/*
* Verify.
*/
@ -41,10 +42,16 @@ int ram_verify(unsigned long start, unsigned long stop, int max_errors)
printk_err("%08lx:%08lx\n", addr, value);
}
}
else {
if (++correct <= max_errors) {
/* Display address without error */
printk_err("%08lx:%08lx\n", addr, value);
}
}
}
/* Display final address */
printk_debug("%08lx\nDRAM verified %d/%d errors\n",
addr, errors, (stop - start)/4);
printk_debug("%08lx\nDRAM verified %d/%d errors %d/%d correct\n",
addr, errors, (stop - start)/4, correct, (stop - start)/4);
return errors;
}

View file

@ -108,6 +108,7 @@ ramtest:
6:
CONSOLE_INFO_TX_STRING($rt_done)
mov %ebp, %esp
#endif
RETSP

View file

@ -1,3 +1,16 @@
object southbridge.o
object nvram.o
object amd766_ioapic.o
object amd766_lpc.o
object amd766_mem.o
object amd766_mouse.o
object amd766_pm.o
object amd766_reset.o
object amd766_watchdog.o
object amd766_power.o
object amd766_reboot.o
object amd766_ide.o

View file

@ -0,0 +1,48 @@
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/amd/amd766.h>
#include <ide.h>
void amd766_enable_ide(int enable_a, int enable_b)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7411, 0);
if (dev != NULL) {
/* Enable ide devices so the linux ide driver will work */
u16 word;
pci_read_config_word(dev, 0x40, &word);
/* Ensure prefetch is disabled */
word &= ~((1 << 15) | (1 << 13));
if (enable_b) {
/* Enable secondary ide interface */
word |= (1<<0);
}
if (enable_a) {
/* Enable primary ide interface */
word |= (1<<1);
}
pci_write_config_word(dev, 0x40, word);
/* The AMD766 has a bug where the BM DMA address must be
* 256 byte aligned while it is only 16 bytes long.
* Hard code this to a valid address below 0x1000
* where automatic port address assignment starts.
*/
pci_write_config_dword(dev, 0x20, 0xf01);
#if 0
if (enable_a) {
ide_probe(0x1f0, 0);
}
if (enable_b) {
ide_probe(0x170, 2);
}
#endif
#if 0
if (enable_a) {
ide_spinup(0x1f0, 0);
}
if (enable_b) {
ide_spinup(0x170, 2);
}
#endif
}
}

View file

@ -0,0 +1,14 @@
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/amd/amd766.h>
void amd766_enable_ioapic(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410,0);
if (dev != NULL) {
/* Enable the ioapic */
pci_write_config_byte(dev, 0x4b, (0 << 3)|(0 <<2)|(0 << 1)|(1<< 0));
}
}

View file

@ -0,0 +1,17 @@
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/amd/amd766.h>
void amd766_enable_serial_irqs(int continuous, unsigned frames, unsigned startclocks)
{
struct pci_dev *dev;
unsigned value;
value = ((!!continuous) << 6)|((frames & 0xf) << 2)|((startclocks & 3) << 0);
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413,0);
if (dev != NULL) {
/* Setup serial irq's for the LPC bus. */
pci_write_config_byte(dev, 0x4a, value);
}
}

View file

@ -0,0 +1,15 @@
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/amd/amd766.h>
void amd766_posted_memory_write_enable(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
if (dev != NULL) {
unsigned char byte;
pci_read_config_byte(dev, 0x46, &byte);
pci_write_config_byte(dev, 0x46, byte | (1<<0));
}
}

View file

@ -0,0 +1,15 @@
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/amd/amd766.h>
void amd766_mouse_sends_irq12(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
if (dev != NULL) {
unsigned short word;
/* Setup so irq12 is sent by the ps2 mouse port. */
pci_read_config_word(dev, 0x46, &word);
pci_write_config_word(dev, 0x46, word | (1<<9));
}
}

View file

@ -0,0 +1,13 @@
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/amd/amd766.h>
void amd766_set_pm_classcode(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
if (dev != NULL) {
pci_write_config_dword(dev, 0x60, 0x06800000);
}
}

View file

@ -0,0 +1,21 @@
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/amd/amd766.h>
void amd766_power_after_power_fail(int on)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
if (dev != NULL) {
unsigned char byte;
pci_read_config_byte(dev, 0x43, &byte);
if (on) {
byte &= ~(1<<6);
}
else {
byte |= (1<<6);
}
pci_write_config_byte(dev, 0x43, byte);
}
}

View file

@ -0,0 +1,15 @@
#include <pci.h>
#include <pci_ids.h>
#include <arch/io.h>
#include <southbridge/amd/amd766.h>
void amd766_hard_reset(void)
{
pci_set_method();
/* Allow the watchdog timer to reboot us, and enable 0xcf9 */
pcibios_write_config_byte(0, (AMD766_DEV >> 8) | 3, 0x41, (1<<5)|(1<<1));
/* Try rebooting though port 0xcf9 */
outb((0<<3)|(1<<2)|(1<<1), 0xcf9);
return;
}

View file

@ -0,0 +1,39 @@
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/amd/amd766.h>
void amd766_enable_port92_reset(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
if (dev != NULL) {
unsigned char byte;
/* Enable reset using port 0x92 */
pci_read_config_byte(dev, 0x41, &byte);
pci_write_config_byte(dev, 0x41, byte | (1<<5));
}
}
void amd766_cpu_reset_sends_init(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7410, 0);
if (dev != NULL) {
unsigned char byte;
pci_read_config_byte(dev, 0x47, &byte);
pci_write_config_byte(dev, 0x47, byte | (1<<7));
}
}
void amd766_decode_stop_grant(unsigned how)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
if (dev != NULL) {
unsigned char byte;
pci_read_config_byte(dev, 0x41, &byte);
pci_write_config_byte(dev, 0x41, byte | ((how & 1)<<1));
}
}

View file

@ -0,0 +1,17 @@
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/amd/amd766.h>
void amd766_usb_setup(void)
{
/* FIXME this is untested incomplete implementation. */
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7414, 0);
if (dev) {
u32 cmd;
pci_read_config_dword(dev, PCI_COMMAND, &cmd);
pci_write_config_dword(dev, PCI_COMMAND,
cmd | PCI_COMMAND_IO | PCI_COMMAND_MEMORY |
PCI_COMMAND_MASTER | PCI_COMMAND_INVALIDATE);
}
}

View file

@ -0,0 +1,15 @@
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/amd/amd766.h>
void amd766_disable_watchdog(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_AMD, PCI_DEVICE_ID_AMD_VIPER_7413, 0);
if (dev != NULL) {
unsigned char byte;
/* Disable the watchdog timer */
pci_read_config_byte(dev, 0x41, &byte);
pci_write_config_byte(dev, 0x41, byte | (1<<6)|(1<<2));
}
}

View file

@ -0,0 +1,116 @@
/* The algorithm is as follows:
*
* Step 1: Test for cpu reset
* That is, did I just boot or is this a later boot since power on.
* The result of this test in %al
* %al == 1 -- We are rebooting
* %al == 0 -- This is the initial boot
*
* Step 2: Cpu filter
* On an initial boot if we are not the bootstrap CPU go to
* sleep.
*
* Step 3: Test for CMOS validity.
* On an initial boot if the CMOS checksum or the CMOS error
* condition is signaled clear the CMOS ram.
*
* Step 4: Test for which copy of linuxbios to boot.
* We use 2 bits of CMOS ram.
* Bit 0: Initial boot direction
* 0 - Boot the failsafe image.
* 1 - Boot the other image.
* Bit 1: Reboot direction
* 0 - Boot the failsafe image.
* 1 - Boot the other image.
*
* On initial boot we read bit0, and write it to bit1, and clear
* bit0.
*
* On a reboot the bits are not touched.
*
* Then the appropriate image is jumped to.
*
*
*/
#include <pc80/mc146818rtc.h>
#include <part/fallback_boot.h>
/* See if the CMOS error condition has been flagged */
movb $RTC_REG_D, %al
outb %al, $0x70
inb $0x71, %al
andb $RTC_VRT, %al
testb %al, %al
jz __rtc_failed
/* Compute the cmos checksum, and see if it is valid */
movb $PC_CKS_RANGE_START, %bl
xorl %ecx, %ecx
1:
movb %bl, %al
outb %al, $0x70
xorl %eax, %eax
inb $0x71, %al
addl %eax, %ecx
incb %bl
cmpb $PC_CKS_RANGE_END, %bl
jbe 1b
/* Compute the cmos checksum, and see if it is valid */
/* Read the stored checksum */
movb $(PC_CKS_LOC), %al
outb %al,$0x70
inb $0x71, %al
movb %al, %bh
movb $(PC_CKS_LOC+1), %al
outb %al, $0x70
inb $0x71, %al
movb %al, %bl
/* Now finally test the checksum */
cmpw %cx, %bx
je __rtc_ok
/* There are no impossible values, no checksums
* so just trust whatever value we have in the
* cmos, but clear the fallback bit.
*/
__rtc_failed:
movb $RTC_BOOT_BYTE, %al
outb %al, $0x70
inb $0x71, %al
andb $0xfc, %al
outb %al, $0x71
jmp __rtc_ok
/* The byte is o.k. see where to go */
__rtc_ok:
movb $RTC_BOOT_BYTE, %al
outb %al, $0x70
inb $0x71, %al
/* Transfer the boot bit from bit 0 to bit 1.
* And clear bit 0 so that unless we say it works we
* fallback to the other bios image immediately.
*/
movb %al, %bl
andb $0xfc, %al
andb $1, %bl
shlb %bl
orb %bl, %al
outb %al, $0x71
testb $(1<<1), %al
jz __failover_boot
/* Enable 4MB rom access at 0xFFC00000 - 0xFFFFFFFF */
movl $(0x80000000 | AMD766_DEV | 0x40), %eax
movw $0xcf8, %dx
outl %eax, %dx
movw $(0xcfc + 3), %dx
inb %dx, %al
orb $0x80, %al
outb %al, %dx
jmp __normal_image
__failover_boot:

View file

@ -0,0 +1,50 @@
/* The algorithm is as follows:
*
* Step 1: Test for cpu reset
* That is, did I just boot or is this a later boot since power on.
* The result of this test in %al
* %al == 1 -- We are rebooting
* %al == 0 -- This is the initial boot
*
* Step 2: Cpu filter
* On an initial boot if we are not the bootstrap CPU go to
* sleep.
*
* Step 3: Test for CMOS validity.
* On an initial boot if the CMOS checksum or the CMOS error
* condition is signaled clear the CMOS ram.
*
* Step 4: Test for which copy of linuxbios to boot.
* We use 2 bits of CMOS ram.
* Bit 0: Initial boot direction
* 0 - Boot the failsafe image.
* 1 - Boot the other image.
* Bit 1: Reboot direction
* 0 - Boot the failsafe image.
* 1 - Boot the other image.
*
* On initial boot we read bit0, and write it to bit1, and clear
* bit0.
*
* On a reboot the bits are not touched.
*
* Then the appropriate image is jumped to.
*
*
*/
#include <pc80/mc146818rtc.h>
#include <part/fallback_boot.h>
testb %al, %al
jz __failover_boot
__failover_reset:
movb $RTC_BOOT_BYTE, %al
outb %al, $0x70
inb $0x71, %al
testb $(1<<1), %al
jnz __normal_image
jmp __cpu_reset
__failover_boot:

View file

@ -55,7 +55,7 @@ __failover_boot:
movl $((RTC_DEVFN << 8) | GEN_PMCON_3), %eax
PCI_READ_CONFIG_DWORD
testl $RTC_FAILED, %eax
jz __rtc_ok
jz __cs_test
/* There are no impossible values, no checksums
* so just trust whatever value we have in the
@ -67,8 +67,41 @@ __rtc_failed:
inb $0x71, %al
andb $0xfc, %al
outb %al, $0x71
jmp __rtc_ok
jmp __cs_test
/* test the checksum */
__cs_test:
movl $77,%ecx
xor %ebx,%ebx
movl $RTC_BOOT_BYTE, %edx
1:
addl $1, %edx
movl %edx, %eax
outb %al, $0x70
inb $0x71, %al
addl %eax,%ebx
subl $1,%ecx
jnz 1b
not %ebx
addl $1, %edx
movl %edx, %eax
outb %al, $0x70
inb $0x71, %al
movb %al,%ch
addl $1, %edx
movl %edx, %eax
outb %al, $0x70
inb $0x71, %al
movb %ch,%ah
cmpw %ax,%bx
jz __rtc_ok
/* Set to fall back mode */
movb $RTC_BOOT_BYTE, %al
outb %al, $0x70
inb $0x71, %al
andb $0xfc, %al
outb %al, $0x71
/* The byte is o.k. see where to go */
__rtc_ok:
movb $RTC_BOOT_BYTE, %al

View file

@ -1,4 +1,6 @@
#include <pci.h>
#include <arch/io.h>
#include <printk.h>
#include <pci_ids.h>
#include <southbridge/intel/82801.h>
#include "82801.h"
@ -7,11 +9,15 @@ void ich2_enable_ioapic(void)
{
struct pci_dev *dev;
u32 dword;
dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_1F0, 0);
dev = pci_find_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82801BA_1F0, 0);
if (!dev) {
printk_debug("*** ERROR Southbridge device %x not found\n",
PCI_DEVICE_ID_INTEL_82801BA_1F0);
return;
}
pci_read_config_dword(dev, GEN_CNTL, &dword);
dword |= (3 << 7);
pci_write_config_dword(dev, GEN_CNTL, dword);
printk_debug("ioapic southbridge enabled %x\n",dword);
}

View file

@ -0,0 +1,532 @@
/* Useful macros PCIBUS, and SMBUS functions for getting DRAM going. */
/* courtesy Eric Biederman of linuxnetworx.com */
#define CS_WRITE_BYTE(addr, byte) \
movl $addr, %eax ; \
movl $byte, %edx ; \
PCI_WRITE_CONFIG_BYTE
#define CS_WRITE_WORD(addr, word) \
movl $addr, %eax ; \
movl $word, %ecx ; \
PCI_WRITE_CONFIG_WORD
#define CS_WRITE_LONG(addr, dword) \
movl $addr, %eax ; \
movl $dword, %ecx ; \
PCI_WRITE_CONFIG_DWORD
#define DEVFN(device, function) (((device) << 3) + (function))
#ifndef CONFIG_ADDR
#define CONFIG_ADDR(bus,devfn,where) (((bus) << 16) | ((devfn) << 8) | (where))
#endif
/* jump around these subrs */
jmp smbus_pcibus_end
/* generic SMB routines that work for many systems. The only one that might
* not work is the enable_smbus.
* you have to define PM_FUNCTION for this to work.
*/#define SMBUS_IO_BASE 0xf00
#define SMBHSTSTAT 0
#define SMBHSTCTL 2
#define SMBHSTCMD 3
#define SMBHSTADD 4
#define SMBHSTDAT0 5
#define SMBHSTDAT1 6
#define SMBBLKDAT 7
enable_smbus:
/* put the SMBUS at port 0xf00 */
CS_WRITE_LONG(PM_DEVFN+ 0x90, SMBUS_IO_BASE|1) /* iobase addr */
CS_WRITE_BYTE(PM_DEVFN + 0xd2, (0x4 << 1) | 1) /* smbus enable */
CS_WRITE_WORD(PM_DEVFN + 0x4, 1) /* iospace enable */
RET_LABEL(enable_smbus)
/*
* Routine: setup_smbus
* Arguments: none
* Results: none
* Trashed: eax, edx
* Effects: The smbus is enabled
*/
setup_smbus:
xor %eax,%eax
movl $(SMBUS_IO_BASE +SMBHSTSTAT), %edx
outb %al, %dx
RET_LABEL(setup_smbus)
#define SMBUS_MEM_DEVICE_0 (0xa << 3)
#define SMBUS_MEM_DEVICE_1 (SMBUS_MEM_DEVICE_0 +1)
#define SMBUS_MEM_DEVICE_2 (SMBUS_MEM_DEVICE_0 +2)
#define SMBUS_MEM_DEVICE_3 (SMBUS_MEM_DEVICE_0 +3)
/*
* Routine: smbus_wait_until_ready
* Arguments: none
* Results: none
* Trashed: eax, edx
* Effects: Upon return the smbus is ready to accept commands
*/
smbus_wait_until_ready:
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
1: inb %dx, %al
testb $1, %al
jnz 1b
RET_LABEL(smbus_wait_until_ready)
/*
* Routine: smbus_wait_until_done
* Arguments: none
* Results: none
* Trashed: eax, edx
* Effects: Upon return the smbus has completed it's most recent transation
*/
smbus_wait_until_done:
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
1: inb %dx, %al
testb $1, %al
jnz 1b
2: testb $0xFE, %al
jnz 3f
inb %dx, %al
testb $0xFE, %al
jz 2b
3: RET_LABEL(smbus_wait_until_done)
/*
* Routine: smbus_read_byte
* Arguments: %esp return address
* %bl device on the smbus to read from
* %bh address on the smbus to read
*
* Results: zf clear
* byte read %eax
* On Error:
* zf set
* %eax trashed
*
* Trashed: %edx, %eax
* Effects: reads a byte off of the smbus
*/
#define SMBUS_READ_BYTE(device, address) \
movl $( (device) | ((address) << 8)), %ebx ; \
CALLSP(smbus_read_byte)
smbus_read_byte:
/* poll until the smbus is ready for commands */
CALL_LABEL(smbus_wait_until_ready)
/* clear any lingering errors, so that the transaction will run */
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
inb %dx, %al
outb %al, %dx
/* set the device I'm talking to */
movl $(SMBUS_IO_BASE + SMBHSTADD), %edx
movb %bl /* device */, %al
shlb $1, %al
orb $1, %al
outb %al, %dx
/* set the command address... */
movl $(SMBUS_IO_BASE + SMBHSTCMD), %edx
movb %bh /* address */, %al
outb %al, %dx
/* clear the data byte */
movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx
xorl %eax, %eax
outb %al, %dx
/* start a byte read, with interrupts disabled */
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
movl $((0x2 << 2) | (1 << 6)), %eax
outb %al, %dx
/* poll for transaction completion */
CALL_LABEL(smbus_wait_until_done)
/* read the results and see if we succeded */
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
inb %dx, %al
testb $0x02, %al
jz 1f
movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx
inb %dx, %al
1:
RETSP
/* now for code to actually do the deed. Eric did such a good job that
* this stuff is basically generic.
*/
/*
* Routine: spd_set_drb
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esi, %edi, %ebp, %esp, %eflags
* Effects: Uses serial presence detect to set the
* DRB registers which holds the ending memory address assigned
* to each DIMM.
* Notes: %ebp holds the currently detected end of memory.
* %ebx holds the configuration port & SMBUS_MEM_DEVICE for
* the current iteration through the loop.
* %edi holds the memory size for the first side of the DIMM.
* %esi holds the memory size for the second side of the DIMM.
* memory size is represent as a power of 2.
* An unset memory size is represented as -1 ie. 0xFFFFFFFF
*/
spd_set_drb:
xorl %ebp, %ebp /* clear the memory address */
movl $((DRAM_CONFIG_PORT << 16) |SMBUS_MEM_DEVICE_0), %ebx
spd_set_drb_loop_top:
// set -1 power-of-two for side 1 (called bank0 in most chipset docs)
xorl %edi, %edi
subl $1, %edi
// set -1 power-of-two for side 2 (called bank1 in most chipset docs)
xorl %esi, %esi
subl $1, %esi
movb $3, %bh /* rows */
CALLSP(smbus_read_byte)
// If it's zero, then we just set current %ebp into the row
// end register
jz 20f
andl $0xf, %eax
addl %eax, %edi
movb $4, %bh /* columns */
CALLSP(smbus_read_byte)
andl $0xf, %eax
addl %eax, %edi
movb $17, %bh /* banks */
CALLSP(smbus_read_byte)
andl $0xff, %eax
bsrl %eax, %ecx
addl %ecx, %edi
/* Get the module data width and convert it to a power of two */
movb $7, %bh /* (high byte) */
CALLSP(smbus_read_byte)
andl $0xff, %eax
movl %eax, %ecx
shll $8, %ecx
movb $6, %bh /* (low byte) */
CALLSP(smbus_read_byte)
andl $0xff, %eax
orl %eax, %ecx
bsrl %ecx, %eax
addl %eax, %edi
/* now I have the ram size in bits as a power of two (less 1) */
// It is less 1 since we started with -1 above.
// OK, BITS as power of two (but minus 1)
// So, e.g., 8 MB is 64 Mb, 64 Mb is 26 bits. Subtract
// (26-1) or 25
subl $25, %edi /* Make it multiples of 8MB */
/* side two */
movb $5, %bh /* number of physical banks */
CALLSP(smbus_read_byte)
cmp $1, %al
// it's only one bank
jbe 20f
// It's two banks. So assign edi to esi
/* for now only handle the symmetrical case */
// it's two banks, assume however that they're the same size.
// it's stupid to have any other kind, right?
movl %edi, %esi
20:
/* Compute the end address for the DRB register */
// If it is >= 8, i.e. >= 2^8 or 256, skip it.
// >= 8 is a bogus value.
cmpl $8, %edi
jae 21f
movl $1, %eax
movl %edi, %ecx
shll %cl, %eax
// increment row-end by the size of this DIMM half
addl %eax, %ebp
21:
/* Write the comuputed value for the first half of the DIMM */
movl %ebp, %edx /* value to write into %edx */
movl %ebx, %eax
shrl $16, %eax /* port address into %eax */
PCI_WRITE_CONFIG_BYTE
/* Compute the end address for the DRB register */
cmpl $8, %esi
jae 30f
mov $1, %eax
movl %esi, %ecx
shll %cl, %eax
addl %eax, %ebp
30:
/* Write the comuputed value for the second half of the DIMM */
movl %ebp, %edx /* value to write into %edx */
movl %ebx, %eax
shrl $16, %eax /* port address into %eax */
addl $1, %eax /* The second half uses one port high */
PCI_WRITE_CONFIG_BYTE
addl $0x00020001, %ebx /* increment the smbus device & the config port */
cmpb $LAST_SMBUS_MEM_DEVICE, %bl /* see if I have reached the end */
jbe spd_set_drb_loop_top
/* o.k. I'm done return now */
RET_LABEL(spd_set_drb)
/*
* Routine: spd_set_dramc
* Arguments: None
*
* Trashed: %eax, %ebx, %edx, %esp, %eflags
* Effects: Uses serial presence detect to set the
* DRAMC register, which records if ram is registerd or not,
* and controls the refresh rate.
* The refresh rate is not set here, as memory refresh
* cannot be enbaled until after memory is initialized.
* see spd_enable_refresh.
* Notes:
* FIXME: Check for illegal/unsupported ram configurations and abort
* FIXME: won't work with non-contiguous DRAM size regs (like VIA)
* need an indirect pointer to an array of reg #s
*/
spd_set_dramc:
/* auto detect if ram is registered or not. */
/* The DRAMC register also contorls the refresh rate but we can't
* set that here because we must leave refresh disabled.
* see: spd_enable_refresh
*/
/* Find the first dimm and assume the rest are the same */
/* Load the smbus device and port int %ebx */
movl $((21 << 8) | SMBUS_MEM_DEVICE_0), %ebx
1: CALLSP(smbus_read_byte)
jz 2f
andl $0x12, %eax
jmp spd_set_dramc_out
2: addl $1, %ebx /* increment the device */
cmpb $LAST_SMBUS_MEM_DEVICE, %bl
jbe 1b
/* We couldn't find anything we must have no memory */
jmp no_memory
spd_set_dramc_out:
testb $0x12, %al
jz 2f
movl REGISTERED_DRAM, %eax
jmp 1f
2: movl NONREGISTERED_DRAM, %eax
1: movl %eax, %edx
movl REGISTERED_DRAM_REGISTER, %eax
PCI_WRITE_CONFIG_BYTE
RET_LABEL(spd_set_dramc)
/*
* Routine: spd_read_refresh
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esp, %eflags
* Effects: Uses serial presence detect to find refresh rates.
* returns the rate in %eax
* It's up to you to set hardware up.
* FIXME: Check for illegal/unsupported ram configurations and abort
*/
spd_read_refresh:
/* Find the first dimm and assume the rest are the same */
/* Load the smbus device and port int %ebx */
movl $((12 << 8) | SMBUS_MEM_DEVICE_0), %ebx
1: CALLSP(smbus_read_byte)
jz 2f
andl $0x7f, %eax
jmp spd_enable_refresh_out
2: addl $1, %ebx /* increment the device */
cmpb $LAST_SMBUS_MEM_DEVICE, %bl
jbe 1b
/* We couldn't find anything we must have no memory */
xorl %eax, %eax
spd_enable_refresh_out:
RET_LABEL(spd_enable_refresh)
/*
* Routine: spd_set_rps
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esi, %edi, %esp, %eflags
* Effects: Uses serial presence detect to set the row size
* on a given DIMM
* Notes: %esi accumulates the row sizes of all of the DIMMs
* %ecx holds the current bit into into %esi
* %bl holds the current SMBUS device
* FIXME: Check for illegal/unsupported ram configurations and abort
*/
spd_set_rps:
/* The RPS register holds the size of a ``page'' of DRAM on each DIMM */
/* default all page sizes to 2KB */
xorl %esi, %esi
/* Index into %esi of bit to set */
movl $0 , %ecx
/* Load the smbus device into %ebx */
movl $SMBUS_MEM_DEVICE_0, %ebx
1: movb $3, %bh
CALLSP(smbus_read_byte) /* row address bits */
jz 2f
andl $0xf, %eax
movl %eax, %edi
/* I now have the row page size as a power of 2 */
subl $11, %edi /* Now make it in multiples of 2Kb */
jbe 2f
/* FIXME: do something with page sizes greather than 8KB!! */
shll %cl, %edi
orl %edi, %esi
/* side two */
movb $5, %bh
CALLSP(smbus_read_byte) /* number of physical banks */
cmp $1, %al
jbe 2f
/* for now only handle the symmtrical case */
shll $2, %edi
shll %cl, %edi
orl %edi, %esi
2: addl $1, %ebx /* increment the device */
addl $4, %ecx /* increment the shift count */
cmpb $LAST_SMBUS_MEM_DEVICE, %bl
jbe 1b
movl $0x7f, %eax
/* I'm not sure what we should do here. Do nothing. */
/* PCI_WRITE_CONFIG_WORD*/
RET_LABEL(spd_set_rps)
/*
* Routine: spd_set_pgpol
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esi, %esp, %eflags
* Effects: Uses serial presence detect to set the number of banks
* on a given DIMM
* Notes: %esi accumulates the banks sizes of all of the DIMMs
* %ecx holds the current bit into into %esi
* %bl holds the current SMBUS device
* FIXME: Check for illegal/unsupported ram configurations and abort
*/
spd_set_pgpol:
/* The PGPOL register stores the number of logical banks per DIMM,
* and number of clocks the DRAM controller waits in the idle
* state.
*/
/* default all bank counts 2 */
xorl %esi, %esi
/* Index into %esi of bit to set */
movl $0 , %ecx
/* Load the smbus device into %ebx */
movl $SMBUS_MEM_DEVICE_0, %ebx
1: movb $17, %bh
CALLSP(smbus_read_byte) /* logical banks */
jz 2f
cmp $0x4, %eax
jl 2f
movl $0x1, %eax
shll %cl, %eax
orl %eax, %esi
/* side two */
movb $5, %bh
CALLSP(smbus_read_byte) /* number of physical banks */
cmp $1, %al
jbe 2f
/* for now only handle the symmtrical case */
movl $0x2, %eax
shll %cl, %eax
orl %eax, %esi
2: addl $1, %ebx /* increment the device */
addl $2, %ecx /* increment the shift count */
cmpb $LAST_SMBUS_MEM_DEVICE, %bl
jbe 1b
shll $8, %esi
orl $0x7, %esi /* 32 clocks idle time */
movl %esi, %ecx
movl $0x78, %eax
/* I'm unclear on the concept for non-intel devices */
/* PCI_WRITE_CONFIG_WORD*/
RET_LABEL(spd_set_pgpol)
/*
* Routine: spd_enable_nbxcfg
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esi, %esp, %eflags
* Effects: Uses serial presence detect to set the
* ECC support flags in the NBXCFG register
* Notes: %esi accumulates the ECC support of the individual DIMMs.
* %ecx holds the bit that should be flipped for the current DIMM.
* %bl holds the smbus device that corresponds to the current DIMM.
* FIXME: Check for illegal/unsupported ram configurations and abort
*/
spd_set_nbxcfg:
/* say all dimms have no ECC support */
movl $0xFF, %esi
/* Index into %esi of bit to set */
movl $0 , %ecx
/* Load the smbus device into %ebx */
movl $SMBUS_MEM_DEVICE_0, %ebx
1: movb $11, %bh
CALLSP(smbus_read_byte) /* module error correction type */
jz 2f
cmp $0x2, %eax /* 0 == None, 1 == Parity, 2 == ECC */
jne 2f
movl $0x1, %eax
shll %cl, %eax
xorl %eax, %esi
/* side two */
movb $5, %bh
CALLSP(smbus_read_byte) /* number of physical banks */
cmp $1, %al
jbe 2f
/* The only is the symmtrical case */
movl $0x2, %eax
shll %cl, %eax
xorl %eax, %esi
2: addl $1, %ebx /* increment the device */
addl $2, %ecx /* increment the shift count */
cmpb $LAST_SMBUS_MEM_DEVICE, %bl
jbe 1b
movl %esi, %edx
/* at some point, we need to indicate how to turn ECC on. Not yet.
movl $0x53, %eax
PCI_WRITE_CONFIG_BYTE
*/
RET_LABEL(spd_set_nbxcfg)
smbus_pcibus_end:
CALL_LABEL(enable_smbus)
CALL_LABEL(setup_smbus)

View file

@ -0,0 +1,40 @@
#define PCI_DMA_CFG 0x90
#define SERIRQ_CNTL 0x64
#define GEN_CNTL 0xd0
#define GEN_STS 0xd4
#define RTC_CONF 0xd8
#define GEN_PMCON_3 0xa4
#define PCICMD 0x04
#define PMBASE 0x40
#define ACPI_CNTL 0x44
#define BIOS_CNTL 0x4E
#define GPIO_BASE 0x58
#define GPIO_CNTL 0x5C
#define PIRQA_ROUT 0x60
#define PIRQE_ROUT 0x68
#define COM_DEC 0xE0
#define LPC_EN 0xE6
#define FUNC_DIS 0xF2
/* 1e f0 244e */
#define CMD 0x04
#define SBUS_NUM 0x19
#define SUB_BUS_NUM 0x1A
#define SMLT 0x1B
#define IOBASE 0x1C
#define IOLIM 0x1D
#define MEMBASE 0x20
#define MEMLIM 0x22
#define CNF 0x50
#define MTT 0x70
#define PCI_MAST_STS 0x82
#define RTC_BUS 0
#define RTC_DEVFN ((0x1f << 3) + 0)
#define RTC_FAILED (1 <<2)
#define SMBUS_BUS 0
#define SMBUS_DEVFN ((0x1f << 3) + 3)

View file

@ -0,0 +1,11 @@
object nvram.o
object ich3_ioapic.o
object ich3_lpc.o
object ich3_ide.o
object ich3_reset.o
object ich3_smbus.o
object ich3_cpu.o
object ich3_rtc.o
object ich3_power.o
object ich3_1e0_misc.o
object ich3_1f0_misc.o

View file

@ -0,0 +1,124 @@
/* The algorithm is as follows:
*
* Step 1: Test for cpu reset
* That is, did I just boot or is this a later boot since power on.
* The result of this test in %al
* %al == 1 -- We are rebooting
* %al == 0 -- This is the initial boot
*
* Step 2: Cpu filter
* On an initial boot if we are not the bootstrap CPU go to
* sleep.
*
* Step 3: Test for CMOS validity.
* On an initial boot if the CMOS checksum or the CMOS error
* condition is signaled clear the CMOS ram.
*
* Step 4: Test for which copy of linuxbios to boot.
* We use 2 bits of CMOS ram.
* Bit 0: Initial boot direction
* 0 - Boot the failsafe image.
* 1 - Boot the other image.
* Bit 1: Reboot direction
* 0 - Boot the failsafe image.
* 1 - Boot the other image.
*
* On initial boot we read bit0, and write it to bit1, and clear
* bit0.
*
* On a reboot the bits are not touched.
*
* Then the appropriate image is jumped to.
*
*
*/
#include "82801.h"
#include <pc80/mc146818rtc.h>
#include <part/fallback_boot.h>
/* Intel systems magically stop the second cpu in hardware */
testb %al, %al
jz __failover_boot
__failover_reset:
movb $RTC_BOOT_BYTE, %al
outb %al, $0x70
inb $0x71, %al
testb $(1<<1), %al
jnz __normal_image
jmp __cpu_reset
__failover_boot:
/* See if the cmos clear jumper has been set */
movl $((RTC_DEVFN << 8) | GEN_PMCON_3), %eax
PCI_READ_CONFIG_DWORD
testl $RTC_FAILED, %eax
jz __cs_test
/* There are no impossible values, no checksums
* so just trust whatever value we have in the
* cmos.
*/
__rtc_failed:
movb $RTC_BOOT_BYTE, %al
outb %al, $0x70
inb $0x71, %al
andb $0xfc, %al
outb %al, $0x71
jmp __cs_test
/* test the checksum */
__cs_test:
movl $77,%ecx
xor %ebx,%ebx
movl $RTC_BOOT_BYTE, %edx
1:
addl $1, %edx
movl %edx, %eax
outb %al, $0x70
inb $0x71, %al
addl %eax,%ebx
subl $1,%ecx
jnz 1b
not %ebx
addl $1, %edx
movl %edx, %eax
outb %al, $0x70
inb $0x71, %al
movb %al,%ch
addl $1, %edx
movl %edx, %eax
outb %al, $0x70
inb $0x71, %al
movb %ch,%ah
cmpw %ax,%bx
jz __rtc_ok
/* Set to fall back mode */
movb $RTC_BOOT_BYTE, %al
outb %al, $0x70
inb $0x71, %al
andb $0xfc, %al
outb %al, $0x71
/* The byte is o.k. see where to go */
__rtc_ok:
movb $RTC_BOOT_BYTE, %al
outb %al, $0x70
inb $0x71, %al
/* Transfer the boot bit from bit 0 to bit 1.
* And clear bit 0 so that unless we say it works we
* fallback to the other bios image immediately.
*/
movb %al, %bl
andb $0xfc, %al
andb $1, %bl
shlb %bl
orb %bl, %al
outb %al, $0x71
testb $(1<<1), %al
jnz __normal_image

View file

@ -0,0 +1,31 @@
#include <pci.h>
#include <arch/io.h>
#include <printk.h>
#include <pci_ids.h>
#include <southbridge/intel/82801.h>
#include "82801.h"
void ich3_1e0_misc(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82801CA_1E0, 0);
if (!dev) {
printk_debug("*** ERROR Southbridge device %x not found\n",
PCI_DEVICE_ID_INTEL_82801CA_1E0);
return;
}
#if 0
pci_write_config_word(dev, CMD, 0x0147);
pci_write_config_byte(dev, SMLT, 0x40);
pci_write_config_byte(dev, IOBASE, 0x20);
pci_write_config_byte(dev, IOLIM, 0x20);
pci_write_config_word(dev, MEMBASE, 0xd410);
pci_write_config_word(dev, MEMLIM, 0xd5f0);
pci_write_config_byte(dev, CNF, 0x02);
pci_write_config_byte(dev, MTT, 0x40);
pci_write_config_byte(dev, PCI_MAST_STS, 0x86);
#endif
}

View file

@ -0,0 +1,30 @@
#include <pci.h>
#include <arch/io.h>
#include <printk.h>
#include <pci_ids.h>
#include <southbridge/intel/82801.h>
#include "82801.h"
void ich3_1f0_misc(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82801CA_1F0, 0);
if (!dev) {
printk_debug("*** ERROR Southbridge device %x not found\n",
PCI_DEVICE_ID_INTEL_82801CA_1F0);
return;
}
pci_write_config_word(dev, PCICMD, 0x014f);
pci_write_config_dword(dev, PMBASE, 0x00001001);
pci_write_config_byte(dev, ACPI_CNTL, 0x10);
pci_write_config_dword(dev, GPIO_BASE, 0x00001181);
pci_write_config_byte(dev, GPIO_CNTL, 0x10);
pci_write_config_dword(dev, PIRQA_ROUT, 0x0A05030B);
pci_write_config_byte(dev, PIRQE_ROUT, 0x07);
pci_write_config_byte(dev, RTC_CONF, 0x04);
pci_write_config_byte(dev, COM_DEC, 0xE0);
pci_write_config_word(dev, LPC_EN, 0x000D);
pci_write_config_word(dev, FUNC_DIS, 0x8060);
}

View file

@ -0,0 +1,37 @@
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/intel/82801.h>
#include <printk.h>
#include <part/hard_reset.h>
#include <part/fallback_boot.h>
#include "82801.h"
void ich3_set_cpu_multiplier(unsigned multiplier)
{
u32 dword, old_dword;
struct pci_dev *dev;
unsigned old_multiplier;
dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_1F0, 0);
if (!dev) {
printk_err("Cannot find device %08x:%08x\n",
PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_1F0);
return;
}
pci_read_config_dword(dev, GEN_STS, &old_dword);
dword = old_dword;
dword &= ~((1 << 12) - (1 << 8));
#if 0
dword |= (multiplier & 0xf) << 8;
#else
dword |= (0x0c) << 8;
#endif
if (dword != old_dword) {
dword |= (1<<1);
pci_write_config_dword(dev, GEN_STS, dword);
printk_info("Rebooting to change the cpu multiplier\n");
boot_successful();
hard_reset();
}
dword |= (1<<1);
pci_write_config_dword(dev, GEN_STS, dword);
}

View file

@ -0,0 +1,24 @@
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/intel/82801.h>
void ich3_enable_ide(int enable_a, int enable_b)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_1F1, 0);
if (dev != NULL) {
/* Enable ide devices so the linux ide driver will work */
u16 word;
/* enable ide0 */
pci_read_config_word(dev, 0x40, &word);
word &= ~(1 << 15);
word |= ((!!enable_a) << 15);
pci_write_config_word(dev, 0x40, word);
/* enable ide1 */
pci_read_config_word(dev, 0x42, &word);
word &= ~(1 << 15);
word |= ((!!enable_b) << 15);
pci_write_config_word(dev, 0x42, word);
}
}

View file

@ -0,0 +1,45 @@
#include <pci.h>
#include <arch/io.h>
#include <printk.h>
#include <pci_ids.h>
#include <southbridge/intel/82801.h>
#include "82801.h"
void ich3_enable_ioapic(void)
{
struct pci_dev *dev;
u32 dword;
volatile u32 *ioapic_sba=0xfec00000;
volatile u32 *ioapic_sbd=0xfec00010;
dev = pci_find_device(PCI_VENDOR_ID_INTEL,
PCI_DEVICE_ID_INTEL_82801CA_1F0, 0);
if (!dev) {
printk_debug("*** ERROR Southbridge device %x not found\n",
PCI_DEVICE_ID_INTEL_82801CA_1F0);
return;
}
pci_read_config_dword(dev, GEN_CNTL, &dword);
dword |= (3 << 7); /* enable ioapic */
dword |= (1 <<13); /* coprocessor error enable */
dword |= (1 << 1); /* delay transaction enable */
dword |= (1 << 2); /* DMA collection buf enable */
pci_write_config_dword(dev, GEN_CNTL, dword);
printk_debug("ioapic southbridge enabled %x\n",dword);
*ioapic_sba=0;
*ioapic_sbd=(2<<24);
*ioapic_sba=3;
*ioapic_sbd=1;
*ioapic_sba=0;
dword=*ioapic_sbd;
printk_debug("Southbridge apic id = %x\n",dword);
if(dword!=(2<<24))
for(;;);
*ioapic_sba=3;
dword=*ioapic_sbd;
printk_debug("Southbridge apic DT = %x\n",dword);
if(dword!=1)
for(;;);
}

View file

@ -0,0 +1,33 @@
#include <pci.h>
#include <pci_ids.h>
#include <southbridge/intel/82801.h>
#include "82801.h"
void ich3_enable_serial_irqs(void)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_1F0, 0);
if (!dev) {
return;
}
pci_write_config_byte(dev, SERIRQ_CNTL, (1 << 7)|(1 << 6)|((21 - 17) << 2)|(0 << 0));
}
void ich3_lpc_route_dma(unsigned char mask)
{
struct pci_dev *dev;
u16 word;
int i;
dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_1F0, 0);
if (!dev) {
return;
}
pci_read_config_word(dev, PCI_DMA_CFG, &word);
word &= ((1 << 10) - (1 << 8));
for(i = 0; i < 8; i++) {
if (i == 4)
continue;
word |= ((mask & (1 << i))? 3:1) << (i*2);
}
pci_write_config_word(dev, PCI_DMA_CFG, word);
}

View file

@ -0,0 +1,21 @@
#include <southbridge/intel/82801.h>
#include <pci.h>
#include <pci_ids.h>
#include <printk.h>
#include "82801.h"
void ich3_power_after_power_fail(int on)
{
struct pci_dev *dev;
dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801CA_1F0, 0);
if (!dev) {
return;
}
/* FIXME this doesn't work! */
/* Which state do we want to goto after g3 (power restored)?
* 0 == S0 Full On
* 1 == S5 Soft Off
*/
pci_write_config_byte(dev, GEN_PMCON_3, on?0:1);
printk_info("set power %s after power fail\n", on?"on":"off");
}

View file

@ -0,0 +1,9 @@
#include <arch/io.h>
#include <southbridge/intel/82801.h>
void ich3_hard_reset(void)
{
/* Try rebooting through port 0xcf9 */
outb((0 <<3)|(1<<2)|(1<<1), 0xcf9);
}

View file

@ -0,0 +1,23 @@
#include <southbridge/intel/82801.h>
#include <pc80/mc146818rtc.h>
#include <pci.h>
#include <pci_ids.h>
#include <printk.h>
#include "82801.h"
void ich3_rtc_init(void)
{
unsigned char byte;
u32 dword;
int rtc_failed;
pcibios_read_config_byte(RTC_BUS, RTC_DEVFN, GEN_PMCON_3, &byte);
rtc_failed = byte & RTC_FAILED;
if (rtc_failed) {
byte &= ~(1 << 1); /* preserve the power fail state */
pcibios_write_config_byte(RTC_BUS, RTC_DEVFN, GEN_PMCON_3, byte);
}
pcibios_read_config_dword(RTC_BUS, RTC_DEVFN, GEN_STS, &dword);
rtc_failed |= dword & (1 << 2);
rtc_init(rtc_failed);
}

View file

@ -0,0 +1,121 @@
#include <smbus.h>
#include <arch/io.h>
#include <pci.h>
#include <southbridge/intel/82801.h>
#include "82801.h"
#define SMBUS_IO_BASE 0x1000
#define SMBHSTSTAT 0x0
#define SMBHSTCTL 0x2
#define SMBHSTCMD 0x3
#define SMBXMITADD 0x4
#define SMBHSTDAT0 0x5
#define SMBHSTDAT1 0x6
#define SMBBLKDAT 0x7
#define SMBTRNSADD 0x9
#define SMBSLVDATA 0xa
#define SMLINK_PIN_CTL 0xe
#define SMBUS_PIN_CTL 0xf
void smbus_setup(void)
{
pcibios_write_config_dword(SMBUS_BUS, SMBUS_DEVFN, 0x20, SMBUS_IO_BASE | 1);
pcibios_write_config_byte(SMBUS_BUS, SMBUS_DEVFN, 0x40, 1);
pcibios_write_config_word(SMBUS_BUS, SMBUS_DEVFN, 0x4, 1);
/* Disable interrupt generation */
outb(0, SMBUS_IO_BASE + SMBHSTCTL);
}
static void smbus_wait_until_ready(void)
{
while((inb(SMBUS_IO_BASE + SMBHSTSTAT) & 1) == 1) {
/* nop */
}
}
static void smbus_wait_until_done(void)
{
unsigned char byte;
do {
byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
} while((byte &1) == 1);
while( (byte & ~((1<<6)|(1<<0))) == 0) {
byte = inb(SMBUS_IO_BASE + SMBHSTSTAT);
}
}
#if 0
static void smbus_print_error(unsigned char host_status_register)
{
printk_debug("smbus_error: 0x%02x\n", host_status_register);
if (host_status_register & (1 << 7)) {
printk_debug("Byte Done Status\n");
}
if (host_status_register & (1 << 6)) {
printk_debug("In Use Status\n");
}
if (host_status_register & (1 << 5)) {
printk_debug("SMBus Alert Status\n");
}
if (host_status_register & (1 << 4)) {
printk_debug("Interrup/SMI# was Failed Bus Transaction\n");
}
if (host_status_register & (1 << 3)) {
printk_debug("Bus Error\n");
}
if (host_status_register & (1 << 2)) {
printk_debug("Device Error\n");
}
if (host_status_register & (1 << 1)) {
printk_debug("Interrupt/SMI# was Successful Completion\n");
}
if (host_status_register & (1 << 0)) {
printk_debug("Host Busy\n");
}
}
#endif
int smbus_read_byte(unsigned device, unsigned address, unsigned char *result)
{
unsigned char host_status_register;
unsigned char byte;
smbus_wait_until_ready();
/* setup transaction */
/* disable interrupts */
outb(inb(SMBUS_IO_BASE + SMBHSTCTL) & (~1), SMBUS_IO_BASE + SMBHSTCTL);
/* set the device I'm talking too */
outb(((device & 0x7f) << 1) | 1, SMBUS_IO_BASE + SMBXMITADD);
/* set the command/address... */
outb(address & 0xFF, SMBUS_IO_BASE + SMBHSTCMD);
/* set up for a byte data read */
outb((inb(SMBUS_IO_BASE + SMBHSTCTL) & 0xE3) | (0x2 << 2), SMBUS_IO_BASE + SMBHSTCTL);
/* clear any lingering errors, so the transaction will run */
outb(inb(SMBUS_IO_BASE + SMBHSTSTAT), SMBUS_IO_BASE + SMBHSTSTAT);
/* clear the data byte...*/
outb(0, SMBUS_IO_BASE + SMBHSTDAT0);
/* start the command */
outb((inb(SMBUS_IO_BASE + SMBHSTCTL) | 0x40), SMBUS_IO_BASE + SMBHSTCTL);
/* poll for transaction completion */
smbus_wait_until_done();
host_status_register = inb(SMBUS_IO_BASE + SMBHSTSTAT);
/* Ignore the In Use Status... */
host_status_register &= ~(1 << 6);
/* read results of transaction */
byte = inb(SMBUS_IO_BASE + SMBHSTDAT0);
*result = byte;
return host_status_register != 0x02;
}

View file

@ -0,0 +1,8 @@
#include <part/nvram.h>
#include <printk.h>
void nvram_on(void)
{
printk_notice("Please turn on nvram\n");
return;
}

View file

@ -0,0 +1,532 @@
/* Useful macros PCIBUS, and SMBUS functions for getting DRAM going. */
/* courtesy Eric Biederman of linuxnetworx.com */
#define CS_WRITE_BYTE(addr, byte) \
movl $addr, %eax ; \
movl $byte, %edx ; \
PCI_WRITE_CONFIG_BYTE
#define CS_WRITE_WORD(addr, word) \
movl $addr, %eax ; \
movl $word, %ecx ; \
PCI_WRITE_CONFIG_WORD
#define CS_WRITE_LONG(addr, dword) \
movl $addr, %eax ; \
movl $dword, %ecx ; \
PCI_WRITE_CONFIG_DWORD
#define DEVFN(device, function) (((device) << 3) + (function))
#ifndef CONFIG_ADDR
#define CONFIG_ADDR(bus,devfn,where) (((bus) << 16) | ((devfn) << 8) | (where))
#endif
/* jump around these subrs */
jmp smbus_pcibus_end
/* generic SMB routines that work for many systems. The only one that might
* not work is the enable_smbus.
* you have to define PM_FUNCTION for this to work.
*/#define SMBUS_IO_BASE 0xf00
#define SMBHSTSTAT 0
#define SMBHSTCTL 2
#define SMBHSTCMD 3
#define SMBHSTADD 4
#define SMBHSTDAT0 5
#define SMBHSTDAT1 6
#define SMBBLKDAT 7
enable_smbus:
/* put the SMBUS at port 0xf00 */
CS_WRITE_LONG(PM_DEVFN+ 0x90, SMBUS_IO_BASE|1) /* iobase addr */
CS_WRITE_BYTE(PM_DEVFN + 0xd2, (0x4 << 1) | 1) /* smbus enable */
CS_WRITE_WORD(PM_DEVFN + 0x4, 1) /* iospace enable */
RET_LABEL(enable_smbus)
/*
* Routine: setup_smbus
* Arguments: none
* Results: none
* Trashed: eax, edx
* Effects: The smbus is enabled
*/
setup_smbus:
xor %eax,%eax
movl $(SMBUS_IO_BASE +SMBHSTSTAT), %edx
outb %al, %dx
RET_LABEL(setup_smbus)
#define SMBUS_MEM_DEVICE_0 (0xa << 3)
#define SMBUS_MEM_DEVICE_1 (SMBUS_MEM_DEVICE_0 +1)
#define SMBUS_MEM_DEVICE_2 (SMBUS_MEM_DEVICE_0 +2)
#define SMBUS_MEM_DEVICE_3 (SMBUS_MEM_DEVICE_0 +3)
/*
* Routine: smbus_wait_until_ready
* Arguments: none
* Results: none
* Trashed: eax, edx
* Effects: Upon return the smbus is ready to accept commands
*/
smbus_wait_until_ready:
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
1: inb %dx, %al
testb $1, %al
jnz 1b
RET_LABEL(smbus_wait_until_ready)
/*
* Routine: smbus_wait_until_done
* Arguments: none
* Results: none
* Trashed: eax, edx
* Effects: Upon return the smbus has completed it's most recent transation
*/
smbus_wait_until_done:
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
1: inb %dx, %al
testb $1, %al
jnz 1b
2: testb $0xFE, %al
jnz 3f
inb %dx, %al
testb $0xFE, %al
jz 2b
3: RET_LABEL(smbus_wait_until_done)
/*
* Routine: smbus_read_byte
* Arguments: %esp return address
* %bl device on the smbus to read from
* %bh address on the smbus to read
*
* Results: zf clear
* byte read %eax
* On Error:
* zf set
* %eax trashed
*
* Trashed: %edx, %eax
* Effects: reads a byte off of the smbus
*/
#define SMBUS_READ_BYTE(device, address) \
movl $( (device) | ((address) << 8)), %ebx ; \
CALLSP(smbus_read_byte)
smbus_read_byte:
/* poll until the smbus is ready for commands */
CALL_LABEL(smbus_wait_until_ready)
/* clear any lingering errors, so that the transaction will run */
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
inb %dx, %al
outb %al, %dx
/* set the device I'm talking to */
movl $(SMBUS_IO_BASE + SMBHSTADD), %edx
movb %bl /* device */, %al
shlb $1, %al
orb $1, %al
outb %al, %dx
/* set the command address... */
movl $(SMBUS_IO_BASE + SMBHSTCMD), %edx
movb %bh /* address */, %al
outb %al, %dx
/* clear the data byte */
movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx
xorl %eax, %eax
outb %al, %dx
/* start a byte read, with interrupts disabled */
movl $(SMBUS_IO_BASE + SMBHSTCTL), %edx
movl $((0x2 << 2) | (1 << 6)), %eax
outb %al, %dx
/* poll for transaction completion */
CALL_LABEL(smbus_wait_until_done)
/* read the results and see if we succeded */
movl $(SMBUS_IO_BASE + SMBHSTSTAT), %edx
inb %dx, %al
testb $0x02, %al
jz 1f
movl $(SMBUS_IO_BASE + SMBHSTDAT0), %edx
inb %dx, %al
1:
RETSP
/* now for code to actually do the deed. Eric did such a good job that
* this stuff is basically generic.
*/
/*
* Routine: spd_set_drb
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esi, %edi, %ebp, %esp, %eflags
* Effects: Uses serial presence detect to set the
* DRB registers which holds the ending memory address assigned
* to each DIMM.
* Notes: %ebp holds the currently detected end of memory.
* %ebx holds the configuration port & SMBUS_MEM_DEVICE for
* the current iteration through the loop.
* %edi holds the memory size for the first side of the DIMM.
* %esi holds the memory size for the second side of the DIMM.
* memory size is represent as a power of 2.
* An unset memory size is represented as -1 ie. 0xFFFFFFFF
*/
spd_set_drb:
xorl %ebp, %ebp /* clear the memory address */
movl $((DRAM_CONFIG_PORT << 16) |SMBUS_MEM_DEVICE_0), %ebx
spd_set_drb_loop_top:
// set -1 power-of-two for side 1 (called bank0 in most chipset docs)
xorl %edi, %edi
subl $1, %edi
// set -1 power-of-two for side 2 (called bank1 in most chipset docs)
xorl %esi, %esi
subl $1, %esi
movb $3, %bh /* rows */
CALLSP(smbus_read_byte)
// If it's zero, then we just set current %ebp into the row
// end register
jz 20f
andl $0xf, %eax
addl %eax, %edi
movb $4, %bh /* columns */
CALLSP(smbus_read_byte)
andl $0xf, %eax
addl %eax, %edi
movb $17, %bh /* banks */
CALLSP(smbus_read_byte)
andl $0xff, %eax
bsrl %eax, %ecx
addl %ecx, %edi
/* Get the module data width and convert it to a power of two */
movb $7, %bh /* (high byte) */
CALLSP(smbus_read_byte)
andl $0xff, %eax
movl %eax, %ecx
shll $8, %ecx
movb $6, %bh /* (low byte) */
CALLSP(smbus_read_byte)
andl $0xff, %eax
orl %eax, %ecx
bsrl %ecx, %eax
addl %eax, %edi
/* now I have the ram size in bits as a power of two (less 1) */
// It is less 1 since we started with -1 above.
// OK, BITS as power of two (but minus 1)
// So, e.g., 8 MB is 64 Mb, 64 Mb is 26 bits. Subtract
// (26-1) or 25
subl $25, %edi /* Make it multiples of 8MB */
/* side two */
movb $5, %bh /* number of physical banks */
CALLSP(smbus_read_byte)
cmp $1, %al
// it's only one bank
jbe 20f
// It's two banks. So assign edi to esi
/* for now only handle the symmetrical case */
// it's two banks, assume however that they're the same size.
// it's stupid to have any other kind, right?
movl %edi, %esi
20:
/* Compute the end address for the DRB register */
// If it is >= 8, i.e. >= 2^8 or 256, skip it.
// >= 8 is a bogus value.
cmpl $8, %edi
jae 21f
movl $1, %eax
movl %edi, %ecx
shll %cl, %eax
// increment row-end by the size of this DIMM half
addl %eax, %ebp
21:
/* Write the comuputed value for the first half of the DIMM */
movl %ebp, %edx /* value to write into %edx */
movl %ebx, %eax
shrl $16, %eax /* port address into %eax */
PCI_WRITE_CONFIG_BYTE
/* Compute the end address for the DRB register */
cmpl $8, %esi
jae 30f
mov $1, %eax
movl %esi, %ecx
shll %cl, %eax
addl %eax, %ebp
30:
/* Write the comuputed value for the second half of the DIMM */
movl %ebp, %edx /* value to write into %edx */
movl %ebx, %eax
shrl $16, %eax /* port address into %eax */
addl $1, %eax /* The second half uses one port high */
PCI_WRITE_CONFIG_BYTE
addl $0x00020001, %ebx /* increment the smbus device & the config port */
cmpb $LAST_SMBUS_MEM_DEVICE, %bl /* see if I have reached the end */
jbe spd_set_drb_loop_top
/* o.k. I'm done return now */
RET_LABEL(spd_set_drb)
/*
* Routine: spd_set_dramc
* Arguments: None
*
* Trashed: %eax, %ebx, %edx, %esp, %eflags
* Effects: Uses serial presence detect to set the
* DRAMC register, which records if ram is registerd or not,
* and controls the refresh rate.
* The refresh rate is not set here, as memory refresh
* cannot be enbaled until after memory is initialized.
* see spd_enable_refresh.
* Notes:
* FIXME: Check for illegal/unsupported ram configurations and abort
* FIXME: won't work with non-contiguous DRAM size regs (like VIA)
* need an indirect pointer to an array of reg #s
*/
spd_set_dramc:
/* auto detect if ram is registered or not. */
/* The DRAMC register also contorls the refresh rate but we can't
* set that here because we must leave refresh disabled.
* see: spd_enable_refresh
*/
/* Find the first dimm and assume the rest are the same */
/* Load the smbus device and port int %ebx */
movl $((21 << 8) | SMBUS_MEM_DEVICE_0), %ebx
1: CALLSP(smbus_read_byte)
jz 2f
andl $0x12, %eax
jmp spd_set_dramc_out
2: addl $1, %ebx /* increment the device */
cmpb $LAST_SMBUS_MEM_DEVICE, %bl
jbe 1b
/* We couldn't find anything we must have no memory */
jmp no_memory
spd_set_dramc_out:
testb $0x12, %al
jz 2f
movl REGISTERED_DRAM, %eax
jmp 1f
2: movl NONREGISTERED_DRAM, %eax
1: movl %eax, %edx
movl REGISTERED_DRAM_REGISTER, %eax
PCI_WRITE_CONFIG_BYTE
RET_LABEL(spd_set_dramc)
/*
* Routine: spd_read_refresh
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esp, %eflags
* Effects: Uses serial presence detect to find refresh rates.
* returns the rate in %eax
* It's up to you to set hardware up.
* FIXME: Check for illegal/unsupported ram configurations and abort
*/
spd_read_refresh:
/* Find the first dimm and assume the rest are the same */
/* Load the smbus device and port int %ebx */
movl $((12 << 8) | SMBUS_MEM_DEVICE_0), %ebx
1: CALLSP(smbus_read_byte)
jz 2f
andl $0x7f, %eax
jmp spd_enable_refresh_out
2: addl $1, %ebx /* increment the device */
cmpb $LAST_SMBUS_MEM_DEVICE, %bl
jbe 1b
/* We couldn't find anything we must have no memory */
xorl %eax, %eax
spd_enable_refresh_out:
RET_LABEL(spd_enable_refresh)
/*
* Routine: spd_set_rps
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esi, %edi, %esp, %eflags
* Effects: Uses serial presence detect to set the row size
* on a given DIMM
* Notes: %esi accumulates the row sizes of all of the DIMMs
* %ecx holds the current bit into into %esi
* %bl holds the current SMBUS device
* FIXME: Check for illegal/unsupported ram configurations and abort
*/
spd_set_rps:
/* The RPS register holds the size of a ``page'' of DRAM on each DIMM */
/* default all page sizes to 2KB */
xorl %esi, %esi
/* Index into %esi of bit to set */
movl $0 , %ecx
/* Load the smbus device into %ebx */
movl $SMBUS_MEM_DEVICE_0, %ebx
1: movb $3, %bh
CALLSP(smbus_read_byte) /* row address bits */
jz 2f
andl $0xf, %eax
movl %eax, %edi
/* I now have the row page size as a power of 2 */
subl $11, %edi /* Now make it in multiples of 2Kb */
jbe 2f
/* FIXME: do something with page sizes greather than 8KB!! */
shll %cl, %edi
orl %edi, %esi
/* side two */
movb $5, %bh
CALLSP(smbus_read_byte) /* number of physical banks */
cmp $1, %al
jbe 2f
/* for now only handle the symmtrical case */
shll $2, %edi
shll %cl, %edi
orl %edi, %esi
2: addl $1, %ebx /* increment the device */
addl $4, %ecx /* increment the shift count */
cmpb $LAST_SMBUS_MEM_DEVICE, %bl
jbe 1b
movl $0x7f, %eax
/* I'm not sure what we should do here. Do nothing. */
/* PCI_WRITE_CONFIG_WORD*/
RET_LABEL(spd_set_rps)
/*
* Routine: spd_set_pgpol
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esi, %esp, %eflags
* Effects: Uses serial presence detect to set the number of banks
* on a given DIMM
* Notes: %esi accumulates the banks sizes of all of the DIMMs
* %ecx holds the current bit into into %esi
* %bl holds the current SMBUS device
* FIXME: Check for illegal/unsupported ram configurations and abort
*/
spd_set_pgpol:
/* The PGPOL register stores the number of logical banks per DIMM,
* and number of clocks the DRAM controller waits in the idle
* state.
*/
/* default all bank counts 2 */
xorl %esi, %esi
/* Index into %esi of bit to set */
movl $0 , %ecx
/* Load the smbus device into %ebx */
movl $SMBUS_MEM_DEVICE_0, %ebx
1: movb $17, %bh
CALLSP(smbus_read_byte) /* logical banks */
jz 2f
cmp $0x4, %eax
jl 2f
movl $0x1, %eax
shll %cl, %eax
orl %eax, %esi
/* side two */
movb $5, %bh
CALLSP(smbus_read_byte) /* number of physical banks */
cmp $1, %al
jbe 2f
/* for now only handle the symmtrical case */
movl $0x2, %eax
shll %cl, %eax
orl %eax, %esi
2: addl $1, %ebx /* increment the device */
addl $2, %ecx /* increment the shift count */
cmpb $LAST_SMBUS_MEM_DEVICE, %bl
jbe 1b
shll $8, %esi
orl $0x7, %esi /* 32 clocks idle time */
movl %esi, %ecx
movl $0x78, %eax
/* I'm unclear on the concept for non-intel devices */
/* PCI_WRITE_CONFIG_WORD*/
RET_LABEL(spd_set_pgpol)
/*
* Routine: spd_enable_nbxcfg
* Arguments: None
*
* Trashed: %eax, %ebx, %ecx, %edx, %esi, %esp, %eflags
* Effects: Uses serial presence detect to set the
* ECC support flags in the NBXCFG register
* Notes: %esi accumulates the ECC support of the individual DIMMs.
* %ecx holds the bit that should be flipped for the current DIMM.
* %bl holds the smbus device that corresponds to the current DIMM.
* FIXME: Check for illegal/unsupported ram configurations and abort
*/
spd_set_nbxcfg:
/* say all dimms have no ECC support */
movl $0xFF, %esi
/* Index into %esi of bit to set */
movl $0 , %ecx
/* Load the smbus device into %ebx */
movl $SMBUS_MEM_DEVICE_0, %ebx
1: movb $11, %bh
CALLSP(smbus_read_byte) /* module error correction type */
jz 2f
cmp $0x2, %eax /* 0 == None, 1 == Parity, 2 == ECC */
jne 2f
movl $0x1, %eax
shll %cl, %eax
xorl %eax, %esi
/* side two */
movb $5, %bh
CALLSP(smbus_read_byte) /* number of physical banks */
cmp $1, %al
jbe 2f
/* The only is the symmtrical case */
movl $0x2, %eax
shll %cl, %eax
xorl %eax, %esi
2: addl $1, %ebx /* increment the device */
addl $2, %ecx /* increment the shift count */
cmpb $LAST_SMBUS_MEM_DEVICE, %bl
jbe 1b
movl %esi, %edx
/* at some point, we need to indicate how to turn ECC on. Not yet.
movl $0x53, %eax
PCI_WRITE_CONFIG_BYTE
*/
RET_LABEL(spd_set_nbxcfg)
smbus_pcibus_end:
CALL_LABEL(enable_smbus)
CALL_LABEL(setup_smbus)

Some files were not shown because too many files have changed in this diff Show more