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:
parent
ddf646c178
commit
9e334b9ec3
105 changed files with 6483 additions and 1703 deletions
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
|
|
|||
|
|
@ -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
21
src/arch/i386/lib/id.inc
Normal 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
6
src/arch/i386/lib/id.lds
Normal file
|
|
@ -0,0 +1,6 @@
|
|||
SECTIONS {
|
||||
. = (_ROMBASE + ROM_IMAGE_SIZE - 0x10) - (__id_end - __id_start);
|
||||
.id (.): {
|
||||
*(.id)
|
||||
}
|
||||
}
|
||||
|
|
@ -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;
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1,5 +1,6 @@
|
|||
#include <arch/cache_ram.h>
|
||||
|
||||
|
||||
/* copy data segment from FLASH ROM to CACHE */
|
||||
movl $_clrodata, %esi
|
||||
movl $_rodata, %edi
|
||||
|
|
|
|||
123
src/cpu/i786/cache_ram_test.inc
Normal file
123
src/cpu/i786/cache_ram_test.inc
Normal 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')
|
||||
|
||||
|
||||
|
|
@ -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) {
|
||||
|
|
|
|||
|
|
@ -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
|
||||
*/
|
||||
|
|
|
|||
99
src/cpu/i786/logical_cpu.inc
Normal file
99
src/cpu/i786/logical_cpu.inc
Normal 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
|
||||
|
||||
|
||||
|
|
@ -1,3 +1,3 @@
|
|||
option k7
|
||||
option CPU_FIXUP
|
||||
option k7=1
|
||||
option CPU_FIXUP=1
|
||||
object cpufixup.o
|
||||
|
|
|
|||
|
|
@ -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
100
src/cpu/p5/delay_tsc.c
Normal 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);
|
||||
}
|
||||
}
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
3
src/include/cpu/i786/thermal_monitoring.h
Normal file
3
src/include/cpu/i786/thermal_monitoring.h
Normal file
|
|
@ -0,0 +1,3 @@
|
|||
#define THERMAL_MONITORING_OFF 0
|
||||
#define THERMAL_MONITORING_SET 0x00000008
|
||||
#define MISC_ENABLE 0x01a0
|
||||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
19
src/include/southbridge/amd/amd766.h
Normal file
19
src/include/southbridge/amd/amd766.h
Normal 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 */
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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
|
|
@ -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
|
||||
|
|
@ -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();
|
||||
|
||||
|
|
|
|||
|
|
@ -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... */
|
||||
|
|
|
|||
265
src/mainboard/supermicro/p4dc6p/Config
Normal file
265
src/mainboard/supermicro/p4dc6p/Config
Normal 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
|
||||
104
src/mainboard/supermicro/p4dc6p/example-fallback.config
Normal file
104
src/mainboard/supermicro/p4dc6p/example-fallback.config
Normal 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
|
||||
|
||||
105
src/mainboard/supermicro/p4dc6p/example-normal.config
Normal file
105
src/mainboard/supermicro/p4dc6p/example-normal.config
Normal 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
|
||||
|
||||
29
src/mainboard/supermicro/p4dc6p/irq_tables.c
Normal file
29
src/mainboard/supermicro/p4dc6p/irq_tables.c
Normal 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}
|
||||
}
|
||||
};
|
||||
202
src/mainboard/supermicro/p4dc6p/mainboard.c
Normal file
202
src/mainboard/supermicro/p4dc6p/mainboard.c
Normal 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");
|
||||
}
|
||||
|
||||
}
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
138
src/mainboard/supermicro/p4dc6p/mptable.c
Normal file
138
src/mainboard/supermicro/p4dc6p/mptable.c
Normal 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);
|
||||
}
|
||||
|
||||
|
||||
49
src/mainboard/supermicro/p4dc6p/mtrr_values.c
Normal file
49
src/mainboard/supermicro/p4dc6p/mtrr_values.c
Normal 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},
|
||||
};
|
||||
273
src/mainboard/supermicro/p4dpr/Config
Normal file
273
src/mainboard/supermicro/p4dpr/Config
Normal 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
|
||||
104
src/mainboard/supermicro/p4dpr/example-fallback.config
Normal file
104
src/mainboard/supermicro/p4dpr/example-fallback.config
Normal 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
|
||||
|
||||
105
src/mainboard/supermicro/p4dpr/example-normal.config
Normal file
105
src/mainboard/supermicro/p4dpr/example-normal.config
Normal 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
|
||||
|
||||
43
src/mainboard/supermicro/p4dpr/irq_tables.c
Normal file
43
src/mainboard/supermicro/p4dpr/irq_tables.c
Normal 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}
|
||||
}
|
||||
};
|
||||
209
src/mainboard/supermicro/p4dpr/mainboard.c
Normal file
209
src/mainboard/supermicro/p4dpr/mainboard.c
Normal 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
|
||||
|
||||
|
||||
|
||||
|
||||
1
src/mainboard/supermicro/p4dpr/mainboard_raminit.inc
Normal file
1
src/mainboard/supermicro/p4dpr/mainboard_raminit.inc
Normal file
|
|
@ -0,0 +1 @@
|
|||
|
||||
197
src/mainboard/supermicro/p4dpr/mptable.c
Normal file
197
src/mainboard/supermicro/p4dpr/mptable.c
Normal 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);
|
||||
}
|
||||
|
||||
|
|
@ -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
|
||||
|
||||
|
||||
|
|
|
|||
|
|
@ -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();
|
||||
}
|
||||
|
|
|
|||
|
|
@ -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... */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
34
src/northbridge/amd/amd76x/amd76x_pci.c
Normal file
34
src/northbridge/amd/amd76x/amd76x_pci.c
Normal 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));
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -5,4 +5,4 @@
|
|||
movl $0x58, %eax
|
||||
PCI_READ_CONFIG_DWORD
|
||||
testl $(1<<25), %eax
|
||||
jnz __cpu_reset
|
||||
jnz __cpu_reset
|
||||
|
|
|
|||
|
|
@ -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:
|
||||
|
|
@ -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)
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
|
|
|
|||
9
src/northbridge/intel/E7500/Config
Normal file
9
src/northbridge/intel/E7500/Config
Normal 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
|
||||
18
src/northbridge/intel/E7500/northbridge.c
Normal file
18
src/northbridge/intel/E7500/northbridge.c
Normal 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;
|
||||
|
||||
}
|
||||
1140
src/northbridge/intel/E7500/raminit.inc
Normal file
1140
src/northbridge/intel/E7500/raminit.inc
Normal file
File diff suppressed because it is too large
Load diff
10
src/northbridge/intel/E7500/reset_test.inc
Normal file
10
src/northbridge/intel/E7500/reset_test.inc
Normal 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
|
||||
118
src/northbridge/intel/E7500/sdram_enable.inc
Normal file
118
src/northbridge/intel/E7500/sdram_enable.inc
Normal 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:
|
||||
|
|
@ -1 +1,3 @@
|
|||
object ide.o
|
||||
#object ide_probe.o
|
||||
|
||||
|
|
|
|||
|
|
@ -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 */
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -1 +1,2 @@
|
|||
object ramtest.o USE_RAMTEST
|
||||
#object ramtest.o USE_RAMTEST
|
||||
object ramtest.o
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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;
|
||||
}
|
||||
|
||||
|
|
|
|||
|
|
@ -108,6 +108,7 @@ ramtest:
|
|||
6:
|
||||
CONSOLE_INFO_TX_STRING($rt_done)
|
||||
mov %ebp, %esp
|
||||
|
||||
#endif
|
||||
RETSP
|
||||
|
||||
|
|
|
|||
|
|
@ -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
|
||||
|
||||
|
||||
|
||||
|
||||
|
|
|
|||
48
src/southbridge/amd/amd766/amd766_ide.c
Normal file
48
src/southbridge/amd/amd766/amd766_ide.c
Normal 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
|
||||
}
|
||||
}
|
||||
14
src/southbridge/amd/amd766/amd766_ioapic.c
Normal file
14
src/southbridge/amd/amd766/amd766_ioapic.c
Normal 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));
|
||||
}
|
||||
|
||||
}
|
||||
17
src/southbridge/amd/amd766/amd766_lpc.c
Normal file
17
src/southbridge/amd/amd766/amd766_lpc.c
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
15
src/southbridge/amd/amd766/amd766_mem.c
Normal file
15
src/southbridge/amd/amd766/amd766_mem.c
Normal 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));
|
||||
}
|
||||
|
||||
}
|
||||
15
src/southbridge/amd/amd766/amd766_mouse.c
Normal file
15
src/southbridge/amd/amd766/amd766_mouse.c
Normal 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));
|
||||
}
|
||||
}
|
||||
13
src/southbridge/amd/amd766/amd766_pm.c
Normal file
13
src/southbridge/amd/amd766/amd766_pm.c
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
21
src/southbridge/amd/amd766/amd766_power.c
Normal file
21
src/southbridge/amd/amd766/amd766_power.c
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
15
src/southbridge/amd/amd766/amd766_reboot.c
Normal file
15
src/southbridge/amd/amd766/amd766_reboot.c
Normal 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;
|
||||
}
|
||||
39
src/southbridge/amd/amd766/amd766_reset.c
Normal file
39
src/southbridge/amd/amd766/amd766_reset.c
Normal 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));
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
17
src/southbridge/amd/amd766/amd766_usb.c
Normal file
17
src/southbridge/amd/amd766/amd766_usb.c
Normal 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);
|
||||
}
|
||||
}
|
||||
15
src/southbridge/amd/amd766/amd766_watchdog.c
Normal file
15
src/southbridge/amd/amd766/amd766_watchdog.c
Normal 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));
|
||||
}
|
||||
}
|
||||
116
src/southbridge/amd/amd766/cmos_boot_failover.inc
Normal file
116
src/southbridge/amd/amd766/cmos_boot_failover.inc
Normal 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:
|
||||
50
src/southbridge/amd/amd766/cmos_reset_failover.inc
Normal file
50
src/southbridge/amd/amd766/cmos_reset_failover.inc
Normal 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:
|
||||
|
|
@ -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
|
||||
|
|
|
|||
|
|
@ -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);
|
||||
}
|
||||
|
|
|
|||
532
src/southbridge/intel/82801/smbus.inc
Normal file
532
src/southbridge/intel/82801/smbus.inc
Normal 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)
|
||||
|
||||
|
||||
40
src/southbridge/intel/82801ca/82801.h
Normal file
40
src/southbridge/intel/82801ca/82801.h
Normal 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)
|
||||
11
src/southbridge/intel/82801ca/Config
Normal file
11
src/southbridge/intel/82801ca/Config
Normal 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
|
||||
124
src/southbridge/intel/82801ca/cmos_failover.inc
Normal file
124
src/southbridge/intel/82801ca/cmos_failover.inc
Normal 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
|
||||
|
||||
31
src/southbridge/intel/82801ca/ich3_1e0_misc.c
Normal file
31
src/southbridge/intel/82801ca/ich3_1e0_misc.c
Normal 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
|
||||
|
||||
}
|
||||
30
src/southbridge/intel/82801ca/ich3_1f0_misc.c
Normal file
30
src/southbridge/intel/82801ca/ich3_1f0_misc.c
Normal 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);
|
||||
}
|
||||
37
src/southbridge/intel/82801ca/ich3_cpu.c
Normal file
37
src/southbridge/intel/82801ca/ich3_cpu.c
Normal 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);
|
||||
}
|
||||
24
src/southbridge/intel/82801ca/ich3_ide.c
Normal file
24
src/southbridge/intel/82801ca/ich3_ide.c
Normal 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);
|
||||
}
|
||||
|
||||
}
|
||||
45
src/southbridge/intel/82801ca/ich3_ioapic.c
Normal file
45
src/southbridge/intel/82801ca/ich3_ioapic.c
Normal 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(;;);
|
||||
|
||||
|
||||
}
|
||||
33
src/southbridge/intel/82801ca/ich3_lpc.c
Normal file
33
src/southbridge/intel/82801ca/ich3_lpc.c
Normal 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);
|
||||
}
|
||||
21
src/southbridge/intel/82801ca/ich3_power.c
Normal file
21
src/southbridge/intel/82801ca/ich3_power.c
Normal 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");
|
||||
}
|
||||
9
src/southbridge/intel/82801ca/ich3_reset.c
Normal file
9
src/southbridge/intel/82801ca/ich3_reset.c
Normal 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);
|
||||
}
|
||||
|
||||
23
src/southbridge/intel/82801ca/ich3_rtc.c
Normal file
23
src/southbridge/intel/82801ca/ich3_rtc.c
Normal 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);
|
||||
}
|
||||
121
src/southbridge/intel/82801ca/ich3_smbus.c
Normal file
121
src/southbridge/intel/82801ca/ich3_smbus.c
Normal 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;
|
||||
}
|
||||
8
src/southbridge/intel/82801ca/nvram.c
Normal file
8
src/southbridge/intel/82801ca/nvram.c
Normal file
|
|
@ -0,0 +1,8 @@
|
|||
#include <part/nvram.h>
|
||||
#include <printk.h>
|
||||
|
||||
void nvram_on(void)
|
||||
{
|
||||
printk_notice("Please turn on nvram\n");
|
||||
return;
|
||||
}
|
||||
532
src/southbridge/intel/82801ca/smbus.inc
Normal file
532
src/southbridge/intel/82801ca/smbus.inc
Normal 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
Loading…
Add table
Add a link
Reference in a new issue