From 9e334b9ec34339c13d14100703d7ea44c8f6ae27 Mon Sep 17 00:00:00 2001 From: "Eric W. Biederman" Date: Thu, 20 Jun 2002 00:11:56 +0000 Subject: [PATCH] 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 --- src/arch/i386/boot/linuxbios_table.c | 32 +- src/arch/i386/lib/cpu_reset.inc | 83 -- src/arch/i386/lib/hardwaremain.c | 48 +- src/arch/i386/lib/id.inc | 21 + src/arch/i386/lib/id.lds | 6 + src/arch/i386/smp/start_stop.c | 21 +- src/cpu/i786/cache_ram_init.inc | 21 +- src/cpu/i786/cache_ram_start.inc | 1 + src/cpu/i786/cache_ram_test.inc | 123 ++ src/cpu/i786/delay_i786.c | 2 +- src/cpu/i786/earlymtrr.inc | 1 + src/cpu/i786/logical_cpu.inc | 99 ++ src/cpu/k7/Config | 4 +- src/cpu/k7/earlymtrr.inc | 18 +- src/cpu/p5/delay_tsc.c | 100 ++ src/include/boot/linuxbios_table.h | 1 + src/include/boot/linuxbios_tables.h | 9 + src/include/cpu/i786/thermal_monitoring.h | 3 + src/include/cpu/k7/mtrr.h | 20 +- src/include/pc80/mc146818rtc.h | 4 + src/include/pci_ids.h | 11 + src/include/southbridge/amd/amd766.h | 19 + src/lib/compute_ip_checksum.c | 24 +- src/lib/subr.c | 3 +- src/mainboard/asus/a7m/Config | 1 - src/mainboard/supermicro/p4dc6/Config | 19 +- src/mainboard/supermicro/p4dc6/cacheramtest.c | 1077 ---------------- src/mainboard/supermicro/p4dc6/failover.inc | 10 - src/mainboard/supermicro/p4dc6/mainboard.c | 8 +- src/mainboard/supermicro/p4dc6/mptable.c | 16 +- src/mainboard/supermicro/p4dc6p/Config | 265 ++++ .../supermicro/p4dc6p/example-fallback.config | 104 ++ .../supermicro/p4dc6p/example-normal.config | 105 ++ src/mainboard/supermicro/p4dc6p/irq_tables.c | 29 + src/mainboard/supermicro/p4dc6p/mainboard.c | 202 +++ src/mainboard/supermicro/p4dc6p/mptable.c | 138 ++ src/mainboard/supermicro/p4dc6p/mtrr_values.c | 49 + src/mainboard/supermicro/p4dpr/Config | 273 ++++ .../supermicro/p4dpr/example-fallback.config | 104 ++ .../supermicro/p4dpr/example-normal.config | 105 ++ src/mainboard/supermicro/p4dpr/irq_tables.c | 43 + src/mainboard/supermicro/p4dpr/mainboard.c | 209 +++ .../supermicro/p4dpr/mainboard_raminit.inc | 1 + src/mainboard/supermicro/p4dpr/mptable.c | 197 +++ src/mainboard/tyan/guiness/Config | 296 ++++- src/mainboard/tyan/guiness/mainboard.c | 408 +----- src/mainboard/tyan/guiness/mptable.c | 16 +- src/northbridge/amd/amd76x/Config | 3 +- src/northbridge/amd/amd76x/amd76x_pci.c | 34 + src/northbridge/amd/amd76x/mpinit.inc | 24 +- src/northbridge/amd/amd76x/northbridge.c | 2 +- src/northbridge/amd/amd76x/raminit.inc | 4 - src/northbridge/amd/amd76x/reset_test.inc | 2 +- .../amd/amd76x/set_memory_size.inc | 22 +- src/northbridge/intel/82860/rdram_debug.c | 3 +- src/northbridge/intel/82860/rdram_setup.c | 161 ++- src/northbridge/intel/E7500/Config | 9 + src/northbridge/intel/E7500/northbridge.c | 18 + src/northbridge/intel/E7500/raminit.inc | 1140 +++++++++++++++++ src/northbridge/intel/E7500/reset_test.inc | 10 + src/northbridge/intel/E7500/sdram_enable.inc | 118 ++ src/pc80/ide/Config | 2 + src/pc80/mc146818rtc.c | 56 +- src/pc80/serial.inc | 6 +- src/ram/Config | 3 +- src/ram/dump_northbridge.inc | 16 + src/ram/ramtest.c | 11 +- src/ram/ramtest.inc | 1 + src/southbridge/amd/amd766/Config | 13 + src/southbridge/amd/amd766/amd766_ide.c | 48 + src/southbridge/amd/amd766/amd766_ioapic.c | 14 + src/southbridge/amd/amd766/amd766_lpc.c | 17 + src/southbridge/amd/amd766/amd766_mem.c | 15 + src/southbridge/amd/amd766/amd766_mouse.c | 15 + src/southbridge/amd/amd766/amd766_pm.c | 13 + src/southbridge/amd/amd766/amd766_power.c | 21 + src/southbridge/amd/amd766/amd766_reboot.c | 15 + src/southbridge/amd/amd766/amd766_reset.c | 39 + src/southbridge/amd/amd766/amd766_usb.c | 17 + src/southbridge/amd/amd766/amd766_watchdog.c | 15 + .../amd/amd766/cmos_boot_failover.inc | 116 ++ .../amd/amd766/cmos_reset_failover.inc | 50 + src/southbridge/intel/82801/cmos_failover.inc | 37 +- src/southbridge/intel/82801/ich2_ioapic.c | 8 +- src/southbridge/intel/82801/smbus.inc | 532 ++++++++ src/southbridge/intel/82801ca/82801.h | 40 + src/southbridge/intel/82801ca/Config | 11 + .../intel/82801ca/cmos_failover.inc | 124 ++ src/southbridge/intel/82801ca/ich3_1e0_misc.c | 31 + src/southbridge/intel/82801ca/ich3_1f0_misc.c | 30 + src/southbridge/intel/82801ca/ich3_cpu.c | 37 + src/southbridge/intel/82801ca/ich3_ide.c | 24 + src/southbridge/intel/82801ca/ich3_ioapic.c | 45 + src/southbridge/intel/82801ca/ich3_lpc.c | 33 + src/southbridge/intel/82801ca/ich3_power.c | 21 + src/southbridge/intel/82801ca/ich3_reset.c | 9 + src/southbridge/intel/82801ca/ich3_rtc.c | 23 + src/southbridge/intel/82801ca/ich3_smbus.c | 121 ++ src/southbridge/intel/82801ca/nvram.c | 8 + src/southbridge/intel/82801ca/smbus.inc | 532 ++++++++ src/southbridge/intel/82870/82870.h | 5 + src/southbridge/intel/82870/Config | 1 + src/southbridge/intel/82870/p64h2_ioapic.c | 80 ++ util/config/NLBConfig.py | 35 +- util/lb-dump/dump_lb_table.c | 13 +- 105 files changed, 6491 insertions(+), 1711 deletions(-) create mode 100644 src/arch/i386/lib/id.inc create mode 100644 src/arch/i386/lib/id.lds create mode 100644 src/cpu/i786/cache_ram_test.inc create mode 100644 src/cpu/i786/logical_cpu.inc create mode 100644 src/cpu/p5/delay_tsc.c create mode 100644 src/include/cpu/i786/thermal_monitoring.h create mode 100644 src/include/southbridge/amd/amd766.h create mode 100644 src/mainboard/supermicro/p4dc6p/Config create mode 100644 src/mainboard/supermicro/p4dc6p/example-fallback.config create mode 100644 src/mainboard/supermicro/p4dc6p/example-normal.config create mode 100644 src/mainboard/supermicro/p4dc6p/irq_tables.c create mode 100644 src/mainboard/supermicro/p4dc6p/mainboard.c create mode 100644 src/mainboard/supermicro/p4dc6p/mptable.c create mode 100644 src/mainboard/supermicro/p4dc6p/mtrr_values.c create mode 100644 src/mainboard/supermicro/p4dpr/Config create mode 100644 src/mainboard/supermicro/p4dpr/example-fallback.config create mode 100644 src/mainboard/supermicro/p4dpr/example-normal.config create mode 100644 src/mainboard/supermicro/p4dpr/irq_tables.c create mode 100644 src/mainboard/supermicro/p4dpr/mainboard.c create mode 100644 src/mainboard/supermicro/p4dpr/mainboard_raminit.inc create mode 100644 src/mainboard/supermicro/p4dpr/mptable.c create mode 100644 src/northbridge/amd/amd76x/amd76x_pci.c create mode 100644 src/northbridge/intel/E7500/Config create mode 100644 src/northbridge/intel/E7500/northbridge.c create mode 100644 src/northbridge/intel/E7500/raminit.inc create mode 100644 src/northbridge/intel/E7500/reset_test.inc create mode 100644 src/northbridge/intel/E7500/sdram_enable.inc create mode 100644 src/southbridge/amd/amd766/amd766_ide.c create mode 100644 src/southbridge/amd/amd766/amd766_ioapic.c create mode 100644 src/southbridge/amd/amd766/amd766_lpc.c create mode 100644 src/southbridge/amd/amd766/amd766_mem.c create mode 100644 src/southbridge/amd/amd766/amd766_mouse.c create mode 100644 src/southbridge/amd/amd766/amd766_pm.c create mode 100644 src/southbridge/amd/amd766/amd766_power.c create mode 100644 src/southbridge/amd/amd766/amd766_reboot.c create mode 100644 src/southbridge/amd/amd766/amd766_reset.c create mode 100644 src/southbridge/amd/amd766/amd766_usb.c create mode 100644 src/southbridge/amd/amd766/amd766_watchdog.c create mode 100644 src/southbridge/amd/amd766/cmos_boot_failover.inc create mode 100644 src/southbridge/amd/amd766/cmos_reset_failover.inc create mode 100644 src/southbridge/intel/82801/smbus.inc create mode 100644 src/southbridge/intel/82801ca/82801.h create mode 100644 src/southbridge/intel/82801ca/Config create mode 100644 src/southbridge/intel/82801ca/cmos_failover.inc create mode 100644 src/southbridge/intel/82801ca/ich3_1e0_misc.c create mode 100644 src/southbridge/intel/82801ca/ich3_1f0_misc.c create mode 100644 src/southbridge/intel/82801ca/ich3_cpu.c create mode 100644 src/southbridge/intel/82801ca/ich3_ide.c create mode 100644 src/southbridge/intel/82801ca/ich3_ioapic.c create mode 100644 src/southbridge/intel/82801ca/ich3_lpc.c create mode 100644 src/southbridge/intel/82801ca/ich3_power.c create mode 100644 src/southbridge/intel/82801ca/ich3_reset.c create mode 100644 src/southbridge/intel/82801ca/ich3_rtc.c create mode 100644 src/southbridge/intel/82801ca/ich3_smbus.c create mode 100644 src/southbridge/intel/82801ca/nvram.c create mode 100644 src/southbridge/intel/82801ca/smbus.inc create mode 100644 src/southbridge/intel/82870/82870.h create mode 100644 src/southbridge/intel/82870/Config create mode 100644 src/southbridge/intel/82870/p64h2_ioapic.c diff --git a/src/arch/i386/boot/linuxbios_table.c b/src/arch/i386/boot/linuxbios_table.c index 699cef6033..6d7c51593c 100644 --- a/src/arch/i386/boot/linuxbios_table.c +++ b/src/arch/i386/boot/linuxbios_table.c @@ -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 */ diff --git a/src/arch/i386/lib/cpu_reset.inc b/src/arch/i386/lib/cpu_reset.inc index 1c375b7ebb..c7c05e2198 100644 --- a/src/arch/i386/lib/cpu_reset.inc +++ b/src/arch/i386/lib/cpu_reset.inc @@ -1,89 +1,6 @@ jmp cpu_reset_out -#include -#include -#include - - -.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 diff --git a/src/arch/i386/lib/hardwaremain.c b/src/arch/i386/lib/hardwaremain.c index 1de6ccf4e6..fa70f3ef9a 100644 --- a/src/arch/i386/lib/hardwaremain.c +++ b/src/arch/i386/lib/hardwaremain.c @@ -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 #include #include @@ -58,6 +62,7 @@ static char rcsid[] = "$Id$"; #include #include #include +#include /* 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 + /* copy data segment from FLASH ROM to CACHE */ movl $_clrodata, %esi movl $_rodata, %edi diff --git a/src/cpu/i786/cache_ram_test.inc b/src/cpu/i786/cache_ram_test.inc new file mode 100644 index 0000000000..4ca259e21e --- /dev/null +++ b/src/cpu/i786/cache_ram_test.inc @@ -0,0 +1,123 @@ +#include + +#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') + + diff --git a/src/cpu/i786/delay_i786.c b/src/cpu/i786/delay_i786.c index d9d7fb9a77..e134145818 100644 --- a/src/cpu/i786/delay_i786.c +++ b/src/cpu/i786/delay_i786.c @@ -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) { diff --git a/src/cpu/i786/earlymtrr.inc b/src/cpu/i786/earlymtrr.inc index 21553489a4..751b597cde 100644 --- a/src/cpu/i786/earlymtrr.inc +++ b/src/cpu/i786/earlymtrr.inc @@ -1,5 +1,6 @@ #include + /* The fixed and variable MTRRs are powered-up with random values, clear them to * MTRR_TYPE_UNCACHABLE for safty reason */ diff --git a/src/cpu/i786/logical_cpu.inc b/src/cpu/i786/logical_cpu.inc new file mode 100644 index 0000000000..2c739c48ac --- /dev/null +++ b/src/cpu/i786/logical_cpu.inc @@ -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 + + diff --git a/src/cpu/k7/Config b/src/cpu/k7/Config index 287bc09e4a..fb58ad0840 100644 --- a/src/cpu/k7/Config +++ b/src/cpu/k7/Config @@ -1,3 +1,3 @@ -option k7 -option CPU_FIXUP +option k7=1 +option CPU_FIXUP=1 object cpufixup.o diff --git a/src/cpu/k7/earlymtrr.inc b/src/cpu/k7/earlymtrr.inc index 59c7bf78fa..b190ce3a19 100644 --- a/src/cpu/k7/earlymtrr.inc +++ b/src/cpu/k7/earlymtrr.inc @@ -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: diff --git a/src/cpu/p5/delay_tsc.c b/src/cpu/p5/delay_tsc.c new file mode 100644 index 0000000000..4e84ff4d6f --- /dev/null +++ b/src/cpu/p5/delay_tsc.c @@ -0,0 +1,100 @@ +#include +#include +#include + +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); + } +} diff --git a/src/include/boot/linuxbios_table.h b/src/include/boot/linuxbios_table.h index a5aeb95d68..f653c6fa93 100644 --- a/src/include/boot/linuxbios_table.h +++ b/src/include/boot/linuxbios_table.h @@ -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 diff --git a/src/include/boot/linuxbios_tables.h b/src/include/boot/linuxbios_tables.h index aa4686dcb1..0e5ddbb404 100644 --- a/src/include/boot/linuxbios_tables.h +++ b/src/include/boot/linuxbios_tables.h @@ -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 */ diff --git a/src/include/cpu/i786/thermal_monitoring.h b/src/include/cpu/i786/thermal_monitoring.h new file mode 100644 index 0000000000..163f6e6649 --- /dev/null +++ b/src/include/cpu/i786/thermal_monitoring.h @@ -0,0 +1,3 @@ +#define THERMAL_MONITORING_OFF 0 +#define THERMAL_MONITORING_SET 0x00000008 +#define MISC_ENABLE 0x01a0 diff --git a/src/include/cpu/k7/mtrr.h b/src/include/cpu/k7/mtrr.h index 10c27be83c..02973457f1 100644 --- a/src/include/cpu/k7/mtrr.h +++ b/src/include/cpu/k7/mtrr.h @@ -3,10 +3,26 @@ #include -#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 */ diff --git a/src/include/pc80/mc146818rtc.h b/src/include/pc80/mc146818rtc.h index 3b8428d636..726734f364 100644 --- a/src/include/pc80/mc146818rtc.h +++ b/src/include/pc80/mc146818rtc.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 diff --git a/src/include/pci_ids.h b/src/include/pci_ids.h index bab1d0bbd3..a02e8e5a63 100644 --- a/src/include/pci_ids.h +++ b/src/include/pci_ids.h @@ -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 diff --git a/src/include/southbridge/amd/amd766.h b/src/include/southbridge/amd/amd766.h new file mode 100644 index 0000000000..b8d0fe90c5 --- /dev/null +++ b/src/include/southbridge/amd/amd766.h @@ -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 */ diff --git a/src/lib/compute_ip_checksum.c b/src/lib/compute_ip_checksum.c index 0402387e54..ab41f97437 100644 --- a/src/lib/compute_ip_checksum.c +++ b/src/lib/compute_ip_checksum.c @@ -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) diff --git a/src/lib/subr.c b/src/lib/subr.c index 64101b5647..c11ed6196b 100644 --- a/src/lib/subr.c +++ b/src/lib/subr.c @@ -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(); diff --git a/src/mainboard/asus/a7m/Config b/src/mainboard/asus/a7m/Config index 6c0fb9f070..31b485d88e 100644 --- a/src/mainboard/asus/a7m/Config +++ b/src/mainboard/asus/a7m/Config @@ -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 diff --git a/src/mainboard/supermicro/p4dc6/Config b/src/mainboard/supermicro/p4dc6/Config index 21c873302d..55ec3c5dd2 100644 --- a/src/mainboard/supermicro/p4dc6/Config +++ b/src/mainboard/supermicro/p4dc6/Config @@ -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) diff --git a/src/mainboard/supermicro/p4dc6/cacheramtest.c b/src/mainboard/supermicro/p4dc6/cacheramtest.c index 26592b2945..e69de29bb2 100644 --- a/src/mainboard/supermicro/p4dc6/cacheramtest.c +++ b/src/mainboard/supermicro/p4dc6/cacheramtest.c @@ -1,1077 +0,0 @@ -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include -#include - -#define LPC_BUS 0 -#define LPC_DEVFN ((0x1f << 3) + 0) - -#define ICH2HUB_BUS 0 -#define ICH2HUB_DEVFN ((0x1e << 3) + 0) - -#define I860MCH_BUS 0 -#define I860MCH_DEVFN ((0x00 << 3) + 0) - -#define I860HUBA_BUS 0 -#define I860HUBA_DEVFN ((0x01 << 3) + 0) - -#define I860HUBB_BUS 0 -#define I860HUBB_DEVFN ((0x02 << 3) + 0) - -#define SMBUS_MEM_DEVICE_0 (0xa << 3) - -#define TSCYCLE_SLOW 1000 /* ns */ -#define TSCYCLE_FAST 10 /* ns */ -static void ndelay(unsigned long); -static void ram_zap(unsigned long, unsigned long); - -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); -} - -#define I860_MCH_BUS 0 -#define I860_MCH_DEVFN 0 - -#define MCH_GAR0 0x40 -#define MCH_GAR1 0x41 -#define MCH_GAR2 0x42 -#define MCH_GAR3 0x43 -#define MCH_GAR4 0x44 -#define MCH_GAR5 0x45 -#define MCH_GAR6 0x46 -#define MCH_GAR7 0x47 -#define MCH_GAR8 0x48 -#define MCH_GAR9 0x49 -#define MCH_GAR10 0x4a -#define MCH_GAR11 0x4b -#define MCH_GAR12 0x4c -#define MCH_GAR13 0x4d -#define MCH_GAR14 0x4e -#define MCH_GAR15 0x4f -#define MCH_MCHCFG 0x50 -#define MCH_FDHC 0x58 -#define MCH_PAM0 0x59 -#define MCH_PAM1 0x5a -#define MCH_PAM2 0x5b -#define MCH_PAM3 0x5c -#define MCH_PAM4 0x5d -#define MCH_PAM5 0x5e -#define MCH_PAM6 0x5f -#define MCH_GBA0 0x60 -#define MCH_GBA1 0x62 -#define MCH_GBA2 0x64 -#define MCH_GBA3 0x66 -#define MCH_GBA4 0x68 -#define MCH_GBA5 0x6a -#define MCH_GBA6 0x6c -#define MCH_GBA7 0x6e -#define MCH_GBA8 0x70 -#define MCH_GBA9 0x72 -#define MCH_GBA10 0x74 -#define MCH_GBA11 0x76 -#define MCH_GBA12 0x78 -#define MCH_GBA13 0x7a -#define MCH_GBA14 0x7c -#define MCH_GBA15 0x7e -#define MCH_RDPS 0x88 -#define MCH_DRD 0x90 -#define MCH_RICM 0x94 -#define MCH_SMRAM 0x9d -#define MCH_ESMRAM 0x9e -#define MCH_RDT 0xbe -#define MCH_TOM 0xc4 -#define MCH_ERRSTS 0xc8 -#define MCH_ERRCMD 0xca -#define MCH_SMICMD 0xcc -#define MCH_SCICMD 0xce -#define MCH_DRAMRC 0xdc -#define MCH_DERRCTL 0xe2 -#define MCH_EAP 0xe4 - -#define RICM_BUSY (1 << 23) -#define RICM_DONE (1 << 27) - - -#define __S(NAME) NAME##_SHIFT -#define __B(NAME) NAME##_BITS -#define __BIT_MASK(SHIFT, BITS) ((1 << (BITS + SHIFT)) - (1 << (SHIFT))) -#define MASK(NAME) __BIT_MASK(__S(NAME), __B(NAME)) -#define NVAL(NAME, VAL) (MASK(NAME) & ((VAL) << __S(NAME))) -#define VAL(NAME, VALUE) ((MASK(NAME) & VALUE) >> __S(NAME)) - -#define RICM_CMD_SHIFT 0 -#define RICM_CMD_BITS 5 -#define RICM_ADDR_SHIFT 5 -#define RICM_ADDR_BITS 5 -#define RICM_REG_SHIFT 10 -#define RICM_REG_BITS 9 -#define RICM_BROADCAST_SHIFT 19 -#define RICM_BROADCAST_BITS 1 -#define RICM_CHANNEL_SHIFT 20 -#define RICM_CHANNEL_BITS 2 - -#define CMD_RDRAM_READ_REG 0 -#define CMD_RDRAM_WRITE_REG 1 -#define CMD_RDRAM_SET_RESET 2 -#define CMD_SET_FAST_CLK 4 -#define CMD_TEMP_CALIBRATE_ENABLE 5 -#define CMD_TEMP_CALIBRATE 6 -#define CMD_MRH_REDIRECT_NEXT_SIO 8 -#define CMD_MRH_STICK_SIO_RESET 9 -#define CMD_RDRAM_CLEAR_RESET 11 -#define CMD_RDRAM_CURRENT_CALIBRATION 16 -#define CMD_RDRAM_SIO_RESET 17 -#define CMD_RDRAM_POWERDOWN_EXIT 18 -#define CMD_RDRAM_POWERDOWN_ENTRY 19 -#define CMD_RDRAM_NAP_ENTRY 20 -#define CMD_RDRAM_NAP_EXIT 21 -#define CMD_RDRAM_REFRESH 22 -#define CMD_RDRAM_PRECHARGE 23 -#define CMD_MANUAL_CURRENT_CALIBRATION 24 -#define CMD_MCH_RAC_LOAD_RACA_CONFIG 25 -#define CMD_MCH_RAC_LOAD_RACB_CONFIG 26 -#define CMD_MCH_INITIALIZE_RAC 27 -#define CMD_MCH_RAC_CURRENT_CALIBRATION 28 -#define CMD_MCH_RAC_TEMP_CALIBRATE 29 -#define CMD_POWERUP_ALL_SEQUENCE 31 - -#define REG_INIT 0x21 -#define REG_TEST34 0x22 -#define REG_CNFGA 0x23 -#define REG_CNFGB 0x24 -#define REG_DEVID 0x40 -#define REG_REFB 0x41 -#define REG_REFR 0x42 -#define REG_CCA 0x43 -#define REG_CCB 0x44 -#define REG_NAPX 0x45 -#define REG_PDNXA 0x46 -#define REG_PDNX 0x47 -#define REG_TPARM 0x48 -#define REG_TFRM 0x49 -#define REG_TCDLY1 0x4a -#define REG_SKIP 0x4b -#define REG_TCYCLE 0x4c -#define REG_TEST77 0x4d -#define REG_TEST78 0x4e -#define REG_TEST79 0x4f - -#define BCAST 0xffff - -static void rdram_wait_until_ready(void) -{ - u32 ricm; - do { - pcibios_read_config_dword(I860_MCH_BUS, I860_MCH_DEVFN, MCH_RICM, &ricm); - } while(ricm & RICM_BUSY); - ndelay(1000); /* delay after ready because the documentation says to */ -} - -struct rdram_reg_values { - u16 channel_a; - u16 channel_b; -}; - -/* rdram timing tables */ -static u16 tparm[5]={0x3a,0x3a,0x3a,0x4a,0x5a}; -static u16 tcdly1[5]={0,1,2,2,2}; - -/* serial presence detect needed variables */ -/* Byte 99 number of devices for each stick */ -static u8 spd_devices[4]={0,0,0,0}; -/* Byte 4 # of row address bits, # of column address bits */ -static u8 spd_row_col[4]={0,0,0,0}; -/* Byte 5 # of bank bits lower nibble */ -static u8 spd_banks[4]={0,0,0,0}; -/* Byte 9 Misc. Device configuration S28, and S3 bits are used */ -static u8 spd_misc_conf[4]={0,0,0,0}; -/* Byte 31 power down exit max time phase A (tPDNXA,max) */ -static u8 spd_pdnxa_max[4]={0,0,0,0}; -/* Byte 32 power down exit max time phase B (tPDNXB,max) */ -static u8 spd_pdnxb_max[4]={0,0,0,0}; -/* Byte 33 Map exit max time phase A (tNAPXA,max) */ -static u8 spd_napxa_max[4]={0,0,0,0}; -/* Byte 34 Nap exit max time phase B (tNAPXB,max) */ -static u8 spd_napxb_max[4]={0,0,0,0}; -/* Byte 12 Min ras to cas cycles */ -static u8 spd_rcd_min[4]={0,0,0,0}; -/* Byte 100 Module data width */ -static u8 spd_data_width[4]={0,0,0,0}; -/* Byte 35 bits 0-3<<8 + byte 37 give the rdram max mhz rate */ -static u16 spd_mhz_max[4]={0,0,0,0}; -/* Byte 35 bits 4-7<<4 + byte 36 give the rdram min mhz rate */ -static u16 spd_mhz_min[4]={0,0,0,0}; -/* The size of each device in mega bytes. */ -static u8 spd_size[2]={0,0}; - -static int rdram_chips=0; /* number of ram chips on the rimms */ -static u32 total_rdram; /* Total rdram found */ - -/* register index tables */ -static u8 mch_gar[16] ={MCH_GAR0,MCH_GAR1,MCH_GAR2,MCH_GAR3,MCH_GAR4,MCH_GAR5, - MCH_GAR6,MCH_GAR7,MCH_GAR8,MCH_GAR9,MCH_GAR10,MCH_GAR11, - MCH_GAR12,MCH_GAR13,MCH_GAR14,MCH_GAR15}; - -static u8 mch_gba[16] ={MCH_GBA0,MCH_GBA1,MCH_GBA2,MCH_GBA3,MCH_GBA4,MCH_GBA5, - MCH_GBA6,MCH_GBA7,MCH_GBA8,MCH_GBA9,MCH_GBA10,MCH_GBA11, - MCH_GBA12,MCH_GBA13,MCH_GBA14,MCH_GBA15}; - -static void __rdram_run_command(u8 channel, u16 sdevice_id, u16 reg, u16 command) -{ - u32 ricm; - int broadcast; - - broadcast = 0; - if (sdevice_id == BCAST) { - broadcast = 1; - sdevice_id = 0; - } - - /* Read the old register value and modify it */ - pcibios_read_config_dword(I860_MCH_BUS, I860_MCH_DEVFN, MCH_RICM, &ricm); - ricm &= ~(MASK(RICM_CHANNEL) | MASK(RICM_BROADCAST) | MASK(RICM_ADDR) | - MASK(RICM_REG) | MASK(RICM_CMD)); - ricm |= NVAL(RICM_CHANNEL, channel); - ricm |= NVAL(RICM_BROADCAST, broadcast); - ricm |= NVAL(RICM_ADDR, sdevice_id); - ricm |= NVAL(RICM_REG, reg); - ricm |= NVAL(RICM_CMD, command); - - /* Write the command */ - pcibios_write_config_dword(I860_MCH_BUS, I860_MCH_DEVFN, MCH_RICM, ricm); - - /* Start the command running */ - ricm |= RICM_BUSY; - pcibios_write_config_dword(I860_MCH_BUS, I860_MCH_DEVFN, MCH_RICM, ricm); - - /* Wait until the command completes */ - rdram_wait_until_ready(); -} - -static void rdram_run_command(u8 channel, u16 sdevice_id, u16 command) -{ - /* Wait until the previous cmd completes */ - rdram_wait_until_ready(); - - /* Run the command */ - __rdram_run_command(channel, sdevice_id, 0, command); -} - -static void rdram_read_reg(u8 channel, u16 sdevice_id, u16 reg, struct rdram_reg_values *res) -{ - u32 drd; - - /* Wait until the previous cmd completes */ - rdram_wait_until_ready(); - - __rdram_run_command(channel, sdevice_id, reg, CMD_RDRAM_READ_REG); - - /* Read back the register value */ - pcibios_read_config_dword(I860_MCH_BUS, I860_MCH_DEVFN, MCH_DRD, &drd); - - res->channel_a = (drd >> 16) &0xffff; - res->channel_b = drd & 0xffff; - return; -} - - -static void rdram_write_reg(u8 channel, u16 sdevice_id, u16 reg, - u16 channel_a, u16 channel_b) -{ - u32 drd; - - /* Wait until the previous cmd completes */ - rdram_wait_until_ready(); - - - /* Write the data values */ - drd = (((u32)channel_a) << 16) | channel_b; - pcibios_write_config_dword(I860_MCH_BUS, I860_MCH_DEVFN, MCH_DRD, drd); - - __rdram_run_command(channel, sdevice_id, reg, CMD_RDRAM_WRITE_REG); - - /* Wait until the command completes */ - rdram_wait_until_ready(); - - return; -} - -u16 rdram_regs[] = { - REG_INIT, - REG_TEST34, - REG_CNFGA, - REG_CNFGB, - REG_DEVID, - REG_REFB, - REG_REFR, - REG_CCA, - REG_CCB, - REG_NAPX, - REG_PDNXA, - REG_PDNX, - REG_TPARM, - REG_TFRM, - REG_TCDLY1, - REG_SKIP, - REG_TCYCLE, - REG_TEST77, - REG_TEST78, - REG_TEST79, -}; -char *rdram_reg_names[] = { - "INIT", - "TEST34", - "CNFGA", - "CNFGB", - "DEVID", - "REFB", - "REFR", - "CCA", - "CCB", - "NAPX", - "PDNXA", - "PDNX", - "TPARM", - "TFRM", - "TCDLY1", - "SKIP", - "TCYCLE", - "TEST77", - "TEST78", - "TEST79", -}; - -static void set_sdevid(int rdram_devices) -{ - int i; - /* First disable the repeater and set every RDRAM to the - * maximum address I can address - */ - rdram_write_reg(0, BCAST, REG_INIT, 0x1f, 0x1f); - for(i = 0; i < rdram_devices; i++) { - /* Set SDEVID and reenable the repeater */ - rdram_write_reg(0, 0x1f, REG_INIT, - (1 << 7) | (i & 0x1f), (1 << 7) | (i & 0x1f)); - - } -} - -static void set_devid(int rdram_devices) -{ - int i; - for(i = 0; i < rdram_devices; i++) { - /* FIXME make this smarter */ - /* Initially set DEVID == SDEVID */ - if ((i % 4) != 5) { - rdram_write_reg(0, i, REG_DEVID, i, i ); - } else { - rdram_write_reg(0, i, REG_DEVID, 0x1f, i); - } - } -} - -static void set_init_bits(int rdram_devices) -{ - int i; - for(i = 0; i < rdram_devices; i++) { - /* Now that the chip is up and running setup the - * power management modes. - */ - rdram_write_reg(0, i, REG_INIT, - (1 << 9) | (1 << 7) | (1 << 6) | (i & 0x1f), - (1 << 9) | (1 << 7) | (1 << 6) | (i & 0x1f) - ); - } -} - -static void rdram_read_domain_initialization(int rdram_devices) -{ - u8 rdt=0x8d; - int i,j,k; - u32 data; - u32 *mem; - u8 adj_a[32],adj_b[32]; - u8 l=20; - - total_rdram=0; - /* Set all the rdram devices to the fastest clock cycles */ - rdram_write_reg(0, BCAST, REG_TCDLY1, 0, 0 ); - rdram_write_reg(0, BCAST, REG_TPARM, 0x3a, 0x3a); - - /* find the slowest RDT timming */ - pcibios_write_config_byte(I860_MCH_BUS,I860_MCH_DEVFN,MCH_RDT,rdt); - mem=RAM_ADDR(0x100000); - for(j=0;j7) { - data-=00000004; - i=0; - } - mem[k]=data; - } - printk_debug("Device = %d, %x, %x\n",j,mem[0],mem[4]); - adj_a[j]=(mem[0]&0x0ff)-1; - adj_b[j]=(mem[4]&0x0ff)-1; - if(adj_a[j] count) { - rdtscll(count); - } -} - -static void rdram_set_clear_reset(void) -{ - int delay=0; - int tcycle; - - rdram_write_reg(0, BCAST, REG_TEST78, 0x04, 0x04); - rdram_write_reg(0, BCAST, REG_TEST34, 0x40, 0x40); - rdram_run_command(0, BCAST, CMD_RDRAM_SET_RESET); - /* Compute max of 16 * Tscycle or 2816 * Tcycle */ - if(spd_mhz_min[0]) { - tcycle=(999+spd_mhz_min[0])/spd_mhz_min[0]; - delay=tcycle*2816; - } - if(delay>(16*TSCYCLE_SLOW)) - ndelay(delay); - 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); -} - -/* - - ro CNFGA, CNFGB, - - ok REFB, REFR - - SKIP, TEST79 - TEST34, TEST78, - TEST77, - TCYCLE, - INIT, - DEVID, - PDNXA, PDNX, NAPX, TPARM, TCDLY1, TFRM, REG_CCA, REG, CCB -*/ -static void rdram_init(int rdram_devices) -{ - u16 tcycle; - u16 pdnxa,pdnxb,pdnx,napx,napxa,napxb; - u16 tfrm; - int i; - - /* 3.1/3.2 RDRAM SIO reset */ - rdram_run_command(0, 0, CMD_RDRAM_SIO_RESET); - - /* 3.3 Clear TEST77 */ - rdram_write_reg(0, BCAST, REG_TEST77, 0, 0); - - /* 3.4 Write Tcycle */ - /* Calculate the Tcycle */ - for(tcycle=spd_mhz_max[0],i=1;i<4;i++) - if(spd_mhz_max[i]&&(tcycle>spd_mhz_max[i])) - tcycle=spd_mhz_max[i]; - tcycle = 15625 / tcycle; - rdram_write_reg(0, BCAST, REG_TCYCLE, tcycle, tcycle); - printk_debug("Tcycle = %x\n",tcycle); - - /* 3.5 Set SDEVID */ - set_sdevid(rdram_devices); - - /* 3.6 Set DEVID */ - set_devid(rdram_devices); - - /* 3.7 Write PDNX, PDNXA Registers */ - /* tscycle=10ns or <= 100MHz MCH datasheet pg 156 */ - for(pdnxa=(u16)spd_pdnxa_max[0],i=1;i<4;i++) - if(pdnxa 10) - tfrm-=4; - } - else { - tfrm = 9; - } - rdram_write_reg(0, BCAST, REG_TFRM, tfrm, tfrm); - - /* 3.12 SETR/CLRR */ - rdram_set_clear_reset(); - - /* 3.13 Write CCA and CCB Registers */ - /* Program all Current controll registers with - * an initial approximation. 1/2 their maximum is recommended. - */ - rdram_write_reg(0, BCAST, REG_CCA, 0x40, 0x40); - rdram_write_reg(0, BCAST, REG_CCB, 0x40, 0x40); - - /* 3.14 Powerdown Exit */ - /* test is S28IECO is set, if yes power up ram from PDN state */ - if(spd_misc_conf[0]&4) - rdram_run_command(0, BCAST, CMD_RDRAM_POWERDOWN_EXIT); - - /* 3.15 SETF */ - rdram_run_command(0, BCAST, CMD_SET_FAST_CLK); -} - -void mch_init(void) -{ - u8 byte; - u16 word; -// u32 dword; - u16 top; - int bits1,bits2; - int reg,reg_last,dev; - - /* Program Group Attribute Registers */ - /* Calculate the GAR value */ - bits1=(spd_row_col[0]>>4)+(spd_row_col[0]&0x0f)+spd_banks[0]; - byte=0x80; - if(bits1==21) { - byte=0x84; - spd_size[0]=32; - } - else if(bits1==20) { - byte=0x82; - spd_size[0]=16; - } - if(byte!=0x80) { - if(spd_banks[0]==5) byte|=0x10; - if((spd_row_col[0]&0x0f)==7) byte|=0x40; - } - for(reg=dev=0;dev>4)+(spd_row_col[1]&0x0f)+spd_banks[1]; - byte=0x80; - if(bits2==21) { - byte=0x84; - spd_size[1]=32; - } - else if(bits2==20) { - byte=0x82; - spd_size[1]=16; - } - if(byte!=0x80) { - if(spd_banks[1]==5) byte|=0x10; - if((spd_row_col[1]&0x0f)==7) byte|=0x40; - } - for(dev=0;dev>4),(spd_row_col[i]&0x0f),spd_banks[i]); - for(i=0;i<2;i++) { - if(spd_devices&&(spd_devices[i]==spd_devices[i+2])&& - (spd_row_col[i]==spd_row_col[i+2])&& - (spd_banks[i]==spd_banks[i+2])) - rdram_devices+=spd_devices[i]; - } - if(rdram_devices==0){ - printk_debug("ERROR - Memory Rimms are not matched.\n"); - for(;;) i=1; /* Freeze the system error */ - } - else { - rdram_chips=rdram_devices; - } - printk_debug("RDRAM Chips = %d\n",rdram_chips); - - /* 1. Start the clocks */ - rdram_run_command(0, 0, CMD_POWERUP_ALL_SEQUENCE); - - /* 2. RAC initialization */ - rdram_run_command(0, 0, CMD_MCH_INITIALIZE_RAC); - - /* 3. Rdram initialize */ - rdram_init(rdram_devices); - - /* 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); - } - - /* 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 #include +#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... */ diff --git a/src/mainboard/supermicro/p4dc6p/Config b/src/mainboard/supermicro/p4dc6p/Config new file mode 100644 index 0000000000..f110e6bdf3 --- /dev/null +++ b/src/mainboard/supermicro/p4dc6p/Config @@ -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 diff --git a/src/mainboard/supermicro/p4dc6p/example-fallback.config b/src/mainboard/supermicro/p4dc6p/example-fallback.config new file mode 100644 index 0000000000..362c375515 --- /dev/null +++ b/src/mainboard/supermicro/p4dc6p/example-fallback.config @@ -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 + diff --git a/src/mainboard/supermicro/p4dc6p/example-normal.config b/src/mainboard/supermicro/p4dc6p/example-normal.config new file mode 100644 index 0000000000..0ce189d2bf --- /dev/null +++ b/src/mainboard/supermicro/p4dc6p/example-normal.config @@ -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 + diff --git a/src/mainboard/supermicro/p4dc6p/irq_tables.c b/src/mainboard/supermicro/p4dc6p/irq_tables.c new file mode 100644 index 0000000000..6c614c38ec --- /dev/null +++ b/src/mainboard/supermicro/p4dc6p/irq_tables.c @@ -0,0 +1,29 @@ +/* PCI: Interrupt Routing Table found at 0x4011ced0 size = 176 */ + +#include + +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} + } +}; diff --git a/src/mainboard/supermicro/p4dc6p/mainboard.c b/src/mainboard/supermicro/p4dc6p/mainboard.c new file mode 100644 index 0000000000..f1ad1cf3e4 --- /dev/null +++ b/src/mainboard/supermicro/p4dc6p/mainboard.c @@ -0,0 +1,202 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#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"); + } + +} + + + + + + diff --git a/src/mainboard/supermicro/p4dc6p/mptable.c b/src/mainboard/supermicro/p4dc6p/mptable.c new file mode 100644 index 0000000000..63361ac3da --- /dev/null +++ b/src/mainboard/supermicro/p4dc6p/mptable.c @@ -0,0 +1,138 @@ +#include +#include +#include + +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); +} + + diff --git a/src/mainboard/supermicro/p4dc6p/mtrr_values.c b/src/mainboard/supermicro/p4dc6p/mtrr_values.c new file mode 100644 index 0000000000..68c1a6eefc --- /dev/null +++ b/src/mainboard/supermicro/p4dc6p/mtrr_values.c @@ -0,0 +1,49 @@ +#include + +/* 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}, +}; diff --git a/src/mainboard/supermicro/p4dpr/Config b/src/mainboard/supermicro/p4dpr/Config new file mode 100644 index 0000000000..afc060c59d --- /dev/null +++ b/src/mainboard/supermicro/p4dpr/Config @@ -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 diff --git a/src/mainboard/supermicro/p4dpr/example-fallback.config b/src/mainboard/supermicro/p4dpr/example-fallback.config new file mode 100644 index 0000000000..362c375515 --- /dev/null +++ b/src/mainboard/supermicro/p4dpr/example-fallback.config @@ -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 + diff --git a/src/mainboard/supermicro/p4dpr/example-normal.config b/src/mainboard/supermicro/p4dpr/example-normal.config new file mode 100644 index 0000000000..0ce189d2bf --- /dev/null +++ b/src/mainboard/supermicro/p4dpr/example-normal.config @@ -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 + diff --git a/src/mainboard/supermicro/p4dpr/irq_tables.c b/src/mainboard/supermicro/p4dpr/irq_tables.c new file mode 100644 index 0000000000..0c23b742a9 --- /dev/null +++ b/src/mainboard/supermicro/p4dpr/irq_tables.c @@ -0,0 +1,43 @@ +/* PCI: Interrupt Routing Table found at 0x4011ce40 size = 416 */ + +#include + +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} + } +}; diff --git a/src/mainboard/supermicro/p4dpr/mainboard.c b/src/mainboard/supermicro/p4dpr/mainboard.c new file mode 100644 index 0000000000..22cb3adcdf --- /dev/null +++ b/src/mainboard/supermicro/p4dpr/mainboard.c @@ -0,0 +1,209 @@ +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include +#include + + +#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 + + + + diff --git a/src/mainboard/supermicro/p4dpr/mainboard_raminit.inc b/src/mainboard/supermicro/p4dpr/mainboard_raminit.inc new file mode 100644 index 0000000000..8d1c8b69c3 --- /dev/null +++ b/src/mainboard/supermicro/p4dpr/mainboard_raminit.inc @@ -0,0 +1 @@ + diff --git a/src/mainboard/supermicro/p4dpr/mptable.c b/src/mainboard/supermicro/p4dpr/mptable.c new file mode 100644 index 0000000000..25fd4b7a43 --- /dev/null +++ b/src/mainboard/supermicro/p4dpr/mptable.c @@ -0,0 +1,197 @@ +#include +#include +#include + +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); +} + diff --git a/src/mainboard/tyan/guiness/Config b/src/mainboard/tyan/guiness/Config index ca1cf7d8cb..1858aca259 100644 --- a/src/mainboard/tyan/guiness/Config +++ b/src/mainboard/tyan/guiness/Config @@ -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 + + diff --git a/src/mainboard/tyan/guiness/mainboard.c b/src/mainboard/tyan/guiness/mainboard.c index 16dcda9013..1eaeab3398 100644 --- a/src/mainboard/tyan/guiness/mainboard.c +++ b/src/mainboard/tyan/guiness/mainboard.c @@ -7,6 +7,11 @@ #include #include #include +#include +#include +#include +#include +#include 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(); } diff --git a/src/mainboard/tyan/guiness/mptable.c b/src/mainboard/tyan/guiness/mptable.c index 8fe88fcb80..b8334fadeb 100644 --- a/src/mainboard/tyan/guiness/mptable.c +++ b/src/mainboard/tyan/guiness/mptable.c @@ -3,12 +3,16 @@ #include #include +#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... */ diff --git a/src/northbridge/amd/amd76x/Config b/src/northbridge/amd/amd76x/Config index e7140ddefa..1073b29a2b 100644 --- a/src/northbridge/amd/amd76x/Config +++ b/src/northbridge/amd/amd76x/Config @@ -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 \ No newline at end of file +object northbridge.o +object amd76x_pci.o diff --git a/src/northbridge/amd/amd76x/amd76x_pci.c b/src/northbridge/amd/amd76x/amd76x_pci.c new file mode 100644 index 0000000000..07f68d6977 --- /dev/null +++ b/src/northbridge/amd/amd76x/amd76x_pci.c @@ -0,0 +1,34 @@ +#include +#include +#include + +/* 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)); + } +} + + diff --git a/src/northbridge/amd/amd76x/mpinit.inc b/src/northbridge/amd/amd76x/mpinit.inc index 44192d074c..319922c94d 100644 --- a/src/northbridge/amd/amd76x/mpinit.inc +++ b/src/northbridge/amd/amd76x/mpinit.inc @@ -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 diff --git a/src/northbridge/amd/amd76x/northbridge.c b/src/northbridge/amd/amd76x/northbridge.c index d6a0dfce47..86c630eccb 100644 --- a/src/northbridge/amd/amd76x/northbridge.c +++ b/src/northbridge/amd/amd76x/northbridge.c @@ -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 */ diff --git a/src/northbridge/amd/amd76x/raminit.inc b/src/northbridge/amd/amd76x/raminit.inc index 31a9c0e8a9..1b4a64a819 100644 --- a/src/northbridge/amd/amd76x/raminit.inc +++ b/src/northbridge/amd/amd76x/raminit.inc @@ -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 diff --git a/src/northbridge/amd/amd76x/reset_test.inc b/src/northbridge/amd/amd76x/reset_test.inc index 3c174bb11e..6414f5152f 100644 --- a/src/northbridge/amd/amd76x/reset_test.inc +++ b/src/northbridge/amd/amd76x/reset_test.inc @@ -5,4 +5,4 @@ movl $0x58, %eax PCI_READ_CONFIG_DWORD testl $(1<<25), %eax - jnz __cpu_reset + jnz __cpu_reset diff --git a/src/northbridge/amd/amd76x/set_memory_size.inc b/src/northbridge/amd/amd76x/set_memory_size.inc index 2506ec869a..49a07093f1 100644 --- a/src/northbridge/amd/amd76x/set_memory_size.inc +++ b/src/northbridge/amd/amd76x/set_memory_size.inc @@ -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: \ No newline at end of file diff --git a/src/northbridge/intel/82860/rdram_debug.c b/src/northbridge/intel/82860/rdram_debug.c index bea6a33d4b..dff7ad22ad 100644 --- a/src/northbridge/intel/82860/rdram_debug.c +++ b/src/northbridge/intel/82860/rdram_debug.c @@ -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) diff --git a/src/northbridge/intel/82860/rdram_setup.c b/src/northbridge/intel/82860/rdram_setup.c index 1275901315..f32ddc2d1b 100644 --- a/src/northbridge/intel/82860/rdram_setup.c +++ b/src/northbridge/intel/82860/rdram_setup.c @@ -16,6 +16,8 @@ #include #include #include +#include + #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](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 +#include +#include +#include + +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; + +} diff --git a/src/northbridge/intel/E7500/raminit.inc b/src/northbridge/intel/E7500/raminit.inc new file mode 100644 index 0000000000..5df9ce7b6a --- /dev/null +++ b/src/northbridge/intel/E7500/raminit.inc @@ -0,0 +1,1140 @@ +jmp intel_E7500_out + +#define USE_SPD 0 + +#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 + +#if 1 +#define DRB0 0x10 +#define DRB1 0x10 +#define DRB2 0x10 +#define DRB3 0x10 +#define DRB4 0x10 +#define DRB5 0x10 +#define DRB6 0x10 +#define DRB7 0x10 +#else +/* Conservative setting 8MB of ram on first DIMM... */ +#define DRB0 0x01 +#define DRB1 0x01 +#define DRB2 0x01 +#define DRB3 0x01 +#define DRB4 0x01 +#define DRB5 0x01 +#define DRB6 0x01 +#define DRB7 0x01 +#endif + +#define DRA0 0x0c +#define DRA1 0x0 +#define DRA2 0x0 +#define DRA3 0x0 +#define DRA4 0x0 +#define DRA5 0x0 +#define DRA6 0x0 +#define DRA7 0x0 + + +#define CAS_LATENCY 3 + + /* CAS latency 2 */ +#if (CAS_LATENCY == 2) +#define CAS_NB 0x17 + /* + * 7 == 0111 + * 1 == 0001 + */ +#define CAS_MODE 0x2a + /* + * a == 1010 + * 2 == 0010 + */ +#endif + + /* CAS latency 3 */ +#if (CAS_LATENCY == 3) +#define CAS_NB 0x13 + /* + * 3 == 0011 + * 1 == 0001 + */ +#define CAS_MODE 0x3a + /* + * a == 1010 + * 3 == 0011 + */ +#endif + +#ifndef CAS_NB +#error "Nothing defined" +#endif + +#if 0 +#define RAM_READ 0x0400 +#else +#define RAM_READ 0x0000 +#endif + +#define DIMM0_BASE \ + xorl %eax, %eax + +#define DIMM_BASE(n) \ + movl $(0x60 + ((n) -1)), %eax ; \ + PCI_READ_CONFIG_BYTE ; \ + andl $0xFF, %eax ; \ + shll $26, %eax ; \ + +#define DIMM_READ \ + addl %ebx, %eax ; \ +#if 0 + movl (%eax), %edx ; \ + xorl $0xdff8, %eax ; \ +#endif + movl (%eax), %edx + +#define DIMM0_READ DIMM0_BASE ; DIMM_READ +#define DIMM1_READ DIMM_BASE(1) ; DIMM_READ +#define DIMM2_READ DIMM_BASE(2) ; DIMM_READ +#define DIMM3_READ DIMM_BASE(3) ; DIMM_READ +#define DIMM4_READ DIMM_BASE(4) ; DIMM_READ +#define DIMM5_READ DIMM_BASE(5) ; DIMM_READ +#define DIMM6_READ DIMM_BASE(6) ; DIMM_READ +#define DIMM7_READ DIMM_BASE(7) ; DIMM_READ + +#define DIMMS_READ_EBX_OFFSET \ + DIMM0_READ ; \ + DIMM1_READ ; \ + DIMM2_READ ; \ + DIMM3_READ ; \ + DIMM4_READ ; \ + DIMM5_READ ; \ + DIMM6_READ ; \ + DIMM7_READ + +#define DIMMS_READ(offset) \ + movl $offset, %ebx ; \ + DIMMS_READ_EBX_OFFSET + +#define MD_SHIFT 4 + +#define RAM_COMMAND_NONE 0x0 +#define RAM_COMMAND_NOP 0x1 +#define RAM_COMMAND_PRECHARGE 0x2 +#define RAM_COMMAND_MRS 0x3 +#define RAM_COMMAND_EMRS 0x4 +#define RAM_COMMAND_CBR 0x6 +#define RAM_COMMAND_NORMAL 0x7 + +#define SET_RAM_COMMAND(command) \ + movl $0x7c, %eax ; \ + PCI_READ_CONFIG_BYTE ; \ + andl $0x8F, %eax ; \ + orl $((command) << 4), %eax ; \ + movl %eax, %edx ; \ + movl $0x7c, %eax ; \ + PCI_WRITE_CONFIG_BYTE + +#if 0 +#define COMPUTE_CAS_MODE \ + movl $0x76, %eax ; \ + PCI_READ_CONFIG_BYTE ; \ + andl $0x4, %eax ; \ + xorl $0x4, %eax ; \ + shll $2, %eax ; \ + orl $0x2a, %eax ; \ + +#endif + +#define SET_RAM_MODE_REGISTER \ + SET_RAM_COMMAND(RAM_COMMAND_MRS) ; \ + COMPUTE_CAS_MODE ; \ + shll $3, %eax ; \ + movl %eax, %ebx ; \ + DIMMS_READ_EBX_OFFSET + +#if 0 +#define ASSERT_RAM_COMMAND() DIMMS_READ(RAM_READ) +#define ASSERT_MRS_RAM_COMMAND(mode) DIMMS_READ(mode) +#else +#define ASSERT_RAM_COMMAND() movl (0), %eax +#endif + +#if 0 +#if ! USE_SPD +#define ENABLE_REFRESH() \ + movl $(0x57), %eax ; \ + PCI_READ_CONFIG_BYTE ; \ + orb 0x1, %al ; \ + mov %al, %dl ; \ + movl $(0x57), %eax ; \ + PCI_WRITE_CONFIG_BYTE + +#else /* USE_SPD */ +#define ENABLE_REFRESH() CALL_LABEL(spd_enable_refresh) +#endif +#else +#define ENABLE_REFRESH() \ + CS_WRITE_BYTE(0x7d, 0x02) ; \ + CS_WRITE_BYTE(0x7e, 0x45) ; \ + CS_WRITE_BYTE(0x7f, 0x20) + +#endif + +/* Default values for config registers */ + + /* NBXCFG 0x50 - 0x53 */ + /* f == 1111 + * 0 == 0000 + * 0 == 0000 + * 0 == 0000 + * 0 == 0000 + * 1 == 0001 + * 8 == 1000 + * c == 1100 + * SDRAM Row without ECC: + * row 0 == 1 No ECC + * row 1 == 1 No ECC + * row 2 == 1 No ECC + * row 3 == 1 No ECC + * row 4 == 1 No ECC + * row 5 == 1 No ECC + * row 6 == 1 No ECC + * row 7 == 1 No ECC + * Host Bus Fast Data Ready Enable == 0 Disabled + * IDSEL_REDIRECT == 0 (430TX compatibility disable?) + * WSC# Hanshake Disable == 0 enable (Use External IOAPIC) + * Host/DRAM Frequence == 00 100Mhz + * AGP to PCI Access Enable == 0 Disable + * PCI Agent to Aperture Access Disable == 0 Enable (Ignored) + * Aperture Access Global Enable == 0 Disable + * DRAM Data Integrity Mode == 11 (Error Checking/Correction) + * ECC Diagnostic Mode Enable == 0 Not Enabled + * MDA present == 0 Not Present + * USWC Write Post During During I/O Bridge Access Enable == 1 Enabled + * In Order Queue Depth (IQD) (RO) == ?? + */ +#if 0 +#define SET_NBXCFG \ + CS_WRITE_LONG(0x50, 0xff00018c) +#else +#define SET_NBXCFG \ + CS_WRITE_LONG(0x50, 0xff00000c) +#endif + +#define SET_DRAMC \ + /* DRAMC */ \ + CS_WRITE_BYTE(0x57, 0x8) \ + /* 0 == 0000 \ + * 8 == 1000 \ + * Not registered SDRAM \ + * refresh disabled \ + */ + + /* PAM - Programmable Attribute Map Registers */ + /* Ideally we want to enable all of these as DRAM and teach + * linux it is o.k. to use them... + */ +#define SET_PAM \ + CS_WRITE_BYTE(0x59, 0x30) ; \ + CS_WRITE_BYTE(0x5a, 0x33) ; \ + CS_WRITE_BYTE(0x5b, 0x33) ; \ + CS_WRITE_BYTE(0x5c, 0x33) ; \ + CS_WRITE_BYTE(0x5d, 0x33) ; \ + CS_WRITE_BYTE(0x5e, 0x33) ; \ + CS_WRITE_BYTE(0x5f, 0x33) + +#define SET_DRB \ + /* DRB - DRAM Row Boundary Registers */ \ + CS_WRITE_BYTE(0x60, DRB0) ; \ + CS_WRITE_BYTE(0x61, DRB1) ; \ + CS_WRITE_BYTE(0x62, DRB2) ; \ + CS_WRITE_BYTE(0x63, DRB3) ; \ + CS_WRITE_BYTE(0x64, DRB4) ; \ + CS_WRITE_BYTE(0x65, DRB5) ; \ + CS_WRITE_BYTE(0x66, DRB6) ; \ + CS_WRITE_BYTE(0x67, DRB7) + +#define SET_DRA \ + /* DRA - DRAM Row Attribute Registers */ \ + CS_WRITE_BYTE(0x70, DRA0) ; \ + CS_WRITE_BYTE(0x71, DRA1) ; \ + CS_WRITE_BYTE(0x72, DRA2) ; \ + CS_WRITE_BYTE(0x73, DRA3) ; \ + CS_WRITE_BYTE(0x74, DRA4) ; \ + CS_WRITE_BYTE(0x75, DRA5) ; \ + CS_WRITE_BYTE(0x76, DRA6) ; \ + CS_WRITE_BYTE(0x77, DRA7) + + +#define SET_TOLM \ + /* TOLM - Top Of Low Memory Registers */ \ + CS_WRITE_BYTE(0xc4, 0x00) ; \ + CS_WRITE_BYTE(0xc5, 0x80) + +#define SET_DVNP \ + /* DVNP - Device Not Present Registers */ \ + CS_WRITE_BYTE(0xe0, 0x1e) + + + /* FDHC */ +#define SET_FDHC \ + CS_WRITE_BYTE(0x68, 0x00) + + +#if 0 + /* MBSC - Memory Buffer Strength Control */ + /* 00c00003e820 + * [47:44] 0 == 0000 + * [43:40] 0 == 0000 + * [39:36] c == 1100 + * [35:32] 0 == 0000 + * [31:28] 0 == 0000 + * [27:24] 0 == 0000 + * [23:20] 0 == 0000 + * [19:16] 3 == 0011 + * [15:12] e == 1110 + * [11: 8] 8 == 1000 + * [ 7: 4] 2 == 0010 + * [ 3: 0] 0 == 0000 + * MAA[14:0]#, WEA#, SRASA#, SCASA# Buffer Strengths == 3x + * MAB[14,13,10,12:11,9:0]#, WEB#, SRASB#, SCASB# Buffer Strengths == 1x + * MD[63:0]# Buffer Strength Control 2 == 1x + * MD[63:0]# Buffer Strength Control 1 == 1x + * MECC[7:0] Buffer Strength Control 2 == 1x + * MECC[7:0] Buffer Strength Control 1 == 1x + * CSB7# Buffer Strength == 1x + * CSA7# Buffer Strength == 1x + * CSB6# Buffer Strength == 1x + * CSA6# Buffer Strength == 1x + * CSA5#/CSB5# Buffer Strength == 1x + * CSA4#/CSB4# Buffer Strength == 1x + * CSA3#/CSB3# Buffer Strength == 2x + * CSA2#/CSB2# Buffer Strength == 2x + * CSA1#/CSB1# Buffer Strength == 2x + * CSA0#/CSB0# Buffer Strength == 2x + * DQMA5 Buffer Strength == 2x + * DQMA1 Buffer Strength == 2x + * DQMB5 Buffer Strength == 1x + * DQMB1 Buffer Strength == 1x + * DQMA[7:6,4:2,0] Buffer Strength == 2x + * GCKE Buffer Strength == 1x + * FENA Buffer Strength == 1x + */ + +#define SET_MBSC \ + CS_WRITE_BYTE(0x69, 0x20) ; \ + CS_WRITE_BYTE(0x6a, 0xe8) ; \ + CS_WRITE_BYTE(0x6b, 0x03) ; \ + CS_WRITE_BYTE(0x6c, 0x00) ; \ + CS_WRITE_BYTE(0x6d, 0xc0) ; \ + CS_WRITE_BYTE(0x6e, 0x00) +#else + /* MBSC - Memory Buffer Strength Control */ + /* 00c00003e820 + * [47:44] 0 == 0000 + * [43:40] 0 == 0000 + * [39:36] c == 1100 + * [35:32] 0 == 0000 + * [31:28] 0 == 0000 + * [27:24] 0 == 0000 + * [23:20] 0 == 0000 + * [19:16] 3 == 0011 + * [15:12] e == 1110 + * [11: 8] 8 == 1000 + * [ 7: 4] 2 == 0010 + * [ 3: 0] 0 == 0000 + * MAA[14:0]#, WEA#, SRASA#, SCASA# Buffer Strengths == 3x + * MAB[14,13,10,12:11,9:0]#, WEB#, SRASB#, SCASB# Buffer Strengths == 3x + * MD[63:0]# Buffer Strength Control 2 == 3x + * MD[63:0]# Buffer Strength Control 1 == 3x + * MECC[7:0] Buffer Strength Control 2 == 3x + * MECC[7:0] Buffer Strength Control 1 == 3x + * CSB7# Buffer Strength == 3x + * CSA7# Buffer Strength == 3x + * CSB6# Buffer Strength == 3x + * CSA6# Buffer Strength == 3x + * CSA5#/CSB5# Buffer Strength == 2x + * CSA4#/CSB4# Buffer Strength == 2x + * CSA3#/CSB3# Buffer Strength == 2x + * CSA2#/CSB2# Buffer Strength == 2x + * CSA1#/CSB1# Buffer Strength == 2x + * CSA0#/CSB0# Buffer Strength == 2x + * DQMA5 Buffer Strength == 2x + * DQMA1 Buffer Strength == 3x + * DQMB5 Buffer Strength == 2x + * DQMB1 Buffer Strength == 2x + * DQMA[7:6,4:2,0] Buffer Strength == 3x + * GCKE Buffer Strength == 1x + * FENA Buffer Strength == 3x + */ +#define SET_MBSC \ + CS_WRITE_BYTE(0x69, 0xB3) ; \ + CS_WRITE_BYTE(0x6a, 0xee) ; \ + CS_WRITE_BYTE(0x6b, 0xff) ; \ + CS_WRITE_BYTE(0x6c, 0xff) ; \ + CS_WRITE_BYTE(0x6d, 0xff) ; \ + CS_WRITE_BYTE(0x6e, 0x03) +#endif + + + /* 0x72 SMRAM */ + /* 1 == 0001 + * a == 1010 + * SMM Compatible base segment == 010 (Hardcoded value) + */ +#define SET_SMRAM + /* 0x73 ESMRAMC */ +#define SET_ESRAMC + + /* RPS - Row Page Size Register */ + /* 0x0055 + * [15:12] 0 == 0000 + * [11: 8] 0 == 0000 + * [ 7: 4] 5 == 0101 + * [ 3: 0] 5 == 0101 + * DRB[0] == 4KB + * DRB[1] == 4KB + * DRB[2] == 4KB + * DRB[3] == 4KB + * DRB[4] == 2KB + * DRB[5] == 2KB + * DRB[6] == 2KB + * DRB[7] == 2KB + */ +#define SET_RPS \ + CS_WRITE_WORD(0x74, 0x5555) + + /* SDRAMC */ +#define SET_SDRAMC \ + CS_WRITE_BYTE(0x76, CAS_NB) + + + /* PGPOL - Paging Policy Register */ + /* 0xff07 + * [15:12] f == 1111 + * [11: 8] f == 1111 + * [ 7: 4] 0 == 0000 + * [ 3: 0] 7 == 0111 + * row0 == 4banks + * row1 == 4banks + * row2 == 4banks + * row3 == 4banks + * row4 == 4banks + * row5 == 4banks + * row6 == 4banks + * row7 == 4banks + * Dram Idle Timer (DIT) == 32 clocks + */ +#define SET_PGPOL \ + CS_WRITE_WORD(0x78, 0xff07) + + /* MBFS - Memory Buffer Frequencey Select Register */ + /* 0xffff7f + * [23:20] f == 1111 + * [19:16] f == 1111 + * [15:12] f == 1111 + * [11: 8] f == 1111 + * [ 7: 4] 7 == 0111 + * [ 3: 0] f == 1111 + * MAA[14:0], WEA#, SRASA#, SCASA# == 100Mhz Buffers Enabled + * MAB[14,13,10,12:11,9:0], WEB#, SRASB#, SCASB# == 100Mhz Buffers Enabled + * MD[63:0] Control 2 == 100 Mhz Buffer Enable + * MD[63:0] Control 1 == 100 Mhz B + * MECC[7:0] Control 2 == 100 Mhz B + * + */ +#define SET_MBFS \ + CS_WRITE_BYTE(0xca, 0xff) ; \ + CS_WRITE_BYTE(0xcb, 0xff) ; \ + CS_WRITE_BYTE(0xcc, 0x7f) + + /* DWTC - DRAM Write Thermal Throttle Control */ +#define SET_DWTC \ + CS_WRITE_BYTE(0xe0, 0xb4) ; \ + CS_WRITE_BYTE(0xe1, 0xbe) ; \ + CS_WRITE_BYTE(0xe2, 0xff) ; \ + CS_WRITE_BYTE(0xe3, 0xd7) ; \ + CS_WRITE_BYTE(0xe4, 0x97) ; \ + CS_WRITE_BYTE(0xe5, 0x3e) ; \ + CS_WRITE_BYTE(0xe6, 0x00) ; \ + CS_WRITE_BYTE(0xe7, 0x80) + + /* DRTC - DRAM Read Thermal Throttle Control */ +#define SET_DRTC \ + CS_WRITE_BYTE(0xe8, 0x2c) ; \ + CS_WRITE_BYTE(0xe9, 0xd3) ; \ + CS_WRITE_BYTE(0xea, 0xf7) ; \ + CS_WRITE_BYTE(0xeb, 0xcf) ; \ + CS_WRITE_BYTE(0xec, 0x9d) ; \ + CS_WRITE_BYTE(0xed, 0x3e) ; \ + CS_WRITE_BYTE(0xee, 0x00) ; \ + CS_WRITE_BYTE(0xef, 0x00) + +/* PMCR -- BIOS sets 0x90 into it. + * 0x10 is REQUIRED. + * we have never used it. So why did this ever work? + */ +#define SET_PMCR \ + CS_WRITE_BYTE(0x7a, 0x90); + +#define SET_DRT \ + CS_WRITE_BYTE(0x78, 0x0f) ; \ + CS_WRITE_BYTE(0x79, 0x04) ; \ + CS_WRITE_BYTE(0x7a, 0x00) ; \ + CS_WRITE_BYTE(0x7b, 0x01) + +ram_set_registers: + SET_DRB + SET_PAM + SET_DRA + SET_DRT + SET_TOLM + SET_DVNP + RET_LABEL(ram_set_registers) + + +#define DEVFN(device, function) (((device) << 3) + (function)) +#define CONFIG_ADDR(bus,devfn,where) (((bus) << 16) | ((devfn) << 8) | (where)) +#define PM_FUNCTION CONFIG_ADDR(0, PIIX4_DEVFN+3, 0) + +#if USE_SPD + +#define SMBUS_IO_BASE 0x1000 +#define SMBHSTSTAT 0 +#define SMBHSTCTL 2 +#define SMBHSTCMD 3 +#define SMBHSTADD 4 +#define SMBHSTDAT0 5 +#define SMBHSTDAT1 6 +#define SMBBLKDAT 7 + +enable_smbus: + CS_WRITE_LONG(PM_FUNCTION + 0x90, SMBUS_IO_BASE | 1) /* iobase addr */ + CS_WRITE_BYTE(PM_FUNCTION + 0xd2, (0x4 << 1) | 1) /* smbus enable */ + CS_WRITE_WORD(PM_FUNCTION + 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 + movw $(SMBUS_IO_BASE + SMBHSTSTAT), %dx + 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 + + + /* + * 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 $((0x60 << 16) |SMBUS_MEM_DEVICE_0), %ebx +spd_set_drb_loop_top: + xorl %edi, %edi + subl $1, %edi + xorl %esi, %esi + subl $1, %esi + + movb $3, %bh /* rows */ + CALLSP(smbus_read_byte) + 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) */ + subl $25, %edi /* Make it multiples of 8MB */ + + /* side two */ + movb $5, %bh /* number of physical banks */ + CALLSP(smbus_read_byte) + cmp $1, %al + jbe 20f + + /* for now only handle the symmetrical case */ + movl %edi, %esi +20: + /* Compute the end address for the DRB register */ + cmpl $8, %edi /* Ignore the dimm if it is over 2GB */ + jae 21f + movl $1, %eax + movl %edi, %ecx + shll %cl, %eax + addl %eax, %ebp +21: + /* Write the computed 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 /* Ignore the dimm if it is over 2GB */ + 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 $SMBUS_MEM_DEVICE_3, %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 + */ + +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 $SMBUS_MEM_DEVICE_3, %bl + jbe 1b + /* We couldn't find anything we must have no memory */ + jmp no_memory + +spd_set_dramc_out: + testb $0x12, %al + /* $8 is bit value for non-registered DRAM */ + movl $8, %eax + jz 1f + /* this is a registered part. + * observation: for register parts, BIOS zeros (!) + * registers CA-CC. This has an undocumented meaning. + */ + xorl %edx, %edx + movl $0xca, %eax + PCI_WRITE_CONFIG_BYTE + xorl %edx, %edx + movl $0xcb, %eax + PCI_WRITE_CONFIG_BYTE + xorl %edx, %edx + movl $0xcc, %eax + PCI_WRITE_CONFIG_BYTE + + /* now set the bit value for registered sdram into %eax */ + movl $0x10, %eax +1: movl %eax, %edx + movl $0x57, %eax + PCI_WRITE_CONFIG_BYTE + RET_LABEL(spd_set_dramc) + +#endif /* USE_SPD */ + + /* + * Routine: spd_enable_refresh + * Arguments: None + * + * Trashed: %eax, %ebx, %ecx, %edx, %esp, %eflags + * Effects: Uses serial presence detect to set the + * refresh rate in the DRAMC register. + * see spd_set_dramc for the other values. + * FIXME: Check for illegal/unsupported ram configurations and abort + */ + + +refresh_rates: + .byte 0x01 /* Normal 15.625 us -> 15.6 us */ + .byte 0x05 /* Reduced(.25X) 3.9 us -> 7.8 us */ + .byte 0x05 /* Reduced(.5X) 7.8 us -> 7.8 us */ + .byte 0x02 /* Extended(2x) 31.3 us -> 31.2 us */ + .byte 0x03 /* Extended(4x) 62.5 us -> 62.4 us */ + .byte 0x04 /* Extended(8x) 125 us -> 124.8 us */ + +#if USE_SPD +spd_enable_refresh: + /* Find the first dimm and assume the rest are the same */ + /* Load the smbus device and port into %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 $SMBUS_MEM_DEVICE_3, %bl + jbe 1b + /* We couldn't find anything we must have no memory */ + jmp no_memory + +spd_enable_refresh_out: + cmpb $0x06, %al /* see if the ram refresh is a supported one */ + jae 1f + addl $refresh_rates, %eax /* convert SPD refresh rates to 440GX refresh rates */ + movb (%eax), %cl + jmp 2f +1: movb $0x05, %cl /* unknown ram refresh hard code it to something conservative */ +2: movl $0x57, %eax + PCI_READ_CONFIG_BYTE + andb $0xf8, %al + orb %cl, %al + movb %al, %dl + movl $0x57, %eax + PCI_WRITE_CONFIG_BYTE + 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 + /* one too many shifts here. */ + /* shll %cl, %edi*/ + orl %edi, %esi + +2: addl $1, %ebx /* increment the device */ + addl $4, %ecx /* increment the shift count */ + cmpb $SMBUS_MEM_DEVICE_3, %bl + jbe 1b +/* next block is for Ron's attempt to get registered to work. */ +/* we have just verified that we have to have this code. It appears that + * the registered SDRAMs do indeed set the RPS wrong. sheesh. + */ + /* at this point, %esi holds the RPS for all ram. + * we have verified that for registered DRAM the values are + * 1/2 the size they should be. So we test for registered + * and then double the sizes if needed. + */ + movl $0x57, %eax + PCI_READ_CONFIG_BYTE + + /* is it registered? */ + testb $0x10, %eax + jz 1f + + /* BIOS makes weird page size for registered! */ + /* what we have found is you need to set the EVEN banks to + * twice the size. Fortunately there is a very easy way to + * do this. First, read the WORD value of register 0x74. + */ + + /* now to double the size of the EVEN banks we only need to add 1 */ + /* because the size is log2 + */ + addl $0x1111, %esi + /* now write that final value of %esi into register 0x74 */ +1: + movl %esi, %ecx + movl $0x74, %eax + 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 $SMBUS_MEM_DEVICE_3, %bl + jbe 1b + + shll $8, %esi + orl $0x7, %esi /* 32 clocks idle time */ + movl %esi, %ecx + movl $0x78, %eax + 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 $SMBUS_MEM_DEVICE_3, %bl + jbe 1b + + movl %esi, %edx + movl $0x53, %eax + PCI_WRITE_CONFIG_BYTE + /* Now see if esi is 0xff. If it is we are done. If not, + * we need to set 0x18 into register 0x50.l + * we will do this in two steps, first or in 0x80 to 0x50.b, + * then or in 0x1 to 0x51.b + */ + mov %esi, %eax + cmpb $0xff, %al + je 1f + movl $0x50, %eax + PCI_READ_CONFIG_BYTE + orb $0x80, %al + movb %al, %dl + movl $0x50, %eax + PCI_WRITE_CONFIG_BYTE + movl $0x51, %eax + PCI_READ_CONFIG_BYTE + orb $0x1, %al + movb %al, %dl + movl $0x51, %eax + PCI_WRITE_CONFIG_BYTE + // try this. + // we should be setting bit 2 in register 76 and we're not + // technically we should see if CL=2 for the ram, + // but registered is so screwed up that it's kind of a lost + // cause. + movl $0x76, %eax + PCI_READ_CONFIG_BYTE + orb $0x4, %al + movb %al, %dl + movl $0x76, %eax + PCI_WRITE_CONFIG_BYTE +1: + RET_LABEL(spd_set_nbxcfg) + + +spd_set_sdramc: + RET_LABEL(spd_set_sdramc) + +#endif /* USE_SPD */ + + + + /* PAM FDHC MBSC SMRAM ESRAMC MBFS DWTC DRTC */ +ram_set_spd_registers: +#if 0 +/* #if USE_SPD */ + CALL_LABEL(enable_smbus) + CALL_LABEL(setup_smbus) + CALL_LABEL(spd_set_drb) + CALL_LABEL(spd_set_dramc) + CALL_LABEL(spd_set_rps) + CALL_LABEL(spd_set_sdramc) + CALL_LABEL(spd_set_pgpol) + CALL_LABEL(spd_set_nbxcfg) +#endif + RET_LABEL(ram_set_spd_registers) + +#if 0 +get_ecc_ram_size_bytes_ebx: + /* FIXME handle the no ram case. */ + movl $0x67, %eax /* Read the RAM SIZE */ + PCI_READ_CONFIG_BYTE + andl $0x000000ff, %eax /* Convert it to bytes */ + movl %eax, %ebx + shll $23, %ebx + RET_LABEL(get_ecc_ram_size_bytes_ebx) +#endif + +/* things that are not used */ +#define FIRST_NORMAL_REFERENCE() +#define SPECIAL_FINISHUP() \ + CS_WRITE_BYTE(0x78, 0x0f) ; \ + CS_WRITE_BYTE(0x79, 0x04) ; \ + CS_WRITE_BYTE(0x7a, 0x00) ; \ + CS_WRITE_BYTE(0x7b, 0x00) ; \ + CS_WRITE_BYTE(0xe0, 0x1e) + +#if 0 + CS_WRITE_BYTE(0x52, 0x01) ; \ +1: movl $0x52, %eax ; \ + PCI_READ_CONFIG_BYTE ; \ + andl $0x08, %eax ; \ + jz 1b ; \ + CS_WRITE_BYTE(0x52, 0x0d) ; \ + +#endif + +intel_E7500_out: diff --git a/src/northbridge/intel/E7500/reset_test.inc b/src/northbridge/intel/E7500/reset_test.inc new file mode 100644 index 0000000000..957d7d4619 --- /dev/null +++ b/src/northbridge/intel/E7500/reset_test.inc @@ -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 diff --git a/src/northbridge/intel/E7500/sdram_enable.inc b/src/northbridge/intel/E7500/sdram_enable.inc new file mode 100644 index 0000000000..15e0a6789b --- /dev/null +++ b/src/northbridge/intel/E7500/sdram_enable.inc @@ -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< #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 */ diff --git a/src/pc80/serial.inc b/src/pc80/serial.inc index 94ce874871..b0f12699e1 100644 --- a/src/pc80/serial.inc +++ b/src/pc80/serial.inc @@ -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 diff --git a/src/ram/Config b/src/ram/Config index 0942a6e1bc..aa7289cb0b 100644 --- a/src/ram/Config +++ b/src/ram/Config @@ -1 +1,2 @@ -object ramtest.o USE_RAMTEST +#object ramtest.o USE_RAMTEST +object ramtest.o diff --git a/src/ram/dump_northbridge.inc b/src/ram/dump_northbridge.inc index 7ff8d21e75..4d120c5996 100644 --- a/src/ram/dump_northbridge.inc +++ b/src/ram/dump_northbridge.inc @@ -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 diff --git a/src/ram/ramtest.c b/src/ram/ramtest.c index 6374a7f2c6..f58a9793e9 100644 --- a/src/ram/ramtest.c +++ b/src/ram/ramtest.c @@ -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; } diff --git a/src/ram/ramtest.inc b/src/ram/ramtest.inc index baa4b1288f..f767975d72 100644 --- a/src/ram/ramtest.inc +++ b/src/ram/ramtest.inc @@ -108,6 +108,7 @@ ramtest: 6: CONSOLE_INFO_TX_STRING($rt_done) mov %ebp, %esp + #endif RETSP diff --git a/src/southbridge/amd/amd766/Config b/src/southbridge/amd/amd766/Config index aff8055c22..efd92c8415 100644 --- a/src/southbridge/amd/amd766/Config +++ b/src/southbridge/amd/amd766/Config @@ -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 + + + diff --git a/src/southbridge/amd/amd766/amd766_ide.c b/src/southbridge/amd/amd766/amd766_ide.c new file mode 100644 index 0000000000..7fb14b8284 --- /dev/null +++ b/src/southbridge/amd/amd766/amd766_ide.c @@ -0,0 +1,48 @@ +#include +#include +#include +#include + +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 + } +} diff --git a/src/southbridge/amd/amd766/amd766_ioapic.c b/src/southbridge/amd/amd766/amd766_ioapic.c new file mode 100644 index 0000000000..e1b9d19cf0 --- /dev/null +++ b/src/southbridge/amd/amd766/amd766_ioapic.c @@ -0,0 +1,14 @@ +#include +#include +#include + +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)); + } + +} diff --git a/src/southbridge/amd/amd766/amd766_lpc.c b/src/southbridge/amd/amd766/amd766_lpc.c new file mode 100644 index 0000000000..9c9387e44a --- /dev/null +++ b/src/southbridge/amd/amd766/amd766_lpc.c @@ -0,0 +1,17 @@ +#include +#include +#include + +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); + } + +} diff --git a/src/southbridge/amd/amd766/amd766_mem.c b/src/southbridge/amd/amd766/amd766_mem.c new file mode 100644 index 0000000000..6531cf9480 --- /dev/null +++ b/src/southbridge/amd/amd766/amd766_mem.c @@ -0,0 +1,15 @@ +#include +#include +#include + +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)); + } + +} diff --git a/src/southbridge/amd/amd766/amd766_mouse.c b/src/southbridge/amd/amd766/amd766_mouse.c new file mode 100644 index 0000000000..52e2ccbed0 --- /dev/null +++ b/src/southbridge/amd/amd766/amd766_mouse.c @@ -0,0 +1,15 @@ +#include +#include +#include + +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)); + } +} diff --git a/src/southbridge/amd/amd766/amd766_pm.c b/src/southbridge/amd/amd766/amd766_pm.c new file mode 100644 index 0000000000..240ba3064d --- /dev/null +++ b/src/southbridge/amd/amd766/amd766_pm.c @@ -0,0 +1,13 @@ +#include +#include +#include + +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); + } + +} diff --git a/src/southbridge/amd/amd766/amd766_power.c b/src/southbridge/amd/amd766/amd766_power.c new file mode 100644 index 0000000000..af1a3b0495 --- /dev/null +++ b/src/southbridge/amd/amd766/amd766_power.c @@ -0,0 +1,21 @@ +#include +#include +#include + +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); + } + +} diff --git a/src/southbridge/amd/amd766/amd766_reboot.c b/src/southbridge/amd/amd766/amd766_reboot.c new file mode 100644 index 0000000000..66013dfcf5 --- /dev/null +++ b/src/southbridge/amd/amd766/amd766_reboot.c @@ -0,0 +1,15 @@ +#include +#include +#include +#include + + +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; +} diff --git a/src/southbridge/amd/amd766/amd766_reset.c b/src/southbridge/amd/amd766/amd766_reset.c new file mode 100644 index 0000000000..3bbbad2cca --- /dev/null +++ b/src/southbridge/amd/amd766/amd766_reset.c @@ -0,0 +1,39 @@ +#include +#include +#include + +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)); + } + + +} diff --git a/src/southbridge/amd/amd766/amd766_usb.c b/src/southbridge/amd/amd766/amd766_usb.c new file mode 100644 index 0000000000..d2f9cd8739 --- /dev/null +++ b/src/southbridge/amd/amd766/amd766_usb.c @@ -0,0 +1,17 @@ +#include +#include +#include + +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); + } +} diff --git a/src/southbridge/amd/amd766/amd766_watchdog.c b/src/southbridge/amd/amd766/amd766_watchdog.c new file mode 100644 index 0000000000..c61d5d20d0 --- /dev/null +++ b/src/southbridge/amd/amd766/amd766_watchdog.c @@ -0,0 +1,15 @@ +#include +#include +#include + +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)); + } +} diff --git a/src/southbridge/amd/amd766/cmos_boot_failover.inc b/src/southbridge/amd/amd766/cmos_boot_failover.inc new file mode 100644 index 0000000000..6a606bb6a8 --- /dev/null +++ b/src/southbridge/amd/amd766/cmos_boot_failover.inc @@ -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 +#include + + /* 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: diff --git a/src/southbridge/amd/amd766/cmos_reset_failover.inc b/src/southbridge/amd/amd766/cmos_reset_failover.inc new file mode 100644 index 0000000000..3816683f4a --- /dev/null +++ b/src/southbridge/amd/amd766/cmos_reset_failover.inc @@ -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 +#include + + + 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: diff --git a/src/southbridge/intel/82801/cmos_failover.inc b/src/southbridge/intel/82801/cmos_failover.inc index 48691cdb20..4a4f0a99ee 100644 --- a/src/southbridge/intel/82801/cmos_failover.inc +++ b/src/southbridge/intel/82801/cmos_failover.inc @@ -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 diff --git a/src/southbridge/intel/82801/ich2_ioapic.c b/src/southbridge/intel/82801/ich2_ioapic.c index f236ee4350..58ce24cca4 100644 --- a/src/southbridge/intel/82801/ich2_ioapic.c +++ b/src/southbridge/intel/82801/ich2_ioapic.c @@ -1,4 +1,6 @@ #include +#include +#include #include #include #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); } diff --git a/src/southbridge/intel/82801/smbus.inc b/src/southbridge/intel/82801/smbus.inc new file mode 100644 index 0000000000..ad0808680a --- /dev/null +++ b/src/southbridge/intel/82801/smbus.inc @@ -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) + + diff --git a/src/southbridge/intel/82801ca/82801.h b/src/southbridge/intel/82801ca/82801.h new file mode 100644 index 0000000000..d4f2652e66 --- /dev/null +++ b/src/southbridge/intel/82801ca/82801.h @@ -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) diff --git a/src/southbridge/intel/82801ca/Config b/src/southbridge/intel/82801ca/Config new file mode 100644 index 0000000000..c6adb65c7d --- /dev/null +++ b/src/southbridge/intel/82801ca/Config @@ -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 diff --git a/src/southbridge/intel/82801ca/cmos_failover.inc b/src/southbridge/intel/82801ca/cmos_failover.inc new file mode 100644 index 0000000000..4a4f0a99ee --- /dev/null +++ b/src/southbridge/intel/82801ca/cmos_failover.inc @@ -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 +#include + + + /* 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 + diff --git a/src/southbridge/intel/82801ca/ich3_1e0_misc.c b/src/southbridge/intel/82801ca/ich3_1e0_misc.c new file mode 100644 index 0000000000..7d4bd53f62 --- /dev/null +++ b/src/southbridge/intel/82801ca/ich3_1e0_misc.c @@ -0,0 +1,31 @@ +#include +#include +#include +#include +#include +#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 + +} diff --git a/src/southbridge/intel/82801ca/ich3_1f0_misc.c b/src/southbridge/intel/82801ca/ich3_1f0_misc.c new file mode 100644 index 0000000000..0ca71987de --- /dev/null +++ b/src/southbridge/intel/82801ca/ich3_1f0_misc.c @@ -0,0 +1,30 @@ +#include +#include +#include +#include +#include +#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); +} diff --git a/src/southbridge/intel/82801ca/ich3_cpu.c b/src/southbridge/intel/82801ca/ich3_cpu.c new file mode 100644 index 0000000000..eed76fc148 --- /dev/null +++ b/src/southbridge/intel/82801ca/ich3_cpu.c @@ -0,0 +1,37 @@ +#include +#include +#include +#include +#include +#include +#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); +} diff --git a/src/southbridge/intel/82801ca/ich3_ide.c b/src/southbridge/intel/82801ca/ich3_ide.c new file mode 100644 index 0000000000..169ec0083b --- /dev/null +++ b/src/southbridge/intel/82801ca/ich3_ide.c @@ -0,0 +1,24 @@ +#include +#include +#include + +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); + } + +} diff --git a/src/southbridge/intel/82801ca/ich3_ioapic.c b/src/southbridge/intel/82801ca/ich3_ioapic.c new file mode 100644 index 0000000000..b3e0ac5113 --- /dev/null +++ b/src/southbridge/intel/82801ca/ich3_ioapic.c @@ -0,0 +1,45 @@ +#include +#include +#include +#include +#include +#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(;;); + + +} diff --git a/src/southbridge/intel/82801ca/ich3_lpc.c b/src/southbridge/intel/82801ca/ich3_lpc.c new file mode 100644 index 0000000000..8548736d26 --- /dev/null +++ b/src/southbridge/intel/82801ca/ich3_lpc.c @@ -0,0 +1,33 @@ +#include +#include +#include +#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); +} diff --git a/src/southbridge/intel/82801ca/ich3_power.c b/src/southbridge/intel/82801ca/ich3_power.c new file mode 100644 index 0000000000..0323b0b7b8 --- /dev/null +++ b/src/southbridge/intel/82801ca/ich3_power.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#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"); +} diff --git a/src/southbridge/intel/82801ca/ich3_reset.c b/src/southbridge/intel/82801ca/ich3_reset.c new file mode 100644 index 0000000000..3d3271982e --- /dev/null +++ b/src/southbridge/intel/82801ca/ich3_reset.c @@ -0,0 +1,9 @@ +#include +#include + +void ich3_hard_reset(void) +{ + /* Try rebooting through port 0xcf9 */ + outb((0 <<3)|(1<<2)|(1<<1), 0xcf9); +} + diff --git a/src/southbridge/intel/82801ca/ich3_rtc.c b/src/southbridge/intel/82801ca/ich3_rtc.c new file mode 100644 index 0000000000..90d61da2b6 --- /dev/null +++ b/src/southbridge/intel/82801ca/ich3_rtc.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include +#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); +} diff --git a/src/southbridge/intel/82801ca/ich3_smbus.c b/src/southbridge/intel/82801ca/ich3_smbus.c new file mode 100644 index 0000000000..ab890b668f --- /dev/null +++ b/src/southbridge/intel/82801ca/ich3_smbus.c @@ -0,0 +1,121 @@ +#include +#include +#include +#include +#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; +} diff --git a/src/southbridge/intel/82801ca/nvram.c b/src/southbridge/intel/82801ca/nvram.c new file mode 100644 index 0000000000..891d8d20d6 --- /dev/null +++ b/src/southbridge/intel/82801ca/nvram.c @@ -0,0 +1,8 @@ +#include +#include + +void nvram_on(void) +{ + printk_notice("Please turn on nvram\n"); + return; +} diff --git a/src/southbridge/intel/82801ca/smbus.inc b/src/southbridge/intel/82801ca/smbus.inc new file mode 100644 index 0000000000..ad0808680a --- /dev/null +++ b/src/southbridge/intel/82801ca/smbus.inc @@ -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) + + diff --git a/src/southbridge/intel/82870/82870.h b/src/southbridge/intel/82870/82870.h new file mode 100644 index 0000000000..5aa195e0a0 --- /dev/null +++ b/src/southbridge/intel/82870/82870.h @@ -0,0 +1,5 @@ +#define PCICMD 0x04 +#define SUBSYS 0x2c +#define MBAR 0x10 +#define ABAR 0x40 + diff --git a/src/southbridge/intel/82870/Config b/src/southbridge/intel/82870/Config new file mode 100644 index 0000000000..5b2b8ec4ce --- /dev/null +++ b/src/southbridge/intel/82870/Config @@ -0,0 +1 @@ +object p64h2_ioapic.o diff --git a/src/southbridge/intel/82870/p64h2_ioapic.c b/src/southbridge/intel/82870/p64h2_ioapic.c new file mode 100644 index 0000000000..d20139cc85 --- /dev/null +++ b/src/southbridge/intel/82870/p64h2_ioapic.c @@ -0,0 +1,80 @@ +#include +#include +#include +#include +#include +#include "82870.h" + +void p64h2_enable_ioapic(void) +{ + struct pci_dev *dev; + u32 dword; + u16 word; + int i; + volatile u32 *ioapic_1a=0xfec80000; + volatile u32 *ioapic_1d=0xfec80010; + volatile u32 *ioapic_2a=0xfec80400; + volatile u32 *ioapic_2d=0xfec80410; + + + + for(i=0,dev=0;i<4;i++) { + dev = pci_find_device(PCI_VENDOR_ID_INTEL, + PCI_DEVICE_ID_INTEL_82870_1F0, dev); + if (!dev) { + if(i<2) + printk_debug("*** ERROR Southbridge device %x not found\n", + PCI_DEVICE_ID_INTEL_82870_1F0); + break; + } +// pci_read_config_dword(dev, GEN_CNTL, &dword); + word = 0x0146; + pci_write_config_word(dev, PCICMD, word); + dword = 0x358015d9; + pci_write_config_dword(dev, SUBSYS, dword); + if(i==0){ + dword = 0xfc100000; + pci_write_config_dword(dev, MBAR, dword); + word = 0x8804; + pci_write_config_word(dev, ABAR, word); + } + if(i==1){ + dword = 0xfc101000; + pci_write_config_dword(dev, MBAR, dword); + word = 0x8800; + pci_write_config_word(dev, ABAR, word); + } + } + + *ioapic_1a=0; + *ioapic_1d=(3<<24); + *ioapic_1a=3; + *ioapic_1d=1; + *ioapic_1a=0; + dword=*ioapic_1d; + printk_debug("PCI 1 apic id = %x\n",dword); + if(dword!=(3<<24)) + for(;;); + *ioapic_1a=3; + dword=*ioapic_1d; + printk_debug("PCI 1 apic DT = %x\n",dword); + if(dword!=1) + for(;;); + + *ioapic_2a=0; + *ioapic_2d=(4<<24); + *ioapic_2a=3; + *ioapic_2d=1; + *ioapic_2a=0; + dword=*ioapic_2d; + printk_debug("PCI 2 apic id = %x\n",dword); + if(dword!=(4<<24)) + for(;;); + *ioapic_2a=3; + dword=*ioapic_2d; + printk_debug("PCI 2 apic DT = %x\n",dword); + if(dword!=1) + for(;;); + + +} diff --git a/util/config/NLBConfig.py b/util/config/NLBConfig.py index 620d6af2bd..145886501a 100644 --- a/util/config/NLBConfig.py +++ b/util/config/NLBConfig.py @@ -277,6 +277,8 @@ mainboard_dir = None # is executed. def mainboard(dir, mainboard_name): global mainboard_dir + set_option('MAINBOARD_PART_NUMBER', os.path.basename(mainboard_name)) + set_option('MAINBOARD_VENDOR', os.path.dirname(mainboard_name)) mainboard_dir = common_command_action(dir, 'mainboard', mainboard_name) # COMMAND: etherboot @@ -557,9 +559,21 @@ class mkexpr: elif (self.op == "/"): result = lstring + "/" + rstring elif (self.op == "<<"): - result = lstring + "<<" + rstring + ") " + result = lstring + "<<" + rstring elif (self.op == ">>"): - result = lstring + ">>" + rstring + ") " + result = lstring + ">>" + rstring + elif (self.op == ">"): + result = lstring + ">" + rstring + elif (self.op == ">="): + result = lstring + ">=" + rstring + elif (self.op == "<"): + result = lstring + "<" + rstring + elif (self.op == "<="): + result = lstring + "<=" + rstring + elif (self.op == "=="): + result = lstring + "==" + rstring + elif (self.op == "=="): + result = lstring + "!=" + rstring return "(" + result + ")" class expression: @@ -574,10 +588,11 @@ class mkexpr: string = self.expr.perl() return "${shell perl -e 'printf(\"%u\\n\", " + string + ");' }" - # Tokens: ( ) ! | & + - * / << >> option ) + # Tokens: ( ) ! | & + - * / << >> == <= >= < > != option ) start_re = re.compile(r"^\s*(([A-Za-z_][A-Za-z_0-9]*)|((0x[0-9A-Za-z]+)|([0-9]+))|(\()|(!))(.*)$") close_re = re.compile(r"^\s*\)(.*)$") - middle_re = re.compile(r"^\s*((\|)|(&)|(\+)|(-)|(\*)|(/)|(<<)|(>>))(.*)$") +# middle_re = re.compile(r"^\s*((\|)|(&)|(\+)|(-)|(\*)|(/)|(<<)|(>>)|(==)|(<=)|(>=)|(<)|(>))(.*)$") + middle_re = re.compile(r"^\s*((\|)|(&)|(\+)|(-)|(\*)|(/)|(<<)|(>>)|>=|<=|>|<|==|!=)(.*)$") def __init__(self, expr): self.orig_expr = expr @@ -588,12 +603,18 @@ class mkexpr: result = 1 elif (op == "&"): result = 2 - elif (op == "+") or (op == "-"): + elif (op == "<") or (op == ">") or \ + (op == ">=") or (op == "<=") or \ + (op == "==") or (op == "!="): result = 3 - elif (op == "*") or (op == "/"): + elif (op == "+") or (op == "-"): result = 4 - elif (op == "<<") or (op == ">>"): + elif (op == "*") or (op == "/"): result = 5 + elif (op == "<<") or (op == ">>"): + result = 6 + else: + fatal("Unknown operator: %s" % op) def _parse_start(self): diff --git a/util/lb-dump/dump_lb_table.c b/util/lb-dump/dump_lb_table.c index 77652b4230..59afb1253d 100644 --- a/util/lb-dump/dump_lb_table.c +++ b/util/lb-dump/dump_lb_table.c @@ -150,6 +150,17 @@ void print_memory(struct lb_record *ptr, unsigned long addr) } } +void print_mainboard(struct lb_record *ptr, unsigned long addr) +{ + struct lb_mainboard *rec; + int max_size; + rec = (struct lb_mainboard *)ptr; + max_size = rec->size - sizeof(*rec); + printf("vendor: %.*s part number: %.*s\n", + max_size - rec->vendor_idx, rec->strings + rec->vendor_idx, + max_size - rec->vendor_idx, rec->strings + rec->part_number_idx); +} + void print_option_table(struct lb_record *ptr, unsigned long addr) { struct lb_record *rec, *last; @@ -193,7 +204,6 @@ void print_option_enumeration(struct lb_record *ptr, unsigned long addr) rec->text); } - struct { uint32_t type; char *type_name; @@ -202,6 +212,7 @@ struct { { LB_TAG_UNUSED, "Unused", nop_print }, { LB_TAG_MEMORY, "Memory", print_memory }, { LB_TAG_HWRPB, "HWRPB", nop_print }, + { LB_TAG_MAINBOARD, "Mainboard", print_mainboard }, { LB_TAG_CMOS_OPTION_TABLE, "CMOS option table", print_option_table }, { LB_TAG_OPTION, "Option", print_option }, { LB_TAG_OPTION_ENUM, "Option Enumeration", print_option_enumeration },