diff --git a/src/arch/i386/include/arch/cache_ram.h b/src/arch/i386/include/arch/cache_ram.h index 98990899fc..948980d887 100644 --- a/src/arch/i386/include/arch/cache_ram.h +++ b/src/arch/i386/include/arch/cache_ram.h @@ -5,9 +5,20 @@ #define CACHE_RAM_BASE 0 #endif +#if !defined(ASSEMBLY) +#define CACHE_RAM_SEG_BASE (((unsigned long)CACHE_RAM_BASE) - ((unsigned long)_RAMBASE)) +#else #define CACHE_RAM_SEG_BASE (CACHE_RAM_BASE - _RAMBASE) +#endif -#define RAM(type, addr) (*((type *)((unsigned char*)((addr) - CACHE_RAM_SEG_BASE)))) -#define RAM_ADDR( addr) ((void *)((addr) - CACHE_RAM_BASE)) + + +#if !defined(ASSEMBLY) + +#define RAM_ADDR( addr) ((void *)(((unsigned char *)(addr)) - CACHE_RAM_SEG_BASE)) +#define RAM(type, addr) (*((volatile type *)RAM_ADDR(addr))) + +void cache_ram_start(void); +#endif #endif /* CACHE_RAM_H */ diff --git a/src/arch/i386/include/bitops.h b/src/arch/i386/include/bitops.h new file mode 100644 index 0000000000..d9460d4865 --- /dev/null +++ b/src/arch/i386/include/bitops.h @@ -0,0 +1,20 @@ +#ifndef I386_BITOPS_H +#define I386_BITOPS_H + +/** + * log2 - Find the truncated log base 2 of x + */ + +static inline unsigned long log2(unsigned long x) +{ + unsigned long r = 0; + __asm__( + "bsrl %1, %0\n\t" + "jnz 1f\n\t" + "movl $-1, %0\n\t" + "1:\n\t" + : "=r" (r) : "g" (x)); + return r; + +} +#endif /* I386_BITOPS_H */ diff --git a/src/arch/i386/lib/cpu_reset.inc b/src/arch/i386/lib/cpu_reset.inc index fe6e87af76..7dee6b8d12 100644 --- a/src/arch/i386/lib/cpu_reset.inc +++ b/src/arch/i386/lib/cpu_reset.inc @@ -6,7 +6,7 @@ jmp cpu_reset_out .section ".rodata" -#if ASM_CONSOLE_LOGLEVEL >= BIOS_DEBUG +#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"; @@ -16,7 +16,7 @@ cpu_size_set_str: .string "cpu memory size set\r\n"; .text __cpu_reset: - CONSOLE_DEBUG_TX_STRING($cpu_reset_str) + CONSOLE_SPEW_TX_STRING($cpu_reset_str) #ifdef SMP /* Enable the local apic, and map it where we expext it */ @@ -32,15 +32,15 @@ __cpu_reset: movl (APIC_ID + APIC_DEFAULT_BASE), %edi shrl $24, %edi - CONSOLE_DEBUG_TX_STRING($cpu_apic_str) - CONSOLE_DEBUG_TX_HEX32(%edi) - CONSOLE_DEBUG_TX_CHAR($'\r') - CONSOLE_DEBUG_TX_CHAR($'\n') + 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_DEBUG_TX_STRING($cpu_size_set_str); + CONSOLE_SPEW_TX_STRING($cpu_size_set_str); #ifdef SMP /* Test to see if we are the boot strap processor. diff --git a/src/arch/i386/lib/failover.lds b/src/arch/i386/lib/failover.lds new file mode 100644 index 0000000000..c9cf7298f8 --- /dev/null +++ b/src/arch/i386/lib/failover.lds @@ -0,0 +1 @@ + __normal_image = (ZKERNEL_START & 0xfffffff0) - 8; diff --git a/src/arch/i386/lib/hardwaremain.c b/src/arch/i386/lib/hardwaremain.c index 857713ef09..9197a08616 100644 --- a/src/arch/i386/lib/hardwaremain.c +++ b/src/arch/i386/lib/hardwaremain.c @@ -49,6 +49,7 @@ static char rcsid[] = "$Id$"; #include #include #include +#include #include #include #include @@ -289,6 +290,9 @@ void hardwaremain(int boot_complete) post_code(0x96); write_smp_table((void *)16, processor_map); + /* Reset to booting from this image as late as possible */ + boot_successful(); + #ifdef LINUXBIOS printk_info("Jumping to linuxbiosmain()...\n"); // we could go to argc, argv, for main but it seems like overkill. diff --git a/src/arch/i386/lib/noop_failover.inc b/src/arch/i386/lib/noop_failover.inc new file mode 100644 index 0000000000..70c10b0d3e --- /dev/null +++ b/src/arch/i386/lib/noop_failover.inc @@ -0,0 +1,9 @@ +/* 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 + * + */ + testb %al, %al + jnz __cpu_reset diff --git a/src/arch/i386/lib/pirq_routing.c b/src/arch/i386/lib/pirq_routing.c index 6c34d47072..4d6aa8a7af 100644 --- a/src/arch/i386/lib/pirq_routing.c +++ b/src/arch/i386/lib/pirq_routing.c @@ -1,6 +1,7 @@ #include #include #include +#include #ifdef DEBUG void check_pirq_routing_table(void) diff --git a/src/arch/i386/smp/start_stop.c b/src/arch/i386/smp/start_stop.c index 127377633a..50a30ada44 100644 --- a/src/arch/i386/smp/start_stop.c +++ b/src/arch/i386/smp/start_stop.c @@ -4,7 +4,12 @@ #include #include - +#ifndef START_CPU_SEG +#define START_CPU_SEG 0x90000 +#endif +#if (START_CPU_SEG&0xffff) != 0 +#error START_CPU_SEG must be 64k aligned +#endif static inline void hlt(void) { @@ -142,13 +147,13 @@ int start_cpu(unsigned long apicid) return 0; } - start_eip = 0x90000 + (((unsigned long)_start) & 0xf000); + start_eip = START_CPU_SEG + (((unsigned long)_start) & 0xf000); if ((((unsigned long)_start) & 0xfff) != 0) { printk_err("_start is not 4K aligned!\n"); return 0; } memcpy((void *)start_eip, _start, _estart - _start); - printk_spew("start eip=0x%08lx\n", start_eip); + printk_spew("start_eip=0x%08lx\n", start_eip); num_starts = 2; @@ -160,7 +165,7 @@ int start_cpu(unsigned long apicid) maxlvt = 4; for (j = 1; j <= num_starts; j++) { - printk_spew("Sending STARTUP #%d.\n",j); + printk_spew("Sending STARTUP #%d to %u.\n", j, apicid); apic_read_around(APIC_SPIV); apic_write(APIC_ESR, 0); apic_read(APIC_ESR); diff --git a/src/cpu/i386/entry16.inc b/src/cpu/i386/entry16.inc index 25a3c3c49b..369aad9aad 100644 --- a/src/cpu/i386/entry16.inc +++ b/src/cpu/i386/entry16.inc @@ -25,8 +25,6 @@ it with the version available from LANL. * protected mode. */ -#include - .text .code16 .globl EXT(_start) @@ -41,8 +39,8 @@ EXT(_start): /* any further code. Even though paging is disabled we could still get*/ /*false address translations due to the TLB if we didn't invalidate it.*/ /**/ - xor %eax, %eax - mov %eax, %cr3 /* Invalidate TLB*/ + xorl %eax, %eax + movl %eax, %cr3 /* Invalidate TLB*/ /* invalidate the cache */ invd @@ -66,18 +64,28 @@ EXT(_start): * So while this code is relocateable it isn't arbitrarily * relocatable. * - * In particular this code can be run with the base address of - * the code segment at either 0xffff0000 or 0xf0000. - * The first is what is initiallly loaded when the processor - * powers on. The second is normal real mode segment 0xf000. + * The criteria for relocation have been relaxed to their + * utmost, so that we can use the same code for both + * our initial entry point and startup of the second cpu. + * The code assumes when executing at _start that: + * (((cs & 0xfff) == 0) and (ip == _start & 0xffff)) + * or + * ((cs == anything) and (ip == 0)). * - * At this point all the linker script does when calculating - * gdtptr_offset is return the low 16 bits so your segment - * must be 64K aligned. So it wouldn't be too much work - * to support other segments, I just don't see the point - * right now. + * The restrictions in reset16.inc mean that _start initially + * must be loaded at or above 0xffff0000 or below 0x100000. + * + * The linker scripts computs gdtptr16_offset by simply returning + * the low 16 bits. This means that the intial segment used + * when start is called must be 64K aligned. This should not + * restrict the address as the ip address can be anything. */ - data32 lgdt %cs:EXT(gdtptr_offset) + + movw %cs, %ax + shlw $4, %ax + movw $EXT(gdtptr16_offset), %bx + subw %ax, %bx + data32 lgdt %cs:(%bx) movl %cr0, %eax andl $0x7FFAFFD1, %eax /* PG,AM,WP,NE,TS,EM,MP = 0 */ @@ -85,62 +93,19 @@ EXT(_start): movl %eax, %cr0 /* Now that we are in protected mode jump to a 32 bit code segment. */ - data32 ljmp $0x10, $_protected_start + data32 ljmp $0x10, $__protected_start - -/** This gdt has a 4 Gb code segment at 0x10, and a 4 GB data segment +/** The gdt has a 4 Gb code segment at 0x10, and a 4 GB data segment * at 0x18; these are Linux-compatible. */ - -/** GDT. we have modified this from the original freebios to make it - * compatible with linux. This puts text at seg 0x10 and data at 0x18 - */ .align 4 -.globl EXT(gdtptr) -EXT(gdtptr): +.globl EXT(gdtptr16) +EXT(gdtptr16): .word 4*8-1 .long gdt /* we know the offset */ .globl EXT(_estart) EXT(_estart): - -gdt: - .word 0x0000, 0x0000 /* dummy */ - .byte 0x00, 0x00, 0x00, 0x00 - - .word 0xffff, (CACHE_RAM_SEG_BASE & 0xffff) /* flat offset data segment */ - .byte ((CACHE_RAM_SEG_BASE >> 16)& 0xff), 0x93, 0xcf - .byte ((CACHE_RAM_SEG_BASE >> 24) & 0xff) - - .word 0xffff, 0x0000 /* flat code segment */ - .byte 0x00, 0x9b, 0xcf, 0x00 - - .word 0xffff, 0x0000 /* flat data segment */ - .byte 0x00, 0x93, 0xcf, 0x00 - - -/* - * When we come here we are in protected mode. We expand - * the stack and copies the data segment from ROM to the - * memory. - * - * After that, we call the chipset bootstrap routine that - * does what is left of the chipset initialization. - * - * NOTE aligned to 4 so that we are sure that the prefetch - * cache will be reloaded. - */ - .align 4 -_protected_start: .code32 - intel_chip_post_macro(0x10) /* post 10 */ - - movw $0x18, %ax - movw %ax, %ds - movw %ax, %es - movw %ax, %ss - movw %ax, %fs - movw %ax, %gs - diff --git a/src/cpu/i386/entry16.lds b/src/cpu/i386/entry16.lds index d0286b3de9..db37e66302 100644 --- a/src/cpu/i386/entry16.lds +++ b/src/cpu/i386/entry16.lds @@ -1,2 +1,2 @@ - gdtptr_offset = gdtptr & 0xffff; + gdtptr16_offset = gdtptr16 & 0xffff; _start_offset = _start & 0xffff; diff --git a/src/cpu/i386/entry32.inc b/src/cpu/i386/entry32.inc index 7e855f910e..11548dd946 100644 --- a/src/cpu/i386/entry32.inc +++ b/src/cpu/i386/entry32.inc @@ -1,5 +1,63 @@ - /* For starting linuxBIOS in protected mode */ +/* For starting linuxBIOS in protected mode */ + +#include + .text - .align 4 .code32 + +/** This gdt has a 4 Gb code segment at 0x10, and a 4 GB data segment + * at 0x18; these are Linux-compatible. + */ + +/** GDT. we have modified this from the original freebios to make it + * compatible with linux. This puts text at seg 0x10 and data at 0x18 + */ + + .align 4 +.globl EXT(gdtptr) +EXT(gdtptr): + .word 4*8-1 + .long gdt /* we know the offset */ + +gdt: + .word 0x0000, 0x0000 /* dummy */ + .byte 0x00, 0x00, 0x00, 0x00 + + .word 0xffff, (CACHE_RAM_SEG_BASE & 0xffff) /* flat offset data segment */ + .byte ((CACHE_RAM_SEG_BASE >> 16)& 0xff), 0x93, 0xcf + .byte ((CACHE_RAM_SEG_BASE >> 24) & 0xff) + + .word 0xffff, 0x0000 /* flat code segment */ + .byte 0x00, 0x9b, 0xcf, 0x00 + + .word 0xffff, 0x0000 /* flat data segment */ + .byte 0x00, 0x93, 0xcf, 0x00 + +/* + * When we come here we are in protected mode. We expand + * the stack and copies the data segment from ROM to the + * memory. + * + * After that, we call the chipset bootstrap routine that + * does what is left of the chipset initialization. + * + * NOTE aligned to 4 so that we are sure that the prefetch + * cache will be reloaded. + */ + .align 4 +.globl EXT(protected_start) +EXT(protected_start): + + lgdt %cs:gdtptr + ljmp $0x10, $__protected_start + +__protected_start: intel_chip_post_macro(0x10) /* post 10 */ + + movw $0x18, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw %ax, %fs + movw %ax, %gs + diff --git a/src/cpu/i386/reset16.inc b/src/cpu/i386/reset16.inc index 4138c0cad5..7c911d9ff2 100644 --- a/src/cpu/i386/reset16.inc +++ b/src/cpu/i386/reset16.inc @@ -20,5 +20,8 @@ EXT(reset_vector): #error _ROMBASE is an unsupported value #endif + . = 0x8; .code32 + jmp EXT(protected_start) + .previous diff --git a/src/cpu/i386/reset32.inc b/src/cpu/i386/reset32.inc new file mode 100644 index 0000000000..ec743b70cc --- /dev/null +++ b/src/cpu/i386/reset32.inc @@ -0,0 +1,10 @@ + .section ".reset" + .code16 +.globl EXT(reset_vector) +EXT(reset_vector): + + . = 0x8; + .code32 + jmp EXT(protected_start) + + .previous diff --git a/src/cpu/i386/reset32.lds b/src/cpu/i386/reset32.lds new file mode 100644 index 0000000000..fa6db86b1a --- /dev/null +++ b/src/cpu/i386/reset32.lds @@ -0,0 +1,14 @@ +/* + * _ROMTOP : The top of the rom used where we + * need to put the reset vector. + */ + +SECTIONS { + _ROMTOP = _ROMBASE + ROM_IMAGE_SIZE - 0x10; + . = _ROMTOP; + .reset (.): { + *(.reset) + . = 15 ; + BYTE(0x00); + } +} diff --git a/src/cpu/i786/cache_ram_init.inc b/src/cpu/i786/cache_ram_init.inc index c517a5a042..d2048b4ad6 100644 --- a/src/cpu/i786/cache_ram_init.inc +++ b/src/cpu/i786/cache_ram_init.inc @@ -44,4 +44,4 @@ movw %ax, %ds movw %ax, %es movw %ax, %ss -#endif \ No newline at end of file +#endif diff --git a/src/cpu/p6/cache_ram_fini.inc b/src/cpu/p6/cache_ram_fini.inc new file mode 100644 index 0000000000..3deeb7d3ec --- /dev/null +++ b/src/cpu/p6/cache_ram_fini.inc @@ -0,0 +1,40 @@ +#if defined(CACHE_RAM_BASE) && defined(CACHE_RAM_SIZE) + /* Note: We cannot be running from simulated ram in + * this code. If we are evil things will happen. + */ + + /* Disable the cache */ + movl %cr0, %eax + orl $0x40000000, %eax + movl %eax, %cr0 + + /* Flush everything that is left in the cache, + * We don't want random writes to memory to occur later on. + */ + invd + + /* Disable the cache ram mtrr */ + movl $0x204, %ecx + xorl %eax, %eax + xorl %edx, %edx + wrmsr + + movl $0x205, %ecx + xorl %eax, %eax + xorl %edx, %edx + wrmsr + + /* Reenable the cache now that the mtrr is cleared */ + movl %cr0, %eax + andl $0x9fffffff, %eax + movl %eax, %cr0 + + /* Reload the normal data segments */ + movw $0x18, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss + movw %ax, %fs + movw %ax, %gs + +#endif diff --git a/src/cpu/p6/cache_ram_init.inc b/src/cpu/p6/cache_ram_init.inc new file mode 100644 index 0000000000..9ee7e93a97 --- /dev/null +++ b/src/cpu/p6/cache_ram_init.inc @@ -0,0 +1,48 @@ +#if defined(CACHE_RAM_BASE) && defined(CACHE_RAM_SIZE) + /* Disable the cache while we set up the cache ram MTRR */ + movl %cr0, %eax + orl $0x40000000, %eax + movl %eax, %cr0 + + /* Set up an mtrr in write-back mode over some arbitrary + * location. As long as we do not get a capacity miss, + * or a multiprocessor conflict miss this should allow us to + * function as if we have memory even when it hasn't been + * enabled yet. + */ + movl $0x204, %ecx /* mtrr[0] physical base register */ + xorl %edx, %edx + movl $(CACHE_RAM_BASE | 0x006), %eax + wrmsr + + movl $0x205, %ecx /* mtrr[0] physical mask register */ + movl $0x0000000f, %edx + movl $(~(CACHE_RAM_SIZE - 1) | 0x800), %eax + wrmsr + + /* Reenable the cache now that the mtrr is set up */ + movl %cr0, %eax + andl $0x9fffffff, %eax + movl %eax, %cr0 + + /* Force cache ram area into cache + * Note: Some versions of the P4 don't allocate a cache + * line on write immediately after a mtrr change, so + * we make certain we read the address before we write + * to it. + */ + movl $CACHE_RAM_BASE, %esi + movl $(CACHE_RAM_BASE + CACHE_RAM_SIZE), %edi +1: + movl (%esi), %eax + addl $4, %esi + movl %eax, -4(%esi) + cmpl %esi, %edi + jnz 1b + + /* Load a different set of data segments */ + movw $0x08, %ax + movw %ax, %ds + movw %ax, %es + movw %ax, %ss +#endif diff --git a/src/cpu/p6/cache_ram_start.inc b/src/cpu/p6/cache_ram_start.inc new file mode 100644 index 0000000000..5d3418f242 --- /dev/null +++ b/src/cpu/p6/cache_ram_start.inc @@ -0,0 +1,27 @@ +#include + + /* copy data segment from FLASH ROM to CACHE */ + movl $(EXT(_ldata) - CACHE_RAM_SEG_BASE), %esi + movl $EXT(_data), %edi + movl $(EXT(_eldata) - CACHE_RAM_SEG_BASE), %ecx + subl %esi, %ecx + jz 1f /* should not happen */ + rep + movsb +1: + + /** clear bss */ + movl $EXT(_bss), %edi + movl $EXT(_ebss), %ecx + subl %edi, %ecx + jz 1f + xorl %eax, %eax + rep + stosb +1: + + /* set new stack */ + movl $(_stack + STACK_SIZE), %esp + + call cache_ram_start + diff --git a/src/cpu/p6/mtrr.c b/src/cpu/p6/mtrr.c index 916e61037a..39085ff606 100644 --- a/src/cpu/p6/mtrr.c +++ b/src/cpu/p6/mtrr.c @@ -225,6 +225,42 @@ static void intel_set_var_mtrr(unsigned int reg, unsigned long base, unsigned lo } +/* setting variable mtrr, comes from linux kernel source */ +void set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size, unsigned char type) +{ + unsigned int tmp; + + if (reg >= 8) + return; + + // it is recommended that we disable and enable cache when we + // do this. + /* Disable cache */ + /* Write back the cache and flush TLB */ + asm volatile ( + "movl %%cr0, %0\n\t" + "orl $0x40000000, %0\n\t" + "movl %0, %%cr0\n\t" + :"=r" (tmp) + ::"memory"); + + if (size == 0) { + /* The invalid bit is kept in the mask, so we simply clear the + relevant mask register to disable a range. */ + wrmsr (MTRRphysMask_MSR (reg), 0, 0); + } else { + /* Bit 32-35 of MTRRphysMask should be set to 1 */ + wrmsr (MTRRphysBase_MSR (reg), base | type, 0); + wrmsr (MTRRphysMask_MSR (reg), ~(size - 1) | 0x800, 0x0F); + } + + // turn cache back on. + asm volatile ("movl %%cr0, %0\n\t" + "andl $0x9fffffff, %0\n\t" + "movl %0, %%cr0\n\t":"=r" (tmp)::"memory"); + +} + /* fms: find most sigificant bit set, stolen from Linux Kernel Source. */ static __inline__ unsigned int fms(unsigned int x) { diff --git a/src/include/cpu/i786/multiplier.h b/src/include/cpu/i786/multiplier.h new file mode 100644 index 0000000000..e2f81362e8 --- /dev/null +++ b/src/include/cpu/i786/multiplier.h @@ -0,0 +1,55 @@ + +/* + ** NMI A20M IGNNE INTR + * X8 H H H H + * X9 H H H L projected + * X10 H H L H + * X11 H H L L + * X12 H L H H + * X13 H L H L + * X14 H L L H + * X15 H L L L + * X16 L H H H + * X17 L H H L + * X18 L H L H + * X19 L H L L + * X20 L L H H + * X21 L L H L projected + * X22 L L L H projected + * X23 L L L L projected + * + ** NMI INTR IGNNE A20M + * X8 H H H H + * X9 H L H H projected + * X10 H H L H + * X11 H L L H + * X12 H H H L + * X13 H L H L + * X14 H H L L + * X15 H L L L + * X16 L H H H + * X17 L L H H + * X18 L H L H + * X19 L L L H + * X20 L H H L + * X21 L L H L projected + * X22 L H L L projected + * X23 L L L L projected + */ + +#define XEON_X8 0xf +#define XEON_X9 0xb /* projected */ +#define XEON_X10 0xd +#define XEON_X11 0x9 +#define XEON_X12 0xe +#define XEON_X13 0xa +#define XEON_X14 0xc +#define XEON_X15 0x8 +#define XEON_X16 0x7 +#define XEON_X17 0x3 +#define XEON_X18 0x5 +#define XEON_X19 0x1 +#define XEON_X20 0x6 +#define XEON_X21 0x2 /* projected */ +#define XEON_X22 0x4 /* projected */ +#define XEON_X23 0x0 /* projected */ diff --git a/src/include/cpu/p6/mtrr.h b/src/include/cpu/p6/mtrr.h index c560e53872..573bc536c4 100644 --- a/src/include/cpu/p6/mtrr.h +++ b/src/include/cpu/p6/mtrr.h @@ -33,6 +33,7 @@ #if !defined(ASSEMBLY) +void set_var_mtrr(unsigned int reg, unsigned long base, unsigned long size, unsigned char type); #if defined(INTEL_PPRO_MTRR) void setup_mtrrs(unsigned long ramsizeK); #endif diff --git a/src/include/loglevel.h b/src/include/loglevel.h index 34f67e1814..a191b308d3 100644 --- a/src/include/loglevel.h +++ b/src/include/loglevel.h @@ -7,6 +7,10 @@ #define MAXIMUM_CONSOLE_LOGLEVEL 8 #endif +#ifndef DEFAULT_CONSOLE_LOGLEVEL +#define DEFAULT_CONSOLE_LOGLEVEL 8 /* anything MORE serious than BIOS_SPEW */ +#endif + #if (DEFAULT_CONSOLE_LOGLEVEL <= MAXIMUM_CONSOLE_LOGLEVEL) #define ASM_CONSOLE_LOGLEVEL DEFAULT_CONSOLE_LOGLEVEL #else diff --git a/src/include/part/fallback_boot.h b/src/include/part/fallback_boot.h new file mode 100644 index 0000000000..95b0c210a8 --- /dev/null +++ b/src/include/part/fallback_boot.h @@ -0,0 +1,16 @@ +#ifndef PART_FALLBACK_BOOT_H +#define PART_FALLBACK_BOOT_H + +#if !defined(ASSEMBLY) + +#if USE_FALLBACK_BOOT +void boot_successful(void); +# else +# define boot_successful() +#endif + +#endif /* ASSEMBLY */ + +#define RTC_BOOT_BYTE 48 + +#endif /* PART_FALLBACK_BOOT_H */ diff --git a/src/include/pc80/isa_dma.h b/src/include/pc80/isa_dma.h new file mode 100644 index 0000000000..205a1b4d70 --- /dev/null +++ b/src/include/pc80/isa_dma.h @@ -0,0 +1,6 @@ +#ifndef PC80_ISA_DMA_H +#define PC80_ISA_DMA_H + +void isa_dma_init(void); + +#endif /* PC80_ISA_DMA_H */ diff --git a/src/include/pc80/mc146818rtc.h b/src/include/pc80/mc146818rtc.h new file mode 100644 index 0000000000..3cde2c04a5 --- /dev/null +++ b/src/include/pc80/mc146818rtc.h @@ -0,0 +1,95 @@ +#ifndef PC80_MC146818RTC_H +#define PC80_MC146818RTC_H + +#ifndef RTC_BASE_PORT +#define RTC_BASE_PORT 0x70 +#endif + +#define RTC_PORT(x) (RTC_BASE_PORT + (x)) + +/* On PCs, the checksum is built only over bytes 16..45 */ +#define PC_CKS_RANGE_START 16 +#define PC_CKS_RANGE_END 45 +#define PC_CKS_LOC 46 + + +/* control registers - Moto names + */ +#define RTC_REG_A 10 +#define RTC_REG_B 11 +#define RTC_REG_C 12 +#define RTC_REG_D 13 + + +/********************************************************************** + * register details + **********************************************************************/ +#define RTC_FREQ_SELECT RTC_REG_A + +/* update-in-progress - set to "1" 244 microsecs before RTC goes off the bus, + * reset after update (may take 1.984ms @ 32768Hz RefClock) is complete, + * totalling to a max high interval of 2.228 ms. + */ +# define RTC_UIP 0x80 +# define RTC_DIV_CTL 0x70 + /* divider control: refclock values 4.194 / 1.049 MHz / 32.768 kHz */ +# define RTC_REF_CLCK_4MHZ 0x00 +# define RTC_REF_CLCK_1MHZ 0x10 +# define RTC_REF_CLCK_32KHZ 0x20 + /* 2 values for divider stage reset, others for "testing purposes only" */ +# define RTC_DIV_RESET1 0x60 +# define RTC_DIV_RESET2 0x70 + /* Periodic intr. / Square wave rate select. 0=none, 1=32.8kHz,... 15=2Hz */ +# define RTC_RATE_SELECT 0x0F +# define RTC_RATE_NONE 0x00 +# define RTC_RATE_32786HZ 0x01 +# define RTC_RATE_16384HZ 0x02 +# define RTC_RATE_8192HZ 0x03 +# define RTC_RATE_4096HZ 0x04 +# define RTC_RATE_2048HZ 0x05 +# define RTC_RATE_1024HZ 0x06 +# define RTC_RATE_512HZ 0x07 +# define RTC_RATE_256HZ 0x08 +# define RTC_RATE_128HZ 0x09 +# define RTC_RATE_64HZ 0x0a +# define RTC_RATE_32HZ 0x0b +# define RTC_RATE_16HZ 0x0c +# define RTC_RATE_8HZ 0x0d +# define RTC_RATE_4HZ 0x0e +# define RTC_RATE_2HZ 0x0f + +/**********************************************************************/ +#define RTC_CONTROL RTC_REG_B +# define RTC_SET 0x80 /* disable updates for clock setting */ +# define RTC_PIE 0x40 /* periodic interrupt enable */ +# define RTC_AIE 0x20 /* alarm interrupt enable */ +# define RTC_UIE 0x10 /* update-finished interrupt enable */ +# define RTC_SQWE 0x08 /* enable square-wave output */ +# define RTC_DM_BINARY 0x04 /* all time/date values are BCD if clear */ +# define RTC_24H 0x02 /* 24 hour mode - else hours bit 7 means pm */ +# define RTC_DST_EN 0x01 /* auto switch DST - works f. USA only */ + +/**********************************************************************/ +#define RTC_INTR_FLAGS RTC_REG_C +/* caution - cleared by read */ +# define RTC_IRQF 0x80 /* any of the following 3 is active */ +# define RTC_PF 0x40 +# define RTC_AF 0x20 +# define RTC_UF 0x10 + +/**********************************************************************/ +#define RTC_VALID RTC_REG_D +# define RTC_VRT 0x80 /* valid RAM and time */ +/**********************************************************************/ + + +/* On PCs, the checksum is built only over bytes 16..45 */ +#define PC_CKS_RANGE_START 16 +#define PC_CKS_RANGE_END 45 +#define PC_CKS_LOC 46 + +#if !defined(ASSEMBLY) +void rtc_init(int invalid); +#endif + +#endif /* PC80_MC146818RTC_H */ diff --git a/src/include/ramtest.h b/src/include/ramtest.h new file mode 100644 index 0000000000..79922d809b --- /dev/null +++ b/src/include/ramtest.h @@ -0,0 +1,8 @@ +#ifndef RAMTEST_H +#define RAMTEST_H + +void ram_fill(unsigned long start, unsigned long stop); +int ram_verify(unsigned long start, unsigned long stop, int max_errors); +int ramcheck(unsigned long start, unsigned long stop, int max_errors); + +#endif /* RAMTEST_H */ diff --git a/src/include/sdram.h b/src/include/sdram.h new file mode 100644 index 0000000000..5f632320d1 --- /dev/null +++ b/src/include/sdram.h @@ -0,0 +1,23 @@ +#ifndef SDRAM_H +#define SDRAM_H + +void sdram_no_memory(void); +void sdram_initialize(void); +void sdram_set_registers(void); +void sdram_set_spd_registers(void); +void sdram_enable(void); +void sdram_first_normal_reference(void); +void sdram_enable_refresh(void); +void sdram_special_finishup(void); + +void sdram_set_command_noop(void); +void sdram_set_command_precharge(void); +void sdram_set_command_cbr(void); +void sdram_set_command_none(void); +void sdram_assert_command(void); +void sdram_set_mode_register(void); + +void sdram_initialize_ecc(void); +unsigned long sdram_get_ecc_size_bytes(void); + +#endif /* SDRAM_H */ diff --git a/src/include/smbus.h b/src/include/smbus.h new file mode 100644 index 0000000000..c394a0fea9 --- /dev/null +++ b/src/include/smbus.h @@ -0,0 +1,8 @@ +#ifndef SMBUS_H +#define SMBUS_H + +void smbus_enable(void); +void smbus_setup(void); +int smbus_read_byte(unsigned device, unsigned address, unsigned char *result); + +#endif /* SMBUS_H */ diff --git a/src/include/southbridge/intel/82801.h b/src/include/southbridge/intel/82801.h index a373f754bb..81b71fb360 100644 --- a/src/include/southbridge/intel/82801.h +++ b/src/include/southbridge/intel/82801.h @@ -1,5 +1,13 @@ +#ifndef SOUTHBRIDGE_INTEL_82801_H +#define SOUTHBRIDGE_INTEL_82801_H void ich2_enable_serial_irqs(void); void ich2_lpc_route_dma(unsigned char mask); void ich2_enable_ioapic(void); void ich2_enable_ide(int enable_a, int enable_b); +void ich2_hard_reset(void); +void ich2_set_cpu_multiplier(unsigned); +void ich2_rtc_init(void); +void ich2_power_after_power_fail(int on); + +#endif /* SOUTHBRIDGE_INTEL_82801_H */ diff --git a/src/include/superio/generic.h b/src/include/superio/generic.h new file mode 100644 index 0000000000..b8f5c88499 --- /dev/null +++ b/src/include/superio/generic.h @@ -0,0 +1,15 @@ +#ifndef SUPERIO_GENERIC_H +#define SUPERIO_GENERIC_H + +void pnp_write_config(unsigned char port, unsigned char value, unsigned char reg); +unsigned char pnp_read_config(unsigned char port, unsigned char reg); +void pnp_set_logical_device(unsigned char port, int device); +void pnp_set_enable(unsigned char port, int enable); +int pnp_read_enable(unsigned char port); +void pnp_set_iobase0(unsigned char port, unsigned iobase); +void pnp_set_iobase1(unsigned char port, unsigned iobase); +void pnp_set_irq0(unsigned char port, unsigned irq); +void pnp_set_irq1(unsigned char port, unsigned irq); +void pnp_set_drq(unsigned char port, unsigned drq); + +#endif /* SUPERIO_GENERIC_H */ diff --git a/src/include/superio/w83627hf.h b/src/include/superio/w83627hf.h new file mode 100644 index 0000000000..c7d694dd88 --- /dev/null +++ b/src/include/superio/w83627hf.h @@ -0,0 +1,59 @@ +#ifndef SUPERIO_W83627HF_H +#define SUPERIO_W83627HF_H + +/* The base address is 0x2e,0x4e depending on config bytes */ +#ifndef SIO_BASE +#define SIO_BASE 0x2e +#endif + +#define SIO_SYSTEM_CLK_INPUT_48MHZ (1<<6) +#define SIO_SYSTEM_CLK_INPUT_24MHZ (0<<6) + +#if defined(SIO_SYSTEM_CLK_INPUT) +#if (SIO_SYSTEM_CLK_INPUT != SIO_SYSTEM_CLK_INPUT_48MHZ) && (SIO_SYSTEM_CLK_INPUT != SIO_SYSTEM_CLK_INPUT_24MHZ) +#error BAD SIO_SYSTEM_CLK_INPUT_PARAMETER +#endif +#endif + +#define FLOPPY_DEVICE 0 +#define PARALLEL_DEVICE 1 +#define COM1_DEVICE 2 +#define COM2_DEVICE 3 +#define KBC_DEVICE 5 +#define CIR_DEVICE 6 +#define GAME_PORT_DEVICE 7 +#define GPIO_PORT2_DEVICE 8 +#define GPIO_PORT3_DEVICE 9 +#define ACPI_DEVICE 0xa +#define HW_MONITOR_DEVICE 0xb + + +#define FLOPPY_DEFAULT_IOBASE 0x3f0 +#define FLOPPY_DEFAULT_IRQ 6 +#define FLOPPY_DEFAULT_DRQ 2 +#define PARALLEL_DEFAULT_IOBASE 0x378 +#define PARALLEL_DEFAULT_IRQ 7 +#define PARALLEL_DEFAULT_DRQ 4 /* No dma */ +#define COM1_DEFAULT_IOBASE 0x3f8 +#define COM1_DEFAULT_IRQ 4 +#define COM1_DEFAULT_BAUD 115200 +#define COM2_DEFAULT_IOBASE 0x2f8 +#define COM2_DEFAULT_IRQ 3 +#define COM2_DEFAULT_BAUD 115200 +#define KBC_DEFAULT_IOBASE0 0x60 +#define KBC_DEFAULT_IOBASE1 0x64 +#define KBC_DEFAULT_IRQ0 0x1 +#define KBC_DEFAULT_IRQ1 0xc + +#if !defined(ASSEMBLY) +void w83627hf_enter_pnp(unsigned char port); +void w83627hf_exit_pnp(unsigned char port); + +#define POWER_OFF 0 +#define POWER_ON 1 +#define POWER_PREV 2 + +void w832627hf_power_after_power_fail(int state); +#endif + +#endif /* SUPERIO_W83627HF_H */ diff --git a/src/lib/Config b/src/lib/Config index 94e28f88b2..78cd0bcc12 100644 --- a/src/lib/Config +++ b/src/lib/Config @@ -14,4 +14,4 @@ object malloc.o object elfboot.o object do_inflate.o object delay.o - +object fallback_boot.o USE_FALLBACK_BOOT diff --git a/src/lib/fallback_boot.c b/src/lib/fallback_boot.c new file mode 100644 index 0000000000..4838a4e976 --- /dev/null +++ b/src/lib/fallback_boot.c @@ -0,0 +1,20 @@ +#include +#include +#include +#include + +void boot_successful(void) +{ + /* Remember I succesfully booted by setting + * the initial boot direction + * to the direction that I booted. + */ + unsigned char index, byte; + index = inb(RTC_PORT(0)) & 0x80; + index |= RTC_BOOT_BYTE; + outb(index, RTC_PORT(0)); + + byte = inb(RTC_PORT(1)); + byte |= (byte & 2) >> 1; + outb(byte, RTC_PORT(1)); +} diff --git a/src/lib/linuxpci.c b/src/lib/linuxpci.c index dcb66e592f..f8033cd342 100644 --- a/src/lib/linuxpci.c +++ b/src/lib/linuxpci.c @@ -139,12 +139,12 @@ void pci_get_size(struct pci_dev *dev, unsigned long reg, unsigned long addr) // This incidentally catches the common case where registers // read back as 0 for both address and size. if (addr == size) { - printk_err(__FUNCTION__ - "dev_fn 0x%x, register %d, read-only" - " SO, ignoring it\n", - dev->devfn, reg); - printk_err("addr was 0x%x, size was 0x%x\n",addr,size); - type = 0; + printk_debug(__FUNCTION__ + "dev_fn 0x%x, register %d, read-only" + " SO, ignoring it\n", + dev->devfn, reg); + printk_debug("addr was 0x%x, size was 0x%x\n",addr,size); + type = 0; size = 0; } // Now compute the actual size, See PCI Spec 6.2.5.1 ... diff --git a/src/lib/printk.c b/src/lib/printk.c index 5b36d941e3..38ba25eb43 100644 --- a/src/lib/printk.c +++ b/src/lib/printk.c @@ -14,6 +14,7 @@ static char rcsid[] = "$Id$"; #include #include #include +#include /* printk's without a loglevel use this.. */ #define DEFAULT_MESSAGE_LOGLEVEL 4 /* BIOS_WARNING */ @@ -21,10 +22,6 @@ static char rcsid[] = "$Id$"; /* We show everything that is MORE important than this.. */ #define MINIMUM_CONSOLE_LOGLEVEL 1 /* Minimum loglevel we let people use */ -#ifndef DEFAULT_CONSOLE_LOGLEVEL -#define DEFAULT_CONSOLE_LOGLEVEL 8 /* anything MORE serious than BIOS_SPEW */ -#endif - /* Keep together for sysctl support */ int console_loglevel = DEFAULT_CONSOLE_LOGLEVEL; diff --git a/src/lib/serial_subr.c b/src/lib/serial_subr.c index 4b5ffe6cc4..131a0e893d 100644 --- a/src/lib/serial_subr.c +++ b/src/lib/serial_subr.c @@ -6,7 +6,9 @@ static char rcsid[] = "$Id$"; #include /* Base Address */ -#define TTYS0 0x3f8 +#ifndef TTYS0_BASE +#define TTYS0_BASE 0x3f8 +#endif #ifndef TTYS0_BAUD #define TTYS0_BAUD 115200 @@ -153,29 +155,29 @@ inline void uart_init(unsigned base_port, unsigned divisor) void ttys0_init(void) { - uart_init(TTYS0, TTYS0_DIV); + uart_init(TTYS0_BASE, TTYS0_DIV); } void ttys0_tx_byte(unsigned char data) { - uart_tx_byte(TTYS0, data); + uart_tx_byte(TTYS0_BASE, data); } unsigned char ttys0_rx_byte(void) { - return uart_rx_byte(TTYS0); + return uart_rx_byte(TTYS0_BASE); } unsigned long ttys0_rx_bytes(char *buffer, unsigned long size) { - return uart_rx_bytes(TTYS0, buffer, size); + return uart_rx_bytes(TTYS0_BASE, buffer, size); } #ifdef PYRO_SERIAL /* experimental serial read stuffs */ int iskey(void) { - return uart_have_rx_byte(TTYS0); + return uart_have_rx_byte(TTYS0_BASE); } char ttys0_rx_char(void) diff --git a/src/lib/vsprintf.c b/src/lib/vsprintf.c index 370a120f3e..e719a7c537 100644 --- a/src/lib/vsprintf.c +++ b/src/lib/vsprintf.c @@ -324,7 +324,7 @@ int vtxprintf(void (*tx_byte)(unsigned char byte), const char *fmt, va_list args /* FIXME this global makes vsprintf non-reentrant */ static char *str_buf; -static void str_tx_byte(char byte) +static void str_tx_byte(unsigned char byte) { *str_buf = byte; str_buf++; diff --git a/src/mainboard/asus/a7m/Config b/src/mainboard/asus/a7m/Config index 292d1acd11..4825bbb0c4 100644 --- a/src/mainboard/asus/a7m/Config +++ b/src/mainboard/asus/a7m/Config @@ -1,4 +1,8 @@ arch i386 +mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc +ldscript cpu/i386/entry16.lds + mainboardinit northbridge/amd/amd76x/reset_test.inc mainboardinit cpu/k7/earlymtrr.inc mainboardinit northbridge/amd/amd76x/mpinit.inc diff --git a/src/mainboard/asus/a7m/mainboard.c b/src/mainboard/asus/a7m/mainboard.c index 403167db99..ea68a9a649 100644 --- a/src/mainboard/asus/a7m/mainboard.c +++ b/src/mainboard/asus/a7m/mainboard.c @@ -3,6 +3,7 @@ #include #include #include +#include #define CHECKSUM 0x8d @@ -168,6 +169,6 @@ void mainboard_fixup(void) southbridge_fixup(); pci_functions_fixup(); load_irq_routing_table(); -// rtc_init(); +// rtc_init(0); // pci_dump(); } diff --git a/src/mainboard/asus/cua/Config b/src/mainboard/asus/cua/Config index 8ba9d4ba03..aac3e3c87e 100644 --- a/src/mainboard/asus/cua/Config +++ b/src/mainboard/asus/cua/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit northbridge/acer/m1631/chipset_init.inc diff --git a/src/mainboard/dell/350/Config b/src/mainboard/dell/350/Config index 7b6e7710c9..32a4391d30 100644 --- a/src/mainboard/dell/350/Config +++ b/src/mainboard/dell/350/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit cpu/i386/reset16.inc ldscript cpu/i386/reset16.lds diff --git a/src/mainboard/digitallogic/smartcore-p5/Config b/src/mainboard/digitallogic/smartcore-p5/Config index d4f18c5758..56145c3520 100644 --- a/src/mainboard/digitallogic/smartcore-p5/Config +++ b/src/mainboard/digitallogic/smartcore-p5/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit cpu/i386/reset16.inc ldscript cpu/i386/reset16.lds diff --git a/src/mainboard/gigabit/ga-6bxc/Config b/src/mainboard/gigabit/ga-6bxc/Config index 9ac98974c6..8f56f956dc 100644 --- a/src/mainboard/gigabit/ga-6bxc/Config +++ b/src/mainboard/gigabit/ga-6bxc/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit cpu/i386/reset16.inc ldscript cpu/i386/reset16.lds diff --git a/src/mainboard/gigabit/ga-6oxe/Config b/src/mainboard/gigabit/ga-6oxe/Config index f0847753cc..775ca6b2f8 100644 --- a/src/mainboard/gigabit/ga-6oxe/Config +++ b/src/mainboard/gigabit/ga-6oxe/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit cpu/i386/reset16.inc ldscript cpu/i386/reset16.lds diff --git a/src/mainboard/ibm/t23/Config b/src/mainboard/ibm/t23/Config index 63e6db1cdb..66ee5ce6d3 100644 --- a/src/mainboard/ibm/t23/Config +++ b/src/mainboard/ibm/t23/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit cpu/i386/reset16.inc ldscript cpu/i386/reset16.lds diff --git a/src/mainboard/intel/l440bx/Config b/src/mainboard/intel/l440bx/Config index c0cdd659d0..56d439e387 100644 --- a/src/mainboard/intel/l440bx/Config +++ b/src/mainboard/intel/l440bx/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit cpu/i386/reset16.inc ldscript cpu/i386/reset16.lds diff --git a/src/mainboard/intel/l440gx/Config b/src/mainboard/intel/l440gx/Config index 2e26cba9df..e8d2a910a1 100644 --- a/src/mainboard/intel/l440gx/Config +++ b/src/mainboard/intel/l440gx/Config @@ -1,6 +1,7 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit cpu/i386/reset16.inc ldscript cpu/i386/reset16.lds diff --git a/src/mainboard/intel/l440gx/mainboard_raminit.c b/src/mainboard/intel/l440gx/mainboard_raminit.c new file mode 100644 index 0000000000..0d20579873 --- /dev/null +++ b/src/mainboard/intel/l440gx/mainboard_raminit.c @@ -0,0 +1,56 @@ +#include +#include +#include +#include +#include +#include + +#define I440GX_BUS 0 +#define I440GX_DEVFN ((0 << 3) | 0) + +static void debug_raminit(void) +{ + int i; + printk_debug("\n440GX registers"); + for(i = 0; i < 256; i++) { + unsigned char byte; + if ((i & 0x0f) == 0) { + printk_debug("\n%02x: ", i); + } + pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, i, &byte); + printk_debug("%02x ", byte); + } + printk_debug("\n"); +} + +void cache_ram_start(void) +{ + displayinit(); + printk_info("Hello from cache_ram_start\n"); + printk_debug("Calling pci_set_method\n"); + pci_set_method(); + printk_debug("Calling smbus_enable\n"); + smbus_enable(); + printk_debug("Calling smbus_setup\n"); + smbus_setup(); + printk_debug("Calling dump_spd_registers\n"); + dump_spd_registers(); + printk_debug("Calling sdram_initialize\n"); + sdram_initialize(); + printk_debug("Calling debug_raminit\n"); + debug_raminit(); + printk_debug("Calling sdram_initialize_ecc\n"); + sdram_initialize_ecc(); + printk_debug("Calling ramcheck\n"); +#if 0 + ramcheck(0, 128*1024, 30); + ramcheck(128*1024, (128+64)*1024, 30); + ramcheck(256*1024, (256+64)*1024, 30); + ramcheck((256+128)*1024, 512*1024, 30); + ramcheck(512*1024, 640*1024, 30); + ramcheck(1024*1024, (1024*1024) + (128*1024), 30); + ramcheck(64*1024*1024, (64*1024*1024) + (128*1024), 30); + ramcheck(127*1024*1024, 128*1024*1024, 30); +#endif + printk_debug("ram is setup\n"); +} diff --git a/src/mainboard/irobot/proto1/Config b/src/mainboard/irobot/proto1/Config index 02389f82ee..ece0087444 100644 --- a/src/mainboard/irobot/proto1/Config +++ b/src/mainboard/irobot/proto1/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit cpu/i386/reset16.inc ldscript cpu/i386/reset16.lds diff --git a/src/mainboard/lanner/em-370/Config b/src/mainboard/lanner/em-370/Config index f32cf1c53b..64a7e11bb4 100644 --- a/src/mainboard/lanner/em-370/Config +++ b/src/mainboard/lanner/em-370/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit cpu/i386/reset16.inc ldscript cpu/i386/reset16.lds diff --git a/src/mainboard/leadtek/winfast6300/Config b/src/mainboard/leadtek/winfast6300/Config index a9545371ed..d17cf67bcb 100644 --- a/src/mainboard/leadtek/winfast6300/Config +++ b/src/mainboard/leadtek/winfast6300/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit superio/sis/950/setup_serial.inc diff --git a/src/mainboard/matsonic/ms7308e/Config b/src/mainboard/matsonic/ms7308e/Config index 20d70d9820..dead2801f2 100644 --- a/src/mainboard/matsonic/ms7308e/Config +++ b/src/mainboard/matsonic/ms7308e/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit superio/sis/950/setup_serial.inc diff --git a/src/mainboard/pcchips/m754lmr/Config b/src/mainboard/pcchips/m754lmr/Config index 059e6fd7d3..7133fcf022 100644 --- a/src/mainboard/pcchips/m754lmr/Config +++ b/src/mainboard/pcchips/m754lmr/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds # These are ONLY used for doc. diff --git a/src/mainboard/pcchips/m810lmr/Config b/src/mainboard/pcchips/m810lmr/Config index ced7f4117a..24a9582564 100644 --- a/src/mainboard/pcchips/m810lmr/Config +++ b/src/mainboard/pcchips/m810lmr/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit superio/sis/950/setup_serial.inc diff --git a/src/mainboard/rcn/dc1100s/Config b/src/mainboard/rcn/dc1100s/Config index 023f974350..a662ecac83 100644 --- a/src/mainboard/rcn/dc1100s/Config +++ b/src/mainboard/rcn/dc1100s/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit superio/via/vt82c686/setup_serial.inc diff --git a/src/mainboard/sis/540/Config b/src/mainboard/sis/540/Config index 1f5d2c012e..bdec6e0c54 100644 --- a/src/mainboard/sis/540/Config +++ b/src/mainboard/sis/540/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit superio/sis/950/setup_serial.inc diff --git a/src/mainboard/sis/550/Config b/src/mainboard/sis/550/Config index 0443b03e5f..f4e38351f1 100644 --- a/src/mainboard/sis/550/Config +++ b/src/mainboard/sis/550/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds northsouthbridge sis/550 diff --git a/src/mainboard/supermicro/p4dc6/Config b/src/mainboard/supermicro/p4dc6/Config index 769b4105ed..f463c4600d 100644 --- a/src/mainboard/supermicro/p4dc6/Config +++ b/src/mainboard/supermicro/p4dc6/Config @@ -1,31 +1,43 @@ arch i386 -mainboardinit cpu/i386/entry16.inc -ldscript cpu/i386/entry16.lds -mainboardinit cpu/i386/reset16.inc -ldscript cpu/i386/reset16.lds +mainboardinit cpu/i386/entry16.inc +ldscript cpu/i386/entry16.lds +mainboardinit cpu/i386/entry32.inc +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 -#rambase 0x04000000 -biosbase 0xffff0000 -option XIP_ROM_BASE=0xffff0000 -option XIP_ROM_SIZE=0x10000 +option ROM_IMAGE_SIZE=32768 +rambase 0x00008000 +option USE_CACHE_RAM=1 option CACHE_RAM_BASE=0xfff70000 option CACHE_RAM_SIZE=0x00010000 -option USE_CACHE_RAM=1 nooption USE_DEFAULT_LAYOUT -#rambase 0xfff70000 -rambase 0x00000800 option STACK_SIZE=0x2000 +option USE_FALLBACK_BOOT=1 +#/* falback */ +option ZKERNEL_START=0xffff0000 +option _ROMBASE= 0xffff8000 +option XIP_ROM_BASE= 0xffff8000 +option XIP_ROM_SIZE= 0x00008000 +##/* normal image */ +#option ZKERNEL_START=0xfff80000 +#option _ROMBASE= 0xfffe8000 +#option XIP_ROM_BASE= 0xfffe8000 +#option XIP_ROM_SIZE= 0x00008000 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 -#mainboardinit southbridge/intel/82801/definitions.inc -#mainboardinit southbridge/intel/82801/disable_watchdog.inc -#mainboardinit southbridge/intel/82801/lpc_com1.inc mainboardinit cpu/i786/earlymtrr.inc + mainboardinit superio/winbond/w83627hf/setup_serial.inc mainboardinit pc80/serial.inc mainboardinit arch/i386/lib/console.inc + #mainboardinit ram/ramtest.inc #mainboardinit northbridge/intel/82860/reset_test.inc mainboardinit cpu/i786/cache_ram_init.inc @@ -52,6 +64,7 @@ object mptable.o HAVE_MP_TABLE object irq_tables.o HAVE_PIRQ_TABLE #keyboard pc80 dir ../../../pc80 +dir /src/superio/winbond/w83627hf # FIXME are the SMBUS DIMM locations documented anywhere? option SMBUS_MEM_DEVICE_START=(0xa << 3) diff --git a/src/mainboard/supermicro/p4dc6/failover.inc b/src/mainboard/supermicro/p4dc6/failover.inc new file mode 100644 index 0000000000..e0ab946780 --- /dev/null +++ b/src/mainboard/supermicro/p4dc6/failover.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 + jnz __cpu_reset diff --git a/src/mainboard/supermicro/p4dc6/mainboard.c b/src/mainboard/supermicro/p4dc6/mainboard.c index 2a2b1c50f6..5893b3fc86 100644 --- a/src/mainboard/supermicro/p4dc6/mainboard.c +++ b/src/mainboard/supermicro/p4dc6/mainboard.c @@ -5,29 +5,36 @@ #include #include #include +#include +#include +#include unsigned long initial_apicid[MAX_CPUS] = { 0, 6 }; + void mainboard_fixup(void) { ich2_enable_ioapic(); ich2_enable_serial_irqs(); ich2_enable_ide(1,1); - rtc_init(); + ich2_rtc_init(); ich2_lpc_route_dma(0xff); isa_dma_init(); +#if 1 + /* FIXME don't hard code these */ + ich2_set_cpu_multiplier(XEON_X17); +#endif + ich2_power_after_power_fail(1); + w832627hf_power_after_power_fail(POWER_ON); printk_notice("Please add a mainboard_fixup!\n"); return; } void hard_reset(void) { - /* Try rebooting through port 0xcf9 */ - outb((0 <<3)|(1<<2)|(1<<1), 0xcf9); - return; + ich2_hard_reset(); } - diff --git a/src/mainboard/technoland/sbc710/Config b/src/mainboard/technoland/sbc710/Config index 923f47cf80..a41fad420b 100644 --- a/src/mainboard/technoland/sbc710/Config +++ b/src/mainboard/technoland/sbc710/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit cpu/i386/reset16.inc ldscript cpu/i386/reset16.lds diff --git a/src/mainboard/tyan/guiness/Config b/src/mainboard/tyan/guiness/Config index e4ff6d0d15..7229c9545a 100644 --- a/src/mainboard/tyan/guiness/Config +++ b/src/mainboard/tyan/guiness/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit cpu/i386/reset16.inc ldscript cpu/i386/reset16.lds diff --git a/src/mainboard/tyan/guiness/mainboard.c b/src/mainboard/tyan/guiness/mainboard.c index 0e5224d47d..16dcda9013 100644 --- a/src/mainboard/tyan/guiness/mainboard.c +++ b/src/mainboard/tyan/guiness/mainboard.c @@ -6,6 +6,7 @@ #include #include #include +#include unsigned long initial_apicid[MAX_CPUS] = { @@ -515,7 +516,7 @@ void mainboard_fixup(void) setup_ide_devices(); onboard_scsi_fixup(); cpu_reset_sends_init(); - rtc_init(); + rtc_init(0); decode_stop_grant_fixup(); posted_memory_write_enable(); pm_controller_classcode_fixup(); diff --git a/src/mainboard/tyan/s1834/Config b/src/mainboard/tyan/s1834/Config index fe246691cc..fbcb9f00b3 100644 --- a/src/mainboard/tyan/s1834/Config +++ b/src/mainboard/tyan/s1834/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit cpu/i386/reset16.inc ldscript cpu/i386/reset16.lds diff --git a/src/mainboard/tyan/s1846/Config b/src/mainboard/tyan/s1846/Config index 6984b5dac8..52122cd57f 100644 --- a/src/mainboard/tyan/s1846/Config +++ b/src/mainboard/tyan/s1846/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit cpu/i386/reset16.inc ldscript cpu/i386/reset16.lds diff --git a/src/mainboard/via/vt5292/Config b/src/mainboard/via/vt5292/Config index 3f8c66fe7c..dcff9aa2e4 100644 --- a/src/mainboard/via/vt5292/Config +++ b/src/mainboard/via/vt5292/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit cpu/i386/reset16.inc ldscript cpu/i386/reset16.lds diff --git a/src/mainboard/via/vt5426/Config b/src/mainboard/via/vt5426/Config index 79fef0c646..789bf8cfbd 100644 --- a/src/mainboard/via/vt5426/Config +++ b/src/mainboard/via/vt5426/Config @@ -1,5 +1,6 @@ arch i386 mainboardinit cpu/i386/entry16.inc +mainboardinit cpu/i386/entry32.inc ldscript cpu/i386/entry16.lds mainboardinit superio/via/vt82c686/setup_serial.inc diff --git a/src/northbridge/intel/440gx/Config b/src/northbridge/intel/440gx/Config index 9c8c550f44..9a65787e69 100644 --- a/src/northbridge/intel/440gx/Config +++ b/src/northbridge/intel/440gx/Config @@ -1,8 +1,10 @@ mainboardinit arch/i386/lib/set_memory_size_noop.inc -mainboardinit northbridge/intel/440gx/raminit.inc -mainboardinit sdram/generic_sdram_enable.inc -mainboardinit sdram/generic_sdram.inc -mainboardinit sdram/generic_zero_ecc_sdram.inc +mainboardinit northbridge/intel/440gx/raminit.inc USE_DEFAULT_LAYOUT +mainboardinit sdram/generic_sdram_enable.inc USE_DEFAULT_LAYOUT +mainboardinit sdram/generic_sdram.inc USE_DEFAULT_LAYOUT +mainboardinit sdram/generic_zero_ecc_sdram.inc USE_DEFAULT_LAYOUT mainboardinit arch/i386/lib/cpu_reset.inc object northbridge.o + +object raminit.o USE_CACHE_RAM diff --git a/src/northbridge/intel/440gx/raminit.c b/src/northbridge/intel/440gx/raminit.c new file mode 100644 index 0000000000..ce98ddb551 --- /dev/null +++ b/src/northbridge/intel/440gx/raminit.c @@ -0,0 +1,796 @@ +#include +#include +#include +#include +#include +#include + +#define I440GX_BUS 0 +#define I440GX_DEVFN ((0x00 << 3) + 0) + +#define USE_ECC 0 + +#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 + + +/* Default values for config registers */ + +static void set_nbxcfg(void) +{ + /* 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) == ?? + */ + pcibios_write_config_dword(I440GX_BUS, I440GX_DEVFN, 0x50, 0xff00000c); +} + +static void set_dramc(void) +{ + /* 0 == 0000 + * 8 == 1000 + * Not registered SDRAM + * refresh disabled + */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57, 0x8); +} + +static void set_pam(void) +{ + /* 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... + */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x59, 0x00); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5a, 0x00); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5b, 0x00); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5d, 0x00); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5e, 0x00); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x5f, 0x00); +} + +static void set_drb(void) +{ + /* DRB - DRAM Row Boundary Registers */ + /* Conservative setting 8MB of ram on first DIMM... */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x60, 0x01); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x61, 0x01); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x62, 0x01); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x63, 0x01); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x64, 0x01); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x65, 0x01); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x66, 0x01); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x67, 0x01); +} + +static void set_fdhc(void) +{ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x68, 0x00); +} +static void set_mbsc(void) +{ + /* 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 + */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x69, 0xB3); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6a, 0xee); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6b, 0xff); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6c, 0xff); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6d, 0xff); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x6e, 0x03); +} + +static void set_smram(void) +{ + /* 0x72 SMRAM */ + /* 1 == 0001 + * a == 1010 + * SMM Compatible base segment == 010 (Hardcoded value) + */ +} + +static void set_esramc(void) +{ + /* 0x73 ESMRAMC */ +} + +static void set_rps(void) +{ + /* 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 + */ + pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x74, 0x5555); +} + +static void set_sdramc(void) +{ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, CAS_NB); +} + +static void set_pgpol(void) +{ + /* 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 + */ + pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x78, 0xff07); +} + +static void set_mbfs(void) +{ + /* 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 + * + */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xca, 0xff); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcb, 0xff); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcc, 0x7f); +} + +static void set_dwtc(void) +{ + /* DWTC - DRAM Write Thermal Throttle Control */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe0, 0xb4); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe1, 0xbe); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe2, 0xff); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe3, 0xd7); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe4, 0x97); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe5, 0x3e); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe6, 0x00); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe7, 0x80); +} + +static void set_drtc(void) +{ + /* DRTC - DRAM Read Thermal Throttle Control */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe8, 0x2c); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xe9, 0xd3); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xea, 0xf7); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xeb, 0xcf); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xec, 0x9d); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xed, 0x3e); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xee, 0x00); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xef, 0x00); +} + +static void set_pmcr(void) +{ + /* PMCR -- BIOS sets 0x90 into it. + * 0x10 is REQUIRED. + * we have never used it. So why did this ever work? + */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x7a, 0x90); + +} +void sdram_set_registers(void) +{ + set_nbxcfg(); + set_dramc(); + set_pam(); + set_drb(); + set_fdhc(); + set_mbsc(); + set_smram(); + set_esramc(); + set_rps(); + set_sdramc(); + set_pgpol(); + set_mbfs(); + set_dwtc(); + set_drtc(); + set_pmcr(); +} + + +static void spd_set_drb(void) +{ + /* + * Effects: Uses serial presence detect to set the + * DRB registers which holds the ending memory address assigned + * to each DIMM. + */ + unsigned end_of_memory; + unsigned device; + unsigned drb_reg; + + end_of_memory = 0; /* in multiples of 8MiB */ + device = SMBUS_MEM_DEVICE_START; + drb_reg = 0x60; + while (device <= SMBUS_MEM_DEVICE_END) { + unsigned side1_bits, side2_bits; + unsigned char byte, byte2; + int status; + + side1_bits = side2_bits = -1; + + /* rows */ + status = smbus_read_byte(device, 3, &byte); + if (status != 0) goto set_drb_reg; + side1_bits += byte & 0xf; + + /* columns */ + status = smbus_read_byte(device, 4, &byte); + side1_bits += byte & 0xf; + + /* banks */ + status = smbus_read_byte(device, 17, &byte); + side1_bits += log2(byte); + + /* Get the moduel data width and convert it to a power of two */ + /* low byte */ + status = smbus_read_byte(device, 6, &byte); + /* high byte */ + status = smbus_read_byte(device, 7, &byte2); + side1_bits += log2((((unsigned long)byte2 << 8)| byte)); + + /* now I have the ram size in bits as a power of two (less 1) */ + /* Make it mulitples of 8MB */ + side1_bits -= 25; + + /* side two */ + + /* number of physical banks */ + status = smbus_read_byte(device, 5, &byte); + if (byte <= 1) goto set_drb_reg; + + /* for now only handle the symmetrical case */ + side2_bits = side1_bits; + + set_drb_reg: + /* Compute the end address for the DRB register */ + /* Only process dimms < 2GB (2^8 * 8MB) */ + if (side1_bits < 8) { + end_of_memory += (1 << side1_bits); + } + printk_debug("end_of_memory: %08x\n", end_of_memory); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, drb_reg, end_of_memory); + + if (side2_bits < 8 ) { + end_of_memory += (1 << side2_bits); + } + printk_debug("end_of_memory: %08x\n", end_of_memory); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, drb_reg +1, end_of_memory); + + drb_reg += 2; + device += SMBUS_MEM_DEVICE_INC; + } +} + +static void spd_set_dramc(void) +{ + /* + * 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. + */ + /* 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 */ + /* FIXME Check for illegal/unsupported ram configurations and abort */ + unsigned device; + int status; + unsigned char byte; + unsigned dramc; + status = -1; + device = SMBUS_MEM_DEVICE_START; + while ((status != 0) && (device <= SMBUS_MEM_DEVICE_END)) { + status = smbus_read_byte(device, 21, &byte); + device += SMBUS_MEM_DEVICE_INC; + } + if (status != 0) { + /* We couldn't find anything we must have no memory */ + sdram_no_memory(); + } + dramc = 0x8; + if ((byte & 0x12) != 0) { + /* this is a registered part. + * observation: for register parts, BIOS zeros (!) + * registers CA-CC. This has an undocumented meaning. + */ + /* But it does make sense the oppisite of registered + * sdram is buffered and 0xca - 0xcc control the buffers. + * Clearing them aparently disables them. + */ + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xca, 0); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcb, 0); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0xcc, 0); + dramc = 0x10; + } + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57, dramc); +} + +static void spd_enable_refresh(void) +{ + /* + * 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 + */ + static const unsigned char refresh_rates[] = { + 0x01, /* Normal 15.625 us -> 15.6 us */ + 0x05, /* Reduced(.25X) 3.9 us -> 7.8 us */ + 0x05, /* Reduced(.5X) 7.8 us -> 7.8 us */ + 0x02, /* Extended(2x) 31.3 us -> 31.2 us */ + 0x03, /* Extended(4x) 62.5 us -> 62.4 us */ + 0x04, /* Extended(8x) 125 us -> 124.8 us */ + }; + /* Find the first dimm and assume the rest are the same */ + int status; + unsigned char byte; + unsigned device; + unsigned refresh_rate; + byte = 0; + status = -1; + device = SMBUS_MEM_DEVICE_START; + while ((status != 0) && (device <= SMBUS_MEM_DEVICE_END)) { + status = smbus_read_byte(device, 12, &byte); + device += SMBUS_MEM_DEVICE_INC; + } + if (status != 0) { + /* We couldn't find anything we must have no memory */ + sdram_no_memory(); + } + byte &= 0x7f; + /* Default refresh rate be conservative */ + refresh_rate = 5; + /* see if the ram refresh is a supported one */ + if (byte < 6) { + refresh_rate = refresh_rates[byte]; + } + pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57, &byte); + byte &= 0xf8; + byte |= refresh_rate; + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57, byte); +} + +static void spd_set_sdramc(void) +{ + return; +} + +static void spd_set_rps(void) +{ + /* + * Effects: Uses serial presence detect to set the row size + * on a given DIMM + * FIXME: Check for illegal/unsupported ram configurations and abort + */ + /* The RPS register holds the size of a ``page'' of DRAM on each DIMM */ + unsigned page_sizes; + unsigned index; + unsigned device; + unsigned char dramc; + /* default all page sizes to 2KB */ + page_sizes = 0; + index = 0; + device = SMBUS_MEM_DEVICE_START; + while (device <= SMBUS_MEM_DEVICE_END) { + int status; + unsigned char byte; + int page_size; + + status = smbus_read_byte(device, 3, &byte); + if (status != 0) goto next; + + /* I now have the row page size as a power of 2 */ + page_size = byte & 0xf; + /* make it in multiples of 2Kb */ + page_size -= 11; + if (page_size <= 0) goto next; + /* FIXME: do something with page sizes greather than 8KB!! */ + page_sizes |= (page_size << index); + + /* side two */ + status = smbus_read_byte(device, 5, &byte); + if (byte <= 1) goto next; + + /* For now only handle the symmetrical case */ + page_sizes |= (page_size << (index +2)); + + next: + index += 4; + device += SMBUS_MEM_DEVICE_INC; + } + + /* 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, page_sizes 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. + */ + + pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x57, &dramc); + if (dramc & 0x10) { + /* registered */ + + /* 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. + */ + page_sizes += 0x1111; + } + + pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x74, page_sizes); +} + +static void spd_set_pgpol(void) +{ + /* + * Effects: Uses serial presence detect to set the number of banks + * on a given DIMM + * FIXME: Check for illegal/unsupported ram configurations and abort + */ + /* The PGPOL register stores the number of logical banks per DIMM, + * and number of clocks the DRAM controller waits in the idle + * state. + */ + unsigned device; + unsigned bank_sizes; + unsigned bank; + unsigned reg; + /* default all bank counts 2 */ + bank_sizes = 0; + bank = 0; + device = SMBUS_MEM_DEVICE_START; + while (device <= SMBUS_MEM_DEVICE_END) { + int status; + unsigned char byte; + + /* logical banks */ + status = smbus_read_byte(device, 17, &byte); + if (status != 0) goto next; + if (byte < 4) goto next; + bank_sizes |= (1 << bank); + + /* side 2 */ + /* Number of physical banks */ + status = smbus_read_byte(device, 5, &byte); + if (byte <= 1) goto next; + /* for now only handle the symmetrical case */ + bank_sizes |= (1 << (bank +1)); + next: + bank += 2; + device += SMBUS_MEM_DEVICE_INC; + } + reg = bank_sizes << 8; + reg |= 0x7; /* 32 clocks idle time */ + pcibios_write_config_word(I440GX_BUS, I440GX_DEVFN, 0x78, reg); +} + +static void spd_set_nbxcfg(void) +{ + /* + * Effects: Uses serial presence detect to set the + * ECC support flags in the NBXCFG register + * FIXME: Check for illegal/unsupported ram configurations and abort + */ + unsigned reg; + unsigned index; + unsigned device; + + /* Say all dimms have no ECC support */ + reg = 0xff; + index = 0; + + device = SMBUS_MEM_DEVICE_START; + while (device <= SMBUS_MEM_DEVICE_END) { + int status; + unsigned char byte; + + status = smbus_read_byte(device, 11, &byte); + if (status != 0) goto next; +#if !USE_ECC /* Disable ECC */ + byte = 0; +#endif + /* 0 == None, 1 == Parity, 2 == ECC */ + if (byte != 2) goto next; + reg ^= (1 << index); + + /* side two */ + /* number of physical banks */ + status = smbus_read_byte(device, 5, &byte); + if (byte <= 1) goto next; + /* There is only the symmetrical case */ + reg ^= (1 << (index +1)); + next: + index += 2; + device += SMBUS_MEM_DEVICE_INC; + } + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x53, reg); + /* Now see if reg is 0xff. If it is we are done. If not, + * we need to set 0x18 into regster 0x50.l + * we will do this in two steps, first or in 0x80 to 0x50.b, + * then or in 0x1 to 0x51.b + */ + printk_debug("spd_set_nbxcfg reg=0x%02x\n", reg); + if (reg != 0xff) { + unsigned char byte; + pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x50, &byte); + byte |= 0x80; + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x50, byte); + pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x51, &byte); + byte |= 1; + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x51, 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. + */ + pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, &byte); + byte |= 4; + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, byte); + printk_debug("spd_set_nbxcfg 0x76.b=0x%02x\n", byte); + } +} + +void sdram_set_spd_registers(void) +{ + spd_set_drb(); + spd_set_dramc(); + spd_set_rps(); + spd_set_sdramc(); + spd_set_pgpol(); + spd_set_nbxcfg(); +} + +void sdram_first_normal_reference(void) +{ + return; +} + +void sdram_special_finishup(void) +{ + return; +} + +static void set_ram_command(unsigned command) +{ + unsigned char byte; + command &= 0x7; + pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, &byte); + byte &= 0x1f; + byte |= (command << 5); + pcibios_write_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, byte); + printk_debug("set_ram_command 0x76.b=%02x\n", byte); +} + +#define RAM_COMMAND_NONE 0x0 +#define RAM_COMMAND_NOOP 0x1 +#define RAM_COMMAND_PRECHARGE 0x2 +#define RAM_COMMAND_MRS 0x3 +#define RAM_COMMAND_CBR 0x4 + +void sdram_set_command_none(void) +{ + set_ram_command(RAM_COMMAND_NONE); +} +void sdram_set_command_noop(void) +{ + set_ram_command(RAM_COMMAND_NOOP); +} +void sdram_set_command_precharge(void) +{ + set_ram_command(RAM_COMMAND_PRECHARGE); +} + +static unsigned long dimm_base(int n) +{ + unsigned char byte; + unsigned long result; + if (n == 0) { + return 0; + } + + pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x60 + (n - 1), &byte); + result = byte; + result <<= 23; + return result; +} + +static void dimms_read(unsigned long offset) +{ + int i; + for(i = 0; i < 8; i++) { + unsigned long dummy; + unsigned long addr; + unsigned long next_base; + + next_base = dimm_base(i +1); + addr = dimm_base(i); + if (addr == next_base) { + continue; + } + addr += offset; + printk_debug("Reading 0x%08x\n", addr); + dummy = RAM(unsigned long, addr); + printk_debug("Reading 0x%08x\n", addr ^ 0xddf8); + dummy = RAM(unsigned long, addr ^ 0xdff8); + printk_debug("Read 0x%08x 0x%08x\n", addr , addr ^ 0xddf8); + } +} + +void sdram_set_command_cbr(void) +{ + set_ram_command(RAM_COMMAND_CBR); +} + +void sdram_assert_command(void) +{ + dimms_read(0x400); +} + +void sdram_set_mode_register(void) +{ + unsigned char byte; + unsigned cas_mode; + set_ram_command(RAM_COMMAND_MRS); + pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x76, &byte); + cas_mode = byte & 0x4; + cas_mode ^= 4; + cas_mode <<= 2; + cas_mode |= 0x2a; + cas_mode <<= 3; + dimms_read(cas_mode); +} + +void sdram_enable_refresh(void) +{ + spd_enable_refresh(); +} + + +unsigned long sdram_get_ecc_size_bytes(void) +{ + unsigned char byte; + unsigned long size; + /* FIXME handle the no ram case. */ + /* Read the RAM SIZE */ + pcibios_read_config_byte(I440GX_BUS, I440GX_DEVFN, 0x67, &byte); + /* Convert it to bytes */ + size = byte; + size <<= 23; +#if !USE_ECC + size = 0; +#endif + return size; +} diff --git a/src/northbridge/intel/440gx/raminit.inc b/src/northbridge/intel/440gx/raminit.inc index 063c46b513..c1e359647e 100644 --- a/src/northbridge/intel/440gx/raminit.inc +++ b/src/northbridge/intel/440gx/raminit.inc @@ -783,7 +783,7 @@ refresh_rates: #if USE_SPD spd_enable_refresh: /* Find the first dimm and assume the rest are the same */ - /* Load the smbus device and port int %ebx */ + /* Load the smbus device and port into %ebx */ movl $((12 << 8) | SMBUS_MEM_DEVICE_0), %ebx 1: CALLSP(smbus_read_byte) jz 2f @@ -798,7 +798,7 @@ spd_enable_refresh: spd_enable_refresh_out: cmpb $0x06, %al /* see if the ram refresh is a supported one */ - ja 1f + jae 1f addl $refresh_rates, %eax /* convert SPD refresh rates to 440GX refresh rates */ movb (%eax), %cl jmp 2f diff --git a/src/northbridge/intel/82860/reset_test.inc b/src/northbridge/intel/82860/reset_test.inc index e0ab946780..957d7d4619 100644 --- a/src/northbridge/intel/82860/reset_test.inc +++ b/src/northbridge/intel/82860/reset_test.inc @@ -6,5 +6,5 @@ */ movl $MCH_RICM, %eax PCI_READ_CONFIG_DWORD - testl $RICM_DONE, %eax - jnz __cpu_reset + testl $RICM_DONE, %eax + setnz %al diff --git a/src/pc80/mc146818rtc.c b/src/pc80/mc146818rtc.c index 8f18e461fb..498901945c 100644 --- a/src/pc80/mc146818rtc.c +++ b/src/pc80/mc146818rtc.c @@ -1,7 +1,6 @@ #include #include - -#define RTC_PORT(x) (0x70 + (x)) +#include #define CMOS_READ(addr) ({ \ outb_p((addr),RTC_PORT(0)); \ @@ -83,10 +82,6 @@ outb_p((val),RTC_PORT(1)); \ /**********************************************************************/ -/* On PCs, the checksum is built only over bytes 16..45 */ -#define PC_CKS_RANGE_START 16 -#define PC_CKS_RANGE_END 45 -#define PC_CKS_LOC 46 static int rtc_checksum_valid(void) { @@ -123,32 +118,40 @@ static void rtc_set_checksum(void) #define RTC_CONTROL_DEFAULT (RTC_SQWE | RTC_24H) #define RTC_FREQ_SELECT_DEFAULT (RTC_REF_CLCK_32KHZ | RTC_RATE_1024HZ) #endif -void rtc_init(void) +void rtc_init(int invalid) { unsigned char x; - int cmos_valid; + int cmos_invalid, checksum_invalid; /* See if there has been a CMOS power problem. */ x = CMOS_READ(RTC_VALID); - cmos_valid = !(x & RTC_VRT); + cmos_invalid = !(x & RTC_VRT); /* See if there is a CMOS checksum error */ - cmos_valid = rtc_checksum_valid(); + checksum_invalid = !rtc_checksum_valid(); - if (!cmos_valid) { + if (invalid || cmos_invalid || checksum_invalid) { int i; - printk_warning("RTC power problem, zeroing cmos\n"); - for(i = 0x0; i < 128; i++) { + printk_warning("RTC:%s%s%s zeroing cmos\n", + invalid?" Clear requested":"", + cmos_invalid?" Power Problem":"", + checksum_invalid?" Checksum invalid":""); + CMOS_WRITE(0, 0x01); + CMOS_WRITE(0, 0x03); + CMOS_WRITE(0, 0x05); + for(i = 10; i < 128; i++) { CMOS_WRITE(0, i); } - /* Now setup a default date of Sat 1 January 2000 */ - CMOS_WRITE(0, 0x00); /* seconds */ - CMOS_WRITE(0, 0x02); /* minutes */ - CMOS_WRITE(1, 0x04); /* hours */ - CMOS_WRITE(7, 0x06); /* day of week */ - CMOS_WRITE(1, 0x07); /* day of month */ - CMOS_WRITE(1, 0x08); /* month */ - CMOS_WRITE(0, 0x09); /* year */ + if (cmos_invalid) { + /* Now setup a default date of Sat 1 January 2000 */ + CMOS_WRITE(0, 0x00); /* seconds */ + CMOS_WRITE(0, 0x02); /* minutes */ + CMOS_WRITE(1, 0x04); /* hours */ + CMOS_WRITE(7, 0x06); /* day of week */ + CMOS_WRITE(1, 0x07); /* day of month */ + CMOS_WRITE(1, 0x08); /* month */ + CMOS_WRITE(0, 0x09); /* year */ + } } /* Setup the real time clock */ CMOS_WRITE(RTC_CONTROL_DEFAULT, RTC_CONTROL); diff --git a/src/ram/Config b/src/ram/Config new file mode 100644 index 0000000000..0942a6e1bc --- /dev/null +++ b/src/ram/Config @@ -0,0 +1 @@ +object ramtest.o USE_RAMTEST diff --git a/src/ram/ramtest.c b/src/ram/ramtest.c new file mode 100644 index 0000000000..6374a7f2c6 --- /dev/null +++ b/src/ram/ramtest.c @@ -0,0 +1,68 @@ +#include +#include +#include + +void ram_fill(unsigned long start, unsigned long stop) +{ + unsigned long addr; + /* + * Fill. + */ + printk_debug("DRAM fill: %08lx-%08lx\n", start, stop); + for(addr = start; addr < stop ; addr += 4) { + /* Display address being filled */ + if ((addr & 0xffff) == 0) + printk_debug("%08lx\r", addr); + RAM(unsigned long, addr) = addr; + }; + /* Display final address */ + printk_debug("%08lx\nDRAM filled\n", addr); + + +} + +int ram_verify(unsigned long start, unsigned long stop, int max_errors) +{ + unsigned long addr; + int errors = 0; + /* + * Verify. + */ + printk_debug("DRAM verify: %08lx-%08lx\n", start, stop); + for(addr = start; addr < stop ; addr += 4) { + unsigned long value; + /* Display address being tested */ + if ((addr & 0xffff) == 0) + printk_debug("%08lx\r", addr); + value = RAM(unsigned long, addr); + if (value != addr) { + if (++errors <= max_errors) { + /* Display address with 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); + return errors; +} + + +int ramcheck(unsigned long start, unsigned long stop, int max_errors) +{ + int result; + /* + * This is much more of a "Is my DRAM properly configured?" + * test than a "Is my DRAM faulty?" test. Not all bits + * are tested. -Tyson + */ + printk_debug("Testing DRAM : %08lx-%08lx\n", + start, stop); + + ram_fill(start, stop); + result = ram_verify(start, stop, max_errors); + printk_debug("Done.\n"); + return result; +} + diff --git a/src/sdram/Config b/src/sdram/Config new file mode 100644 index 0000000000..e78b16df2d --- /dev/null +++ b/src/sdram/Config @@ -0,0 +1,4 @@ +object generic_sdram.o USE_GENERIC_SDRAM +object generic_sdram_enable.o USE_GENERIC_SDRAM_ENABLE +object generic_dump_spd.o USE_GENERIC_DUMP_SPD +object generic_zero_ecc_sdram.o USE_GENERIC_ZERO_ECC_SDRAM diff --git a/src/sdram/generic_dump_spd.c b/src/sdram/generic_dump_spd.c new file mode 100644 index 0000000000..a7c9aeab06 --- /dev/null +++ b/src/sdram/generic_dump_spd.c @@ -0,0 +1,28 @@ +#include +#include + +void dump_spd_registers(void) +{ + unsigned device; + device = SMBUS_MEM_DEVICE_START; + printk_debug("\n"); + while(device <= SMBUS_MEM_DEVICE_END) { + int status = 0; + int i; + printk_debug("dimm %02x", device); + for(i = 0; (i < 256) && (status == 0); i++) { + unsigned char byte; + if ((i % 20) == 0) { + printk_debug("\n%3d: ", i); + } + status = smbus_read_byte(device, i, &byte); + if (status != 0) { + printk_debug("bad device\n"); + continue; + } + printk_debug("%02x ", byte); + } + device += SMBUS_MEM_DEVICE_INC; + printk_debug("\n"); + } +} diff --git a/src/sdram/generic_sdram.c b/src/sdram/generic_sdram.c new file mode 100644 index 0000000000..784867c16b --- /dev/null +++ b/src/sdram/generic_sdram.c @@ -0,0 +1,36 @@ +#include +#include + +void sdram_no_memory(void) +{ + printk_err("No memory!!\n"); + while(1) ; +} + +/* Setup SDRAM */ +void sdram_initialize(void) +{ + printk_debug("Ram1\n"); + /* Set the registers we can set once to reasonable values */ + sdram_set_registers(); + + printk_debug("Ram2\n"); + /* Now setup those things we can auto detect */ + sdram_set_spd_registers(); + + printk_debug("Ram3\n"); + /* Now that everything is setup enable the SDRAM. + * Some chipsets do the work for use while on others + * we need to it by hand. + */ + sdram_enable(); + + printk_debug("Ram4\n"); + sdram_first_normal_reference(); + + printk_debug("Ram5\n"); + sdram_enable_refresh(); + sdram_special_finishup(); + + printk_debug("Ram6\n"); +} diff --git a/src/sdram/generic_sdram_enable.c b/src/sdram/generic_sdram_enable.c new file mode 100644 index 0000000000..6043ddaa53 --- /dev/null +++ b/src/sdram/generic_sdram_enable.c @@ -0,0 +1,51 @@ +#include +#include +#include + +void sdram_enable(void) +{ + printk_debug("Ram Enable 1\n"); + + /* noop command */ + sdram_set_command_noop(); + udelay(200); + sdram_assert_command(); + + /* Precharge all */ + sdram_set_command_precharge(); + sdram_assert_command(); + + /* wait until the all banks idle state... */ + printk_debug("Ram Enable 2\n"); + + /* Now we need 8 AUTO REFRESH / CBR cycles to be performed */ + + sdram_set_command_cbr(); + sdram_assert_command(); + sdram_assert_command(); + sdram_assert_command(); + sdram_assert_command(); + sdram_assert_command(); + sdram_assert_command(); + sdram_assert_command(); + sdram_assert_command(); + + printk_debug("Ram Enable 3\n"); + + /* mode register set */ + sdram_set_mode_register(); + /* MAx[14:0] lines, + * MAx[2:0 ] 010 == burst mode of 4 + * MAx[3:3 ] 1 == interleave wrap type + * MAx[4:4 ] == CAS# latency bit + * MAx[6:5 ] == 01 + * MAx[12:7] == 0 + */ + + printk_debug("Ram Enable 4\n"); + + /* normal operation */ + sdram_set_command_none(); + + printk_debug("Ram Enable 5\n"); +} diff --git a/src/sdram/generic_zero_ecc_sdram.c b/src/sdram/generic_zero_ecc_sdram.c new file mode 100644 index 0000000000..76c9f09e1f --- /dev/null +++ b/src/sdram/generic_zero_ecc_sdram.c @@ -0,0 +1,101 @@ +#include +#include +#include +#include +#include +#include + +#if 0 +void sdram_initialize_ecc(void) +{ + unsigned long size; + void *start_addr; + printk_debug("ecc_ram_1\n"); + size = sdram_get_ecc_size_bytes(); + + /* If we don't have an ECC SDRAM size skip the zeroing */ + if (size > 0) { + /* Compute the next greater power of two memory size, + * to use in the mtrrs */ + unsigned long bits; + unsigned long mtrr_size; + bits = log2(size); + /* See if I need to round up */ + if (size & ((1 << bits) -1)) { + bits++; + } + mtrr_size = (1 << bits); + + /* Set caching on all of memory into write-combining mode. + * So we can zero it quickly. + */ + set_var_mtrr(0, 0, mtrr_size, MTRR_TYPE_WRCOMB); + + /* Now zero the memory */ + printk_debug("ecc_ram_2\n"); +#if defined(HAVE_PC80_MEMORY_HOLE) || 1 + printk_debug("zeroing 0 - 640K\n"); + start_addr = RAM_ADDR(0); + memset(start_addr, 0, 640*1024); + printk_debug("zeroing 1M - %dM\n", size/(1024*1024)); + start_addr = RAM_ADDR(1024*1024); + memset(start_addr, 0, size - (1024*1024)); +#else + printk_debug("zeroing 0 - 0x%08x\n", size); + start_addr = RAM_ADDR(0); + memset(start_addr, 0, size); +#endif + printk_debug("ecc_ram_3\n"); + /* Fully disable caching on ram again. */ + set_var_mtrr(0, 0, 0, MTRR_TYPE_UNCACHABLE); + } + printk_debug("ecc_ram_4\n"); + +} +#else +static void ram_clear(unsigned long start, unsigned long stop) +{ +#if 0 + unsigned long addr; + /* + * Fill. + */ + printk_debug("DRAM clear: %08lx-%08lx\n", start, stop); + for(addr = start; addr < stop ; addr += 4) { + /* Display address being filled */ + if ((addr & 0xffff) == 0) + printk_debug("%08lx\r", addr); + RAM(unsigned long, addr) = 0; + }; + /* Display final address */ + printk_debug("%08lx\nDRAM cleared\n", addr); +#else + printk_debug("DRAM clear: %08lx-%08lx\n", start, stop); + __asm__ volatile( + "cld\n\t" + "rep stosl\n\t" + : + : "a" (0), "D" (RAM_ADDR(start)), "c" ((stop - start)/4) + ); +#endif +} + +void sdram_initialize_ecc(void) +{ + unsigned long size; + printk_debug("stupid_ecc_ram_1\n"); + size = sdram_get_ecc_size_bytes(); + + /* If we don't have an ECC SDRAM size skip the zeroing */ + if (size > 0) { + printk_debug("stupid_ecc_ram_2\n"); + set_var_mtrr(0, 0, size, MTRR_TYPE_WRCOMB); + printk_debug("stupid_ecc_ram_3\n"); + ram_clear(0, 640*1024); + ram_clear(1024*1024, size); + }; + printk_debug("stupid_ecc_ram_4\n"); + +} + +#endif diff --git a/src/sdram/generic_zero_ecc_sdram.inc b/src/sdram/generic_zero_ecc_sdram.inc index ad2c968859..f0bec86351 100644 --- a/src/sdram/generic_zero_ecc_sdram.inc +++ b/src/sdram/generic_zero_ecc_sdram.inc @@ -57,7 +57,7 @@ ecc_ram_initialize: cld #if !defined(HAVE_PC80_MEMORY_HOLE) - /* The 640KB - 1MB memory should not be enabled at this point. */ + /* The 640KB - 1MB memory hole should not be enabled at this point. */ xorl %eax, %eax xorl %edi, %edi movl %ebp, %ecx diff --git a/src/southbridge/intel/82801/82801.h b/src/southbridge/intel/82801/82801.h index 7a18bcd4a5..53f4adae8b 100644 --- a/src/southbridge/intel/82801/82801.h +++ b/src/southbridge/intel/82801/82801.h @@ -1,3 +1,14 @@ #define PCI_DMA_CFG 0x90 #define SERIRQ_CNTL 0x64 #define GEN_CNTL 0xd0 +#define GEN_STS 0xd4 +#define GEN_PMCON_3 0xa4 + + +#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/82801/Config b/src/southbridge/intel/82801/Config index 871ad87571..8ed11849f8 100644 --- a/src/southbridge/intel/82801/Config +++ b/src/southbridge/intel/82801/Config @@ -2,3 +2,8 @@ object nvram.o object ich2_ioapic.o object ich2_lpc.o object ich2_ide.o +object ich2_reset.o +object ich2_smbus.o +object ich2_cpu.o +object ich2_rtc.o +object ich2_power.o diff --git a/src/southbridge/intel/82801/cmos_failover.inc b/src/southbridge/intel/82801/cmos_failover.inc new file mode 100644 index 0000000000..453dd880f2 --- /dev/null +++ b/src/southbridge/intel/82801/cmos_failover.inc @@ -0,0 +1,90 @@ +/* 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 __rtc_ok + + /* 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 + xorb %al, %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 + jnz __normal_image + diff --git a/src/southbridge/intel/82801/ich2_cpu.c b/src/southbridge/intel/82801/ich2_cpu.c new file mode 100644 index 0000000000..6477815d89 --- /dev/null +++ b/src/southbridge/intel/82801/ich2_cpu.c @@ -0,0 +1,21 @@ +#include +#include +#include +#include +#include "82801.h" + +void ich2_set_cpu_multiplier(unsigned multiplier) +{ + u32 dword; + struct pci_dev *dev; + dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_1F0, 0); + if (!dev) { + printk_err("Cannot find device %08x:%08x\n", + PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_1F0); + return; + } + pci_read_config_dword(dev, GEN_STS, &dword); + dword &= ~((1 << 12) - (1 << 8)); + dword |= (multiplier & 0xf) << 8; + pci_write_config_dword(dev, GEN_STS, dword); +} diff --git a/src/southbridge/intel/82801/ich2_power.c b/src/southbridge/intel/82801/ich2_power.c new file mode 100644 index 0000000000..60925842f5 --- /dev/null +++ b/src/southbridge/intel/82801/ich2_power.c @@ -0,0 +1,22 @@ +#include +#include +#include +#include +#include "82801.h" + +void ich2_power_after_power_fail(int on) +{ + struct pci_dev *dev; + unsigned char byte; + dev = pci_find_device(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82801BA_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/82801/ich2_reset.c b/src/southbridge/intel/82801/ich2_reset.c new file mode 100644 index 0000000000..a20e1bfb34 --- /dev/null +++ b/src/southbridge/intel/82801/ich2_reset.c @@ -0,0 +1,9 @@ +#include +#include + +void ich2_hard_reset(void) +{ + /* Try rebooting through port 0xcf9 */ + outb((0 <<3)|(1<<2)|(1<<1), 0xcf9); +} + diff --git a/src/southbridge/intel/82801/ich2_rtc.c b/src/southbridge/intel/82801/ich2_rtc.c new file mode 100644 index 0000000000..d567fb2876 --- /dev/null +++ b/src/southbridge/intel/82801/ich2_rtc.c @@ -0,0 +1,23 @@ +#include +#include +#include +#include +#include +#include "82801.h" + + +void ich2_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/82801/ich2_smbus.c b/src/southbridge/intel/82801/ich2_smbus.c new file mode 100644 index 0000000000..ab890b668f --- /dev/null +++ b/src/southbridge/intel/82801/ich2_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/piix4e/Config b/src/southbridge/intel/piix4e/Config index 094297c0ab..6cb635f481 100644 --- a/src/southbridge/intel/piix4e/Config +++ b/src/southbridge/intel/piix4e/Config @@ -1 +1,2 @@ object southbridge.o +object smbus.o USE_PIIX4E_SMBUS diff --git a/src/southbridge/intel/piix4e/smbus.c b/src/southbridge/intel/piix4e/smbus.c new file mode 100644 index 0000000000..7cf929df86 --- /dev/null +++ b/src/southbridge/intel/piix4e/smbus.c @@ -0,0 +1,87 @@ +#include +#include +#include + +#define PM_BUS 0 +#define PM_DEVFN (PIIX4_DEVFN+3) + +#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 + +void smbus_enable(void) +{ + /* iobase addr */ + pcibios_write_config_dword(PM_BUS, PM_DEVFN, 0x90, SMBUS_IO_BASE | 1); + /* smbus enable */ + pcibios_write_config_byte(PM_BUS, PM_DEVFN, 0xd2, (0x4 << 1) | 1); + /* iospace enable */ + pcibios_write_config_word(PM_BUS, PM_DEVFN, 0x4, 1); +} + +void smbus_setup(void) +{ + outb(0, SMBUS_IO_BASE + SMBHSTSTAT); +} + +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) == 0) { + byte = inb(SMBUS_IO_BASE + SMBHSTSTAT); + } +} + +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 + SMBHSTADD); + /* 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); + + /* read results of transaction */ + byte = inb(SMBUS_IO_BASE + SMBHSTDAT0); + + *result = byte; + return host_status_register != 0x02; +} diff --git a/src/superio/generic/Config b/src/superio/generic/Config new file mode 100644 index 0000000000..6834c5e8f5 --- /dev/null +++ b/src/superio/generic/Config @@ -0,0 +1,2 @@ +object generic_superio.o + diff --git a/src/superio/generic/generic_superio.c b/src/superio/generic/generic_superio.c new file mode 100644 index 0000000000..ad5f7ee27e --- /dev/null +++ b/src/superio/generic/generic_superio.c @@ -0,0 +1,57 @@ +#include +#include + +void pnp_write_config(unsigned char port, + unsigned char value, unsigned char reg) +{ + outb(reg, port); + outb(value, port + 1); +} + +unsigned char pnp_read_config(unsigned char port, unsigned char reg) +{ + outb(reg, port); + return inb(port +1); +} + +void pnp_set_logical_device(unsigned char port, int device) +{ + pnp_write_config(port, device, 0x07); +} + +void pnp_set_enable(unsigned char port, int enable) +{ + pnp_write_config(port, enable?0x1:0x0, 0x30); +} + +int pnp_read_enable(unsigned char port) +{ + return !!pnp_read_config(port, 0x30); +} + +void pnp_set_iobase0(unsigned char port, unsigned iobase) +{ + pnp_write_config(port, (iobase >> 8) & 0xff, 0x60); + pnp_write_config(port, iobase & 0xff, 0x61); +} + +void pnp_set_iobase1(unsigned char port, unsigned iobase) +{ + pnp_write_config(port, (iobase >> 8) & 0xff, 0x62); + pnp_write_config(port, iobase & 0xff, 0x63); +} + +void pnp_set_irq0(unsigned char port, unsigned irq) +{ + pnp_write_config(port, irq, 0x70); +} + +void pnp_set_irq1(unsigned char port, unsigned irq) +{ + pnp_write_config(port, irq, 0x72); +} + +void pnp_set_drq(unsigned char port, unsigned drq) +{ + pnp_write_config(port, drq & 0xff, 0x74); +} diff --git a/src/superio/generic/generic_superio.h b/src/superio/generic/generic_superio.h new file mode 100644 index 0000000000..e7b0f17d74 --- /dev/null +++ b/src/superio/generic/generic_superio.h @@ -0,0 +1,56 @@ +#include + +void pnp_write_config(unsigned char port, + unsigned char value, unsigned char reg) +{ + outb(reg, port); + outb(value, port + 1); +} + +unsigned char pnp_read_config(unsigned char port, unsigned char reg) +{ + outb(reg, port); + return inb(port +1); +} + +void pnp_set_logical_device(unsigned char port, int device) +{ + pnp_write_config(port, device, 0x07); +} + +void pnp_set_enable(unsigned char port, int enable) +{ + pnp_write_config(port, enable?0x1:0x0, 0x30); +} + +int pnp_read_enable(unsigned char port) +{ + return !!pnp_read_config(port, 0x30); +} + +void pnp_set_iobase0(unsigned char port, unsigned iobase) +{ + pnp_write_config(port, (iobase >> 8) & 0xff, 0x60); + pnp_write_config(port, iobase & 0xff, 0x61); +} + +void set_iobase1(unsigned char port, unsigned iobase) +{ + pnp_write_config(port, (iobase >> 8) & 0xff, 0x62); + pnp_write_config(port, iobase & 0xff, 0x63); +} + +void set_irq0(unsigned char port, unsigned irq) +{ + pnp_write_config(port, irq, 0x70); +} + +void set_irq1(unsigned char port, unsigned irq) +{ + pnp_write_config(port, irq, 0x72); +} + +void set_drq(unsigned char port, unsigned drq) +{ + pnp_write_config(port, drq & 0xff, 0x74); +} diff --git a/src/superio/winbond/w83627hf/Config b/src/superio/winbond/w83627hf/Config new file mode 100644 index 0000000000..4e520054ab --- /dev/null +++ b/src/superio/winbond/w83627hf/Config @@ -0,0 +1,2 @@ +dir /src/superio/generic +object w83627hf_power.o diff --git a/src/superio/winbond/w83627hf/setup_serial.inc b/src/superio/winbond/w83627hf/setup_serial.inc index 804bf5dc12..a2c0251e8d 100644 --- a/src/superio/winbond/w83627hf/setup_serial.inc +++ b/src/superio/winbond/w83627hf/setup_serial.inc @@ -4,28 +4,16 @@ /* The base address is 0x2e,0x4e depending on config bytes */ +#include #define SIO_INDEX SIO_BASE #define SIO_DATA SIO_BASE+1 -#define SIO_SYSTEM_CLK_INPUT_48MHZ (1<<6) -#define SIO_SYSTEM_CLK_INPUT_24MHZ (0<<6) - -#if defined(SIO_SYSTEM_CLK_INPUT) -#if (SIO_SYSTEM_CLK_INPUT != SIO_SYSTEM_CLK_INPUT_48MHZ) && (SIO_SYSTEM_CLK_INPUT != SIO_SYSTEM_CLK_INPUT_24MHZ) -#error BAD SIO_SYSTEM_CLK_INPUT_PARAMETER -#endif -#endif - - -#define SIO_COM1_DEVICE 2 - #define SIO_ENTER_PNP_MODE() \ movb $0x87, %al ; \ outb %al, $(SIO_BASE) ; \ outb %al, $(SIO_BASE) - #define SIO_EXIT_PNP_MODE() \ movb $0xaa, %al ; \ outb %al, $(SIO_BASE) @@ -52,7 +40,7 @@ SIO_WRITE_CONFIG((0x84 | SIO_SYSTEM_CLK_INPUT), 0x24) #endif /* enable serial 1 */ - SIO_SET_LOGICAL_DEVICE(SIO_COM1_DEVICE) + SIO_SET_LOGICAL_DEVICE(COM1_DEVICE) SIO_WRITE_CONFIG(1, 0x30) SIO_WRITE_CONFIG(0x3, 0x60) SIO_WRITE_CONFIG(0xf8, 0x61) diff --git a/src/superio/winbond/w83627hf/superio.c b/src/superio/winbond/w83627hf/superio.c index 9aff5d1363..e6c60a298d 100644 --- a/src/superio/winbond/w83627hf/superio.c +++ b/src/superio/winbond/w83627hf/superio.c @@ -2,119 +2,51 @@ #include #include #include +#include +#include +#include -#define FLOPPY_DEVICE 0 -#define PARALLEL_DEVICE 1 -#define COM1_DEVICE 2 -#define COM2_DEVICE 3 -#define KBC_DEVICE 5 -#define CIR_DEVICE 6 -#define GAME_PORT_DEVICE 7 -#define GPIO_PORT2_DEVICE 8 -#define GPIO_PORT3_DEVICE 9 -#define ACPI_DEVICE 0xa -#define HW_MONITOR_DEVICE 0xb - - -#define FLOPPY_DEFAULT_IOBASE 0x3f0 -#define FLOPPY_DEFAULT_IRQ 6 -#define FLOPPY_DEFAULT_DRQ 2 -#define PARALLEL_DEFAULT_IOBASE 0x378 -#define PARALLEL_DEFAULT_IRQ 7 -#define PARALLEL_DEFAULT_DRQ 4 /* No dma */ -#define COM1_DEFAULT_IOBASE 0x3f8 -#define COM1_DEFAULT_IRQ 4 -#define COM1_DEFAULT_BAUD 115200 -#define COM2_DEFAULT_IOBASE 0x2f8 -#define COM2_DEFAULT_IRQ 3 -#define COM2_DEFAULT_BAUD 115200 -#define KBC_DEFAULT_IOBASE0 0x60 -#define KBC_DEFAULT_IOBASE1 0x64 -#define KBC_DEFAULT_IRQ0 0x1 -#define KBC_DEFAULT_IRQ1 0xc - - -static void enter_pnp(struct superio *sio) -{ - outb(0x87, sio->port); - outb(0x87, sio->port); -} - -static void exit_pnp(struct superio *sio) -{ - outb(0xaa, sio->port); -} - -static void write_config(struct superio *sio, - unsigned char value, unsigned char reg) -{ - outb(reg, sio->port); - outb(value, sio->port +1); -} - -static unsigned char read_config(struct superio *sio, unsigned char reg) -{ - outb(reg, sio->port); - return inb(sio->port +1); -} -static void set_logical_device(struct superio *sio, int device) -{ - write_config(sio, device, 0x07); -} - -static void set_enable(struct superio *sio, int enable) -{ - write_config(sio, enable?0x1:0x0, 0x30); -#if 0 - if (enable) { - printk_debug("enabled superio device: %d\n", - read_config(sio, 0x07)); - } +#if defined(SERIAL_CONSOLE) +# if !defined(TTYS0_BASE) +# define TTYS0_BASE 0x3f8 +# endif +#else +#undef TTYS0_BASE #endif + +void w83627hf_enter_pnp(unsigned char port) +{ + outb(0x87, port); + outb(0x87, port); } -static void set_iobase0(struct superio *sio, unsigned iobase) +void w83627hf_exit_pnp(unsigned char port) { - write_config(sio, (iobase >> 8) & 0xff, 0x60); - write_config(sio, iobase & 0xff, 0x61); -} + outb(0xaa, port); -static void set_iobase1(struct superio *sio, unsigned iobase) -{ - write_config(sio, (iobase >> 8) & 0xff, 0x62); - write_config(sio, iobase & 0xff, 0x63); -} - -static void set_irq0(struct superio *sio, unsigned irq) -{ - write_config(sio, irq, 0x70); -} - -static void set_irq1(struct superio *sio, unsigned irq) -{ - write_config(sio, irq, 0x72); -} - -static void set_drq(struct superio *sio, unsigned drq) -{ - write_config(sio, drq & 0xff, 0x74); } static void setup_com(struct superio *sio, struct com_ports *com, int device) { int divisor = 115200/com->baud; + if ((com->base == TTYS0_BASE) && (!!pnp_read_enable(sio->port) == !!com->enable)) { + /* Don't reinitialize the console serial port, + * This is especially nasty in SMP. + */ + return; + } printk_debug("Enabling com device: %02x\n", device); printk_debug(" iobase = 0x%04x irq=%d\n", com->base, com->irq); /* Select the device */ - set_logical_device(sio, device); + pnp_set_logical_device(sio->port, device); /* Disable it while it is initialized */ - set_enable(sio, 0); + pnp_set_enable(sio->port, 0); if (com->enable) { - set_iobase0(sio, com->base); - set_irq0(sio, com->irq); + pnp_set_iobase0(sio->port, com->base); + pnp_set_irq0(sio->port, com->irq); /* We are initialized so enable the device */ - set_enable(sio, 1); + pnp_set_enable(sio->port, 1); /* Now initialize the com port */ uart_init(com->base, divisor); } @@ -127,14 +59,14 @@ static void setup_floppy(struct superio *sio) unsigned irq = FLOPPY_DEFAULT_IRQ; unsigned drq = FLOPPY_DEFAULT_DRQ; /* Select the device */ - set_logical_device(sio, FLOPPY_DEVICE); + pnp_set_logical_device(sio->port, FLOPPY_DEVICE); /* Disable it while initializing */ - set_enable(sio, 0); + pnp_set_enable(sio->port, 0); if (sio->floppy) { - set_iobase0(sio, iobase); - set_irq0(sio, irq); - set_drq(sio, drq); - set_enable(sio, 1); + pnp_set_iobase0(sio->port, iobase); + pnp_set_irq0(sio->port, irq); + pnp_set_drq(sio->port, drq); + pnp_set_enable(sio->port, 1); } } @@ -145,14 +77,14 @@ static void setup_parallel(struct superio *sio) unsigned irq = PARALLEL_DEFAULT_IRQ; unsigned drq = PARALLEL_DEFAULT_DRQ; /* Select the device */ - set_logical_device(sio, PARALLEL_DEVICE); + pnp_set_logical_device(sio->port, PARALLEL_DEVICE); /* Disable it while initializing */ - set_enable(sio, 0); + pnp_set_enable(sio->port, 0); if (sio->lpt) { - set_iobase0(sio, iobase); - set_irq0(sio, irq); - set_drq(sio, drq); - set_enable(sio, 1); + pnp_set_iobase0(sio->port, iobase); + pnp_set_irq0(sio->port, irq); + pnp_set_drq(sio->port, drq); + pnp_set_enable(sio->port, 1); } } @@ -164,15 +96,15 @@ static void setup_keyboard(struct superio *sio) unsigned irq0 = KBC_DEFAULT_IRQ0; unsigned irq1 = KBC_DEFAULT_IRQ1; /* Select the device */ - set_logical_device(sio, KBC_DEVICE); + pnp_set_logical_device(sio->port, KBC_DEVICE); /* Disable it while initializing */ - set_enable(sio, 0); + pnp_set_enable(sio->port, 0); if (sio->keyboard) { - set_iobase0(sio, iobase0); - set_iobase1(sio, iobase1); - set_irq0(sio, irq0); - set_irq1(sio, irq1); - set_enable(sio, 1); + pnp_set_iobase0(sio->port, iobase0); + pnp_set_iobase1(sio->port, iobase1); + pnp_set_irq0(sio->port, irq0); + pnp_set_irq1(sio->port, irq1); + pnp_set_enable(sio->port, 1); /* Initialize the keyboard */ pc_keyboard_init(); } @@ -182,10 +114,10 @@ static void setup_keyboard(struct superio *sio) #if 0 static void setup_acpi_registers(struct superio *sio) { - set_logical_device(sio, ACPI_DEVICE); + pnp_set_logical_device(sio->port, ACPI_DEVICE); /* Enable power on after power fail */ - write_config(sio, (1 << 7)|(0 <<5), 0xe4); - set_enable(sio, 1); + pnp_write_config(sio->port, (1 << 7)|(0 <<5), 0xe4); + pnp_set_enable(sio->port, 1); } #endif @@ -201,7 +133,12 @@ static void enable_devices(struct superio *sio) if (sio->com2.irq == 0) sio->com2.irq = COM2_DEFAULT_IRQ; if (sio->com2.baud == 0) sio->com2.baud = COM2_DEFAULT_BAUD; - enter_pnp(sio); + w83627hf_enter_pnp(sio->port); + +#if defined(SIO_SYSTEM_CLK_INPUT) + /* Setup the clock input */ + pnp_write_config(sio->port, (0x84 | SIO_SYSTEM_CLK_INPUT), 0x24); +#endif /* enable/disable floppy */ setup_floppy(sio); @@ -219,28 +156,28 @@ static void enable_devices(struct superio *sio) setup_keyboard(sio); /* enable/disable cir */ - set_logical_device(sio, CIR_DEVICE); - set_enable(sio, sio->cir); + pnp_set_logical_device(sio->port, CIR_DEVICE); + pnp_set_enable(sio->port, sio->cir); /* game */ - set_logical_device(sio, GAME_PORT_DEVICE); - set_enable(sio, sio->game); + pnp_set_logical_device(sio->port, GAME_PORT_DEVICE); + pnp_set_enable(sio->port, sio->game); /* gpio_port2 */ - set_logical_device(sio, GPIO_PORT2_DEVICE); - set_enable(sio, sio->gpio2); + pnp_set_logical_device(sio->port, GPIO_PORT2_DEVICE); + pnp_set_enable(sio->port, sio->gpio2); /* gpio_port3 */ - set_logical_device(sio, GPIO_PORT3_DEVICE); - set_enable(sio, sio->gpio3); + pnp_set_logical_device(sio->port, GPIO_PORT3_DEVICE); + pnp_set_enable(sio->port, sio->gpio3); /* enable/disable acpi */ - set_logical_device(sio, ACPI_DEVICE); - set_enable(sio, sio->acpi); + pnp_set_logical_device(sio->port, ACPI_DEVICE); + pnp_set_enable(sio->port, sio->acpi); /* enable/disable hw monitor */ - set_logical_device(sio, HW_MONITOR_DEVICE); - set_enable(sio, sio->hwmonitor); + pnp_set_logical_device(sio->port, HW_MONITOR_DEVICE); + pnp_set_enable(sio->port, sio->hwmonitor); #if 0 /* setup acpi registers so I am certain to get @@ -249,7 +186,7 @@ static void enable_devices(struct superio *sio) setup_acpi_registers(sio); #endif - exit_pnp(sio); + w83627hf_exit_pnp(sio->port); } /* The base address is either 0x2e or 0x4e */ diff --git a/src/superio/winbond/w83627hf/w83627hf_power.c b/src/superio/winbond/w83627hf/w83627hf_power.c new file mode 100644 index 0000000000..9e4eb8b4f7 --- /dev/null +++ b/src/superio/winbond/w83627hf/w83627hf_power.c @@ -0,0 +1,20 @@ +#include +#include + +void w832627hf_power_after_power_fail(int state) +{ + unsigned char byte; + w83627hf_enter_pnp(SIO_BASE); + pnp_set_logical_device(SIO_BASE, ACPI_DEVICE); + pnp_set_enable(SIO_BASE, 1); + + /* Enable power on after power fail */ + byte = pnp_read_config(SIO_BASE, 0xe4); + byte &= ~(3 << 5); + byte |= (state & 3) << 5; + pnp_write_config(SIO_BASE, byte, 0xe4); + + w83627hf_exit_pnp(SIO_BASE); +} + +