diff options
Diffstat (limited to 'arch/i386')
-rw-r--r-- | arch/i386/cpu/Makefile | 2 | ||||
-rw-r--r-- | arch/i386/cpu/interrupts.c | 214 | ||||
-rw-r--r-- | arch/i386/cpu/sc520/sc520.c | 33 | ||||
-rw-r--r-- | arch/i386/cpu/sc520/sc520_asm.S | 214 | ||||
-rw-r--r-- | arch/i386/cpu/sc520/sc520_pci.c | 63 | ||||
-rw-r--r-- | arch/i386/cpu/sc520/sc520_ssi.c | 27 | ||||
-rw-r--r-- | arch/i386/cpu/sc520/sc520_timer.c | 35 | ||||
-rw-r--r-- | arch/i386/cpu/serial.c | 506 | ||||
-rw-r--r-- | arch/i386/cpu/start.S | 137 | ||||
-rw-r--r-- | arch/i386/cpu/start16.S | 29 | ||||
-rw-r--r-- | arch/i386/include/asm/bootparam.h | 120 | ||||
-rw-r--r-- | arch/i386/include/asm/e820.h | 155 | ||||
-rw-r--r-- | arch/i386/include/asm/ic/pci.h | 30 | ||||
-rw-r--r-- | arch/i386/include/asm/ic/sc520.h | 30 | ||||
-rw-r--r-- | arch/i386/include/asm/ioctl.h | 1 | ||||
-rw-r--r-- | arch/i386/include/asm/ist.h | 34 | ||||
-rw-r--r-- | arch/i386/include/asm/u-boot-i386.h | 2 | ||||
-rw-r--r-- | arch/i386/include/asm/unaligned.h | 1 | ||||
-rw-r--r-- | arch/i386/include/asm/video/edid.h | 16 | ||||
-rw-r--r-- | arch/i386/lib/bios_setup.c | 2 | ||||
-rw-r--r-- | arch/i386/lib/board.c | 85 | ||||
-rw-r--r-- | arch/i386/lib/realmode.c | 2 | ||||
-rw-r--r-- | arch/i386/lib/zimage.c | 127 |
23 files changed, 1040 insertions, 825 deletions
diff --git a/arch/i386/cpu/Makefile b/arch/i386/cpu/Makefile index c658c6e..bb0a48f 100644 --- a/arch/i386/cpu/Makefile +++ b/arch/i386/cpu/Makefile @@ -29,7 +29,7 @@ include $(TOPDIR)/config.mk LIB = $(obj)lib$(CPU).a START = start.o start16.o resetvec.o -COBJS = serial.o interrupts.o cpu.o +COBJS = interrupts.o cpu.o SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c) OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS)) diff --git a/arch/i386/cpu/interrupts.c b/arch/i386/cpu/interrupts.c index 4b57437..51023f3 100644 --- a/arch/i386/cpu/interrupts.c +++ b/arch/i386/cpu/interrupts.c @@ -5,6 +5,9 @@ * (C) Copyright 2002 * Daniel Engström, Omicron Ceti AB, daniel@omicron.se. * + * Portions of this file are derived from the Linux kernel source + * Copyright (C) 1991, 1992 Linus Torvalds + * * See file CREDITS for list of people who contributed to this * project. * @@ -32,12 +35,112 @@ ".hidden irq_"#x"\n" \ ".type irq_"#x", @function\n" \ "irq_"#x":\n" \ - "pushl %ebp\n" \ - "movl %esp,%ebp\n" \ - "pusha\n" \ "pushl $"#x"\n" \ "jmp irq_common_entry\n" +/* + * Volatile isn't enough to prevent the compiler from reordering the + * read/write functions for the control registers and messing everything up. + * A memory clobber would solve the problem, but would prevent reordering of + * all loads stores around it, which can hurt performance. Solution is to + * use a variable and mimic reads and writes to it to enforce serialization + */ +static unsigned long __force_order; + +static inline unsigned long read_cr0(void) +{ + unsigned long val; + asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order)); + return val; +} + +static inline unsigned long read_cr2(void) +{ + unsigned long val; + asm volatile("mov %%cr2,%0\n\t" : "=r" (val), "=m" (__force_order)); + return val; +} + +static inline unsigned long read_cr3(void) +{ + unsigned long val; + asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order)); + return val; +} + +static inline unsigned long read_cr4(void) +{ + unsigned long val; + asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order)); + return val; +} + +static inline unsigned long get_debugreg(int regno) +{ + unsigned long val = 0; /* Damn you, gcc! */ + + switch (regno) { + case 0: + asm("mov %%db0, %0" :"=r" (val)); + break; + case 1: + asm("mov %%db1, %0" :"=r" (val)); + break; + case 2: + asm("mov %%db2, %0" :"=r" (val)); + break; + case 3: + asm("mov %%db3, %0" :"=r" (val)); + break; + case 6: + asm("mov %%db6, %0" :"=r" (val)); + break; + case 7: + asm("mov %%db7, %0" :"=r" (val)); + break; + default: + val = 0; + } + return val; +} + +void dump_regs(struct pt_regs *regs) +{ + unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; + unsigned long d0, d1, d2, d3, d6, d7; + + printf("EIP: %04x:[<%08lx>] EFLAGS: %08lx\n", + (u16)regs->xcs, regs->eip, regs->eflags); + + printf("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", + regs->eax, regs->ebx, regs->ecx, regs->edx); + printf("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n", + regs->esi, regs->edi, regs->ebp, regs->esp); + printf(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n", + (u16)regs->xds, (u16)regs->xes, (u16)regs->xfs, (u16)regs->xgs, (u16)regs->xss); + + cr0 = read_cr0(); + cr2 = read_cr2(); + cr3 = read_cr3(); + cr4 = read_cr4(); + + printf("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", + cr0, cr2, cr3, cr4); + + d0 = get_debugreg(0); + d1 = get_debugreg(1); + d2 = get_debugreg(2); + d3 = get_debugreg(3); + + printf("DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n", + d0, d1, d2, d3); + + d6 = get_debugreg(6); + d7 = get_debugreg(7); + printf("DR6: %08lx DR7: %08lx\n", + d6, d7); +} + struct idt_entry { u16 base_low; u16 selector; @@ -122,7 +225,7 @@ int disable_interrupts(void) } /* IRQ Low-Level Service Routine */ -__isr__ irq_llsr(int ip, int seg, int irq) +__isr__ irq_llsr(struct pt_regs *regs) { /* * For detailed description of each exception, refer to: @@ -131,73 +234,92 @@ __isr__ irq_llsr(int ip, int seg, int irq) * Order Number: 253665-029US, November 2008 * Table 6-1. Exceptions and Interrupts */ - switch (irq) { + switch (regs->orig_eax) { case 0x00: - printf("Divide Error (Division by zero) at %04x:%08x\n", seg, ip); + printf("Divide Error (Division by zero)\n"); + dump_regs(regs); while(1); break; case 0x01: - printf("Debug Interrupt (Single step) at %04x:%08x\n", seg, ip); + printf("Debug Interrupt (Single step)\n"); + dump_regs(regs); break; case 0x02: - printf("NMI Interrupt at %04x:%08x\n", seg, ip); + printf("NMI Interrupt\n"); + dump_regs(regs); break; case 0x03: - printf("Breakpoint at %04x:%08x\n", seg, ip); + printf("Breakpoint\n"); + dump_regs(regs); break; case 0x04: - printf("Overflow at %04x:%08x\n", seg, ip); + printf("Overflow\n"); + dump_regs(regs); while(1); break; case 0x05: - printf("BOUND Range Exceeded at %04x:%08x\n", seg, ip); + printf("BOUND Range Exceeded\n"); + dump_regs(regs); while(1); break; case 0x06: - printf("Invalid Opcode (UnDefined Opcode) at %04x:%08x\n", seg, ip); + printf("Invalid Opcode (UnDefined Opcode)\n"); + dump_regs(regs); while(1); break; case 0x07: - printf("Device Not Available (No Math Coprocessor) at %04x:%08x\n", seg, ip); + printf("Device Not Available (No Math Coprocessor)\n"); + dump_regs(regs); while(1); break; case 0x08: - printf("Double fault at %04x:%08x\n", seg, ip); + printf("Double fault\n"); + dump_regs(regs); while(1); break; case 0x09: - printf("Co-processor segment overrun at %04x:%08x\n", seg, ip); + printf("Co-processor segment overrun\n"); + dump_regs(regs); while(1); break; case 0x0a: - printf("Invalid TSS at %04x:%08x\n", seg, ip); + printf("Invalid TSS\n"); + dump_regs(regs); break; case 0x0b: - printf("Segment Not Present at %04x:%08x\n", seg, ip); + printf("Segment Not Present\n"); + dump_regs(regs); while(1); break; case 0x0c: - printf("Stack Segment Fault at %04x:%08x\n", seg, ip); + printf("Stack Segment Fault\n"); + dump_regs(regs); while(1); break; case 0x0d: - printf("General Protection at %04x:%08x\n", seg, ip); + printf("General Protection\n"); + dump_regs(regs); break; case 0x0e: - printf("Page fault at %04x:%08x\n", seg, ip); + printf("Page fault\n"); + dump_regs(regs); while(1); break; case 0x0f: - printf("Floating-Point Error (Math Fault) at %04x:%08x\n", seg, ip); + printf("Floating-Point Error (Math Fault)\n"); + dump_regs(regs); break; case 0x10: - printf("Alignment check at %04x:%08x\n", seg, ip); + printf("Alignment check\n"); + dump_regs(regs); break; case 0x11: - printf("Machine Check at %04x:%08x\n", seg, ip); + printf("Machine Check\n"); + dump_regs(regs); break; case 0x12: - printf("SIMD Floating-Point Exception at %04x:%08x\n", seg, ip); + printf("SIMD Floating-Point Exception\n"); + dump_regs(regs); break; case 0x13: case 0x14: @@ -212,12 +334,13 @@ __isr__ irq_llsr(int ip, int seg, int irq) case 0x1d: case 0x1e: case 0x1f: - printf("Reserved Exception %d at %04x:%08x\n", irq, seg, ip); + printf("Reserved Exception\n"); + dump_regs(regs); break; default: /* Hardware or User IRQ */ - do_irq(irq); + do_irq(regs->orig_eax); } } @@ -226,22 +349,45 @@ __isr__ irq_llsr(int ip, int seg, int irq) * fully relocatable code. * - The call to irq_llsr will be a relative jump * - The IRQ entries will be guaranteed to be in order - * It's a bit annoying that we need to waste 3 bytes per interrupt entry - * (total of 768 code bytes), but we MUST create a Stack Frame and this is - * the easiest way I could do it. Maybe it can be made better later. + * Interrupt entries are now very small (a push and a jump) but they are + * now slower (all registers pushed on stack which provides complete + * crash dumps in the low level handlers */ asm(".globl irq_common_entry\n" \ ".hidden irq_common_entry\n" \ ".type irq_common_entry, @function\n" \ "irq_common_entry:\n" \ - "pushl $0\n" \ - "pushl $0\n" \ + "cld\n" \ + "pushl %gs\n" \ + "pushl %fs\n" \ + "pushl %es\n" \ + "pushl %ds\n" \ + "pushl %eax\n" \ + "pushl %ebp\n" \ + "pushl %edi\n" \ + "pushl %esi\n" \ + "pushl %edx\n" \ + "pushl %ecx\n" \ + "pushl %ebx\n" \ + "mov %esp, %eax\n" \ + "pushl %ebp\n" \ + "movl %esp,%ebp\n" \ + "pushl %eax\n" \ "call irq_llsr\n" \ "popl %eax\n" \ - "popl %eax\n" \ - "popl %eax\n" \ - "popa\n" \ "leave\n"\ + "popl %ebx\n" \ + "popl %ecx\n" \ + "popl %edx\n" \ + "popl %esi\n" \ + "popl %edi\n" \ + "popl %ebp\n" \ + "popl %eax\n" \ + "popl %ds\n" \ + "popl %es\n" \ + "popl %fs\n" \ + "popl %gs\n" \ + "add $4, %esp\n" \ "iret\n" \ DECLARE_INTERRUPT(0) \ DECLARE_INTERRUPT(1) \ diff --git a/arch/i386/cpu/sc520/sc520.c b/arch/i386/cpu/sc520/sc520.c index 4b566a7..519bfd8 100644 --- a/arch/i386/cpu/sc520/sc520.c +++ b/arch/i386/cpu/sc520/sc520.c @@ -44,24 +44,24 @@ void init_sc520(void) /* Set the UARTxCTL register at it's slower, * baud clock giving us a 1.8432 MHz reference */ - sc520_mmcr->uart1ctl = 0x07; - sc520_mmcr->uart2ctl = 0x07; + writeb(0x07, &sc520_mmcr->uart1ctl); + writeb(0x07, &sc520_mmcr->uart2ctl); /* first set the timer pin mapping */ - sc520_mmcr->clksel = 0x72; /* no clock frequency selected, use 1.1892MHz */ + writeb(0x72, &sc520_mmcr->clksel); /* no clock frequency selected, use 1.1892MHz */ /* enable PCI bus arbitrer */ - sc520_mmcr->sysarbctl = 0x02; /* enable concurrent mode */ + writeb(0x02, &sc520_mmcr->sysarbctl); /* enable concurrent mode */ - sc520_mmcr->sysarbmenb = 0x1f; /* enable external grants */ - sc520_mmcr->hbctl = 0x04; /* enable posted-writes */ + writeb(0x1f, &sc520_mmcr->sysarbmenb); /* enable external grants */ + writeb(0x04, &sc520_mmcr->hbctl); /* enable posted-writes */ if (CONFIG_SYS_SC520_HIGH_SPEED) { - sc520_mmcr->cpuctl = 0x02; /* set it to 133 MHz and write back */ + writeb(0x02, &sc520_mmcr->cpuctl); /* set it to 133 MHz and write back */ gd->cpu_clk = 133000000; printf("## CPU Speed set to 133MHz\n"); } else { - sc520_mmcr->cpuctl = 0x01; /* set it to 100 MHz and write back */ + writeb(0x01, &sc520_mmcr->cpuctl); /* set it to 100 MHz and write back */ printf("## CPU Speed set to 100MHz\n"); gd->cpu_clk = 100000000; } @@ -74,7 +74,7 @@ void init_sc520(void) "loop 0b\n": : : "ecx"); /* turn on the SDRAM write buffer */ - sc520_mmcr->dbctl = 0x11; + writeb(0x11, &sc520_mmcr->dbctl); /* turn on the cache and disable write through */ asm("movl %%cr0, %%eax\n" @@ -88,6 +88,7 @@ unsigned long init_sc520_dram(void) u32 dram_present=0; u32 dram_ctrl; + #ifdef CONFIG_SYS_SDRAM_DRCTMCTL /* these memory control registers are set up in the assember part, * in sc520_asm.S, during 'mem_init'. If we muck with them here, @@ -97,7 +98,8 @@ unsigned long init_sc520_dram(void) * simply dictates it. */ #else - int val; + u8 tmp; + u8 val; int cas_precharge_delay = CONFIG_SYS_SDRAM_PRECHARGE_DELAY; int refresh_rate = CONFIG_SYS_SDRAM_REFRESH_RATE; @@ -116,9 +118,10 @@ unsigned long init_sc520_dram(void) val = 3; /* 62.4us */ } - sc520_mmcr->drcctl = (sc520_mmcr->drcctl & 0xcf) | (val<<4); + tmp = (readb(&sc520_mmcr->drcctl) & 0xcf) | (val<<4); + writeb(tmp, &sc520_mmcr->drcctl); - val = sc520_mmcr->drctmctl & 0xf0; + val = readb(&sc520_mmcr->drctmctl) & 0xf0; if (cas_precharge_delay==3) { val |= 0x04; /* 3T */ @@ -133,12 +136,12 @@ unsigned long init_sc520_dram(void) } else { val |= 1; } - sc520_mmcr->drctmctl = val; + writeb(val, &c520_mmcr->drctmctl); #endif /* We read-back the configuration of the dram * controller that the assembly code wrote */ - dram_ctrl = sc520_mmcr->drcbendadr; + dram_ctrl = readl(&sc520_mmcr->drcbendadr); bd->bi_dram[0].start = 0; if (dram_ctrl & 0x80) { @@ -191,7 +194,7 @@ void reset_cpu(ulong addr) { printf("Resetting using SC520 MMCR\n"); /* Write a '1' to the SYS_RST of the RESCFG MMCR */ - sc520_mmcr->rescfg = 0x01; + writeb(0x01, &sc520_mmcr->rescfg); /* NOTREACHED */ } diff --git a/arch/i386/cpu/sc520/sc520_asm.S b/arch/i386/cpu/sc520/sc520_asm.S index 2042d9b..fff56c0 100644 --- a/arch/i386/cpu/sc520/sc520_asm.S +++ b/arch/i386/cpu/sc520/sc520_asm.S @@ -25,48 +25,85 @@ * copyright is included below */ -/* - * ============================================================================= - * - * Copyright 1999 Advanced Micro Devices, Inc. - * - * This software is the property of Advanced Micro Devices, Inc (AMD) which - * specifically grants the user the right to modify, use and distribute this - * software provided this COPYRIGHT NOTICE is not removed or altered. All - * other rights are reserved by AMD. - * - * THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY - * OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT OF - * THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY PARTICULAR PURPOSE. - * IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER - * (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS - * INTERRUPTION, LOSS OF INFORMAITON) ARISING OUT OF THE USE OF OR INABILITY - * TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY OF - * SUCH DAMAGES. BECAUSE SOME JURSIDICTIONS PROHIBIT THE EXCLUSION OR - * LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE - * LIMITATION MAY NOT APPLY TO YOU. - * - * AMD does not assume any responsibility for any errors that may appear in - * the Materials nor any responsibility to support or update the Materials. - * AMD retains the right to make changes to its test specifications at any - * time, without notice. - * - * So that all may benefit from your experience, please report any problems - * or suggestions about this software back to AMD. Please include your name, - * company, telephone number, AMD product requiring support and question or - * problem encountered. - * - * Advanced Micro Devices, Inc. Worldwide support and contact - * Embedded Processor Division information available at: - * Systems Engineering epd.support@amd.com - * 5204 E. Ben White Blvd. -or- - * Austin, TX 78741 http://www.amd.com/html/support/techsup.html - * ============================================================================ +/* TITLE SIZER - Aspen DRAM Sizing Routine. + * ============================================================================= + * + * Copyright 1999 Advanced Micro Devices, Inc. + * You may redistribute this program and/or modify this program under the terms + * of the GNU General Public License as published by the Free Software Foundation; + * either version 2 of the License, or (at your option) any later version. + * + * This program is distributed WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY + * OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT OF + * THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY PARTICULAR PURPOSE. + * IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER + * (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS + * INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR INABILITY + * TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. BECAUSE SOME JURSIDICTIONS PROHIBIT THE EXCLUSION OR + * LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE + * LIMITATION MAY NOT APPLY TO YOU. + * + * AMD does not assume any responsibility for any errors that may appear in + * the Materials nor any responsibility to support or update the Materials. + * AMD retains the right to make changes to its test specifications at any + * time, without notice. + * ============================================================================== */ - -/******************************************************************************* - * AUTHOR : Buddy Fey - Original. +/* + ****************************************************************************** + * + * FILE : sizer.asm - SDRAM DIMM Sizing Algorithm + * + * + * + * FUNCTIONS : sizemem() - jumped to, not called. To be executed after + * reset to determine the size of the SDRAM DIMMs. Initializes + * the memory subsystem. + * + * + * AUTHOR : Buddy Fey - Original. + * + * + * DESCRIPTION : Performs sizing on SDRAM DIMMs on ASPEN processor. + * NOTE: This is a small memory model version + * + * + * INPUTS : BP contains return address offset + * CACHE is assumed to be disabled. + * The FS segment limit has already been set to big real mode + * (full 32-bit addressing capability) + * + * + * OUTPUTS : None + * + * + * REG USE : ax,bx,cx,dx,di,si,bp, fs + * + * + * REVISION : See PVCS info below + * + * + * TEST PLAN CROSS REFERENCE: + * + * + * $Workfile: $ + * $Revision: 1.2 $ + * $Date: 1999/09/22 12:49:33 $ + * $Author: chipf $ + * $Log: sizer.asm $ + * Revision 1.2 1999/09/22 12:49:33 chipf + * Add legal header + * ******************************************************************************* */ @@ -463,7 +500,7 @@ emptybank: /* just have your hardware desinger _GIVE_ you what you need here! */ movl $DRCTMCTL, %edi movb $CONFIG_SYS_SDRAM_DRCTMCTL,%al - movb (%edi), %al + movb %al, (%edi) #else #if defined(CONFIG_SYS_SDRAM_CAS_LATENCY_2T) || defined(CONFIG_SYS_SDRAM_CAS_LATENCY_3T) /* set the CAS latency now since it is hard to do @@ -498,48 +535,21 @@ bad_ram: dram_done: - /* readback DRCBENDADR and return the number - * of available ram bytes in %eax */ - - movl $DRCBENDADR, %edi /* DRAM ending address register */ - - movl (%edi), %eax - movl %eax, %ecx - andl $0x80000000, %ecx - jz bank2 - andl $0x7f000000, %eax - shrl $2, %eax - movl %eax, %ebx - -bank2: movl (%edi), %eax - movl %eax, %ecx - andl $0x00800000, %ecx - jz bank1 - andl $0x007f0000, %eax - shll $6, %eax - movl %eax, %ebx - -bank1: movl (%edi), %eax - movl %eax, %ecx - andl $0x00008000, %ecx - jz bank0 - andl $0x00007f00, %eax - shll $14, %eax - movl %eax, %ebx - -bank0: movl (%edi), %eax - movl %eax, %ecx - andl $0x00000080, %ecx - jz done - andl $0x0000007f, %eax - shll $22, %eax - movl %eax, %ebx +#if CONFIG_SYS_SDRAM_ECC_ENABLE + /* + * We are in the middle of an existing 'call' - Need to store the + * existing return address before making another 'call' + */ + movl %ebp, %ebx + /* Get the memory size */ + movl $init_ecc, %ebp + jmpl get_mem_size -done: - movl %ebx, %eax +init_ecc: + /* Restore the orignal return address */ + movl %ebx, %ebp -#if CONFIG_SYS_SDRAM_ECC_ENABLE /* A nominal memory test: just a byte at each address line */ movl %eax, %ecx shrl $0x1, %ecx @@ -576,6 +586,50 @@ set_ecc: mov $0x05, %al movb %al, (%edi) #endif + out: + jmp *%ebp + +/* + * Read and decode the sc520 DRCBENDADR MMCR and return the number of + * available ram bytes in %eax + */ +.globl get_mem_size +get_mem_size: + movl $DRCBENDADR, %edi /* DRAM ending address register */ + +bank0: movl (%edi), %eax + movl %eax, %ecx + andl $0x00000080, %ecx + jz bank1 + andl $0x0000007f, %eax + shll $22, %eax + movl %eax, %ebx + +bank1: movl (%edi), %eax + movl %eax, %ecx + andl $0x00008000, %ecx + jz bank2 + andl $0x00007f00, %eax + shll $14, %eax + movl %eax, %ebx + +bank2: movl (%edi), %eax + movl %eax, %ecx + andl $0x00800000, %ecx + jz bank3 + andl $0x007f0000, %eax + shll $6, %eax + movl %eax, %ebx + +bank3: movl (%edi), %eax + movl %eax, %ecx + andl $0x80000000, %ecx + jz done + andl $0x7f000000, %eax + shrl $2, %eax + movl %eax, %ebx + +done: movl %ebx, %eax jmp *%ebp diff --git a/arch/i386/cpu/sc520/sc520_pci.c b/arch/i386/cpu/sc520/sc520_pci.c index f446c6d..b917734 100644 --- a/arch/i386/cpu/sc520/sc520_pci.c +++ b/arch/i386/cpu/sc520/sc520_pci.c @@ -25,7 +25,9 @@ #include <common.h> #include <pci.h> +#include <asm/io.h> #include <asm/pci.h> +#include <asm/ic/pci.h> #include <asm/ic/sc520.h> static struct { @@ -63,6 +65,8 @@ int sc520_pci_ints[15] = { int pci_sc520_set_irq(int pci_pin, int irq) { int i; + u8 tmpb; + u16 tmpw; # if 1 printf("set_irq(): map INT%c to IRQ%d\n", pci_pin + 'A', irq); @@ -80,31 +84,34 @@ int pci_sc520_set_irq(int pci_pin, int irq) /* PCI interrupt mapping (A through D)*/ for (i=0; i<=3 ;i++) { - if (sc520_mmcr->pci_int_map[i] == sc520_irq[irq].priority) - sc520_mmcr->pci_int_map[i] = SC520_IRQ_DISABLED; + if (readb(&sc520_mmcr->pci_int_map[i]) == sc520_irq[irq].priority) + writeb(SC520_IRQ_DISABLED, &sc520_mmcr->pci_int_map[i]); } /* GP IRQ interrupt mapping */ for (i=0; i<=10 ;i++) { - if (sc520_mmcr->gp_int_map[i] == sc520_irq[irq].priority) - sc520_mmcr->gp_int_map[i] = SC520_IRQ_DISABLED; + if (readb(&sc520_mmcr->gp_int_map[i]) == sc520_irq[irq].priority) + writeb(SC520_IRQ_DISABLED, &sc520_mmcr->gp_int_map[i]); } /* Set the trigger to level */ - sc520_mmcr->pic_mode[sc520_irq[irq].level_reg] = - sc520_mmcr->pic_mode[sc520_irq[irq].level_reg] | sc520_irq[irq].level_bit; + tmpb = readb(&sc520_mmcr->pic_mode[sc520_irq[irq].level_reg]); + tmpb |= sc520_irq[irq].level_bit; + writeb(tmpb, &sc520_mmcr->pic_mode[sc520_irq[irq].level_reg]); if (pci_pin < 4) { /* PCI INTA-INTD */ /* route the interrupt */ - sc520_mmcr->pci_int_map[pci_pin] = sc520_irq[irq].priority; + writeb(sc520_irq[irq].priority, &sc520_mmcr->pci_int_map[pci_pin]); } else { /* GPIRQ0-GPIRQ10 used for additional PCI INTS */ - sc520_mmcr->gp_int_map[pci_pin - 4] = sc520_irq[irq].priority; + writeb(sc520_irq[irq].priority, &sc520_mmcr->gp_int_map[pci_pin - 4]); /* also set the polarity in this case */ - sc520_mmcr->intpinpol = sc520_mmcr->intpinpol | (1 << (pci_pin-4)); + tmpw = readw(&sc520_mmcr->intpinpol); + tmpw |= (1 << (pci_pin-4)); + writew(tmpw, &sc520_mmcr->intpinpol); } /* register the pin */ @@ -118,43 +125,7 @@ void pci_sc520_init(struct pci_controller *hose) { hose->first_busno = 0; hose->last_busno = 0xff; - - /* System memory space */ - pci_set_region(hose->regions + 0, - SC520_PCI_MEMORY_BUS, - SC520_PCI_MEMORY_PHYS, - SC520_PCI_MEMORY_SIZE, - PCI_REGION_MEM | PCI_REGION_SYS_MEMORY); - - /* PCI memory space */ - pci_set_region(hose->regions + 1, - SC520_PCI_MEM_BUS, - SC520_PCI_MEM_PHYS, - SC520_PCI_MEM_SIZE, - PCI_REGION_MEM); - - /* ISA/PCI memory space */ - pci_set_region(hose->regions + 2, - SC520_ISA_MEM_BUS, - SC520_ISA_MEM_PHYS, - SC520_ISA_MEM_SIZE, - PCI_REGION_MEM); - - /* PCI I/O space */ - pci_set_region(hose->regions + 3, - SC520_PCI_IO_BUS, - SC520_PCI_IO_PHYS, - SC520_PCI_IO_SIZE, - PCI_REGION_IO); - - /* ISA/PCI I/O space */ - pci_set_region(hose->regions + 4, - SC520_ISA_IO_BUS, - SC520_ISA_IO_PHYS, - SC520_ISA_IO_SIZE, - PCI_REGION_IO); - - hose->region_count = 5; + hose->region_count = pci_set_regions(hose); pci_setup_type1(hose, SC520_REG_ADDR, diff --git a/arch/i386/cpu/sc520/sc520_ssi.c b/arch/i386/cpu/sc520/sc520_ssi.c index 8dbe17a..6e5e346 100644 --- a/arch/i386/cpu/sc520/sc520_ssi.c +++ b/arch/i386/cpu/sc520/sc520_ssi.c @@ -24,6 +24,7 @@ /* stuff specific for the sc520, but independent of implementation */ #include <common.h> +#include <asm/io.h> #include <asm/ic/ssi.h> #include <asm/ic/sc520.h> @@ -61,34 +62,34 @@ int ssi_set_interface(int freq, int lsb_first, int inv_clock, int inv_phase) temp |= PHS_INV_ENB; } - sc520_mmcr->ssictl = temp; + writeb(temp, &sc520_mmcr->ssictl); return 0; } u8 ssi_txrx_byte(u8 data) { - sc520_mmcr->ssixmit = data; - while (sc520_mmcr->ssista & SSISTA_BSY); - sc520_mmcr->ssicmd = SSICMD_CMD_SEL_XMITRCV; - while (sc520_mmcr->ssista & SSISTA_BSY); + writeb(data, &sc520_mmcr->ssixmit); + while (readb(&sc520_mmcr->ssista) & SSISTA_BSY); + writeb(SSICMD_CMD_SEL_XMITRCV, &sc520_mmcr->ssicmd); + while (readb(&sc520_mmcr->ssista) & SSISTA_BSY); - return sc520_mmcr->ssircv; + return readb(&sc520_mmcr->ssircv); } void ssi_tx_byte(u8 data) { - sc520_mmcr->ssixmit = data; - while (sc520_mmcr->ssista & SSISTA_BSY); - sc520_mmcr->ssicmd = SSICMD_CMD_SEL_XMIT; + writeb(data, &sc520_mmcr->ssixmit); + while (readb(&sc520_mmcr->ssista) & SSISTA_BSY); + writeb(SSICMD_CMD_SEL_XMIT, &sc520_mmcr->ssicmd); } u8 ssi_rx_byte(void) { - while (sc520_mmcr->ssista & SSISTA_BSY); - sc520_mmcr->ssicmd = SSICMD_CMD_SEL_RCV; - while (sc520_mmcr->ssista & SSISTA_BSY); + while (readb(&sc520_mmcr->ssista) & SSISTA_BSY); + writeb(SSICMD_CMD_SEL_RCV, &sc520_mmcr->ssicmd); + while (readb(&sc520_mmcr->ssista) & SSISTA_BSY); - return sc520_mmcr->ssircv; + return readb(&sc520_mmcr->ssircv); } diff --git a/arch/i386/cpu/sc520/sc520_timer.c b/arch/i386/cpu/sc520/sc520_timer.c index 93b5b55..d5617e9 100644 --- a/arch/i386/cpu/sc520/sc520_timer.c +++ b/arch/i386/cpu/sc520/sc520_timer.c @@ -24,13 +24,14 @@ /* stuff specific for the sc520, but independent of implementation */ #include <common.h> +#include <asm/io.h> #include <asm/interrupt.h> #include <asm/ic/sc520.h> void sc520_timer_isr(void) { /* Ack the GP Timer Interrupt */ - sc520_mmcr->gptmrsta = 0x02; + writeb(0x02, &sc520_mmcr->gptmrsta); } int timer_init(void) @@ -42,43 +43,47 @@ int timer_init(void) irq_install_handler (0, timer_isr, NULL); /* Map GP Timer 1 to Master PIC IR0 */ - sc520_mmcr->gp_tmr_int_map[1] = 0x01; + writeb(0x01, &sc520_mmcr->gp_tmr_int_map[1]); /* Disable GP Timers 1 & 2 - Allow configuration writes */ - sc520_mmcr->gptmr1ctl = 0x4000; - sc520_mmcr->gptmr2ctl = 0x4000; + writew(0x4000, &sc520_mmcr->gptmr1ctl); + writew(0x4000, &sc520_mmcr->gptmr2ctl); /* Reset GP Timers 1 & 2 */ - sc520_mmcr->gptmr1cnt = 0x0000; - sc520_mmcr->gptmr2cnt = 0x0000; + writew(0x0000, &sc520_mmcr->gptmr1cnt); + writew(0x0000, &sc520_mmcr->gptmr2cnt); /* Setup GP Timer 2 as a 100kHz (10us) prescaler */ - sc520_mmcr->gptmr2maxcmpa = 83; - sc520_mmcr->gptmr2ctl = 0xc001; + writew(83, &sc520_mmcr->gptmr2maxcmpa); + writew(0xc001, &sc520_mmcr->gptmr2ctl); /* Setup GP Timer 1 as a 1000 Hz (1ms) interrupt generator */ - sc520_mmcr->gptmr1maxcmpa = 100; - sc520_mmcr->gptmr1ctl = 0xe009; + writew(100, &sc520_mmcr->gptmr1maxcmpa); + writew(0xe009, &sc520_mmcr->gptmr1ctl); unmask_irq (0); /* Clear the GP Timer 1 status register to get the show rolling*/ - sc520_mmcr->gptmrsta = 0x02; + writeb(0x02, &sc520_mmcr->gptmrsta); return 0; } +/* Allow boards to override udelay implementation */ void __udelay(unsigned long usec) + __attribute__((weak, alias("sc520_udelay"))); + +void sc520_udelay(unsigned long usec) { int m = 0; long u; long temp; - temp = sc520_mmcr->swtmrmilli; - temp = sc520_mmcr->swtmrmicro; + temp = readw(&sc520_mmcr->swtmrmilli); + temp = readw(&sc520_mmcr->swtmrmicro); do { - m += sc520_mmcr->swtmrmilli; - u = sc520_mmcr->swtmrmicro + (m * 1000); + m += readw(&sc520_mmcr->swtmrmilli); + u = readw(&sc520_mmcr->swtmrmicro) + (m * 1000); } while (u < usec); } diff --git a/arch/i386/cpu/serial.c b/arch/i386/cpu/serial.c deleted file mode 100644 index e7025a3..0000000 --- a/arch/i386/cpu/serial.c +++ /dev/null @@ -1,506 +0,0 @@ -/* - * (C) Copyright 2002 - * Daniel Engström, Omicron Ceti AB, daniel@omicron.se - * - * (C) Copyright 2000 - * Wolfgang Denk, DENX Software Engineering, wd@denx.de. - * - * See file CREDITS for list of people who contributed to this - * project. - * - * This program is free software; you can redistribute it and/or - * modify it under the terms of the GNU General Public License as - * published by the Free Software Foundation; either version 2 of - * the License, or (at your option) any later version. - * - * This program is distributed in the hope that it will be useful, - * but WITHOUT ANY WARRANTY; without even the implied warranty of - * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the - * GNU General Public License for more details. - * - * You should have received a copy of the GNU General Public License - * along with this program; if not, write to the Free Software - * Foundation, Inc., 59 Temple Place, Suite 330, Boston, - * MA 02111-1307 USA - */ -/*------------------------------------------------------------------------------+ */ - -/* - * This source code is dual-licensed. You may use it under the terms of the - * GNU General Public License version 2, or under the license below. - * - * This source code has been made available to you by IBM on an AS-IS - * basis. Anyone receiving this source is licensed under IBM - * copyrights to use it in any way he or she deems fit, including - * copying it, modifying it, compiling it, and redistributing it either - * with or without modifications. No license under IBM patents or - * patent applications is to be implied by the copyright license. - * - * Any user of this software should understand that IBM cannot provide - * technical support for this software and will not be responsible for - * any consequences resulting from the use of this software. - * - * Any person who transfers this source code or any derivative work - * must include the IBM copyright notice, this paragraph, and the - * preceding two paragraphs in the transferred software. - * - * COPYRIGHT I B M CORPORATION 1995 - * LICENSED MATERIAL - PROGRAM PROPERTY OF I B M - */ -/*------------------------------------------------------------------------------- */ - -#include <common.h> -#include <watchdog.h> -#include <asm/io.h> -#include <asm/ibmpc.h> - -#ifdef CONFIG_SERIAL_SOFTWARE_FIFO -#include <malloc.h> -#endif - -DECLARE_GLOBAL_DATA_PTR; - -#define UART_RBR 0x00 -#define UART_THR 0x00 -#define UART_IER 0x01 -#define UART_IIR 0x02 -#define UART_FCR 0x02 -#define UART_LCR 0x03 -#define UART_MCR 0x04 -#define UART_LSR 0x05 -#define UART_MSR 0x06 -#define UART_SCR 0x07 -#define UART_DLL 0x00 -#define UART_DLM 0x01 - -/*-----------------------------------------------------------------------------+ - | Line Status Register. - +-----------------------------------------------------------------------------*/ -#define asyncLSRDataReady1 0x01 -#define asyncLSROverrunError1 0x02 -#define asyncLSRParityError1 0x04 -#define asyncLSRFramingError1 0x08 -#define asyncLSRBreakInterrupt1 0x10 -#define asyncLSRTxHoldEmpty1 0x20 -#define asyncLSRTxShiftEmpty1 0x40 -#define asyncLSRRxFifoError1 0x80 - - -#ifdef CONFIG_SERIAL_SOFTWARE_FIFO -/*-----------------------------------------------------------------------------+ - | Fifo - +-----------------------------------------------------------------------------*/ -typedef struct { - char *rx_buffer; - ulong rx_put; - ulong rx_get; - int cts; -} serial_buffer_t; - -volatile serial_buffer_t buf_info; -static int serial_buffer_active=0; -#endif - - -static int serial_div(int baudrate) -{ - - switch (baudrate) { - case 1200: - return 96; - case 9600: - return 12; - case 19200: - return 6; - case 38400: - return 3; - case 57600: - return 2; - case 115200: - return 1; - } - - return 12; -} - - -/* - * Minimal serial functions needed to use one of the SMC ports - * as serial console interface. - */ - -int serial_init(void) -{ - volatile char val; - int bdiv = serial_div(gd->baudrate); - - outb(0x80, UART0_BASE + UART_LCR); /* set DLAB bit */ - outb(bdiv, UART0_BASE + UART_DLL); /* set baudrate divisor */ - outb(bdiv >> 8, UART0_BASE + UART_DLM);/* set baudrate divisor */ - outb(0x03, UART0_BASE + UART_LCR); /* clear DLAB; set 8 bits, no parity */ - outb(0x01, UART0_BASE + UART_FCR); /* enable FIFO */ - outb(0x0b, UART0_BASE + UART_MCR); /* Set DTR and RTS active */ - val = inb(UART0_BASE + UART_LSR); /* clear line status */ - val = inb(UART0_BASE + UART_RBR); /* read receive buffer */ - outb(0x00, UART0_BASE + UART_SCR); /* set scratchpad */ - outb(0x00, UART0_BASE + UART_IER); /* set interrupt enable reg */ - - return 0; -} - - -void serial_setbrg(void) -{ - unsigned short bdiv; - - bdiv = serial_div(gd->baudrate); - - outb(0x80, UART0_BASE + UART_LCR); /* set DLAB bit */ - outb(bdiv&0xff, UART0_BASE + UART_DLL); /* set baudrate divisor */ - outb(bdiv >> 8, UART0_BASE + UART_DLM);/* set baudrate divisor */ - outb(0x03, UART0_BASE + UART_LCR); /* clear DLAB; set 8 bits, no parity */ -} - - -void serial_putc(const char c) -{ - int i; - - if (c == '\n') - serial_putc ('\r'); - - /* check THRE bit, wait for transmiter available */ - for (i = 1; i < 3500; i++) { - if ((inb (UART0_BASE + UART_LSR) & 0x20) == 0x20) { - break; - } - udelay(100); - } - outb(c, UART0_BASE + UART_THR); /* put character out */ -} - - -void serial_puts(const char *s) -{ - while (*s) { - serial_putc(*s++); - } -} - - -int serial_getc(void) -{ - unsigned char status = 0; - -#ifdef CONFIG_SERIAL_SOFTWARE_FIFO - if (serial_buffer_active) { - return serial_buffered_getc(); - } -#endif - - while (1) { -#if defined(CONFIG_HW_WATCHDOG) - WATCHDOG_RESET(); /* Reset HW Watchdog, if needed */ -#endif /* CONFIG_HW_WATCHDOG */ - status = inb(UART0_BASE + UART_LSR); - if ((status & asyncLSRDataReady1) != 0x0) { - break; - } - if ((status & ( asyncLSRFramingError1 | - asyncLSROverrunError1 | - asyncLSRParityError1 | - asyncLSRBreakInterrupt1 )) != 0) { - outb(asyncLSRFramingError1 | - asyncLSROverrunError1 | - asyncLSRParityError1 | - asyncLSRBreakInterrupt1, UART0_BASE + UART_LSR); - } - } - return (0x000000ff & (int) inb (UART0_BASE)); -} - - -int serial_tstc(void) -{ - unsigned char status; - -#ifdef CONFIG_SERIAL_SOFTWARE_FIFO - if (serial_buffer_active) { - return serial_buffered_tstc(); - } -#endif - - status = inb(UART0_BASE + UART_LSR); - if ((status & asyncLSRDataReady1) != 0x0) { - return (1); - } - if ((status & ( asyncLSRFramingError1 | - asyncLSROverrunError1 | - asyncLSRParityError1 | - asyncLSRBreakInterrupt1 )) != 0) { - outb(asyncLSRFramingError1 | - asyncLSROverrunError1 | - asyncLSRParityError1 | - asyncLSRBreakInterrupt1, UART0_BASE + UART_LSR); - } - return 0; -} - - -#ifdef CONFIG_SERIAL_SOFTWARE_FIFO - -void serial_isr(void *arg) -{ - int space; - int c; - int rx_put = buf_info.rx_put; - - if (buf_info.rx_get <= rx_put) { - space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - buf_info.rx_get); - } else { - space = buf_info.rx_get - rx_put; - } - - while (inb(UART0_BASE + UART_LSR) & 1) { - c = inb(UART0_BASE); - if (space) { - buf_info.rx_buffer[rx_put++] = c; - space--; - - if (rx_put == buf_info.rx_get) { - buf_info.rx_get++; - if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO) { - buf_info.rx_get = 0; - } - } - - if (rx_put == CONFIG_SERIAL_SOFTWARE_FIFO) { - rx_put = 0; - if (0 == buf_info.rx_get) { - buf_info.rx_get = 1; - } - - } - - } - if (space < CONFIG_SERIAL_SOFTWARE_FIFO / 4) { - /* Stop flow by setting RTS inactive */ - outb(inb(UART0_BASE + UART_MCR) & (0xFF ^ 0x02), - UART0_BASE + UART_MCR); - } - } - buf_info.rx_put = rx_put; -} - -void serial_buffered_init(void) -{ - serial_puts ("Switching to interrupt driven serial input mode.\n"); - buf_info.rx_buffer = malloc (CONFIG_SERIAL_SOFTWARE_FIFO); - buf_info.rx_put = 0; - buf_info.rx_get = 0; - - if (inb (UART0_BASE + UART_MSR) & 0x10) { - serial_puts ("Check CTS signal present on serial port: OK.\n"); - buf_info.cts = 1; - } else { - serial_puts ("WARNING: CTS signal not present on serial port.\n"); - buf_info.cts = 0; - } - - irq_install_handler ( VECNUM_U0 /*UART0 */ /*int vec */ , - serial_isr /*interrupt_handler_t *handler */ , - (void *) &buf_info /*void *arg */ ); - - /* Enable "RX Data Available" Interrupt on UART */ - /* outb(inb(UART0_BASE + UART_IER) |0x01, UART0_BASE + UART_IER); */ - outb(0x01, UART0_BASE + UART_IER); - - /* Set DTR and RTS active, enable interrupts */ - outb(inb (UART0_BASE + UART_MCR) | 0x0b, UART0_BASE + UART_MCR); - - /* Setup UART FIFO: RX trigger level: 1 byte, Enable FIFO */ - outb( /*(1 << 6) |*/ 1, UART0_BASE + UART_FCR); - - serial_buffer_active = 1; -} - -void serial_buffered_putc (const char c) -{ - int i; - /* Wait for CTS */ -#if defined(CONFIG_HW_WATCHDOG) - while (!(inb (UART0_BASE + UART_MSR) & 0x10)) - WATCHDOG_RESET (); -#else - if (buf_info.cts) { - for (i=0;i<1000;i++) { - if ((inb (UART0_BASE + UART_MSR) & 0x10)) { - break; - } - } - if (i!=1000) { - buf_info.cts = 0; - } - } else { - if ((inb (UART0_BASE + UART_MSR) & 0x10)) { - buf_info.cts = 1; - } - } - -#endif - serial_putc (c); -} - -void serial_buffered_puts(const char *s) -{ - serial_puts (s); -} - -int serial_buffered_getc(void) -{ - int space; - int c; - int rx_get = buf_info.rx_get; - int rx_put; - -#if defined(CONFIG_HW_WATCHDOG) - while (rx_get == buf_info.rx_put) - WATCHDOG_RESET (); -#else - while (rx_get == buf_info.rx_put); -#endif - c = buf_info.rx_buffer[rx_get++]; - if (rx_get == CONFIG_SERIAL_SOFTWARE_FIFO) { - rx_get = 0; - } - buf_info.rx_get = rx_get; - - rx_put = buf_info.rx_put; - if (rx_get <= rx_put) { - space = CONFIG_SERIAL_SOFTWARE_FIFO - (rx_put - rx_get); - } else { - space = rx_get - rx_put; - } - if (space > CONFIG_SERIAL_SOFTWARE_FIFO / 2) { - /* Start flow by setting RTS active */ - outb(inb (UART0_BASE + UART_MCR) | 0x02, UART0_BASE + UART_MCR); - } - - return c; -} - -int serial_buffered_tstc(void) -{ - return (buf_info.rx_get != buf_info.rx_put) ? 1 : 0; -} - -#endif /* CONFIG_SERIAL_SOFTWARE_FIFO */ - - -#if defined(CONFIG_CMD_KGDB) -/* - AS HARNOIS : according to CONFIG_KGDB_SER_INDEX kgdb uses serial port - number 0 or number 1 - - if CONFIG_KGDB_SER_INDEX = 1 => serial port number 0 : - configuration has been already done - - if CONFIG_KGDB_SER_INDEX = 2 => serial port number 1 : - configure port 1 for serial I/O with rate = CONFIG_KGDB_BAUDRATE -*/ -#if (CONFIG_KGDB_SER_INDEX & 2) -void kgdb_serial_init(void) -{ - volatile char val; - bdiv = serial_div (CONFIG_KGDB_BAUDRATE); - - /* - * Init onboard 16550 UART - */ - outb(0x80, UART1_BASE + UART_LCR); /* set DLAB bit */ - outb((bdiv & 0xff), UART1_BASE + UART_DLL); /* set divisor for 9600 baud */ - outb((bdiv >> 8 ), UART1_BASE + UART_DLM); /* set divisor for 9600 baud */ - outb(0x03, UART1_BASE + UART_LCR); /* line control 8 bits no parity */ - outb(0x00, UART1_BASE + UART_FCR); /* disable FIFO */ - outb(0x00, UART1_BASE + UART_MCR); /* no modem control DTR RTS */ - val = inb(UART1_BASE + UART_LSR); /* clear line status */ - val = inb(UART1_BASE + UART_RBR); /* read receive buffer */ - outb(0x00, UART1_BASE + UART_SCR); /* set scratchpad */ - outb(0x00, UART1_BASE + UART_IER); /* set interrupt enable reg */ -} - - -void putDebugChar(const char c) -{ - if (c == '\n') - serial_putc ('\r'); - - outb(c, UART1_BASE + UART_THR); /* put character out */ - - /* check THRE bit, wait for transfer done */ - while ((inb(UART1_BASE + UART_LSR) & 0x20) != 0x20); -} - - -void putDebugStr(const char *s) -{ - while (*s) { - serial_putc(*s++); - } -} - - -int getDebugChar(void) -{ - unsigned char status = 0; - - while (1) { - status = inb(UART1_BASE + UART_LSR); - if ((status & asyncLSRDataReady1) != 0x0) { - break; - } - if ((status & ( asyncLSRFramingError1 | - asyncLSROverrunError1 | - asyncLSRParityError1 | - asyncLSRBreakInterrupt1 )) != 0) { - outb(asyncLSRFramingError1 | - asyncLSROverrunError1 | - asyncLSRParityError1 | - asyncLSRBreakInterrupt1, UART1_BASE + UART_LSR); - } - } - return (0x000000ff & (int) inb(UART1_BASE)); -} - - -void kgdb_interruptible(int yes) -{ - return; -} - -#else /* ! (CONFIG_KGDB_SER_INDEX & 2) */ - -void kgdb_serial_init(void) -{ - serial_printf ("[on serial] "); -} - -void putDebugChar(int c) -{ - serial_putc (c); -} - -void putDebugStr(const char *str) -{ - serial_puts (str); -} - -int getDebugChar(void) -{ - return serial_getc (); -} - -void kgdb_interruptible(int yes) -{ - return; -} -#endif /* (CONFIG_KGDB_SER_INDEX & 2) */ -#endif diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index 25d32e6..7def8de 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -33,7 +33,27 @@ .type _start, @function .globl _i386boot_start _i386boot_start: + /* + * This is the fail safe 32-bit bootstrap entry point. The + * following code is not executed from a cold-reset (actually, a + * lot of it is, but from real-mode after cold reset. It is + * repeated here to put the board into a state as close to cold + * reset as necessary) + */ + cli + cld + + /* Turn of cache (this might require a 486-class CPU) */ + movl %cr0, %eax + orl $0x60000000,%eax + movl %eax, %cr0 + wbinvd + + /* Tell 32-bit code it is being entered from an in-RAM copy */ + movw $0x0000, %bx _start: + /* This is the 32-bit cold-reset entry point */ + movl $0x18,%eax /* Load our segement registes, the * gdt have already been loaded by start16.S */ movw %ax,%fs @@ -42,6 +62,18 @@ _start: movw %ax,%es movw %ax,%ss + /* Clear the interupt vectors */ + lidt blank_idt_ptr + + /* + * Skip low-level board and memory initialization if not starting + * from cold-reset. This allows us to do a fail safe boot-strap + * into a new build of U-Boot from a known-good boot flash + */ + movw $0x0001, %ax + cmpw %ax, %bx + jne mem_init_ret + /* We call a few functions in the board support package * since we have no stack yet we'll have to use %ebp * to store the return address */ @@ -63,6 +95,58 @@ early_board_init_ret: jmp mem_init mem_init_ret: + /* fetch memory size (into %eax) */ + mov $get_mem_size_ret, %ebp + jmp get_mem_size +get_mem_size_ret: + + /* + * We are now in 'Flat Protected Mode' and we know how much memory + * the board has. The (temporary) Global Descriptor Table is not + * in a 'Safe' place (it is either in Flash which can be erased or + * reprogrammed or in a fail-safe boot-strap image which could be + * over-written). + * + * Move the final gdt to a safe place (top of RAM) and load it. + * This is not a trivial excercise - the lgdt instruction does not + * have a register operand (memory only) and we may well be + * running from Flash, so self modifying code will not work here. + * To overcome this, we copy a stub into upper memory along with + * the GDT. + */ + + /* Reduce upper memory limit by (Stub + GDT Pointer + GDT) */ + subl $(end_gdt_setup - start_gdt_setup), %eax + + /* Copy the GDT and Stub */ + movl $start_gdt_setup, %esi + movl %eax, %edi + movl $(end_gdt_setup - start_gdt_setup), %ecx + shrl $2, %ecx + cld + rep movsl + + /* write the lgdt 'parameter' */ + subl $(jmp_instr - start_gdt_setup - 4), %ebp + addl %eax, %ebp + movl $(gdt_ptr - start_gdt_setup), %ebx + addl %eax, %ebx + movl %ebx, (%ebp) + + /* write the gdt address into the pointer */ + movl $(gdt_addr - start_gdt_setup), %ebp + addl %eax, %ebp + movl $(gdt - start_gdt_setup), %ebx + addl %eax, %ebx + movl %ebx, (%ebp) + + /* Save the return address */ + movl $load_gdt_ret, %ebp + + /* Load the new (safe) Global Descriptor Table */ + jmp *%eax + +load_gdt_ret: /* Check we have enough memory for stack */ movl $CONFIG_SYS_STACK_SIZE, %ecx cmpl %ecx, %eax @@ -133,3 +217,56 @@ stack_ok: die: hlt jmp die hlt + +blank_idt_ptr: + .word 0 /* limit */ + .long 0 /* base */ + +.align 4 +start_gdt_setup: + lgdt gdt_ptr +jmp_instr: + jmp *%ebp + +.align 4 +gdt_ptr: + .word 0x30 /* limit (48 bytes = 6 GDT entries) */ +gdt_addr: + .long gdt /* base */ + + /* The GDT table ... + * + * Selector Type + * 0x00 NULL + * 0x08 Unused + * 0x10 32bit code + * 0x18 32bit data/stack + * 0x20 16bit code + * 0x28 16bit data/stack + */ + +.align 4 +gdt: + .word 0, 0, 0, 0 /* NULL */ + .word 0, 0, 0, 0 /* unused */ + + .word 0xFFFF /* 4Gb - (0x100000*0x1000 = 4Gb) */ + .word 0 /* base address = 0 */ + .word 0x9B00 /* code read/exec */ + .word 0x00CF /* granularity = 4096, 386 (+5th nibble of limit) */ + + .word 0xFFFF /* 4Gb - (0x100000*0x1000 = 4Gb) */ + .word 0x0 /* base address = 0 */ + .word 0x9300 /* data read/write */ + .word 0x00CF /* granularity = 4096, 386 (+5th nibble of limit) */ + + .word 0xFFFF /* 64kb */ + .word 0 /* base address = 0 */ + .word 0x9b00 /* data read/write */ + .word 0x0010 /* granularity = 1 (+5th nibble of limit) */ + + .word 0xFFFF /* 64kb */ + .word 0 /* base address = 0 */ + .word 0x9300 /* data read/write */ + .word 0x0010 /* granularity = 1 (+5th nibble of limit) */ +end_gdt_setup: diff --git a/arch/i386/cpu/start16.S b/arch/i386/cpu/start16.S index 1ebb6bc..3e8b2cc 100644 --- a/arch/i386/cpu/start16.S +++ b/arch/i386/cpu/start16.S @@ -44,11 +44,9 @@ board_init16_ret: movl %eax, %cr0 wbinvd - /* load the descriptor tables */ -o32 cs lidt idt_ptr + /* load the temporary Global Descriptor Table */ o32 cs lgdt gdt_ptr - /* Now, we enter protected mode */ movl %cr0, %eax orl $1,%eax @@ -57,6 +55,8 @@ o32 cs lgdt gdt_ptr /* Flush the prefetch queue */ jmp ff ff: + /* Tell 32-bit code it is being entered from hard-reset */ + movw $0x0001, %bx /* Finally jump to the 32bit initialization code */ movw $code32start, %ax @@ -68,12 +68,13 @@ code32start: .long _start /* offset */ .word 0x10 /* segment */ -idt_ptr: - .word 0 /* limit */ - .long 0 /* base */ - +/* + * The following Global Descriptor Table is just enough to get us into + * 'Flat Protected Mode' - It will be discarded as soon as the final + * GDT is setup in a safe location in RAM + */ gdt_ptr: - .word 0x30 /* limit (48 bytes = 6 GDT entries) */ + .word 0x20 /* limit (32 bytes = 4 GDT entries) */ .long BOOT_SEG + gdt /* base */ /* The GDT table ... @@ -83,8 +84,6 @@ gdt_ptr: * 0x08 Unused * 0x10 32bit code * 0x18 32bit data/stack - * 0x20 16bit code - * 0x28 16bit data/stack */ gdt: @@ -100,13 +99,3 @@ gdt: .word 0x0 /* base address = 0 */ .word 0x9300 /* data read/write */ .word 0x00CF /* granularity = 4096, 386 (+5th nibble of limit) */ - - .word 0xFFFF /* 64kb */ - .word 0 /* base address = 0 */ - .word 0x9b00 /* data read/write */ - .word 0x0010 /* granularity = 1 (+5th nibble of limit) */ - - .word 0xFFFF /* 64kb */ - .word 0 /* base address = 0 */ - .word 0x9300 /* data read/write */ - .word 0x0010 /* granularity = 1 (+5th nibble of limit) */ diff --git a/arch/i386/include/asm/bootparam.h b/arch/i386/include/asm/bootparam.h new file mode 100644 index 0000000..1400951 --- /dev/null +++ b/arch/i386/include/asm/bootparam.h @@ -0,0 +1,120 @@ +#ifndef _ASM_X86_BOOTPARAM_H +#define _ASM_X86_BOOTPARAM_H + +#include <linux/types.h> +#include <linux/screen_info.h> +#include <linux/apm_bios.h> +#include <linux/edd.h> +#include <asm/e820.h> +#include <asm/ist.h> +#include <asm/video/edid.h> + +/* setup data types */ +#define SETUP_NONE 0 +#define SETUP_E820_EXT 1 + +/* extensible setup data list node */ +struct setup_data { + __u64 next; + __u32 type; + __u32 len; + __u8 data[0]; +}; + +struct setup_header { + __u8 setup_sects; + __u16 root_flags; + __u32 syssize; + __u16 ram_size; +#define RAMDISK_IMAGE_START_MASK 0x07FF +#define RAMDISK_PROMPT_FLAG 0x8000 +#define RAMDISK_LOAD_FLAG 0x4000 + __u16 vid_mode; + __u16 root_dev; + __u16 boot_flag; + __u16 jump; + __u32 header; + __u16 version; + __u32 realmode_swtch; + __u16 start_sys; + __u16 kernel_version; + __u8 type_of_loader; + __u8 loadflags; +#define LOADED_HIGH (1<<0) +#define QUIET_FLAG (1<<5) +#define KEEP_SEGMENTS (1<<6) +#define CAN_USE_HEAP (1<<7) + __u16 setup_move_size; + __u32 code32_start; + __u32 ramdisk_image; + __u32 ramdisk_size; + __u32 bootsect_kludge; + __u16 heap_end_ptr; + __u8 ext_loader_ver; + __u8 ext_loader_type; + __u32 cmd_line_ptr; + __u32 initrd_addr_max; + __u32 kernel_alignment; + __u8 relocatable_kernel; + __u8 _pad2[3]; + __u32 cmdline_size; + __u32 hardware_subarch; + __u64 hardware_subarch_data; + __u32 payload_offset; + __u32 payload_length; + __u64 setup_data; +} __attribute__((packed)); + +struct sys_desc_table { + __u16 length; + __u8 table[14]; +}; + +struct efi_info { + __u32 efi_loader_signature; + __u32 efi_systab; + __u32 efi_memdesc_size; + __u32 efi_memdesc_version; + __u32 efi_memmap; + __u32 efi_memmap_size; + __u32 efi_systab_hi; + __u32 efi_memmap_hi; +}; + +/* The so-called "zeropage" */ +struct boot_params { + struct screen_info screen_info; /* 0x000 */ + struct apm_bios_info apm_bios_info; /* 0x040 */ + __u8 _pad2[4]; /* 0x054 */ + __u64 tboot_addr; /* 0x058 */ + struct ist_info ist_info; /* 0x060 */ + __u8 _pad3[16]; /* 0x070 */ + __u8 hd0_info[16]; /* obsolete! */ /* 0x080 */ + __u8 hd1_info[16]; /* obsolete! */ /* 0x090 */ + struct sys_desc_table sys_desc_table; /* 0x0a0 */ + __u8 _pad4[144]; /* 0x0b0 */ + struct edid_info edid_info; /* 0x140 */ + struct efi_info efi_info; /* 0x1c0 */ + __u32 alt_mem_k; /* 0x1e0 */ + __u32 scratch; /* Scratch field! */ /* 0x1e4 */ + __u8 e820_entries; /* 0x1e8 */ + __u8 eddbuf_entries; /* 0x1e9 */ + __u8 edd_mbr_sig_buf_entries; /* 0x1ea */ + __u8 _pad6[6]; /* 0x1eb */ + struct setup_header hdr; /* setup header */ /* 0x1f1 */ + __u8 _pad7[0x290-0x1f1-sizeof(struct setup_header)]; + __u32 edd_mbr_sig_buffer[EDD_MBR_SIG_MAX]; /* 0x290 */ + struct e820entry e820_map[E820MAX]; /* 0x2d0 */ + __u8 _pad8[48]; /* 0xcd0 */ + struct edd_info eddbuf[EDDMAXNR]; /* 0xd00 */ + __u8 _pad9[276]; /* 0xeec */ +} __attribute__((packed)); + +enum { + X86_SUBARCH_PC = 0, + X86_SUBARCH_LGUEST, + X86_SUBARCH_XEN, + X86_SUBARCH_MRST, + X86_NR_SUBARCHS, +}; +#endif /* _ASM_X86_BOOTPARAM_H */ diff --git a/arch/i386/include/asm/e820.h b/arch/i386/include/asm/e820.h new file mode 100644 index 0000000..d155ce9 --- /dev/null +++ b/arch/i386/include/asm/e820.h @@ -0,0 +1,155 @@ +#ifndef _ASM_X86_E820_H +#define _ASM_X86_E820_H +#define E820MAP 0x2d0 /* our map */ +#define E820MAX 128 /* number of entries in E820MAP */ + +/* + * Legacy E820 BIOS limits us to 128 (E820MAX) nodes due to the + * constrained space in the zeropage. If we have more nodes than + * that, and if we've booted off EFI firmware, then the EFI tables + * passed us from the EFI firmware can list more nodes. Size our + * internal memory map tables to have room for these additional + * nodes, based on up to three entries per node for which the + * kernel was built: MAX_NUMNODES == (1 << CONFIG_NODES_SHIFT), + * plus E820MAX, allowing space for the possible duplicate E820 + * entries that might need room in the same arrays, prior to the + * call to sanitize_e820_map() to remove duplicates. The allowance + * of three memory map entries per node is "enough" entries for + * the initial hardware platform motivating this mechanism to make + * use of additional EFI map entries. Future platforms may want + * to allow more than three entries per node or otherwise refine + * this size. + */ + +/* + * Odd: 'make headers_check' complains about numa.h if I try + * to collapse the next two #ifdef lines to a single line: + * #if defined(__KERNEL__) && defined(CONFIG_EFI) + */ +#ifdef __KERNEL__ +#ifdef CONFIG_EFI +#include <linux/numa.h> +#define E820_X_MAX (E820MAX + 3 * MAX_NUMNODES) +#else /* ! CONFIG_EFI */ +#define E820_X_MAX E820MAX +#endif +#else /* ! __KERNEL__ */ +#define E820_X_MAX E820MAX +#endif + +#define E820NR 0x1e8 /* # entries in E820MAP */ + +#define E820_RAM 1 +#define E820_RESERVED 2 +#define E820_ACPI 3 +#define E820_NVS 4 +#define E820_UNUSABLE 5 + +/* reserved RAM used by kernel itself */ +#define E820_RESERVED_KERN 128 + +#ifndef __ASSEMBLY__ +#include <linux/types.h> +struct e820entry { + __u64 addr; /* start of memory segment */ + __u64 size; /* size of memory segment */ + __u32 type; /* type of memory segment */ +} __attribute__((packed)); + +struct e820map { + __u32 nr_map; + struct e820entry map[E820_X_MAX]; +}; + +#define ISA_START_ADDRESS 0xa0000 +#define ISA_END_ADDRESS 0x100000 + +#define BIOS_BEGIN 0x000a0000 +#define BIOS_END 0x00100000 + +#ifdef __KERNEL__ +/* see comment in arch/x86/kernel/e820.c */ +extern struct e820map e820; +extern struct e820map e820_saved; + +extern unsigned long pci_mem_start; +extern int e820_any_mapped(u64 start, u64 end, unsigned type); +extern int e820_all_mapped(u64 start, u64 end, unsigned type); +extern void e820_add_region(u64 start, u64 size, int type); +extern void e820_print_map(char *who); +extern int +sanitize_e820_map(struct e820entry *biosmap, int max_nr_map, u32 *pnr_map); +extern u64 e820_update_range(u64 start, u64 size, unsigned old_type, + unsigned new_type); +extern u64 e820_remove_range(u64 start, u64 size, unsigned old_type, + int checktype); +extern void update_e820(void); +extern void e820_setup_gap(void); +extern int e820_search_gap(unsigned long *gapstart, unsigned long *gapsize, + unsigned long start_addr, unsigned long long end_addr); +struct setup_data; +extern void parse_e820_ext(struct setup_data *data, unsigned long pa_data); + +#if defined(CONFIG_X86_64) || \ + (defined(CONFIG_X86_32) && defined(CONFIG_HIBERNATION)) +extern void e820_mark_nosave_regions(unsigned long limit_pfn); +#else +static inline void e820_mark_nosave_regions(unsigned long limit_pfn) +{ +} +#endif + +#ifdef CONFIG_MEMTEST +extern void early_memtest(unsigned long start, unsigned long end); +#else +static inline void early_memtest(unsigned long start, unsigned long end) +{ +} +#endif + +extern unsigned long end_user_pfn; + +extern u64 find_e820_area(u64 start, u64 end, u64 size, u64 align); +extern u64 find_e820_area_size(u64 start, u64 *sizep, u64 align); +extern void reserve_early(u64 start, u64 end, char *name); +extern void reserve_early_overlap_ok(u64 start, u64 end, char *name); +extern void free_early(u64 start, u64 end); +extern void early_res_to_bootmem(u64 start, u64 end); +extern u64 early_reserve_e820(u64 startt, u64 sizet, u64 align); + +extern unsigned long e820_end_of_ram_pfn(void); +extern unsigned long e820_end_of_low_ram_pfn(void); +extern int e820_find_active_region(const struct e820entry *ei, + unsigned long start_pfn, + unsigned long last_pfn, + unsigned long *ei_startpfn, + unsigned long *ei_endpfn); +extern void e820_register_active_regions(int nid, unsigned long start_pfn, + unsigned long end_pfn); +extern u64 e820_hole_size(u64 start, u64 end); +extern void finish_e820_parsing(void); +extern void e820_reserve_resources(void); +extern void e820_reserve_resources_late(void); +extern void setup_memory_map(void); +extern char *default_machine_specific_memory_setup(void); + +/* + * Returns true iff the specified range [s,e) is completely contained inside + * the ISA region. + */ +/* +static inline bool is_ISA_range(u64 s, u64 e) +{ + return s >= ISA_START_ADDRESS && e <= ISA_END_ADDRESS; +} +*/ +#endif /* __KERNEL__ */ +#endif /* __ASSEMBLY__ */ + +#ifdef __KERNEL__ +/* #include <linux/ioport.h> */ + +#define HIGH_MEMORY (1024*1024) +#endif /* __KERNEL__ */ + +#endif /* _ASM_X86_E820_H */ diff --git a/arch/i386/include/asm/ic/pci.h b/arch/i386/include/asm/ic/pci.h index bcccdbe..2e4376b 100644 --- a/arch/i386/include/asm/ic/pci.h +++ b/arch/i386/include/asm/ic/pci.h @@ -24,6 +24,35 @@ #ifndef _ASM_IC_SC520_PCI_H_ #define _ASM_IC_SC520_PCI_H_ 1 +/* bus mapping constants (used for PCI core initialization) */ /* bus mapping constants */ +#define SC520_REG_ADDR 0x00000cf8 +#define SC520_REG_DATA 0x00000cfc + +#define SC520_ISA_MEM_PHYS 0x00000000 +#define SC520_ISA_MEM_BUS 0x00000000 +#define SC520_ISA_MEM_SIZE 0x01000000 + +#define SC520_ISA_IO_PHYS 0x00000000 +#define SC520_ISA_IO_BUS 0x00000000 +#define SC520_ISA_IO_SIZE 0x00001000 + +/* PCI I/O space from 0x1000 to 0xdfff + * (make 0xe000-0xfdff available for stuff like PCCard boot) */ +#define SC520_PCI_IO_PHYS 0x00001000 +#define SC520_PCI_IO_BUS 0x00001000 +#define SC520_PCI_IO_SIZE 0x0000d000 + +/* system memory from 0x00000000 to 0x0fffffff */ +#define SC520_PCI_MEMORY_PHYS 0x00000000 +#define SC520_PCI_MEMORY_BUS 0x00000000 +#define SC520_PCI_MEMORY_SIZE 0x10000000 + +/* PCI bus memory from 0x10000000 to 0x26ffffff + * (make 0x27000000 - 0x27ffffff available for stuff like PCCard boot) */ +#define SC520_PCI_MEM_PHYS 0x10000000 +#define SC520_PCI_MEM_BUS 0x10000000 +#define SC520_PCI_MEM_SIZE 0x17000000 + /* pin number used for PCI interrupt mappings */ #define SC520_PCI_INTA 0 #define SC520_PCI_INTB 1 @@ -44,6 +73,7 @@ extern int sc520_pci_ints[]; void pci_sc520_init(struct pci_controller *hose); +int pci_set_regions(struct pci_controller *hose); int pci_sc520_set_irq(int pci_pin, int irq); #endif diff --git a/arch/i386/include/asm/ic/sc520.h b/arch/i386/include/asm/ic/sc520.h index 57c9904..053d9c6 100644 --- a/arch/i386/include/asm/ic/sc520.h +++ b/arch/i386/include/asm/ic/sc520.h @@ -28,6 +28,7 @@ void init_sc520(void); unsigned long init_sc520_dram(void); +void sc520_udelay(unsigned long usec); /* Memory mapped configuration registers */ typedef struct sc520_mmcr { @@ -292,35 +293,6 @@ extern volatile sc520_mmcr_t *sc520_mmcr; #define UART2_DIS 0x02 /* UART2 Disable */ #define UART1_DIS 0x01 /* UART1 Disable */ -/* bus mapping constants (used for PCI core initialization) */ /* bus mapping constants */ -#define SC520_REG_ADDR 0x00000cf8 -#define SC520_REG_DATA 0x00000cfc - -#define SC520_ISA_MEM_PHYS 0x00000000 -#define SC520_ISA_MEM_BUS 0x00000000 -#define SC520_ISA_MEM_SIZE 0x01000000 - -#define SC520_ISA_IO_PHYS 0x00000000 -#define SC520_ISA_IO_BUS 0x00000000 -#define SC520_ISA_IO_SIZE 0x00001000 - -/* PCI I/O space from 0x1000 to 0xdfff - * (make 0xe000-0xfdff available for stuff like PCCard boot) */ -#define SC520_PCI_IO_PHYS 0x00001000 -#define SC520_PCI_IO_BUS 0x00001000 -#define SC520_PCI_IO_SIZE 0x0000d000 - -/* system memory from 0x00000000 to 0x0fffffff */ -#define SC520_PCI_MEMORY_PHYS 0x00000000 -#define SC520_PCI_MEMORY_BUS 0x00000000 -#define SC520_PCI_MEMORY_SIZE 0x10000000 - -/* PCI bus memory from 0x10000000 to 0x26ffffff - * (make 0x27000000 - 0x27ffffff available for stuff like PCCard boot) */ -#define SC520_PCI_MEM_PHYS 0x10000000 -#define SC520_PCI_MEM_BUS 0x10000000 -#define SC520_PCI_MEM_SIZE 0x17000000 - /* 0x28000000 - 0x3fffffff is used by the flash banks */ /* 0x40000000 - 0xffffffff is not adressable by the SC520 */ diff --git a/arch/i386/include/asm/ioctl.h b/arch/i386/include/asm/ioctl.h new file mode 100644 index 0000000..b279fe0 --- /dev/null +++ b/arch/i386/include/asm/ioctl.h @@ -0,0 +1 @@ +#include <asm-generic/ioctl.h> diff --git a/arch/i386/include/asm/ist.h b/arch/i386/include/asm/ist.h new file mode 100644 index 0000000..7e5dff1 --- /dev/null +++ b/arch/i386/include/asm/ist.h @@ -0,0 +1,34 @@ +#ifndef _ASM_X86_IST_H +#define _ASM_X86_IST_H + +/* + * Include file for the interface to IST BIOS + * Copyright 2002 Andy Grover <andrew.grover@intel.com> + * + * This program is free software; you can redistribute it and/or modify it + * under the terms of the GNU General Public License as published by the + * Free Software Foundation; either version 2, or (at your option) any + * later version. + * + * This program is distributed in the hope that it will be useful, but + * WITHOUT ANY WARRANTY; without even the implied warranty of + * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + */ + + +#include <linux/types.h> + +struct ist_info { + __u32 signature; + __u32 command; + __u32 event; + __u32 perf_level; +}; + +#ifdef __KERNEL__ + +extern struct ist_info ist_info; + +#endif /* __KERNEL__ */ +#endif /* _ASM_X86_IST_H */ diff --git a/arch/i386/include/asm/u-boot-i386.h b/arch/i386/include/asm/u-boot-i386.h index 521fd35..ce097a3 100644 --- a/arch/i386/include/asm/u-boot-i386.h +++ b/arch/i386/include/asm/u-boot-i386.h @@ -43,6 +43,8 @@ int cpu_init_interrupts(void); int board_init(void); int dram_init(void); +void setup_pcat_compatibility(void); + void isa_unmap_rom(u32 addr); u32 isa_map_rom(u32 bus_addr, int size); diff --git a/arch/i386/include/asm/unaligned.h b/arch/i386/include/asm/unaligned.h new file mode 100644 index 0000000..6cecbbb --- /dev/null +++ b/arch/i386/include/asm/unaligned.h @@ -0,0 +1 @@ +#include <asm-generic/unaligned.h> diff --git a/arch/i386/include/asm/video/edid.h b/arch/i386/include/asm/video/edid.h new file mode 100644 index 0000000..928c342 --- /dev/null +++ b/arch/i386/include/asm/video/edid.h @@ -0,0 +1,16 @@ +#ifndef __linux_video_edid_h__ +#define __linux_video_edid_h__ + +#if !defined(__KERNEL__) || defined(CONFIG_X86) + +struct edid_info { + unsigned char dummy[128]; +}; + +#ifdef __KERNEL__ +extern struct edid_info edid_info; +#endif /* __KERNEL__ */ + +#endif + +#endif /* __linux_video_edid_h__ */ diff --git a/arch/i386/lib/bios_setup.c b/arch/i386/lib/bios_setup.c index 6491e52..a92b77e 100644 --- a/arch/i386/lib/bios_setup.c +++ b/arch/i386/lib/bios_setup.c @@ -141,7 +141,7 @@ static void setvector(int vector, u16 segment, void *handler) int bios_setup(void) { - ulong i386boot_bios = (ulong)&_i386boot_bios; + ulong i386boot_bios = (ulong)&_i386boot_bios + gd->reloc_off; ulong i386boot_bios_size = (ulong)&_i386boot_bios_size; static int done=0; diff --git a/arch/i386/lib/board.c b/arch/i386/lib/board.c index f3b6348..3f849f6 100644 --- a/arch/i386/lib/board.c +++ b/arch/i386/lib/board.c @@ -37,6 +37,7 @@ #include <malloc.h> #include <net.h> #include <ide.h> +#include <serial.h> #include <asm/u-boot-i386.h> #include <elf.h> @@ -52,7 +53,9 @@ extern ulong _i386boot_rel_dyn_start; extern ulong _i386boot_rel_dyn_end; extern ulong _i386boot_bss_start; extern ulong _i386boot_bss_size; -void ram_bootstrap (void *); + +void ram_bootstrap (void *, ulong); + const char version_string[] = U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")"; @@ -147,7 +150,6 @@ static void display_flash_config (ulong size) typedef int (init_fnc_t) (void); init_fnc_t *init_sequence[] = { - serial_init, cpu_init_r, /* basic cpu dependent setup */ board_early_init_r, /* basic board dependent setup */ dram_init, /* configure available RAM banks */ @@ -162,6 +164,7 @@ init_fnc_t *init_sequence[] = { NULL, }; +static gd_t gd_data; gd_t *gd; /* @@ -174,21 +177,18 @@ void board_init_f (ulong stack_limit) Elf32_Rel *rel_dyn_start = (Elf32_Rel *)&_i386boot_rel_dyn_start; Elf32_Rel *rel_dyn_end = (Elf32_Rel *)&_i386boot_rel_dyn_end; void *bss_start = &_i386boot_bss_start; - void *bss_size = &_i386boot_bss_size; + ulong bss_size = (ulong)&_i386boot_bss_size; - size_t uboot_size; - void *ram_start; + ulong uboot_size; + void *dest_addr; ulong rel_offset; Elf32_Rel *re; - void (*start_func)(void *); - - /* compiler optimization barrier needed for GCC >= 3.4 */ - __asm__ __volatile__("": : :"memory"); + void (*start_func)(void *, ulong); - uboot_size = (size_t)u_boot_cmd_end - (size_t)text_start; - ram_start = (void *)stack_limit - (uboot_size + (ulong)bss_size); - rel_offset = text_start - ram_start; + uboot_size = (ulong)u_boot_cmd_end - (ulong)text_start; + dest_addr = (void *)stack_limit - (uboot_size + (ulong)bss_size); + rel_offset = text_start - dest_addr; start_func = ram_bootstrap - rel_offset; /* First stage CPU initialization */ @@ -200,10 +200,10 @@ void board_init_f (ulong stack_limit) hang(); /* Copy U-Boot into RAM */ - memcpy(ram_start, text_start, (size_t)uboot_size); + memcpy(dest_addr, text_start, uboot_size); /* Clear BSS */ - memset(bss_start - rel_offset, 0, (size_t)bss_size); + memset(bss_start - rel_offset, 0, bss_size); /* Perform relocation adjustments */ for (re = rel_dyn_start; re < rel_dyn_end; re++) @@ -213,27 +213,39 @@ void board_init_f (ulong stack_limit) *(ulong *)(re->r_offset - rel_offset) -= (Elf32_Addr)rel_offset; } - start_func(ram_start); - - /* NOTREACHED - relocate_code() does not return */ + /* Enter the relocated U-Boot! */ + start_func(dest_addr, rel_offset); + /* NOTREACHED - board_init_f() does not return */ while(1); } /* - * All attempts to jump straight from board_init_f() to board_init_r() - * have failed, hence this special 'bootstrap' function. + * We cannot initialize gd_data in board_init_f() because we would be + * attempting to write to flash (I have even tried using manual relocation + * adjustments on pointers but it just won't work) and board_init_r() does + * not have enough arguments to allow us to pass the relocation offset + * straight up. This bootstrap function (which runs in RAM) is used to + * setup gd_data in order to pass the relocation offset to the rest of + * U-Boot. + * + * TODO: The compiler optimization barrier is intended to stop GCC from + * optimizing this function into board_init_f(). It seems to work without + * it, but I've left it in to be sure. I think also that the barrier in + * board_init_r() is no longer needed, but left it in 'just in case' */ -void ram_bootstrap (void *ram_start) +void ram_bootstrap (void *dest_addr, ulong rel_offset) { - static gd_t gd_data; - /* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("": : :"memory"); - board_init_r(&gd_data, (ulong)ram_start); + /* tell others: relocation done */ + gd_data.reloc_off = rel_offset; + gd_data.flags |= GD_FLG_RELOC; + + board_init_r(&gd_data, (ulong)dest_addr); } -void board_init_r(gd_t *id, ulong ram_start) +void board_init_r(gd_t *id, ulong dest_addr) { char *s; int i; @@ -247,16 +259,13 @@ void board_init_r(gd_t *id, ulong ram_start) /* compiler optimization barrier needed for GCC >= 3.4 */ __asm__ __volatile__("": : :"memory"); - memset (gd, 0, sizeof (gd_t)); gd->bd = &bd_data; memset (gd->bd, 0, sizeof (bd_t)); show_boot_progress(0x22); gd->baudrate = CONFIG_BAUDRATE; - gd->flags |= GD_FLG_RELOC; /* tell others: relocation done */ - - mem_malloc_init((((ulong)ram_start - CONFIG_SYS_MALLOC_LEN)+3)&~3, + mem_malloc_init((((ulong)dest_addr - CONFIG_SYS_MALLOC_LEN)+3)&~3, CONFIG_SYS_MALLOC_LEN); for (init_fnc_ptr = init_sequence, i=0; *init_fnc_ptr; ++init_fnc_ptr, i++) { @@ -268,6 +277,9 @@ void board_init_r(gd_t *id, ulong ram_start) } show_boot_progress(0x23); +#ifdef CONFIG_SERIAL_MULTI + serial_initialize(); +#endif /* configure available FLASH banks */ size = flash_init(); display_flash_config(size); @@ -280,8 +292,10 @@ void board_init_r(gd_t *id, ulong ram_start) show_boot_progress(0x26); +#ifdef CONFIG_CMD_NET /* IP Address */ bd_data.bi_ip_addr = getenv_IPaddr ("ipaddr"); +#endif #if defined(CONFIG_PCI) /* @@ -420,10 +434,17 @@ void hang (void) unsigned long do_go_exec (ulong (*entry)(int, char *[]), int argc, char *argv[]) { /* - * TODO: Test this function - changed to fix compiler error. - * Original code was: - * return (entry >> 1) (argc, argv); - * with a comment about Nios function pointers are address >> 1 + * x86 does not use a dedicated register to pass the pointer + * to the global_data */ + argv[-1] = (char *)gd; + return (entry) (argc, argv); } + +void setup_pcat_compatibility(void) + __attribute__((weak, alias("__setup_pcat_compatibility"))); + +void __setup_pcat_compatibility(void) +{ +} diff --git a/arch/i386/lib/realmode.c b/arch/i386/lib/realmode.c index 3c3c1fc..b3f5123 100644 --- a/arch/i386/lib/realmode.c +++ b/arch/i386/lib/realmode.c @@ -37,7 +37,7 @@ extern char realmode_enter; int realmode_setup(void) { - ulong i386boot_realmode = (ulong)&_i386boot_realmode; + ulong i386boot_realmode = (ulong)&_i386boot_realmode + gd->reloc_off; ulong i386boot_realmode_size = (ulong)&_i386boot_realmode_size; /* copy the realmode switch code */ diff --git a/arch/i386/lib/zimage.c b/arch/i386/lib/zimage.c index c3b4e59..b39615a 100644 --- a/arch/i386/lib/zimage.c +++ b/arch/i386/lib/zimage.c @@ -34,6 +34,8 @@ #include <asm/zimage.h> #include <asm/realmode.h> #include <asm/byteorder.h> +#include <asm/bootparam.h> +#include <asm/ic/sc520.h> /* * Memory lay-out: @@ -90,48 +92,56 @@ void *load_zimage(char *image, unsigned long kernel_size, int big_image; void *load_address; + struct setup_header *hdr = (struct setup_header *)(image + SETUP_SECTS_OFF); setup_base = (void*)DEFAULT_SETUP_BASE; /* base address for real-mode segment */ - if (KERNEL_MAGIC != *(u16*)(image + BOOT_FLAG_OFF)) { - printf("Error: Invalid kernel magic (found 0x%04x, expected 0xaa55)\n", - *(u16*)(image + BOOT_FLAG_OFF)); + if (KERNEL_MAGIC != hdr->boot_flag) { + printf("Error: Invalid Boot Flag (found 0x%04x, expected 0x%04x)\n", + hdr->boot_flag, KERNEL_MAGIC); return 0; + } else { + printf("Valid Boot Flag\n"); } - /* determine boot protocol version */ - if (KERNEL_V2_MAGIC == *(u32*)(image+HEADER_OFF)) { - bootproto = *(u16*)(image+VERSION_OFF); + if (KERNEL_V2_MAGIC == hdr->header) { + printf("Magic signature found\n"); + + bootproto = hdr->version; } else { /* Very old kernel */ + printf("Magic signature not found\n"); bootproto = 0x0100; } /* determine size of setup */ - if (0 == *(u8*)(image + SETUP_SECTS_OFF)) { + if (0 == hdr->setup_sects) { + printf("Setup Sectors = 0 (defaulting to 4)\n"); setup_size = 5 * 512; } else { - setup_size = (*(u8*)(image + SETUP_SECTS_OFF) + 1) * 512; + setup_size = (hdr->setup_sects + 1) * 512; } + printf("Setup Size = 0x%8.8lx\n", (ulong)setup_size); + if (setup_size > SETUP_MAX_SIZE) { printf("Error: Setup is too large (%d bytes)\n", setup_size); } /* Determine image type */ - big_image = (bootproto >= 0x0200) && (*(u8*)(image + LOADFLAGS_OFF) & BIG_KERNEL_FLAG); + big_image = (bootproto >= 0x0200) && (hdr->loadflags & BIG_KERNEL_FLAG); - /* Derermine load address */ - load_address = (void*)(big_image ? BZIMAGE_LOAD_ADDR:ZIMAGE_LOAD_ADDR); + /* Determine load address */ + load_address = (void*)(big_image ? BZIMAGE_LOAD_ADDR : ZIMAGE_LOAD_ADDR); /* load setup */ + printf("Moving Real-Mode Code to 0x%8.8lx (%d bytes)\n", (ulong)setup_base, setup_size); memmove(setup_base, image, setup_size); printf("Using boot protocol version %x.%02x\n", (bootproto & 0xff00) >> 8, bootproto & 0xff); - if (bootproto == 0x0100) { *(u16*)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC; @@ -154,48 +164,58 @@ void *load_zimage(char *image, unsigned long kernel_size, memset((void*)0x90000 + setup_size, 0, SETUP_MAX_SIZE-setup_size); } + /* We are now setting up the real-mode version of the header */ + hdr = (struct setup_header *)(setup_base + SETUP_SECTS_OFF); + if (bootproto >= 0x0200) { - *(u8*)(setup_base + TYPE_OF_LOADER_OFF) = 0xff; - printf("Linux kernel version %s\n", - (char*)(setup_base + SETUP_START_OFFSET + - *(u16*)(setup_base + START_SYS_OFF + 2))); + hdr->type_of_loader = 8; + + if (hdr->setup_sects >= 15) + printf("Linux kernel version %s\n", (char *) + (setup_base + (hdr->kernel_version + 0x200))); + else + printf("Setup Sectors < 15 - Cannot print kernel version.\n"); if (initrd_addr) { printf("Initial RAM disk at linear address 0x%08lx, size %ld bytes\n", initrd_addr, initrd_size); - *(u32*)(setup_base + RAMDISK_IMAGE_OFF) = initrd_addr; - *(u32*)(setup_base + RAMDISK_SIZE_OFF)=initrd_size; + hdr->ramdisk_image = initrd_addr; + hdr->ramdisk_size = initrd_size; } } if (bootproto >= 0x0201) { - *(u16*)(setup_base + HEAP_END_PTR_OFF) = HEAP_END_OFFSET; - - /* CAN_USE_HEAP */ - *(u8*)(setup_base + LOADFLAGS_OFF) = - *(u8*)(setup_base + LOADFLAGS_OFF) | HEAP_FLAG; + hdr->heap_end_ptr = HEAP_END_OFFSET; + hdr->loadflags |= HEAP_FLAG; } if (bootproto >= 0x0202) { - *(u32*)(setup_base + CMD_LINE_PTR_OFF) = (u32)setup_base + COMMAND_LINE_OFFSET; + hdr->cmd_line_ptr = (u32)setup_base + COMMAND_LINE_OFFSET; } else if (bootproto >= 0x0200) { + *(u16*)(setup_base + CMD_LINE_MAGIC_OFF) = COMMAND_LINE_MAGIC; *(u16*)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET; - *(u16*)(setup_base + SETUP_MOVE_SIZE_OFF) = 0x9100; + + hdr->setup_move_size = 0x9100; } + if (bootproto >= 0x0204) + kernel_size = hdr->syssize * 16; + else + kernel_size -= setup_size; + if (big_image) { - if ((kernel_size - setup_size) > BZIMAGE_MAX_SIZE) { + if ((kernel_size) > BZIMAGE_MAX_SIZE) { printf("Error: bzImage kernel too big! (size: %ld, max: %d)\n", - kernel_size - setup_size, BZIMAGE_MAX_SIZE); + kernel_size, BZIMAGE_MAX_SIZE); return 0; } - } else if ((kernel_size - setup_size) > ZIMAGE_MAX_SIZE) { + } else if ((kernel_size) > ZIMAGE_MAX_SIZE) { printf("Error: zImage kernel too big! (size: %ld, max: %d)\n", - kernel_size - setup_size, ZIMAGE_MAX_SIZE); + kernel_size, ZIMAGE_MAX_SIZE); return 0; } @@ -203,10 +223,10 @@ void *load_zimage(char *image, unsigned long kernel_size, build_command_line(setup_base + COMMAND_LINE_OFFSET, auto_boot); printf("Loading %czImage at address 0x%08x (%ld bytes)\n", big_image ? 'b' : ' ', - (u32)load_address, kernel_size - setup_size); + (u32)load_address, kernel_size); - memmove(load_address, image + setup_size, kernel_size - setup_size); + memmove(load_address, image + setup_size, kernel_size); /* ready for booting */ return setup_base; @@ -218,8 +238,51 @@ void boot_zimage(void *setup_base) memset(®s, 0, sizeof(struct pt_regs)); regs.xds = (u32)setup_base >> 4; - regs.xss = 0x9000; + regs.xes = regs.xds; + regs.xss = regs.xds; regs.esp = 0x9000; regs.eflags = 0; enter_realmode(((u32)setup_base+SETUP_START_OFFSET)>>4, 0, ®s, ®s); } + +int do_zboot (cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + void *base_ptr; + void *bzImage_addr; + ulong bzImage_size = 0; + + disable_interrupts(); + + /* Setup board for maximum PC/AT Compatibility */ + setup_pcat_compatibility(); + + /* argv[1] holds the address of the bzImage */ + bzImage_addr = (void *)simple_strtoul(argv[1], NULL, 16); + + if (argc == 3) + bzImage_size = simple_strtoul(argv[2], NULL, 16); + + /* Lets look for*/ + base_ptr = load_zimage (bzImage_addr, bzImage_size, 0, 0, 0); + + if (NULL == base_ptr) { + printf ("## Kernel loading failed ...\n"); + } else { + printf ("## Transferring control to Linux (at address %08x) ...\n", + (u32)base_ptr); + + /* we assume that the kernel is in place */ + printf("\nStarting kernel ...\n\n"); + + boot_zimage(base_ptr); + /* does not return */ + } + + return -1; +} + +U_BOOT_CMD( + zboot, 3, 0, do_zboot, + "Boot bzImage", + "" +); |