summaryrefslogtreecommitdiff
path: root/arch/i386
diff options
context:
space:
mode:
Diffstat (limited to 'arch/i386')
-rw-r--r--arch/i386/cpu/Makefile2
-rw-r--r--arch/i386/cpu/interrupts.c214
-rw-r--r--arch/i386/cpu/sc520/sc520.c33
-rw-r--r--arch/i386/cpu/sc520/sc520_asm.S214
-rw-r--r--arch/i386/cpu/sc520/sc520_pci.c63
-rw-r--r--arch/i386/cpu/sc520/sc520_ssi.c27
-rw-r--r--arch/i386/cpu/sc520/sc520_timer.c35
-rw-r--r--arch/i386/cpu/serial.c506
-rw-r--r--arch/i386/cpu/start.S137
-rw-r--r--arch/i386/cpu/start16.S29
-rw-r--r--arch/i386/include/asm/bootparam.h120
-rw-r--r--arch/i386/include/asm/e820.h155
-rw-r--r--arch/i386/include/asm/ic/pci.h30
-rw-r--r--arch/i386/include/asm/ic/sc520.h30
-rw-r--r--arch/i386/include/asm/ioctl.h1
-rw-r--r--arch/i386/include/asm/ist.h34
-rw-r--r--arch/i386/include/asm/u-boot-i386.h2
-rw-r--r--arch/i386/include/asm/unaligned.h1
-rw-r--r--arch/i386/include/asm/video/edid.h16
-rw-r--r--arch/i386/lib/bios_setup.c2
-rw-r--r--arch/i386/lib/board.c85
-rw-r--r--arch/i386/lib/realmode.c2
-rw-r--r--arch/i386/lib/zimage.c127
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(&regs, 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, &regs, &regs);
}
+
+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",
+ ""
+);