summaryrefslogtreecommitdiffstats
path: root/arch/x86
diff options
context:
space:
mode:
authorGraeme Russ <graeme.russ@gmail.com>2011-04-13 19:43:28 +1000
committerGraeme Russ <graeme.russ@gmail.com>2011-04-13 19:43:28 +1000
commitfea25720013f84427a0ba8833a38614fcaf488ba (patch)
tree59399e99054261e245a1f2f2dbb478adad1d49ab /arch/x86
parentdbf7115a326fa70ac3e4ca87497c7e21c6642b45 (diff)
downloadblackbird-obmc-uboot-fea25720013f84427a0ba8833a38614fcaf488ba.tar.gz
blackbird-obmc-uboot-fea25720013f84427a0ba8833a38614fcaf488ba.zip
x86: Rename i386 to x86
Signed-off-by: Graeme Russ <graeme.russ@gmail.com>
Diffstat (limited to 'arch/x86')
-rw-r--r--arch/x86/config.mk42
-rw-r--r--arch/x86/cpu/Makefile50
-rw-r--r--arch/x86/cpu/config.mk32
-rw-r--r--arch/x86/cpu/cpu.c157
-rw-r--r--arch/x86/cpu/interrupts.c674
-rw-r--r--arch/x86/cpu/resetvec.S38
-rw-r--r--arch/x86/cpu/sc520/Makefile57
-rw-r--r--arch/x86/cpu/sc520/sc520.c77
-rw-r--r--arch/x86/cpu/sc520/sc520_car.S93
-rw-r--r--arch/x86/cpu/sc520/sc520_pci.c140
-rw-r--r--arch/x86/cpu/sc520/sc520_sdram.c532
-rw-r--r--arch/x86/cpu/sc520/sc520_ssi.c92
-rw-r--r--arch/x86/cpu/sc520/sc520_timer.c90
-rw-r--r--arch/x86/cpu/start.S132
-rw-r--r--arch/x86/cpu/start16.S113
-rw-r--r--arch/x86/cpu/u-boot.lds97
-rw-r--r--arch/x86/include/asm/bitops.h384
-rw-r--r--arch/x86/include/asm/bootparam.h120
-rw-r--r--arch/x86/include/asm/byteorder.h43
-rw-r--r--arch/x86/include/asm/config.h24
-rw-r--r--arch/x86/include/asm/e820.h155
-rw-r--r--arch/x86/include/asm/errno.h1
-rw-r--r--arch/x86/include/asm/global_data.h102
-rw-r--r--arch/x86/include/asm/i8254.h55
-rw-r--r--arch/x86/include/asm/i8259.h88
-rw-r--r--arch/x86/include/asm/ibmpc.h47
-rw-r--r--arch/x86/include/asm/ic/pci.h79
-rw-r--r--arch/x86/include/asm/ic/sc520.h398
-rw-r--r--arch/x86/include/asm/ic/ssi.h34
-rw-r--r--arch/x86/include/asm/interrupt.h46
-rw-r--r--arch/x86/include/asm/io.h237
-rw-r--r--arch/x86/include/asm/ioctl.h1
-rw-r--r--arch/x86/include/asm/ist.h34
-rw-r--r--arch/x86/include/asm/pci.h34
-rw-r--r--arch/x86/include/asm/posix_types.h80
-rw-r--r--arch/x86/include/asm/processor-flags.h100
-rw-r--r--arch/x86/include/asm/processor.h32
-rw-r--r--arch/x86/include/asm/ptrace.h90
-rw-r--r--arch/x86/include/asm/realmode.h32
-rw-r--r--arch/x86/include/asm/string.h32
-rw-r--r--arch/x86/include/asm/types.h53
-rw-r--r--arch/x86/include/asm/u-boot-x86.h59
-rw-r--r--arch/x86/include/asm/u-boot.h61
-rw-r--r--arch/x86/include/asm/unaligned.h1
-rw-r--r--arch/x86/include/asm/video/edid.h16
-rw-r--r--arch/x86/include/asm/zimage.h74
-rw-r--r--arch/x86/lib/Makefile59
-rw-r--r--arch/x86/lib/bios.S531
-rw-r--r--arch/x86/lib/bios.h92
-rw-r--r--arch/x86/lib/bios_pci.S413
-rw-r--r--arch/x86/lib/bios_setup.c241
-rw-r--r--arch/x86/lib/board.c480
-rw-r--r--arch/x86/lib/bootm.c97
-rw-r--r--arch/x86/lib/interrupts.c161
-rw-r--r--arch/x86/lib/pcat_interrupts.c132
-rw-r--r--arch/x86/lib/pcat_timer.c107
-rw-r--r--arch/x86/lib/pci.c150
-rw-r--r--arch/x86/lib/pci_type1.c66
-rw-r--r--arch/x86/lib/realmode.c96
-rw-r--r--arch/x86/lib/realmode_switch.S221
-rw-r--r--arch/x86/lib/timer.c110
-rw-r--r--arch/x86/lib/video.c229
-rw-r--r--arch/x86/lib/video_bios.c222
-rw-r--r--arch/x86/lib/zimage.c296
64 files changed, 8631 insertions, 0 deletions
diff --git a/arch/x86/config.mk b/arch/x86/config.mk
new file mode 100644
index 0000000000..e9452012a6
--- /dev/null
+++ b/arch/x86/config.mk
@@ -0,0 +1,42 @@
+#
+# (C) Copyright 2000-2002
+# 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
+#
+
+CONFIG_STANDALONE_LOAD_ADDR ?= 0x40000
+
+PLATFORM_CPPFLAGS += -fno-strict-aliasing
+PLATFORM_CPPFLAGS += -Wstrict-prototypes
+PLATFORM_CPPFLAGS += -mregparm=3
+PLATFORM_CPPFLAGS += -fomit-frame-pointer
+PLATFORM_CPPFLAGS += $(call cc-option, -ffreestanding)
+PLATFORM_CPPFLAGS += $(call cc-option, -fno-toplevel-reorder, $(call cc-option, -fno-unit-at-a-time))
+PLATFORM_CPPFLAGS += $(call cc-option, -fno-stack-protector)
+PLATFORM_CPPFLAGS += $(call cc-option, -mpreferred-stack-boundary=2)
+PLATFORM_CPPFLAGS += -fno-dwarf2-cfi-asm
+PLATFORM_CPPFLAGS += -DREALMODE_BASE=0x7c0
+
+PLATFORM_RELFLAGS += -ffunction-sections -fvisibility=hidden
+
+PLATFORM_LDFLAGS += --emit-relocs -Bsymbolic -Bsymbolic-functions
+
+LDFLAGS_FINAL += --gc-sections -pie
+LDSCRIPT := $(SRCTREE)/$(CPUDIR)/u-boot.lds
diff --git a/arch/x86/cpu/Makefile b/arch/x86/cpu/Makefile
new file mode 100644
index 0000000000..ddde83c91d
--- /dev/null
+++ b/arch/x86/cpu/Makefile
@@ -0,0 +1,50 @@
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2002
+# Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(CPU).o
+
+START = start.o start16.o resetvec.o
+COBJS = interrupts.o cpu.o
+
+SRCS := $(START:.o=.S) $(SOBJS:.o=.S) $(COBJS:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS) $(COBJS))
+START := $(addprefix $(obj),$(START))
+
+all: $(obj).depend $(START) $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/x86/cpu/config.mk b/arch/x86/cpu/config.mk
new file mode 100644
index 0000000000..d1b528a437
--- /dev/null
+++ b/arch/x86/cpu/config.mk
@@ -0,0 +1,32 @@
+#
+# (C) Copyright 2002
+# Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+#
+# 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
+#
+
+CROSS_COMPILE ?= i386-linux-
+
+PLATFORM_CPPFLAGS += -DCONFIG_X86 -D__I386__ -march=i386 -Werror
+
+# DO NOT MODIFY THE FOLLOWING UNLESS YOU REALLY KNOW WHAT YOU ARE DOING!
+LDPPFLAGS += -DRESET_SEG_START=0xffff0000
+LDPPFLAGS += -DRESET_SEG_SIZE=0x10000
+LDPPFLAGS += -DRESET_VEC_LOC=0xfff0
+LDPPFLAGS += -DSTART_16=0xf800
diff --git a/arch/x86/cpu/cpu.c b/arch/x86/cpu/cpu.c
new file mode 100644
index 0000000000..0c5d7c3d53
--- /dev/null
+++ b/arch/x86/cpu/cpu.c
@@ -0,0 +1,157 @@
+/*
+ * (C) Copyright 2008-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.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
+ */
+
+#include <common.h>
+#include <command.h>
+#include <asm/processor.h>
+#include <asm/processor-flags.h>
+#include <asm/interrupt.h>
+
+/*
+ * Constructor for a conventional segment GDT (or LDT) entry
+ * This is a macro so it can be used in initialisers
+ */
+#define GDT_ENTRY(flags, base, limit) \
+ ((((base) & 0xff000000ULL) << (56-24)) | \
+ (((flags) & 0x0000f0ffULL) << 40) | \
+ (((limit) & 0x000f0000ULL) << (48-16)) | \
+ (((base) & 0x00ffffffULL) << 16) | \
+ (((limit) & 0x0000ffffULL)))
+
+struct gdt_ptr {
+ u16 len;
+ u32 ptr;
+} __attribute__((packed));
+
+static void reload_gdt(void)
+{
+ /*
+ * There are machines which are known to not boot with the GDT
+ * being 8-byte unaligned. Intel recommends 16 byte alignment
+ */
+ static const u64 boot_gdt[] __attribute__((aligned(16))) = {
+ /* CS: code, read/execute, 4 GB, base 0 */
+ [GDT_ENTRY_32BIT_CS] = GDT_ENTRY(0xc09b, 0, 0xfffff),
+ /* DS: data, read/write, 4 GB, base 0 */
+ [GDT_ENTRY_32BIT_DS] = GDT_ENTRY(0xc093, 0, 0xfffff),
+ /* 16-bit CS: code, read/execute, 64 kB, base 0 */
+ [GDT_ENTRY_16BIT_CS] = GDT_ENTRY(0x109b, 0, 0x0ffff),
+ /* 16-bit DS: data, read/write, 64 kB, base 0 */
+ [GDT_ENTRY_16BIT_DS] = GDT_ENTRY(0x1093, 0, 0x0ffff),
+ };
+ static struct gdt_ptr gdt;
+
+ gdt.len = sizeof(boot_gdt)-1;
+ gdt.ptr = (u32)&boot_gdt;
+
+ asm volatile("lgdtl %0\n" \
+ "movl $((2+1)*8), %%ecx\n" \
+ "movl %%ecx, %%ds\n" \
+ "movl %%ecx, %%es\n" \
+ "movl %%ecx, %%fs\n" \
+ "movl %%ecx, %%gs\n" \
+ "movl %%ecx, %%ss" \
+ : : "m" (gdt) : "ecx");
+}
+
+int x86_cpu_init_f(void)
+{
+ const u32 em_rst = ~X86_CR0_EM;
+ const u32 mp_ne_set = X86_CR0_MP | X86_CR0_NE;
+
+ /* initialize FPU, reset EM, set MP and NE */
+ asm ("fninit\n" \
+ "movl %%cr0, %%eax\n" \
+ "andl %0, %%eax\n" \
+ "orl %1, %%eax\n" \
+ "movl %%eax, %%cr0\n" \
+ : : "i" (em_rst), "i" (mp_ne_set) : "eax");
+
+ return 0;
+}
+int cpu_init_f(void) __attribute__((weak, alias("x86_cpu_init_f")));
+
+int x86_cpu_init_r(void)
+{
+ const u32 nw_cd_rst = ~(X86_CR0_NW | X86_CR0_CD);
+
+ /* turn on the cache and disable write through */
+ asm("movl %%cr0, %%eax\n"
+ "andl %0, %%eax\n"
+ "movl %%eax, %%cr0\n"
+ "wbinvd\n" : : "i" (nw_cd_rst) : "eax");
+
+ reload_gdt();
+
+ /* Initialize core interrupt and exception functionality of CPU */
+ cpu_init_interrupts ();
+ return 0;
+}
+int cpu_init_r(void) __attribute__((weak, alias("x86_cpu_init_r")));
+
+int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ printf ("resetting ...\n");
+
+ /* wait 50 ms */
+ udelay(50000);
+ disable_interrupts();
+ reset_cpu(0);
+
+ /*NOTREACHED*/
+ return 0;
+}
+
+void flush_cache (unsigned long dummy1, unsigned long dummy2)
+{
+ asm("wbinvd\n");
+}
+
+void __attribute__ ((regparm(0))) generate_gpf(void);
+
+/* segment 0x70 is an arbitrary segment which does not exist */
+asm(".globl generate_gpf\n"
+ ".hidden generate_gpf\n"
+ ".type generate_gpf, @function\n"
+ "generate_gpf:\n"
+ "ljmp $0x70, $0x47114711\n");
+
+void __reset_cpu(ulong addr)
+{
+ printf("Resetting using x86 Triple Fault\n");
+ set_vector(13, generate_gpf); /* general protection fault handler */
+ set_vector(8, generate_gpf); /* double fault handler */
+ generate_gpf(); /* start the show */
+}
+void reset_cpu(ulong addr) __attribute__((weak, alias("__reset_cpu")));
diff --git a/arch/x86/cpu/interrupts.c b/arch/x86/cpu/interrupts.c
new file mode 100644
index 0000000000..62bcadc486
--- /dev/null
+++ b/arch/x86/cpu/interrupts.c
@@ -0,0 +1,674 @@
+/*
+ * (C) Copyright 2008-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (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.
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/interrupt.h>
+#include <asm/io.h>
+#include <asm/processor-flags.h>
+
+#define DECLARE_INTERRUPT(x) \
+ ".globl irq_"#x"\n" \
+ ".hidden irq_"#x"\n" \
+ ".type irq_"#x", @function\n" \
+ "irq_"#x":\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 serialisation
+ */
+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 irq_regs *regs)
+{
+ unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L;
+ unsigned long d0, d1, d2, d3, d6, d7;
+ unsigned long sp;
+
+ 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);
+
+ printf("Stack:\n");
+ sp = regs->esp;
+
+ sp += 64;
+
+ while (sp > (regs->esp - 16)) {
+ if (sp == regs->esp)
+ printf("--->");
+ else
+ printf(" ");
+ printf("0x%8.8lx : 0x%8.8lx\n", sp, (ulong)readl(sp));
+ sp -= 4;
+ }
+}
+
+struct idt_entry {
+ u16 base_low;
+ u16 selector;
+ u8 res;
+ u8 access;
+ u16 base_high;
+} __attribute__ ((packed));
+
+struct desc_ptr {
+ unsigned short size;
+ unsigned long address;
+ unsigned short segment;
+} __attribute__((packed));
+
+struct idt_entry idt[256];
+
+struct desc_ptr idt_ptr;
+
+static inline void load_idt(const struct desc_ptr *dtr)
+{
+ asm volatile("cs lidt %0"::"m" (*dtr));
+}
+
+void set_vector(u8 intnum, void *routine)
+{
+ idt[intnum].base_high = (u16)((u32)(routine) >> 16);
+ idt[intnum].base_low = (u16)((u32)(routine) & 0xffff);
+}
+
+void irq_0(void);
+void irq_1(void);
+
+int cpu_init_interrupts(void)
+{
+ int i;
+
+ int irq_entry_size = irq_1 - irq_0;
+ void *irq_entry = (void *)irq_0;
+
+ /* Just in case... */
+ disable_interrupts();
+
+ /* Setup the IDT */
+ for (i=0;i<256;i++) {
+ idt[i].access = 0x8e;
+ idt[i].res = 0;
+ idt[i].selector = 0x10;
+ set_vector(i, irq_entry);
+ irq_entry += irq_entry_size;
+ }
+
+ idt_ptr.size = 256 * 8;
+ idt_ptr.address = (unsigned long) idt;
+ idt_ptr.segment = 0x18;
+
+ load_idt(&idt_ptr);
+
+ /* It is now safe to enable interrupts */
+ enable_interrupts();
+
+ return 0;
+}
+
+void __do_irq(int irq)
+{
+ printf("Unhandled IRQ : %d\n", irq);
+}
+void do_irq(int irq) __attribute__((weak, alias("__do_irq")));
+
+void enable_interrupts(void)
+{
+ asm("sti\n");
+}
+
+int disable_interrupts(void)
+{
+ long flags;
+
+ asm volatile ("pushfl ; popl %0 ; cli\n" : "=g" (flags) : );
+
+ return flags & X86_EFLAGS_IF; /* IE flags is bit 9 */
+}
+
+/* IRQ Low-Level Service Routine */
+void irq_llsr(struct irq_regs *regs)
+{
+ /*
+ * For detailed description of each exception, refer to:
+ * Intel® 64 and IA-32 Architectures Software Developer's Manual
+ * Volume 1: Basic Architecture
+ * Order Number: 253665-029US, November 2008
+ * Table 6-1. Exceptions and Interrupts
+ */
+ switch (regs->irq_id) {
+ case 0x00:
+ printf("Divide Error (Division by zero)\n");
+ dump_regs(regs);
+ while(1);
+ break;
+ case 0x01:
+ printf("Debug Interrupt (Single step)\n");
+ dump_regs(regs);
+ break;
+ case 0x02:
+ printf("NMI Interrupt\n");
+ dump_regs(regs);
+ break;
+ case 0x03:
+ printf("Breakpoint\n");
+ dump_regs(regs);
+ break;
+ case 0x04:
+ printf("Overflow\n");
+ dump_regs(regs);
+ while(1);
+ break;
+ case 0x05:
+ printf("BOUND Range Exceeded\n");
+ dump_regs(regs);
+ while(1);
+ break;
+ case 0x06:
+ printf("Invalid Opcode (UnDefined Opcode)\n");
+ dump_regs(regs);
+ while(1);
+ break;
+ case 0x07:
+ printf("Device Not Available (No Math Coprocessor)\n");
+ dump_regs(regs);
+ while(1);
+ break;
+ case 0x08:
+ printf("Double fault\n");
+ dump_regs(regs);
+ while(1);
+ break;
+ case 0x09:
+ printf("Co-processor segment overrun\n");
+ dump_regs(regs);
+ while(1);
+ break;
+ case 0x0a:
+ printf("Invalid TSS\n");
+ dump_regs(regs);
+ break;
+ case 0x0b:
+ printf("Segment Not Present\n");
+ dump_regs(regs);
+ while(1);
+ break;
+ case 0x0c:
+ printf("Stack Segment Fault\n");
+ dump_regs(regs);
+ while(1);
+ break;
+ case 0x0d:
+ printf("General Protection\n");
+ dump_regs(regs);
+ break;
+ case 0x0e:
+ printf("Page fault\n");
+ dump_regs(regs);
+ while(1);
+ break;
+ case 0x0f:
+ printf("Floating-Point Error (Math Fault)\n");
+ dump_regs(regs);
+ break;
+ case 0x10:
+ printf("Alignment check\n");
+ dump_regs(regs);
+ break;
+ case 0x11:
+ printf("Machine Check\n");
+ dump_regs(regs);
+ break;
+ case 0x12:
+ printf("SIMD Floating-Point Exception\n");
+ dump_regs(regs);
+ break;
+ case 0x13:
+ case 0x14:
+ case 0x15:
+ case 0x16:
+ case 0x17:
+ case 0x18:
+ case 0x19:
+ case 0x1a:
+ case 0x1b:
+ case 0x1c:
+ case 0x1d:
+ case 0x1e:
+ case 0x1f:
+ printf("Reserved Exception\n");
+ dump_regs(regs);
+ break;
+
+ default:
+ /* Hardware or User IRQ */
+ do_irq(regs->irq_id);
+ }
+}
+
+/*
+ * OK - This looks really horrible, but it serves a purpose - It helps create
+ * fully relocatable code.
+ * - The call to irq_llsr will be a relative jump
+ * - The IRQ entries will be guaranteed to be in order
+ * 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
+ *
+ * Interrupt Entry Point:
+ * - Interrupt has caused eflags, CS and EIP to be pushed
+ * - Interrupt Vector Handler has pushed orig_eax
+ * - pt_regs.esp needs to be adjusted by 40 bytes:
+ * 12 bytes pushed by CPU (EFLAGSF, CS, EIP)
+ * 4 bytes pushed by vector handler (irq_id)
+ * 24 bytes pushed before SP (SS, GS, FS, ES, DS, EAX)
+ * NOTE: Only longs are pushed on/popped off the stack!
+ */
+asm(".globl irq_common_entry\n" \
+ ".hidden irq_common_entry\n" \
+ ".type irq_common_entry, @function\n" \
+ "irq_common_entry:\n" \
+ "cld\n" \
+ "pushl %ss\n" \
+ "pushl %gs\n" \
+ "pushl %fs\n" \
+ "pushl %es\n" \
+ "pushl %ds\n" \
+ "pushl %eax\n" \
+ "movl %esp, %eax\n" \
+ "addl $40, %eax\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" \
+ "call irq_llsr\n" \
+ "popl %ebx\n" \
+ "popl %ecx\n" \
+ "popl %edx\n" \
+ "popl %esi\n" \
+ "popl %edi\n" \
+ "popl %ebp\n" \
+ "popl %eax\n" \
+ "popl %eax\n" \
+ "popl %ds\n" \
+ "popl %es\n" \
+ "popl %fs\n" \
+ "popl %gs\n" \
+ "popl %ss\n" \
+ "add $4, %esp\n" \
+ "iret\n" \
+ DECLARE_INTERRUPT(0) \
+ DECLARE_INTERRUPT(1) \
+ DECLARE_INTERRUPT(2) \
+ DECLARE_INTERRUPT(3) \
+ DECLARE_INTERRUPT(4) \
+ DECLARE_INTERRUPT(5) \
+ DECLARE_INTERRUPT(6) \
+ DECLARE_INTERRUPT(7) \
+ DECLARE_INTERRUPT(8) \
+ DECLARE_INTERRUPT(9) \
+ DECLARE_INTERRUPT(10) \
+ DECLARE_INTERRUPT(11) \
+ DECLARE_INTERRUPT(12) \
+ DECLARE_INTERRUPT(13) \
+ DECLARE_INTERRUPT(14) \
+ DECLARE_INTERRUPT(15) \
+ DECLARE_INTERRUPT(16) \
+ DECLARE_INTERRUPT(17) \
+ DECLARE_INTERRUPT(18) \
+ DECLARE_INTERRUPT(19) \
+ DECLARE_INTERRUPT(20) \
+ DECLARE_INTERRUPT(21) \
+ DECLARE_INTERRUPT(22) \
+ DECLARE_INTERRUPT(23) \
+ DECLARE_INTERRUPT(24) \
+ DECLARE_INTERRUPT(25) \
+ DECLARE_INTERRUPT(26) \
+ DECLARE_INTERRUPT(27) \
+ DECLARE_INTERRUPT(28) \
+ DECLARE_INTERRUPT(29) \
+ DECLARE_INTERRUPT(30) \
+ DECLARE_INTERRUPT(31) \
+ DECLARE_INTERRUPT(32) \
+ DECLARE_INTERRUPT(33) \
+ DECLARE_INTERRUPT(34) \
+ DECLARE_INTERRUPT(35) \
+ DECLARE_INTERRUPT(36) \
+ DECLARE_INTERRUPT(37) \
+ DECLARE_INTERRUPT(38) \
+ DECLARE_INTERRUPT(39) \
+ DECLARE_INTERRUPT(40) \
+ DECLARE_INTERRUPT(41) \
+ DECLARE_INTERRUPT(42) \
+ DECLARE_INTERRUPT(43) \
+ DECLARE_INTERRUPT(44) \
+ DECLARE_INTERRUPT(45) \
+ DECLARE_INTERRUPT(46) \
+ DECLARE_INTERRUPT(47) \
+ DECLARE_INTERRUPT(48) \
+ DECLARE_INTERRUPT(49) \
+ DECLARE_INTERRUPT(50) \
+ DECLARE_INTERRUPT(51) \
+ DECLARE_INTERRUPT(52) \
+ DECLARE_INTERRUPT(53) \
+ DECLARE_INTERRUPT(54) \
+ DECLARE_INTERRUPT(55) \
+ DECLARE_INTERRUPT(56) \
+ DECLARE_INTERRUPT(57) \
+ DECLARE_INTERRUPT(58) \
+ DECLARE_INTERRUPT(59) \
+ DECLARE_INTERRUPT(60) \
+ DECLARE_INTERRUPT(61) \
+ DECLARE_INTERRUPT(62) \
+ DECLARE_INTERRUPT(63) \
+ DECLARE_INTERRUPT(64) \
+ DECLARE_INTERRUPT(65) \
+ DECLARE_INTERRUPT(66) \
+ DECLARE_INTERRUPT(67) \
+ DECLARE_INTERRUPT(68) \
+ DECLARE_INTERRUPT(69) \
+ DECLARE_INTERRUPT(70) \
+ DECLARE_INTERRUPT(71) \
+ DECLARE_INTERRUPT(72) \
+ DECLARE_INTERRUPT(73) \
+ DECLARE_INTERRUPT(74) \
+ DECLARE_INTERRUPT(75) \
+ DECLARE_INTERRUPT(76) \
+ DECLARE_INTERRUPT(77) \
+ DECLARE_INTERRUPT(78) \
+ DECLARE_INTERRUPT(79) \
+ DECLARE_INTERRUPT(80) \
+ DECLARE_INTERRUPT(81) \
+ DECLARE_INTERRUPT(82) \
+ DECLARE_INTERRUPT(83) \
+ DECLARE_INTERRUPT(84) \
+ DECLARE_INTERRUPT(85) \
+ DECLARE_INTERRUPT(86) \
+ DECLARE_INTERRUPT(87) \
+ DECLARE_INTERRUPT(88) \
+ DECLARE_INTERRUPT(89) \
+ DECLARE_INTERRUPT(90) \
+ DECLARE_INTERRUPT(91) \
+ DECLARE_INTERRUPT(92) \
+ DECLARE_INTERRUPT(93) \
+ DECLARE_INTERRUPT(94) \
+ DECLARE_INTERRUPT(95) \
+ DECLARE_INTERRUPT(97) \
+ DECLARE_INTERRUPT(96) \
+ DECLARE_INTERRUPT(98) \
+ DECLARE_INTERRUPT(99) \
+ DECLARE_INTERRUPT(100) \
+ DECLARE_INTERRUPT(101) \
+ DECLARE_INTERRUPT(102) \
+ DECLARE_INTERRUPT(103) \
+ DECLARE_INTERRUPT(104) \
+ DECLARE_INTERRUPT(105) \
+ DECLARE_INTERRUPT(106) \
+ DECLARE_INTERRUPT(107) \
+ DECLARE_INTERRUPT(108) \
+ DECLARE_INTERRUPT(109) \
+ DECLARE_INTERRUPT(110) \
+ DECLARE_INTERRUPT(111) \
+ DECLARE_INTERRUPT(112) \
+ DECLARE_INTERRUPT(113) \
+ DECLARE_INTERRUPT(114) \
+ DECLARE_INTERRUPT(115) \
+ DECLARE_INTERRUPT(116) \
+ DECLARE_INTERRUPT(117) \
+ DECLARE_INTERRUPT(118) \
+ DECLARE_INTERRUPT(119) \
+ DECLARE_INTERRUPT(120) \
+ DECLARE_INTERRUPT(121) \
+ DECLARE_INTERRUPT(122) \
+ DECLARE_INTERRUPT(123) \
+ DECLARE_INTERRUPT(124) \
+ DECLARE_INTERRUPT(125) \
+ DECLARE_INTERRUPT(126) \
+ DECLARE_INTERRUPT(127) \
+ DECLARE_INTERRUPT(128) \
+ DECLARE_INTERRUPT(129) \
+ DECLARE_INTERRUPT(130) \
+ DECLARE_INTERRUPT(131) \
+ DECLARE_INTERRUPT(132) \
+ DECLARE_INTERRUPT(133) \
+ DECLARE_INTERRUPT(134) \
+ DECLARE_INTERRUPT(135) \
+ DECLARE_INTERRUPT(136) \
+ DECLARE_INTERRUPT(137) \
+ DECLARE_INTERRUPT(138) \
+ DECLARE_INTERRUPT(139) \
+ DECLARE_INTERRUPT(140) \
+ DECLARE_INTERRUPT(141) \
+ DECLARE_INTERRUPT(142) \
+ DECLARE_INTERRUPT(143) \
+ DECLARE_INTERRUPT(144) \
+ DECLARE_INTERRUPT(145) \
+ DECLARE_INTERRUPT(146) \
+ DECLARE_INTERRUPT(147) \
+ DECLARE_INTERRUPT(148) \
+ DECLARE_INTERRUPT(149) \
+ DECLARE_INTERRUPT(150) \
+ DECLARE_INTERRUPT(151) \
+ DECLARE_INTERRUPT(152) \
+ DECLARE_INTERRUPT(153) \
+ DECLARE_INTERRUPT(154) \
+ DECLARE_INTERRUPT(155) \
+ DECLARE_INTERRUPT(156) \
+ DECLARE_INTERRUPT(157) \
+ DECLARE_INTERRUPT(158) \
+ DECLARE_INTERRUPT(159) \
+ DECLARE_INTERRUPT(160) \
+ DECLARE_INTERRUPT(161) \
+ DECLARE_INTERRUPT(162) \
+ DECLARE_INTERRUPT(163) \
+ DECLARE_INTERRUPT(164) \
+ DECLARE_INTERRUPT(165) \
+ DECLARE_INTERRUPT(166) \
+ DECLARE_INTERRUPT(167) \
+ DECLARE_INTERRUPT(168) \
+ DECLARE_INTERRUPT(169) \
+ DECLARE_INTERRUPT(170) \
+ DECLARE_INTERRUPT(171) \
+ DECLARE_INTERRUPT(172) \
+ DECLARE_INTERRUPT(173) \
+ DECLARE_INTERRUPT(174) \
+ DECLARE_INTERRUPT(175) \
+ DECLARE_INTERRUPT(176) \
+ DECLARE_INTERRUPT(177) \
+ DECLARE_INTERRUPT(178) \
+ DECLARE_INTERRUPT(179) \
+ DECLARE_INTERRUPT(180) \
+ DECLARE_INTERRUPT(181) \
+ DECLARE_INTERRUPT(182) \
+ DECLARE_INTERRUPT(183) \
+ DECLARE_INTERRUPT(184) \
+ DECLARE_INTERRUPT(185) \
+ DECLARE_INTERRUPT(186) \
+ DECLARE_INTERRUPT(187) \
+ DECLARE_INTERRUPT(188) \
+ DECLARE_INTERRUPT(189) \
+ DECLARE_INTERRUPT(190) \
+ DECLARE_INTERRUPT(191) \
+ DECLARE_INTERRUPT(192) \
+ DECLARE_INTERRUPT(193) \
+ DECLARE_INTERRUPT(194) \
+ DECLARE_INTERRUPT(195) \
+ DECLARE_INTERRUPT(196) \
+ DECLARE_INTERRUPT(197) \
+ DECLARE_INTERRUPT(198) \
+ DECLARE_INTERRUPT(199) \
+ DECLARE_INTERRUPT(200) \
+ DECLARE_INTERRUPT(201) \
+ DECLARE_INTERRUPT(202) \
+ DECLARE_INTERRUPT(203) \
+ DECLARE_INTERRUPT(204) \
+ DECLARE_INTERRUPT(205) \
+ DECLARE_INTERRUPT(206) \
+ DECLARE_INTERRUPT(207) \
+ DECLARE_INTERRUPT(208) \
+ DECLARE_INTERRUPT(209) \
+ DECLARE_INTERRUPT(210) \
+ DECLARE_INTERRUPT(211) \
+ DECLARE_INTERRUPT(212) \
+ DECLARE_INTERRUPT(213) \
+ DECLARE_INTERRUPT(214) \
+ DECLARE_INTERRUPT(215) \
+ DECLARE_INTERRUPT(216) \
+ DECLARE_INTERRUPT(217) \
+ DECLARE_INTERRUPT(218) \
+ DECLARE_INTERRUPT(219) \
+ DECLARE_INTERRUPT(220) \
+ DECLARE_INTERRUPT(221) \
+ DECLARE_INTERRUPT(222) \
+ DECLARE_INTERRUPT(223) \
+ DECLARE_INTERRUPT(224) \
+ DECLARE_INTERRUPT(225) \
+ DECLARE_INTERRUPT(226) \
+ DECLARE_INTERRUPT(227) \
+ DECLARE_INTERRUPT(228) \
+ DECLARE_INTERRUPT(229) \
+ DECLARE_INTERRUPT(230) \
+ DECLARE_INTERRUPT(231) \
+ DECLARE_INTERRUPT(232) \
+ DECLARE_INTERRUPT(233) \
+ DECLARE_INTERRUPT(234) \
+ DECLARE_INTERRUPT(235) \
+ DECLARE_INTERRUPT(236) \
+ DECLARE_INTERRUPT(237) \
+ DECLARE_INTERRUPT(238) \
+ DECLARE_INTERRUPT(239) \
+ DECLARE_INTERRUPT(240) \
+ DECLARE_INTERRUPT(241) \
+ DECLARE_INTERRUPT(242) \
+ DECLARE_INTERRUPT(243) \
+ DECLARE_INTERRUPT(244) \
+ DECLARE_INTERRUPT(245) \
+ DECLARE_INTERRUPT(246) \
+ DECLARE_INTERRUPT(247) \
+ DECLARE_INTERRUPT(248) \
+ DECLARE_INTERRUPT(249) \
+ DECLARE_INTERRUPT(250) \
+ DECLARE_INTERRUPT(251) \
+ DECLARE_INTERRUPT(252) \
+ DECLARE_INTERRUPT(253) \
+ DECLARE_INTERRUPT(254) \
+ DECLARE_INTERRUPT(255));
diff --git a/arch/x86/cpu/resetvec.S b/arch/x86/cpu/resetvec.S
new file mode 100644
index 0000000000..c690d2516e
--- /dev/null
+++ b/arch/x86/cpu/resetvec.S
@@ -0,0 +1,38 @@
+/*
+ * U-boot - x86 Startup Code
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+/* Reset vector, jumps to start16.S */
+
+.extern start16
+
+.section .resetvec, "ax"
+.code16
+reset_vector:
+ cli
+ cld
+ jmp start16
+
+ .org 0xf
+ nop
diff --git a/arch/x86/cpu/sc520/Makefile b/arch/x86/cpu/sc520/Makefile
new file mode 100644
index 0000000000..54260b6107
--- /dev/null
+++ b/arch/x86/cpu/sc520/Makefile
@@ -0,0 +1,57 @@
+#
+# (C) Copyright 2008
+# Graeme Russ, graeme.russ@gmail.com.
+#
+# (C) Copyright 2006
+# Wolfgang Denk, DENX Software Engineering, wd@denx.de.
+#
+# (C) Copyright 2002
+# Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+#
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB := $(obj)lib$(SOC).o
+
+COBJS-$(CONFIG_SYS_SC520) += sc520.o
+COBJS-$(CONFIG_PCI) += sc520_pci.o
+COBJS-$(CONFIG_SYS_SC520) += sc520_sdram.o
+COBJS-$(CONFIG_SYS_SC520_SSI) += sc520_ssi.o
+COBJS-$(CONFIG_SYS_SC520_TIMER) += sc520_timer.o
+
+SOBJS-$(CONFIG_SYS_SC520) += sc520_car.o
+
+SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+all: $(obj).depend $(LIB)
+
+$(LIB): $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+######################################################################### \ No newline at end of file
diff --git a/arch/x86/cpu/sc520/sc520.c b/arch/x86/cpu/sc520/sc520.c
new file mode 100644
index 0000000000..edc1a5c0f2
--- /dev/null
+++ b/arch/x86/cpu/sc520/sc520.c
@@ -0,0 +1,77 @@
+/*
+ * (C) Copyright 2008-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/processor-flags.h>
+#include <asm/ic/sc520.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+sc520_mmcr_t *sc520_mmcr = (sc520_mmcr_t *)SC520_MMCR_BASE;
+
+int cpu_init_f(void)
+{
+ if (CONFIG_SYS_SC520_HIGH_SPEED) {
+ /* set it to 133 MHz and write back */
+ writeb(0x02, &sc520_mmcr->cpuctl);
+ gd->cpu_clk = 133000000;
+ } else {
+ /* set it to 100 MHz and write back */
+ writeb(0x01, &sc520_mmcr->cpuctl);
+ gd->cpu_clk = 100000000;
+ }
+
+ /* wait at least one millisecond */
+ asm("movl $0x2000, %%ecx\n"
+ "0: pushl %%ecx\n"
+ "popl %%ecx\n"
+ "loop 0b\n": : : "ecx");
+
+ return x86_cpu_init_f();
+}
+
+int cpu_init_r(void)
+{
+ /* Disable the PAR used for CAR */
+ writel(0x0000000, &sc520_mmcr->par[2]);
+
+ /* turn on the SDRAM write buffer */
+ writeb(0x11, &sc520_mmcr->dbctl);
+
+ return x86_cpu_init_r();
+}
+
+#ifdef CONFIG_SYS_SC520_RESET
+void reset_cpu(ulong addr)
+{
+ printf("Resetting using SC520 MMCR\n");
+ /* Write a '1' to the SYS_RST of the RESCFG MMCR */
+ writeb(0x01, &sc520_mmcr->rescfg);
+
+ /* NOTREACHED */
+}
+#endif
diff --git a/arch/x86/cpu/sc520/sc520_car.S b/arch/x86/cpu/sc520/sc520_car.S
new file mode 100644
index 0000000000..a33f94f491
--- /dev/null
+++ b/arch/x86/cpu/sc520/sc520_car.S
@@ -0,0 +1,93 @@
+/*
+ * (C) Copyright 2010-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * 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
+ */
+
+#include <config.h>
+#include <asm/processor-flags.h>
+#include <asm/ic/sc520.h>
+
+.section .text
+
+.globl car_init
+car_init:
+ /*
+ * How to enable Cache-As-RAM for the AMD Elan SC520:
+ * 1. Turn off the CPU Cache (may not be strictly required)
+ * 2. Set code execution PAR (usually the BOOTCS region) to be
+ * non-cachable
+ * 3. Create a Cachable PAR Region for an area of memory which is
+ * a) NOT where the code is being executed
+ * b) NOT SDRAM (Controller not initialised yet)
+ * c) WILL response to read requests
+ * The easiest way to do this is to create a second BOOTCS
+ * PAR mappnig with an address != the PAR in step 2
+ * 4. Issue a wbinvd to invalidate the CPU cache
+ * 5. Turn on the CPU Cache
+ * 6. Read 16kB from the cached PAR region setup in step 3
+ * 7. Turn off the CPU Cache (but DO NOT issue a wbinvd)
+ *
+ * The following code uses PAR2 as the cached PAR (PAR0 and PAR1
+ * are avoided as these are the only two PARs which can be used
+ * as PCI BUS Memory regions which the board might require)
+ *
+ * The configuration of PAR2 must be set in the board configuration
+ * file as CONFIG_SYS_SC520_CAR_PAR
+ */
+
+ /* Configure Cache-As-RAM PAR */
+ movl $CONFIG_SYS_SC520_CAR_PAR, %eax
+ movl $SC520_PAR2, %edi
+ movl %eax, (%edi)
+
+ /* Trash the cache then turn it on */
+ wbinvd
+ movl %cr0, %eax
+ andl $~(X86_CR0_NW | X86_CR0_CD), %eax
+ movl %eax, %cr0
+
+ /*
+ * The cache is now enabled and empty. Map a region of memory to
+ * it by reading that region.
+ */
+ movl $CONFIG_SYS_CAR_ADDR, %esi
+ movl $CONFIG_SYS_CAR_SIZE, %ecx
+ shrl $2, %ecx /* we are reading longs */
+ cld
+ rep lodsl
+
+ /* Turn off the cache, but don't trash it */
+ movl %cr0, %eax
+ orl $(X86_CR0_NW | X86_CR0_CD), %eax
+ movl %eax, %cr0
+
+ /* Clear the CAR region */
+ xorl %eax, %eax
+ movl $CONFIG_SYS_CAR_ADDR, %edi
+ movl $CONFIG_SYS_CAR_SIZE, %ecx
+ shrl $2, %ecx /* we are writing longs */
+ rep stosl
+
+ /*
+ * Done - We should now have CONFIG_SYS_CAR_SIZE bytes of
+ * Cache-As-RAM
+ */
+ jmp car_init_ret
diff --git a/arch/x86/cpu/sc520/sc520_pci.c b/arch/x86/cpu/sc520/sc520_pci.c
new file mode 100644
index 0000000000..8cd7ffecdb
--- /dev/null
+++ b/arch/x86/cpu/sc520/sc520_pci.c
@@ -0,0 +1,140 @@
+/*
+ * (C) Copyright 2008-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+#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 {
+ u8 priority;
+ u16 level_reg;
+ u8 level_bit;
+} sc520_irq[] = {
+ { SC520_IRQ0, 0, 0x01 },
+ { SC520_IRQ1, 0, 0x02 },
+ { SC520_IRQ2, 1, 0x02 },
+ { SC520_IRQ3, 0, 0x08 },
+ { SC520_IRQ4, 0, 0x10 },
+ { SC520_IRQ5, 0, 0x20 },
+ { SC520_IRQ6, 0, 0x40 },
+ { SC520_IRQ7, 0, 0x80 },
+
+ { SC520_IRQ8, 1, 0x01 },
+ { SC520_IRQ9, 1, 0x02 },
+ { SC520_IRQ10, 1, 0x04 },
+ { SC520_IRQ11, 1, 0x08 },
+ { SC520_IRQ12, 1, 0x10 },
+ { SC520_IRQ13, 1, 0x20 },
+ { SC520_IRQ14, 1, 0x40 },
+ { SC520_IRQ15, 1, 0x80 }
+};
+
+/* The interrupt used for PCI INTA-INTD */
+int sc520_pci_ints[15] = {
+ -1, -1, -1, -1, -1, -1, -1, -1,
+ -1, -1, -1, -1, -1, -1, -1
+};
+
+/* utility function to configure a pci interrupt */
+int pci_sc520_set_irq(int pci_pin, int irq)
+{
+ int i;
+ u8 tmpb;
+ u16 tmpw;
+
+ debug("set_irq(): map INT%c to IRQ%d\n", pci_pin + 'A', irq);
+
+ if (irq < 0 || irq > 15) {
+ return -1; /* illegal irq */
+ }
+
+ if (pci_pin < 0 || pci_pin > 15) {
+ return -1; /* illegal pci int pin */
+ }
+
+ /* first disable any non-pci interrupt source that use
+ * this level */
+
+ /* PCI interrupt mapping (A through D)*/
+ for (i=0; i<=3 ;i++) {
+ 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 (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 */
+ 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 */
+ writeb(sc520_irq[irq].priority, &sc520_mmcr->pci_int_map[pci_pin]);
+ } else {
+ /* GPIRQ0-GPIRQ10 used for additional PCI INTS */
+ writeb(sc520_irq[irq].priority, &sc520_mmcr->gp_int_map[pci_pin - 4]);
+
+ /* also set the polarity in this case */
+ tmpw = readw(&sc520_mmcr->intpinpol);
+ tmpw |= (1 << (pci_pin-4));
+ writew(tmpw, &sc520_mmcr->intpinpol);
+ }
+
+ /* register the pin */
+ sc520_pci_ints[pci_pin] = irq;
+
+
+ return 0; /* OK */
+}
+
+void pci_sc520_init(struct pci_controller *hose)
+{
+ hose->first_busno = 0;
+ hose->last_busno = 0xff;
+ hose->region_count = pci_set_regions(hose);
+
+ pci_setup_type1(hose,
+ SC520_REG_ADDR,
+ SC520_REG_DATA);
+
+ pci_register_hose(hose);
+
+ hose->last_busno = pci_hose_scan(hose);
+
+ /* enable target memory acceses on host brige */
+ pci_write_config_word(0, PCI_COMMAND,
+ PCI_COMMAND_MEMORY | PCI_COMMAND_MASTER);
+}
diff --git a/arch/x86/cpu/sc520/sc520_sdram.c b/arch/x86/cpu/sc520/sc520_sdram.c
new file mode 100644
index 0000000000..f3623f53f2
--- /dev/null
+++ b/arch/x86/cpu/sc520/sc520_sdram.c
@@ -0,0 +1,532 @@
+/*
+ * (C) Copyright 2010,2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/processor-flags.h>
+#include <asm/ic/sc520.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+struct sc520_sdram_info {
+ u8 banks;
+ u8 columns;
+ u8 rows;
+ u8 size;
+};
+
+static void sc520_sizemem(void);
+static void sc520_set_dram_timing(void);
+static void sc520_set_dram_refresh_rate(void);
+static void sc520_enable_dram_refresh(void);
+static void sc520_enable_sdram(void);
+#if CONFIG_SYS_SDRAM_ECC_ENABLE
+static void sc520_enable_ecc(void)
+#endif
+
+int dram_init_f(void)
+{
+ sc520_sizemem();
+ sc520_set_dram_timing();
+ sc520_set_dram_refresh_rate();
+ sc520_enable_dram_refresh();
+ sc520_enable_sdram();
+#if CONFIG_SYS_SDRAM_ECC_ENABLE
+ sc520_enable_ecc();
+#endif
+
+ return 0;
+}
+
+static inline void sc520_dummy_write(void)
+{
+ writew(0x0000, CACHELINESZ);
+}
+static inline void sc520_issue_sdram_op_mode_select(u8 command)
+{
+ writeb(command, &sc520_mmcr->drcctl);
+ sc520_dummy_write();
+}
+
+static inline int check_long(u32 test_long)
+{
+ u8 i;
+ u8 tmp_byte = (u8)(test_long & 0x000000ff);
+
+ for (i = 1; i < 4; i++) {
+ if ((u8)((test_long >> (i * 8)) & 0x000000ff) != tmp_byte)
+ return -1;
+ }
+
+ return 0;
+}
+
+static inline int write_and_test(u32 data, u32 address)
+{
+ writel(data, address);
+ if (readl(address) == data)
+ return 0; /* Good */
+ else
+ return -1; /* Bad */
+}
+
+static void sc520_enable_sdram(void)
+{
+ u32 par_config;
+
+ /* Enable Writes, Caching and Code Execution to SDRAM */
+ par_config = readl(&sc520_mmcr->par[3]);
+ par_config &= ~(SC520_PAR_EXEC_DIS |
+ SC520_PAR_CACHE_DIS |
+ SC520_PAR_WRITE_DIS);
+ writel(par_config, &sc520_mmcr->par[3]);
+
+ par_config = readl(&sc520_mmcr->par[4]);
+ par_config &= ~(SC520_PAR_EXEC_DIS |
+ SC520_PAR_CACHE_DIS |
+ SC520_PAR_WRITE_DIS);
+ writel(par_config, &sc520_mmcr->par[4]);
+}
+
+static void sc520_set_dram_timing(void)
+{
+ u8 drctmctl = 0x00;
+
+#if defined CONFIG_SYS_SDRAM_DRCTMCTL
+ /* just have your hardware designer _GIVE_ you what you need here! */
+ drctmctl = CONFIG_SYS_SDRAM_DRCTMCTL;
+#else
+ switch (CONFIG_SYS_SDRAM_RAS_CAS_DELAY) {
+ case 2:
+ break;
+ case 3:
+ drctmctl |= 0x01;
+ break;
+ case 4:
+ default:
+ drctmctl |= 0x02;
+ break;
+ }
+
+ switch (CONFIG_SYS_SDRAM_PRECHARGE_DELAY) {
+ case 2:
+ break;
+ case 3:
+ drctmctl |= 0x04;
+ break;
+ case 4:
+ default:
+ drctmctl |= 0x08;
+ break;
+
+ case 6:
+ drctmctl |= 0x0c;
+ break;
+ }
+
+ switch (CONFIG_SYS_SDRAM_CAS_LATENCY) {
+ case 2:
+ break;
+ case 3:
+ default:
+ drctmctl |= 0x10;
+ break;
+ }
+#endif
+ writeb(drctmctl, &sc520_mmcr->drctmctl);
+
+ /* Issue load mode register command */
+ sc520_issue_sdram_op_mode_select(0x03);
+}
+
+static void sc520_set_dram_refresh_rate(void)
+{
+ u8 drctl;
+
+ drctl = readb(&sc520_mmcr->drcctl);
+ drctl &= 0xcf;
+
+ switch (CONFIG_SYS_SDRAM_REFRESH_RATE) {
+ case 78:
+ break;
+ case 156:
+ default:
+ drctl |= 0x10;
+ break;
+ case 312:
+ drctl |= 0x20;
+ break;
+ case 624:
+ drctl |= 0x30;
+ break;
+ }
+
+ writeb(drctl, &sc520_mmcr->drcctl);
+}
+
+static void sc520_enable_dram_refresh(void)
+{
+ u8 drctl;
+
+ drctl = readb(&sc520_mmcr->drcctl);
+ drctl &= 0x30; /* keep refresh rate */
+ drctl |= 0x08; /* enable refresh, normal mode */
+
+ writeb(drctl, &sc520_mmcr->drcctl);
+}
+
+static void sc520_get_bank_info(int bank, struct sc520_sdram_info *bank_info)
+{
+ u32 col_data;
+ u32 row_data;
+
+ u32 drcbendadr;
+ u16 drccfg;
+
+ u8 banks = 0x00;
+ u8 columns = 0x00;
+ u8 rows = 0x00;
+
+ bank_info->banks = 0x00;
+ bank_info->columns = 0x00;
+ bank_info->rows = 0x00;
+ bank_info->size = 0x00;
+
+ if ((bank < 0) || (bank > 3)) {
+ printf("Bad Bank ID\n");
+ return;
+ }
+
+ /* Save configuration */
+ drcbendadr = readl(&sc520_mmcr->drcbendadr);
+ drccfg = readw(&sc520_mmcr->drccfg);
+
+ /* Setup SDRAM Bank to largest possible size */
+ writew(0x000b << (bank * 4), &sc520_mmcr->drccfg);
+
+ /* Set ending address for this bank */
+ writel(0x000000ff << (bank * 8), &sc520_mmcr->drcbendadr);
+
+ /* write col 11 wrap adr */
+ if (write_and_test(COL11_DATA, COL11_ADR) != 0)
+ goto restore_and_exit;
+
+ /* write col 10 wrap adr */
+ if (write_and_test(COL10_DATA, COL10_ADR) != 0)
+ goto restore_and_exit;
+
+ /* write col 9 wrap adr */
+ if (write_and_test(COL09_DATA, COL09_ADR) != 0)
+ goto restore_and_exit;
+
+ /* write col 8 wrap adr */
+ if (write_and_test(COL08_DATA, COL08_ADR) != 0)
+ goto restore_and_exit;
+
+ col_data = readl(COL11_ADR);
+
+ /* All four bytes in the read long must be the same */
+ if (check_long(col_data) < 0)
+ goto restore_and_exit;
+
+ if ((col_data >= COL08_DATA) && (col_data <= COL11_DATA))
+ columns = (u8)(col_data & 0x000000ff);
+ else
+ goto restore_and_exit;
+
+ /* write row 14 wrap adr */
+ if (write_and_test(ROW14_DATA, ROW14_ADR) != 0)
+ goto restore_and_exit;
+
+ /* write row 13 wrap adr */
+ if (write_and_test(ROW13_DATA, ROW13_ADR) != 0)
+ goto restore_and_exit;
+
+ /* write row 12 wrap adr */
+ if (write_and_test(ROW12_DATA, ROW12_ADR) != 0)
+ goto restore_and_exit;
+
+ /* write row 11 wrap adr */
+ if (write_and_test(ROW11_DATA, ROW11_ADR) != 0)
+ goto restore_and_exit;
+
+ if (write_and_test(ROW10_DATA, ROW10_ADR) != 0)
+ goto restore_and_exit;
+
+ /*
+ * read data @ row 12 wrap adr to determine number of banks,
+ * and read data @ row 14 wrap adr to determine number of rows.
+ * if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM.
+ * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4
+ * if data @ row 12 wrap == 11 or 12, we have 4 banks,
+ */
+ row_data = readl(ROW12_ADR);
+
+ /* All four bytes in the read long must be the same */
+ if (check_long(row_data) != 0)
+ goto restore_and_exit;
+
+ switch (row_data) {
+ case ROW10_DATA:
+ banks = 2;
+ break;
+
+ case ROW11_DATA:
+ case ROW12_DATA:
+ banks = 4;
+ break;
+
+ default:
+ goto restore_and_exit;
+ }
+
+ row_data = readl(ROW14_ADR);
+
+ /* All four bytes in the read long must be the same */
+ if (check_long(row_data) != 0)
+ goto restore_and_exit;
+
+ switch (row_data) {
+ case ROW11_DATA:
+ case ROW12_DATA:
+ case ROW13_DATA:
+ case ROW14_DATA:
+ rows = (u8)(row_data & 0x000000ff);
+ break;
+
+ default:
+ goto restore_and_exit;
+ }
+
+ bank_info->banks = banks;
+ bank_info->columns = columns;
+ bank_info->rows = rows;
+
+ if ((bank_info->banks != 0) &&
+ (bank_info->columns != 0) &&
+ (bank_info->rows != 0)) {
+ bank_info->size = bank_info->rows;
+ bank_info->size >>= (11 - bank_info->columns);
+ bank_info->size++;
+ }
+
+restore_and_exit:
+ /* Restore configuration */
+ writel(drcbendadr, &sc520_mmcr->drcbendadr);
+ writew(drccfg, &sc520_mmcr->drccfg);
+}
+
+static void sc520_setup_sizemem(void)
+{
+ u8 i;
+
+ /* Disable write buffer */
+ writeb(0x00, &sc520_mmcr->dbctl);
+
+ /* Disable ECC */
+ writeb(0x00, &sc520_mmcr->eccctl);
+
+ /* Set slowest SDRAM timing */
+ writeb(0x1e, &sc520_mmcr->drctmctl);
+
+ /* Issue a NOP to all SDRAM banks */
+ sc520_issue_sdram_op_mode_select(0x01);
+
+ /* Delay for 100 microseconds */
+ udelay(100);
+
+ /* Issue 'All Banks Precharge' command */
+ sc520_issue_sdram_op_mode_select(0x02);
+
+ /* Issue 2 'Auto Refresh Enable' command */
+ sc520_issue_sdram_op_mode_select(0x04);
+ sc520_dummy_write();
+
+ /* Issue 'Load Mode Register' command */
+ sc520_issue_sdram_op_mode_select(0x03);
+
+ /* Issue 8 more 'Auto Refresh Enable' commands */
+ sc520_issue_sdram_op_mode_select(0x04);
+ for (i = 0; i < 7; i++)
+ sc520_dummy_write();
+
+ /* Set control register to 'Normal Mode' */
+ writeb(0x00, &sc520_mmcr->drcctl);
+}
+
+static void sc520_sizemem(void)
+{
+ struct sc520_sdram_info sdram_info[4];
+ u8 bank_config = 0x00;
+ u8 end_addr = 0x00;
+ u16 drccfg = 0x0000;
+ u32 drcbendadr = 0x00000000;
+ u8 i;
+
+ /* Use PARs to disable caching of maximum allowable 256MB SDRAM */
+ writel(SC520_SDRAM1_PAR | SC520_PAR_CACHE_DIS, &sc520_mmcr->par[3]);
+ writel(SC520_SDRAM2_PAR | SC520_PAR_CACHE_DIS, &sc520_mmcr->par[4]);
+
+ sc520_setup_sizemem();
+
+ gd->ram_size = 0;
+
+ /* Size each SDRAM bank */
+ for (i = 0; i <= 3; i++) {
+ sc520_get_bank_info(i, &sdram_info[i]);
+
+ if (sdram_info[i].banks != 0) {
+ /* Update Configuration register */
+ bank_config = sdram_info[i].columns - 8;
+
+ if (sdram_info[i].banks == 4)
+ bank_config |= 0x08;
+
+ drccfg |= bank_config << (i * 4);
+
+ /* Update End Address register */
+ end_addr += sdram_info[i].size;
+ drcbendadr |= (end_addr | 0x80) << (i * 8);
+
+ gd->ram_size += sdram_info[i].size << 22;
+ }
+
+ /* Issue 'All Banks Precharge' command */
+ sc520_issue_sdram_op_mode_select(0x02);
+
+ /* Set control register to 'Normal Mode' */
+ writeb(0x00, &sc520_mmcr->drcctl);
+ }
+
+ writel(drcbendadr, &sc520_mmcr->drcbendadr);
+ writew(drccfg, &sc520_mmcr->drccfg);
+
+ /* Clear PARs preventing caching of SDRAM */
+ writel(0x00000000, &sc520_mmcr->par[3]);
+ writel(0x00000000, &sc520_mmcr->par[4]);
+}
+
+#if CONFIG_SYS_SDRAM_ECC_ENABLE
+static void sc520_enable_ecc(void)
+
+ /* A nominal memory test: just a byte at each address line */
+ movl %eax, %ecx
+ shrl $0x1, %ecx
+ movl $0x1, %edi
+memtest0:
+ movb $0xa5, (%edi)
+ cmpb $0xa5, (%edi)
+ jne out
+ shrl $0x1, %ecx
+ andl %ecx, %ecx
+ jz set_ecc
+ shll $0x1, %edi
+ jmp memtest0
+
+set_ecc:
+ /* clear all ram with a memset */
+ movl %eax, %ecx
+ xorl %esi, %esi
+ xorl %edi, %edi
+ xorl %eax, %eax
+ shrl $0x2, %ecx
+ cld
+ rep stosl
+
+ /* enable read, write buffers */
+ movb $0x11, %al
+ movl $DBCTL, %edi
+ movb %al, (%edi)
+
+ /* enable NMI mapping for ECC */
+ movl $ECCINT, %edi
+ movb $0x10, %al
+ movb %al, (%edi)
+
+ /* Turn on ECC */
+ movl $ECCCTL, %edi
+ movb $0x05, %al
+ movb %al,(%edi)
+
+out:
+ jmp init_ecc_ret
+}
+#endif
+
+int dram_init(void)
+{
+ ulong dram_ctrl;
+ ulong dram_present = 0x00000000;
+
+ /*
+ * We read-back the configuration of the dram
+ * controller that the assembly code wrote
+ */
+ dram_ctrl = readl(&sc520_mmcr->drcbendadr);
+
+ gd->bd->bi_dram[0].start = 0;
+ if (dram_ctrl & 0x80) {
+ /* bank 0 enabled */
+ gd->bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22;
+ dram_present = gd->bd->bi_dram[1].start;
+ gd->bd->bi_dram[0].size = gd->bd->bi_dram[1].start;
+ } else {
+ gd->bd->bi_dram[0].size = 0;
+ gd->bd->bi_dram[1].start = gd->bd->bi_dram[0].start;
+ }
+
+ if (dram_ctrl & 0x8000) {
+ /* bank 1 enabled */
+ gd->bd->bi_dram[2].start = (dram_ctrl & 0x7f00) << 14;
+ dram_present = gd->bd->bi_dram[2].start;
+ gd->bd->bi_dram[1].size = gd->bd->bi_dram[2].start -
+ gd->bd->bi_dram[1].start;
+ } else {
+ gd->bd->bi_dram[1].size = 0;
+ gd->bd->bi_dram[2].start = gd->bd->bi_dram[1].start;
+ }
+
+ if (dram_ctrl & 0x800000) {
+ /* bank 2 enabled */
+ gd->bd->bi_dram[3].start = (dram_ctrl & 0x7f0000) << 6;
+ dram_present = gd->bd->bi_dram[3].start;
+ gd->bd->bi_dram[2].size = gd->bd->bi_dram[3].start -
+ gd->bd->bi_dram[2].start;
+ } else {
+ gd->bd->bi_dram[2].size = 0;
+ gd->bd->bi_dram[3].start = gd->bd->bi_dram[2].start;
+ }
+
+ if (dram_ctrl & 0x80000000) {
+ /* bank 3 enabled */
+ dram_present = (dram_ctrl & 0x7f000000) >> 2;
+ gd->bd->bi_dram[3].size = dram_present -
+ gd->bd->bi_dram[3].start;
+ } else {
+ gd->bd->bi_dram[3].size = 0;
+ }
+
+ gd->ram_size = dram_present;
+
+ return 0;
+}
diff --git a/arch/x86/cpu/sc520/sc520_ssi.c b/arch/x86/cpu/sc520/sc520_ssi.c
new file mode 100644
index 0000000000..ac58d25970
--- /dev/null
+++ b/arch/x86/cpu/sc520/sc520_ssi.c
@@ -0,0 +1,92 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/ic/ssi.h>
+#include <asm/ic/sc520.h>
+
+int ssi_set_interface(int freq, int lsb_first, int inv_clock, int inv_phase)
+{
+ u8 temp=0;
+
+ if (freq >= 8192) {
+ temp |= CTL_CLK_SEL_4;
+ } else if (freq >= 4096) {
+ temp |= CTL_CLK_SEL_8;
+ } else if (freq >= 2048) {
+ temp |= CTL_CLK_SEL_16;
+ } else if (freq >= 1024) {
+ temp |= CTL_CLK_SEL_32;
+ } else if (freq >= 512) {
+ temp |= CTL_CLK_SEL_64;
+ } else if (freq >= 256) {
+ temp |= CTL_CLK_SEL_128;
+ } else if (freq >= 128) {
+ temp |= CTL_CLK_SEL_256;
+ } else {
+ temp |= CTL_CLK_SEL_512;
+ }
+
+ if (!lsb_first) {
+ temp |= MSBF_ENB;
+ }
+
+ if (inv_clock) {
+ temp |= CLK_INV_ENB;
+ }
+
+ if (inv_phase) {
+ temp |= PHS_INV_ENB;
+ }
+
+ writeb(temp, &sc520_mmcr->ssictl);
+
+ return 0;
+}
+
+u8 ssi_txrx_byte(u8 data)
+{
+ 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 readb(&sc520_mmcr->ssircv);
+}
+
+void ssi_tx_byte(u8 data)
+{
+ 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 (readb(&sc520_mmcr->ssista) & SSISTA_BSY);
+ writeb(SSICMD_CMD_SEL_RCV, &sc520_mmcr->ssicmd);
+ while (readb(&sc520_mmcr->ssista) & SSISTA_BSY);
+
+ return readb(&sc520_mmcr->ssircv);
+}
diff --git a/arch/x86/cpu/sc520/sc520_timer.c b/arch/x86/cpu/sc520/sc520_timer.c
new file mode 100644
index 0000000000..1bcfe67c94
--- /dev/null
+++ b/arch/x86/cpu/sc520/sc520_timer.c
@@ -0,0 +1,90 @@
+/*
+ * (C) Copyright 2008-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+#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 */
+ writeb(0x02, &sc520_mmcr->gptmrsta);
+}
+
+int timer_init(void)
+{
+ /* Register the SC520 specific timer interrupt handler */
+ register_timer_isr (sc520_timer_isr);
+
+ /* Install interrupt handler for GP Timer 1 */
+ irq_install_handler (0, timer_isr, NULL);
+
+ /* Map GP Timer 1 to Master PIC IR0 */
+ writeb(0x01, &sc520_mmcr->gp_tmr_int_map[1]);
+
+ /* Disable GP Timers 1 & 2 - Allow configuration writes */
+ writew(0x4000, &sc520_mmcr->gptmr1ctl);
+ writew(0x4000, &sc520_mmcr->gptmr2ctl);
+
+ /* Reset GP Timers 1 & 2 */
+ writew(0x0000, &sc520_mmcr->gptmr1cnt);
+ writew(0x0000, &sc520_mmcr->gptmr2cnt);
+
+ /* Setup GP Timer 2 as a 100kHz (10us) prescaler */
+ writew(83, &sc520_mmcr->gptmr2maxcmpa);
+ writew(0xc001, &sc520_mmcr->gptmr2ctl);
+
+ /* Setup GP Timer 1 as a 1000 Hz (1ms) interrupt generator */
+ 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*/
+ 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 = readw(&sc520_mmcr->swtmrmilli);
+ temp = readw(&sc520_mmcr->swtmrmicro);
+
+ do {
+ m += readw(&sc520_mmcr->swtmrmilli);
+ u = readw(&sc520_mmcr->swtmrmicro) + (m * 1000);
+ } while (u < usec);
+}
diff --git a/arch/x86/cpu/start.S b/arch/x86/cpu/start.S
new file mode 100644
index 0000000000..7ccc076fec
--- /dev/null
+++ b/arch/x86/cpu/start.S
@@ -0,0 +1,132 @@
+/*
+ * U-boot - x86 Startup Code
+ *
+ * (C) Copyright 2008-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+#include <config.h>
+#include <version.h>
+#include <asm/global_data.h>
+#include <asm/processor-flags.h>
+
+.section .text
+.code32
+.globl _start
+.type _start, @function
+.globl _x86boot_start
+_x86boot_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 $(X86_CR0_NW | X86_CR0_CD), %eax
+ movl %eax, %cr0
+ wbinvd
+
+ /* Tell 32-bit code it is being entered from an in-RAM copy */
+ movw $GD_FLG_WARM_BOOT, %bx
+_start:
+ /* This is the 32-bit cold-reset entry point */
+
+ /* Load the segement registes to match the gdt loaded in start16.S */
+ movl $0x18, %eax
+ movw %ax, %fs
+ movw %ax, %ds
+ movw %ax, %gs
+ movw %ax, %es
+ movw %ax, %ss
+
+ /* Clear the interupt vectors */
+ lidt blank_idt_ptr
+
+ /* Early platform init (setup gpio, etc ) */
+ jmp early_board_init
+.globl early_board_init_ret
+early_board_init_ret:
+
+ /* Initialise Cache-As-RAM */
+ jmp car_init
+.globl car_init_ret
+car_init_ret:
+ /*
+ * We now have CONFIG_SYS_CAR_SIZE bytes of Cache-As-RAM (or SRAM,
+ * or fully initialised SDRAM - we really don't care which)
+ * starting at CONFIG_SYS_CAR_ADDR to be used as a temporary stack
+ */
+ movl $CONFIG_SYS_INIT_SP_ADDR, %esp
+
+ /* Set parameter to board_init_f() to boot flags */
+ xorl %eax, %eax
+ movw %bx, %ax
+
+ /* Enter, U-boot! */
+ call board_init_f
+
+ /* indicate (lack of) progress */
+ movw $0x85, %ax
+ jmp die
+
+.globl relocate_code
+.type relocate_code, @function
+relocate_code:
+ /*
+ * SDRAM has been initialised, U-Boot code has been copied into
+ * RAM, BSS has been cleared and relocation adjustments have been
+ * made. It is now time to jump into the in-RAM copy of U-Boot
+ *
+ * %eax = Address of top of stack
+ * %edx = Address of Global Data
+ * %ecx = Base address of in-RAM copy of U-Boot
+ */
+
+ /* Setup stack in RAM */
+ movl %eax, %esp
+
+ /* Setup call address of in-RAM copy of board_init_r() */
+ movl $board_init_r, %ebp
+ addl (GD_RELOC_OFF * 4)(%edx), %ebp
+
+ /* Setup parameters to board_init_r() */
+ movl %edx, %eax
+ movl %ecx, %edx
+
+ /* Jump to in-RAM copy of board_init_r() */
+ call *%ebp
+
+die: hlt
+ jmp die
+ hlt
+
+blank_idt_ptr:
+ .word 0 /* limit */
+ .long 0 /* base */
diff --git a/arch/x86/cpu/start16.S b/arch/x86/cpu/start16.S
new file mode 100644
index 0000000000..f1b9d0a0c9
--- /dev/null
+++ b/arch/x86/cpu/start16.S
@@ -0,0 +1,113 @@
+/*
+ * U-boot - x86 Startup Code
+ *
+ * (C) Copyright 2008-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002,2003
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+#include <asm/global_data.h>
+#include <asm/processor-flags.h>
+
+#define BOOT_SEG 0xffff0000 /* linear segment of boot code */
+#define a32 .byte 0x67;
+#define o32 .byte 0x66;
+
+.section .start16, "ax"
+.code16
+.globl start16
+start16:
+ /* Set the Cold Boot / Hard Reset flag */
+ movl $GD_FLG_COLD_BOOT, %ebx
+
+ /*
+ * First we let the BSP do some early initialization
+ * this code have to map the flash to its final position
+ */
+ jmp board_init16
+.globl board_init16_ret
+board_init16_ret:
+
+ /* Turn of cache (this might require a 486-class CPU) */
+ movl %cr0, %eax
+ orl $(X86_CR0_NW & X86_CR0_CD), %eax
+ movl %eax, %cr0
+ wbinvd
+
+ /* load the temporary Global Descriptor Table */
+o32 cs lidt idt_ptr
+o32 cs lgdt gdt_ptr
+
+ /* Now, we enter protected mode */
+ movl %cr0, %eax
+ orl $X86_CR0_PE, %eax
+ movl %eax, %cr0
+
+ /* Flush the prefetch queue */
+ jmp ff
+ff:
+ /* Finally jump to the 32bit initialization code */
+ movw $code32start, %ax
+ movw %ax, %bp
+o32 cs ljmp *(%bp)
+
+ /* 48-bit far pointer */
+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 0x20 /* limit (32 bytes = 4 GDT entries) */
+ .long BOOT_SEG + gdt /* base */
+
+ /* The GDT table ...
+ *
+ * Selector Type
+ * 0x00 NULL
+ * 0x08 Unused
+ * 0x10 32bit code
+ * 0x18 32bit data/stack
+ */
+
+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) */
diff --git a/arch/x86/cpu/u-boot.lds b/arch/x86/cpu/u-boot.lds
new file mode 100644
index 0000000000..55974228b5
--- /dev/null
+++ b/arch/x86/cpu/u-boot.lds
@@ -0,0 +1,97 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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
+ */
+
+#include <config.h>
+OUTPUT_FORMAT("elf32-i386", "elf32-i386", "elf32-i386")
+OUTPUT_ARCH(i386)
+ENTRY(_start)
+
+SECTIONS
+{
+ . = CONFIG_SYS_TEXT_BASE; /* Location of bootcode in flash */
+ __text_start = .;
+ .text : { *(.text*); }
+
+ . = ALIGN(4);
+ __u_boot_cmd_start = .;
+ .u_boot_cmd : { *(.u_boot_cmd) }
+ . = ALIGN(4);
+ __u_boot_cmd_end = .;
+
+ . = ALIGN(4);
+ .rodata : { *(SORT_BY_ALIGNMENT(SORT_BY_NAME(.rodata*))) }
+
+ . = ALIGN(4);
+ .data : { *(.data*) }
+
+ . = ALIGN(4);
+ .dynsym : { *(.dynsym*) }
+
+ . = ALIGN(4);
+ .hash : { *(.hash*) }
+
+ . = ALIGN(4);
+ .got : { *(.got*) }
+
+ . = ALIGN(4);
+ __data_end = .;
+
+ . = ALIGN(4);
+ __bss_start = ABSOLUTE(.);
+ .bss (NOLOAD) : { *(.bss) }
+ . = ALIGN(4);
+ __bss_end = ABSOLUTE(.);
+
+ . = ALIGN(4);
+ __rel_dyn_start = .;
+ .rel.dyn : { *(.rel.dyn) }
+ __rel_dyn_end = .;
+
+ /DISCARD/ : { *(.dynstr*) }
+ /DISCARD/ : { *(.dynamic*) }
+ /DISCARD/ : { *(.plt*) }
+ /DISCARD/ : { *(.interp*) }
+ /DISCARD/ : { *(.gnu*) }
+
+ /* 16bit realmode trampoline code */
+ .realmode REALMODE_BASE : AT ( LOADADDR(.rel.dyn) + SIZEOF(.rel.dyn) ) { KEEP(*(.realmode)) }
+
+ __realmode_start = LOADADDR(.realmode);
+ __realmode_size = SIZEOF(.realmode);
+
+ /* 16bit BIOS emulation code (just enough to boot Linux) */
+ .bios 0 : AT ( LOADADDR(.realmode) + SIZEOF(.realmode) ) { KEEP(*(.bios)) }
+
+ __bios_start = LOADADDR(.bios);
+ __bios_size = SIZEOF(.bios);
+
+ /*
+ * The following expressions place the 16-bit Real-Mode code and
+ * Reset Vector at the end of the Flash ROM
+ */
+ . = START_16;
+ .start16 : AT (CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE + START_16)) { KEEP(*(.start16)); }
+
+ . = RESET_VEC_LOC;
+ .resetvec : AT (CONFIG_SYS_TEXT_BASE + (CONFIG_SYS_MONITOR_LEN - RESET_SEG_SIZE + RESET_VEC_LOC)) { KEEP(*(.resetvec)); }
+}
diff --git a/arch/x86/include/asm/bitops.h b/arch/x86/include/asm/bitops.h
new file mode 100644
index 0000000000..c7a38f237a
--- /dev/null
+++ b/arch/x86/include/asm/bitops.h
@@ -0,0 +1,384 @@
+#ifndef _I386_BITOPS_H
+#define _I386_BITOPS_H
+
+/*
+ * Copyright 1992, Linus Torvalds.
+ */
+
+
+/*
+ * These have to be done with inline assembly: that way the bit-setting
+ * is guaranteed to be atomic. All bit operations return 0 if the bit
+ * was cleared before the operation and != 0 if it was not.
+ *
+ * bit 0 is the LSB of addr; bit 32 is the LSB of (addr+1).
+ */
+
+#ifdef CONFIG_SMP
+#define LOCK_PREFIX "lock ; "
+#else
+#define LOCK_PREFIX ""
+#endif
+
+#define ADDR (*(volatile long *) addr)
+
+/**
+ * set_bit - Atomically set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * This function is atomic and may not be reordered. See __set_bit()
+ * if you do not require the atomic guarantees.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static __inline__ void set_bit(int nr, volatile void * addr)
+{
+ __asm__ __volatile__( LOCK_PREFIX
+ "btsl %1,%0"
+ :"=m" (ADDR)
+ :"Ir" (nr));
+}
+
+/**
+ * __set_bit - Set a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * Unlike set_bit(), this function is non-atomic and may be reordered.
+ * If it's called on the same region of memory simultaneously, the effect
+ * may be that only one operation succeeds.
+ */
+static __inline__ void __set_bit(int nr, volatile void * addr)
+{
+ __asm__(
+ "btsl %1,%0"
+ :"=m" (ADDR)
+ :"Ir" (nr));
+}
+
+/**
+ * clear_bit - Clears a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * clear_bit() is atomic and may not be reordered. However, it does
+ * not contain a memory barrier, so if it is used for locking purposes,
+ * you should call smp_mb__before_clear_bit() and/or smp_mb__after_clear_bit()
+ * in order to ensure changes are visible on other processors.
+ */
+static __inline__ void clear_bit(int nr, volatile void * addr)
+{
+ __asm__ __volatile__( LOCK_PREFIX
+ "btrl %1,%0"
+ :"=m" (ADDR)
+ :"Ir" (nr));
+}
+#define smp_mb__before_clear_bit() barrier()
+#define smp_mb__after_clear_bit() barrier()
+
+/**
+ * __change_bit - Toggle a bit in memory
+ * @nr: the bit to set
+ * @addr: the address to start counting from
+ *
+ * Unlike change_bit(), this function is non-atomic and may be reordered.
+ * If it's called on the same region of memory simultaneously, the effect
+ * may be that only one operation succeeds.
+ */
+static __inline__ void __change_bit(int nr, volatile void * addr)
+{
+ __asm__ __volatile__(
+ "btcl %1,%0"
+ :"=m" (ADDR)
+ :"Ir" (nr));
+}
+
+/**
+ * change_bit - Toggle a bit in memory
+ * @nr: Bit to clear
+ * @addr: Address to start counting from
+ *
+ * change_bit() is atomic and may not be reordered.
+ * Note that @nr may be almost arbitrarily large; this function is not
+ * restricted to acting on a single-word quantity.
+ */
+static __inline__ void change_bit(int nr, volatile void * addr)
+{
+ __asm__ __volatile__( LOCK_PREFIX
+ "btcl %1,%0"
+ :"=m" (ADDR)
+ :"Ir" (nr));
+}
+
+/**
+ * test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static __inline__ int test_and_set_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__( LOCK_PREFIX
+ "btsl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"=m" (ADDR)
+ :"Ir" (nr) : "memory");
+ return oldbit;
+}
+
+/**
+ * __test_and_set_bit - Set a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail. You must protect multiple accesses with a lock.
+ */
+static __inline__ int __test_and_set_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+
+ __asm__(
+ "btsl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"=m" (ADDR)
+ :"Ir" (nr));
+ return oldbit;
+}
+
+/**
+ * test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static __inline__ int test_and_clear_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__( LOCK_PREFIX
+ "btrl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"=m" (ADDR)
+ :"Ir" (nr) : "memory");
+ return oldbit;
+}
+
+/**
+ * __test_and_clear_bit - Clear a bit and return its old value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is non-atomic and can be reordered.
+ * If two examples of this operation race, one can appear to succeed
+ * but actually fail. You must protect multiple accesses with a lock.
+ */
+static __inline__ int __test_and_clear_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+
+ __asm__(
+ "btrl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"=m" (ADDR)
+ :"Ir" (nr));
+ return oldbit;
+}
+
+/* WARNING: non atomic and it can be reordered! */
+static __inline__ int __test_and_change_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__(
+ "btcl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"=m" (ADDR)
+ :"Ir" (nr) : "memory");
+ return oldbit;
+}
+
+/**
+ * test_and_change_bit - Change a bit and return its new value
+ * @nr: Bit to set
+ * @addr: Address to count from
+ *
+ * This operation is atomic and cannot be reordered.
+ * It also implies a memory barrier.
+ */
+static __inline__ int test_and_change_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__( LOCK_PREFIX
+ "btcl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit),"=m" (ADDR)
+ :"Ir" (nr) : "memory");
+ return oldbit;
+}
+
+#if 0 /* Fool kernel-doc since it doesn't do macros yet */
+/**
+ * test_bit - Determine whether a bit is set
+ * @nr: bit number to test
+ * @addr: Address to start counting from
+ */
+static int test_bit(int nr, const volatile void * addr);
+#endif
+
+static __inline__ int constant_test_bit(int nr, const volatile void * addr)
+{
+ return ((1UL << (nr & 31)) & (((const volatile unsigned int *) addr)[nr >> 5])) != 0;
+}
+
+static __inline__ int variable_test_bit(int nr, volatile void * addr)
+{
+ int oldbit;
+
+ __asm__ __volatile__(
+ "btl %2,%1\n\tsbbl %0,%0"
+ :"=r" (oldbit)
+ :"m" (ADDR),"Ir" (nr));
+ return oldbit;
+}
+
+#define test_bit(nr,addr) \
+(__builtin_constant_p(nr) ? \
+ constant_test_bit((nr),(addr)) : \
+ variable_test_bit((nr),(addr)))
+
+/**
+ * find_first_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to start the search at
+ * @size: The maximum size to search
+ *
+ * Returns the bit-number of the first zero bit, not the number of the byte
+ * containing a bit.
+ */
+static __inline__ int find_first_zero_bit(void * addr, unsigned size)
+{
+ int d0, d1, d2;
+ int res;
+
+ if (!size)
+ return 0;
+ /* This looks at memory. Mark it volatile to tell gcc not to move it around */
+ __asm__ __volatile__(
+ "movl $-1,%%eax\n\t"
+ "xorl %%edx,%%edx\n\t"
+ "repe; scasl\n\t"
+ "je 1f\n\t"
+ "xorl -4(%%edi),%%eax\n\t"
+ "subl $4,%%edi\n\t"
+ "bsfl %%eax,%%edx\n"
+ "1:\tsubl %%ebx,%%edi\n\t"
+ "shll $3,%%edi\n\t"
+ "addl %%edi,%%edx"
+ :"=d" (res), "=&c" (d0), "=&D" (d1), "=&a" (d2)
+ :"1" ((size + 31) >> 5), "2" (addr), "b" (addr));
+ return res;
+}
+
+/**
+ * find_next_zero_bit - find the first zero bit in a memory region
+ * @addr: The address to base the search on
+ * @offset: The bitnumber to start searching at
+ * @size: The maximum size to search
+ */
+static __inline__ int find_next_zero_bit (void * addr, int size, int offset)
+{
+ unsigned long * p = ((unsigned long *) addr) + (offset >> 5);
+ int set = 0, bit = offset & 31, res;
+
+ if (bit) {
+ /*
+ * Look for zero in first byte
+ */
+ __asm__("bsfl %1,%0\n\t"
+ "jne 1f\n\t"
+ "movl $32, %0\n"
+ "1:"
+ : "=r" (set)
+ : "r" (~(*p >> bit)));
+ if (set < (32 - bit))
+ return set + offset;
+ set = 32 - bit;
+ p++;
+ }
+ /*
+ * No zero yet, search remaining full bytes for a zero
+ */
+ res = find_first_zero_bit (p, size - 32 * (p - (unsigned long *) addr));
+ return (offset + set + res);
+}
+
+/**
+ * ffz - find first zero in word.
+ * @word: The word to search
+ *
+ * Undefined if no zero exists, so code should check against ~0UL first.
+ */
+static __inline__ unsigned long ffz(unsigned long word)
+{
+ __asm__("bsfl %1,%0"
+ :"=r" (word)
+ :"r" (~word));
+ return word;
+}
+
+#ifdef __KERNEL__
+
+/**
+ * ffs - find first bit set
+ * @x: the word to search
+ *
+ * This is defined the same way as
+ * the libc and compiler builtin ffs routines, therefore
+ * differs in spirit from the above ffz (man ffs).
+ */
+static __inline__ int ffs(int x)
+{
+ int r;
+
+ __asm__("bsfl %1,%0\n\t"
+ "jnz 1f\n\t"
+ "movl $-1,%0\n"
+ "1:" : "=r" (r) : "g" (x));
+ return r+1;
+}
+#define PLATFORM_FFS
+
+/**
+ * hweightN - returns the hamming weight of a N-bit word
+ * @x: the word to weigh
+ *
+ * The Hamming Weight of a number is the total number of bits set in it.
+ */
+
+#define hweight32(x) generic_hweight32(x)
+#define hweight16(x) generic_hweight16(x)
+#define hweight8(x) generic_hweight8(x)
+
+#endif /* __KERNEL__ */
+
+#ifdef __KERNEL__
+
+#define ext2_set_bit __test_and_set_bit
+#define ext2_clear_bit __test_and_clear_bit
+#define ext2_test_bit test_bit
+#define ext2_find_first_zero_bit find_first_zero_bit
+#define ext2_find_next_zero_bit find_next_zero_bit
+
+/* Bitmap functions for the minix filesystem. */
+#define minix_test_and_set_bit(nr,addr) __test_and_set_bit(nr,addr)
+#define minix_set_bit(nr,addr) __set_bit(nr,addr)
+#define minix_test_and_clear_bit(nr,addr) __test_and_clear_bit(nr,addr)
+#define minix_test_bit(nr,addr) test_bit(nr,addr)
+#define minix_find_first_zero_bit(addr,size) find_first_zero_bit(addr,size)
+
+#endif /* __KERNEL__ */
+
+#endif /* _I386_BITOPS_H */
diff --git a/arch/x86/include/asm/bootparam.h b/arch/x86/include/asm/bootparam.h
new file mode 100644
index 0000000000..140095117e
--- /dev/null
+++ b/arch/x86/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/x86/include/asm/byteorder.h b/arch/x86/include/asm/byteorder.h
new file mode 100644
index 0000000000..7dfeb8bbed
--- /dev/null
+++ b/arch/x86/include/asm/byteorder.h
@@ -0,0 +1,43 @@
+#ifndef _I386_BYTEORDER_H
+#define _I386_BYTEORDER_H
+
+#include <asm/types.h>
+
+#ifdef __GNUC__
+
+
+static __inline__ __u32 ___arch__swab32(__u32 x)
+{
+#ifdef CONFIG_X86_BSWAP
+ __asm__("bswap %0" : "=r" (x) : "0" (x));
+#else
+ __asm__("xchgb %b0,%h0\n\t" /* swap lower bytes */
+ "rorl $16,%0\n\t" /* swap words */
+ "xchgb %b0,%h0" /* swap higher bytes */
+ :"=q" (x)
+ : "0" (x));
+#endif
+ return x;
+}
+
+static __inline__ __u16 ___arch__swab16(__u16 x)
+{
+ __asm__("xchgb %b0,%h0" /* swap bytes */ \
+ : "=q" (x) \
+ : "0" (x)); \
+ return x;
+}
+
+#define __arch__swab32(x) ___arch__swab32(x)
+#define __arch__swab16(x) ___arch__swab16(x)
+
+#if !defined(__STRICT_ANSI__) || defined(__KERNEL__)
+# define __BYTEORDER_HAS_U64__
+# define __SWAB_64_THRU_32__
+#endif
+
+#endif /* __GNUC__ */
+
+#include <linux/byteorder/little_endian.h>
+
+#endif /* _I386_BYTEORDER_H */
diff --git a/arch/x86/include/asm/config.h b/arch/x86/include/asm/config.h
new file mode 100644
index 0000000000..049c44eaf8
--- /dev/null
+++ b/arch/x86/include/asm/config.h
@@ -0,0 +1,24 @@
+/*
+ * Copyright 2009 Freescale Semiconductor, Inc.
+ *
+ * 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
+ *
+ */
+
+#ifndef _ASM_CONFIG_H_
+#define _ASM_CONFIG_H_
+
+#endif
diff --git a/arch/x86/include/asm/e820.h b/arch/x86/include/asm/e820.h
new file mode 100644
index 0000000000..d155ce9cee
--- /dev/null
+++ b/arch/x86/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/x86/include/asm/errno.h b/arch/x86/include/asm/errno.h
new file mode 100644
index 0000000000..4c82b503d9
--- /dev/null
+++ b/arch/x86/include/asm/errno.h
@@ -0,0 +1 @@
+#include <asm-generic/errno.h>
diff --git a/arch/x86/include/asm/global_data.h b/arch/x86/include/asm/global_data.h
new file mode 100644
index 0000000000..f8a16d646f
--- /dev/null
+++ b/arch/x86/include/asm/global_data.h
@@ -0,0 +1,102 @@
+/*
+ * (C) Copyright 2002-2010
+ * 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
+ */
+
+#ifndef __ASM_GBL_DATA_H
+#define __ASM_GBL_DATA_H
+/*
+ * The following data structure is placed in some memory wich is
+ * available very early after boot (like DPRAM on MPC8xx/MPC82xx, or
+ * some locked parts of the data cache) to allow for a minimum set of
+ * global variables during system initialization (until we have set
+ * up the memory controller so that we can use RAM).
+ *
+ * Keep it *SMALL* and remember to set GENERATED_GBL_DATA_SIZE > sizeof(gd_t)
+ */
+
+#ifndef __ASSEMBLY__
+
+typedef struct global_data {
+ bd_t *bd;
+ unsigned long flags;
+ unsigned long baudrate;
+ unsigned long have_console; /* serial_init() was called */
+ unsigned long reloc_off; /* Relocation Offset */
+ unsigned long load_off; /* Load Offset */
+ unsigned long env_addr; /* Address of Environment struct */
+ unsigned long env_valid; /* Checksum of Environment valid? */
+ unsigned long cpu_clk; /* CPU clock in Hz! */
+ unsigned long bus_clk;
+ unsigned long relocaddr; /* Start address of U-Boot in RAM */
+ unsigned long start_addr_sp; /* start_addr_stackpointer */
+ phys_size_t ram_size; /* RAM size */
+ unsigned long reset_status; /* reset status register at boot */
+ void **jt; /* jump table */
+ char env_buf[32]; /* buffer for getenv() before reloc. */
+} gd_t;
+
+extern gd_t *gd;
+
+#endif
+
+/* Word Offsets into Global Data - MUST match struct gd_t */
+#define GD_BD 0
+#define GD_FLAGS 1
+#define GD_BAUDRATE 2
+#define GD_HAVE_CONSOLE 3
+#define GD_RELOC_OFF 4
+#define GD_LOAD_OFF 5
+#define GD_ENV_ADDR 6
+#define GD_ENV_VALID 7
+#define GD_CPU_CLK 8
+#define GD_BUS_CLK 9
+#define GD_RELOC_ADDR 10
+#define GD_START_ADDR_SP 11
+#define GD_RAM_SIZE 12
+#define GD_RESET_STATUS 13
+#define GD_JT 14
+
+#define GD_SIZE 15
+
+/*
+ * Global Data Flags
+ */
+#define GD_FLG_RELOC 0x00001 /* Code was relocated to RAM */
+#define GD_FLG_DEVINIT 0x00002 /* Devices have been initialized */
+#define GD_FLG_SILENT 0x00004 /* Silent mode */
+#define GD_FLG_POSTFAIL 0x00008 /* Critical POST test failed */
+#define GD_FLG_POSTSTOP 0x00010 /* POST seqeunce aborted */
+#define GD_FLG_LOGINIT 0x00020 /* Log Buffer has been initialized */
+#define GD_FLG_DISABLE_CONSOLE 0x00040 /* Disable console (in & out) */
+#define GD_FLG_ENV_READY 0x00080 /* Environment imported into hash table */
+#define GD_FLG_COLD_BOOT 0x00100 /* Cold Boot */
+#define GD_FLG_WARM_BOOT 0x00200 /* Warm Boot */
+
+#if 0
+#define DECLARE_GLOBAL_DATA_PTR
+#else
+#define XTRN_DECLARE_GLOBAL_DATA_PTR extern
+#define DECLARE_GLOBAL_DATA_PTR XTRN_DECLARE_GLOBAL_DATA_PTR \
+gd_t *gd
+#endif
+
+#endif /* __ASM_GBL_DATA_H */
diff --git a/arch/x86/include/asm/i8254.h b/arch/x86/include/asm/i8254.h
new file mode 100644
index 0000000000..aafdfb8060
--- /dev/null
+++ b/arch/x86/include/asm/i8254.h
@@ -0,0 +1,55 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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
+ */
+
+
+/* i8254.h Intel 8254 PIT registers */
+
+
+#ifndef _ASMI386_I8254_H_
+#define _ASMI386_I8954_H_ 1
+
+
+#define PIT_T0 0x00 /* PIT channel 0 count/status */
+#define PIT_T1 0x01 /* PIT channel 1 count/status */
+#define PIT_T2 0x02 /* PIT channel 2 count/status */
+#define PIT_COMMAND 0x03 /* PIT mode control, latch and read back */
+
+/* PIT Command Register Bit Definitions */
+
+#define PIT_CMD_CTR0 0x00 /* Select PIT counter 0 */
+#define PIT_CMD_CTR1 0x40 /* Select PIT counter 1 */
+#define PIT_CMD_CTR2 0x80 /* Select PIT counter 2 */
+
+#define PIT_CMD_LATCH 0x00 /* Counter Latch Command */
+#define PIT_CMD_LOW 0x10 /* Access counter bits 7-0 */
+#define PIT_CMD_HIGH 0x20 /* Access counter bits 15-8 */
+#define PIT_CMD_BOTH 0x30 /* Access counter bits 15-0 in two accesses */
+
+#define PIT_CMD_MODE0 0x00 /* Select mode 0 */
+#define PIT_CMD_MODE1 0x02 /* Select mode 1 */
+#define PIT_CMD_MODE2 0x04 /* Select mode 2 */
+#define PIT_CMD_MODE3 0x06 /* Select mode 3 */
+#define PIT_CMD_MODE4 0x08 /* Select mode 4 */
+#define PIT_CMD_MODE5 0x0A /* Select mode 5 */
+
+#endif
diff --git a/arch/x86/include/asm/i8259.h b/arch/x86/include/asm/i8259.h
new file mode 100644
index 0000000000..774d7a31e7
--- /dev/null
+++ b/arch/x86/include/asm/i8259.h
@@ -0,0 +1,88 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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
+ */
+
+/* i8259.h i8259 PIC Registers */
+
+#ifndef _ASMI386_I8259_H_
+#define _ASMI386_I8959_H_ 1
+
+
+/* PIC I/O mapped registers */
+
+#define IRR 0x0 /* Interrupt Request Register */
+#define ISR 0x0 /* In-Service Register */
+#define ICW1 0x0 /* Initialization Control Word 1 */
+#define OCW2 0x0 /* Operation Control Word 2 */
+#define OCW3 0x0 /* Operation Control Word 3 */
+#define ICW2 0x1 /* Initialization Control Word 2 */
+#define ICW3 0x1 /* Initialization Control Word 3 */
+#define ICW4 0x1 /* Initialization Control Word 4 */
+#define IMR 0x1 /* Interrupt Mask Register */
+
+/* bits for IRR, IMR, ISR and ICW3 */
+#define IR7 0x80 /* IR7 */
+#define IR6 0x40 /* IR6 */
+#define IR5 0x20 /* IR5 */
+#define IR4 0x10 /* IR4 */
+#define IR3 0x08 /* IR3 */
+#define IR2 0x04 /* IR2 */
+#define IR1 0x02 /* IR1 */
+#define IR0 0x01 /* IR0 */
+
+/* bits for SEOI */
+#define SEOI_IR7 0x07 /* IR7 */
+#define SEOI_IR6 0x06 /* IR6 */
+#define SEOI_IR5 0x05 /* IR5 */
+#define SEOI_IR4 0x04 /* IR4 */
+#define SEOI_IR3 0x03 /* IR3 */
+#define SEOI_IR2 0x02 /* IR2 */
+#define SEOI_IR1 0x01 /* IR1 */
+#define SEOI_IR0 0x00 /* IR0 */
+
+/* OCW2 bits */
+#define OCW2_RCLR 0x00 /* Rotate/clear */
+#define OCW2_NEOI 0x20 /* Non specific EOI */
+#define OCW2_NOP 0x40 /* NOP */
+#define OCW2_SEOI 0x60 /* Specific EOI */
+#define OCW2_RSET 0x80 /* Rotate/set */
+#define OCW2_REOI 0xA0 /* Rotate on non specific EOI */
+#define OCW2_PSET 0xC0 /* Priority Set Command */
+#define OCW2_RSEOI 0xE0 /* Rotate on specific EOI */
+
+/* ICW1 bits */
+#define ICW1_SEL 0x10 /* Select ICW1 */
+#define ICW1_LTIM 0x08 /* Level-Triggered Interrupt Mode */
+#define ICW1_ADI 0x04 /* Address Interval */
+#define ICW1_SNGL 0x02 /* Single PIC */
+#define ICW1_EICW4 0x01 /* Expect initilization ICW4 */
+
+/* ICW2 is the starting vector number */
+
+/* ICW2 is bit-mask of present slaves for a master device,
+ * or the slave ID for a slave device */
+
+/* ICW4 bits */
+#define ICW4_AEOI 0x02 /* Automatic EOI Mode */
+#define ICW4_PM 0x01 /* Microprocessor Mode */
+
+#endif
diff --git a/arch/x86/include/asm/ibmpc.h b/arch/x86/include/asm/ibmpc.h
new file mode 100644
index 0000000000..e35cbd887a
--- /dev/null
+++ b/arch/x86/include/asm/ibmpc.h
@@ -0,0 +1,47 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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
+ */
+
+#ifndef __ASM_IBMPC_H_
+#define __ASM_IBMPC_H_ 1
+
+/* misc ports in an ibm compatible pc */
+
+#define MASTER_PIC 0x20
+#define PIT_BASE 0x40
+#define KBDDATA 0x60
+#define SYSCTLB 0x62
+#define KBDCMD 0x64
+#define SYSCTLA 0x92
+#define SLAVE_PIC 0xa0
+
+#if 1
+#define UART0_BASE 0x3f8
+#define UART1_BASE 0x2f8
+#else
+/* FixMe: uarts swapped */
+#define UART0_BASE 0x2f8
+#define UART1_BASE 0x3f8
+#endif
+
+
+#endif
diff --git a/arch/x86/include/asm/ic/pci.h b/arch/x86/include/asm/ic/pci.h
new file mode 100644
index 0000000000..2e4376b9b0
--- /dev/null
+++ b/arch/x86/include/asm/ic/pci.h
@@ -0,0 +1,79 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
+ *
+ * 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
+ */
+
+#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
+#define SC520_PCI_INTC 2
+#define SC520_PCI_INTD 3
+#define SC520_PCI_GPIRQ0 4
+#define SC520_PCI_GPIRQ1 5
+#define SC520_PCI_GPIRQ2 6
+#define SC520_PCI_GPIRQ3 7
+#define SC520_PCI_GPIRQ4 8
+#define SC520_PCI_GPIRQ5 9
+#define SC520_PCI_GPIRQ6 10
+#define SC520_PCI_GPIRQ7 11
+#define SC520_PCI_GPIRQ8 12
+#define SC520_PCI_GPIRQ9 13
+#define SC520_PCI_GPIRQ10 14
+
+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/x86/include/asm/ic/sc520.h b/arch/x86/include/asm/ic/sc520.h
new file mode 100644
index 0000000000..956c1c2636
--- /dev/null
+++ b/arch/x86/include/asm/ic/sc520.h
@@ -0,0 +1,398 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
+ *
+ * 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
+ */
+
+#ifndef _ASM_IC_SC520_H_
+#define _ASM_IC_SC520_H_ 1
+
+#ifndef __ASSEMBLY__
+
+void init_sc520(void);
+unsigned long init_sc520_dram(void);
+void sc520_udelay(unsigned long usec);
+
+/* Memory mapped configuration registers */
+typedef struct sc520_mmcr {
+ u16 revid; /* ElanSC520 microcontroller revision id */
+ u8 cpuctl; /* am5x86 CPU control */
+
+ u8 pad_0x003[0x0d];
+
+ u8 drcctl; /* SDRAM control */
+ u8 pad_0x011[0x01];
+ u8 drctmctl; /* SDRAM timing control */
+ u8 pad_0x013[0x01];
+ u16 drccfg; /* SDRAM bank configuration*/
+ u8 pad_0x016[0x02];
+ u32 drcbendadr; /* SDRAM bank 0-3 ending address*/
+ u8 pad_0x01c[0x04];
+ u8 eccctl; /* ECC control */
+ u8 eccsta; /* ECC status */
+ u8 eccckbpos; /* ECC check bit position */
+ u8 ecccktest; /* ECC Check Code Test */
+ u32 eccsbadd; /* ECC single-bit error address */
+ u32 eccmbadd; /* ECC multi-bit error address */
+
+ u8 pad_0x02c[0x14];
+
+ u8 dbctl; /* SDRAM buffer control */
+
+ u8 pad_0x041[0x0f];
+
+ u16 bootcsctl; /* /BOOTCS control */
+ u8 pad_0x052[0x02];
+ u16 romcs1ctl; /* /ROMCS1 control */
+ u16 romcs2ctl; /* /ROMCS2 control */
+
+ u8 pad_0x058[0x08];
+
+ u16 hbctl; /* host bridge control */
+ u16 hbtgtirqctl; /* host bridge target interrupt control */
+ u16 hbtgtirqsta; /* host bridge target interrupt status */
+ u16 hbmstirqctl; /* host bridge target interrupt control */
+ u16 hbmstirqsta; /* host bridge master interrupt status */
+ u8 pad_0x06a[0x02];
+ u32 mstintadd; /* host bridge master interrupt address */
+
+ u8 sysarbctl; /* system arbiter control */
+ u8 pciarbsta; /* PCI bus arbiter status */
+ u16 sysarbmenb; /* system arbiter master enable */
+ u32 arbprictl; /* arbiter priority control */
+
+ u8 pad_0x078[0x08];
+
+ u8 adddecctl; /* address decode control */
+ u8 pad_0x081[0x01];
+ u16 wpvsta; /* write-protect violation status */
+ u8 pad_0x084[0x04];
+ u32 par[16]; /* programmable address regions */
+
+ u8 pad_0x0c8[0x0b38];
+
+ u8 gpecho; /* GP echo mode */
+ u8 gpcsdw; /* GP chip select data width */
+ u16 gpcsqual; /* GP chip select qualification */
+ u8 pad_0xc04[0x4];
+ u8 gpcsrt; /* GP chip select recovery time */
+ u8 gpcspw; /* GP chip select pulse width */
+ u8 gpcsoff; /* GP chip select offset */
+ u8 gprdw; /* GP read pulse width */
+ u8 gprdoff; /* GP read offset */
+ u8 gpwrw; /* GP write pulse width */
+ u8 gpwroff; /* GP write offset */
+ u8 gpalew; /* GP ale pulse width */
+ u8 gpaleoff; /* GP ale offset */
+
+ u8 pad_0xc11[0x0f];
+
+ u16 piopfs15_0; /* PIO15-PIO0 pin function select */
+ u16 piopfs31_16; /* PIO31-PIO16 pin function select */
+ u8 cspfs; /* chip select pin function select */
+ u8 pad_0xc25[0x01];
+ u8 clksel; /* clock select */
+ u8 pad_0xc27[0x01];
+ u16 dsctl; /* drive strength control */
+ u16 piodir15_0; /* PIO15-PIO0 direction */
+ u16 piodir31_16; /* PIO31-PIO16 direction */
+ u8 pad_0xc2e[0x02];
+ u16 piodata15_0 ; /* PIO15-PIO0 data */
+ u16 piodata31_16; /* PIO31-PIO16 data */
+ u16 pioset15_0; /* PIO15-PIO0 set */
+ u16 pioset31_16; /* PIO31-PIO16 set */
+ u16 pioclr15_0; /* PIO15-PIO0 clear */
+ u16 pioclr31_16; /* PIO31-PIO16 clear */
+
+ u8 pad_0xc3c[0x24];
+
+ u16 swtmrmilli; /* software timer millisecond count */
+ u16 swtmrmicro; /* software timer microsecond count */
+ u8 swtmrcfg; /* software timer configuration */
+
+ u8 pad_0xc65[0x0b];
+
+ u8 gptmrsta; /* GP timers status register */
+ u8 pad_0xc71;
+ u16 gptmr0ctl; /* GP timer 0 mode/control */
+ u16 gptmr0cnt; /* GP timer 0 count */
+ u16 gptmr0maxcmpa; /* GP timer 0 maxcount compare A */
+ u16 gptmr0maxcmpb; /* GP timer 0 maxcount compare B */
+ u16 gptmr1ctl; /* GP timer 1 mode/control */
+ u16 gptmr1cnt; /* GP timer 1 count */
+ u16 gptmr1maxcmpa; /* GP timer 1 maxcount compare A */
+ u16 gptmr1maxcmpb; /* GP timer 1 maxcount compare B*/
+ u16 gptmr2ctl; /* GP timer 2 mode/control */
+ u16 gptmr2cnt; /* GP timer 2 count */
+ u8 pad_0xc86[0x08];
+ u16 gptmr2maxcmpa; /* GP timer 2 maxcount compare A */
+
+ u8 pad_0xc90[0x20];
+
+ u16 wdtmrctl; /* watchdog timer control */
+ u16 wdtmrcntl; /* watchdog timer count low */
+ u16 wdtmrcnth; /* watchdog timer count high */
+
+ u8 pad_0xcb6[0x0a];
+
+ u8 uart1ctl; /* UART 1 general control */
+ u8 uart1sta; /* UART 1 general status */
+ u8 uart1fcrshad; /* UART 1 FIFO control shadow */
+ u8 pad_0xcc3[0x01];
+ u8 uart2ctl; /* UART 2 general control */
+ u8 uart2sta; /* UART 2 general status */
+ u8 uart2fcrshad; /* UART 2 FIFO control shadow */
+
+ u8 pad_0xcc7[0x09];
+
+ u8 ssictl; /* SSI control */
+ u8 ssixmit; /* SSI transmit */
+ u8 ssicmd; /* SSI command */
+ u8 ssista; /* SSI status */
+ u8 ssircv; /* SSI receive */
+
+ u8 pad_0xcd5[0x2b];
+
+ u8 picicr; /* interrupt control */
+ u8 pad_0xd01[0x01];
+ u8 pic_mode[3]; /* PIC interrupt mode */
+ u8 pad_0xd05[0x03];
+ u16 swint16_1; /* software interrupt 16-1 control */
+ u8 swint22_17; /* software interrupt 22-17/NMI control */
+ u8 pad_0xd0b[0x05];
+ u16 intpinpol; /* interrupt pin polarity */
+ u8 pad_0xd12[0x02];
+ u16 pcihostmap; /* PCI host bridge interrupt mapping */
+ u8 pad_0xd16[0x02];
+ u16 eccmap; /* ECC interrupt mapping */
+ u8 gp_tmr_int_map[3]; /* GP timer interrupt mapping */
+ u8 pad_0xd1d[0x03];
+ u8 pit_int_map[3]; /* PIT interrupt mapping */
+ u8 pad_0xd23[0x05];
+ u8 uart_int_map[2]; /* UART interrupt mapping */
+ u8 pad_0xd2a[0x06];
+ u8 pci_int_map[4]; /* PCI interrupt mapping (A through D)*/
+ u8 pad_0xd34[0x0c];
+ u8 dmabcintmap; /* DMA buffer chaining interrupt mapping */
+ u8 ssimap; /* SSI interrupt mapping register */
+ u8 wdtmap; /* watchdog timer interrupt mapping */
+ u8 rtcmap; /* RTC interrupt mapping register */
+ u8 wpvmap; /* write-protect interrupt mapping */
+ u8 icemap; /* AMDebug JTAG Rx/Tx interrupt mapping */
+ u8 ferrmap; /* floating point error interrupt mapping */
+ u8 pad_0xd47[0x09];
+ u8 gp_int_map[11]; /* GP IRQ interrupt mapping */
+
+ u8 pad_0xd5b[0x15];
+
+ u8 sysinfo; /* system board information */
+ u8 pad_0xd71[0x01];
+ u8 rescfg; /* reset configuration */
+ u8 pad_0xd73[0x01];
+ u8 ressta; /* reset status */
+
+ u8 pad_0xd75[0x0b];
+
+ u8 gpdmactl; /* GP-DMA Control */
+ u8 gpdmammio; /* GP-DMA memory-mapped I/O */
+ u16 gpdmaextchmapa; /* GP-DMA resource channel map a */
+ u16 gpdmaextchmapb; /* GP-DMA resource channel map b */
+ u8 gp_dma_ext_pg_0; /* GP-DMA channel extended page 0 */
+ u8 gp_dma_ext_pg_1; /* GP-DMA channel extended page 0 */
+ u8 gp_dma_ext_pg_2; /* GP-DMA channel extended page 0 */
+ u8 gp_dma_ext_pg_3; /* GP-DMA channel extended page 0 */
+ u8 gp_dma_ext_pg_5; /* GP-DMA channel extended page 0 */
+ u8 gp_dma_ext_pg_6; /* GP-DMA channel extended page 0 */
+ u8 gp_dma_ext_pg_7; /* GP-DMA channel extended page 0 */
+ u8 pad_0xd8d[0x03];
+ u8 gpdmaexttc3; /* GP-DMA channel 3 extender transfer count */
+ u8 gpdmaexttc5; /* GP-DMA channel 5 extender transfer count */
+ u8 gpdmaexttc6; /* GP-DMA channel 6 extender transfer count */
+ u8 gpdmaexttc7; /* GP-DMA channel 7 extender transfer count */
+ u8 pad_0xd94[0x4];
+ u8 gpdmabcctl; /* buffer chaining control */
+ u8 gpdmabcsta; /* buffer chaining status */
+ u8 gpdmabsintenb; /* buffer chaining interrupt enable */
+ u8 gpdmabcval; /* buffer chaining valid */
+ u8 pad_0xd9c[0x04];
+ u16 gpdmanxtaddl3; /* GP-DMA channel 3 next address low */
+ u16 gpdmanxtaddh3; /* GP-DMA channel 3 next address high */
+ u16 gpdmanxtaddl5; /* GP-DMA channel 5 next address low */
+ u16 gpdmanxtaddh5; /* GP-DMA channel 5 next address high */
+ u16 gpdmanxtaddl6; /* GP-DMA channel 6 next address low */
+ u16 gpdmanxtaddh6; /* GP-DMA channel 6 next address high */
+ u16 gpdmanxtaddl7; /* GP-DMA channel 7 next address low */
+ u16 gpdmanxtaddh7; /* GP-DMA channel 7 next address high */
+ u16 gpdmanxttcl3; /* GP-DMA channel 3 next transfer count low */
+ u16 gpdmanxttch3; /* GP-DMA channel 3 next transfer count high */
+ u16 gpdmanxttcl5; /* GP-DMA channel 5 next transfer count low */
+ u16 gpdmanxttch5; /* GP-DMA channel 5 next transfer count high */
+ u16 gpdmanxttcl6; /* GP-DMA channel 6 next transfer count low */
+ u16 gpdmanxttch6; /* GP-DMA channel 6 next transfer count high */
+ u16 gpdmanxttcl7; /* GP-DMA channel 7 next transfer count low */
+ u16 gpdmanxttch7; /* GP-DMA channel 7 next transfer count high */
+
+ u8 pad_0xdc0[0x0240];
+} sc520_mmcr_t;
+
+extern sc520_mmcr_t *sc520_mmcr;
+
+#endif
+
+/* Memory Mapped Control Registers (MMCR) Base Address */
+#define SC520_MMCR_BASE 0xfffef000
+
+/* MMCR Addresses (required for assembler code) */
+#define SC520_DRCCTL (SC520_MMCR_BASE + 0x010)
+#define SC520_DRCTMCTL (SC520_MMCR_BASE + 0x012)
+#define SC520_DRCCFG (SC520_MMCR_BASE + 0x014)
+#define SC520_DRCBENDADR (SC520_MMCR_BASE + 0x018)
+#define SC520_ECCCTL (SC520_MMCR_BASE + 0x020)
+#define SC520_DBCTL (SC520_MMCR_BASE + 0x040)
+#define SC520_ECCINT (SC520_MMCR_BASE + 0xd18)
+
+#define SC520_PAR0 (SC520_MMCR_BASE + 0x088)
+#define SC520_PAR1 (SC520_PAR0 + (0x04 * 1))
+#define SC520_PAR2 (SC520_PAR0 + (0x04 * 2))
+#define SC520_PAR3 (SC520_PAR0 + (0x04 * 3))
+#define SC520_PAR4 (SC520_PAR0 + (0x04 * 4))
+#define SC520_PAR5 (SC520_PAR0 + (0x04 * 5))
+#define SC520_PAR6 (SC520_PAR0 + (0x04 * 6))
+#define SC520_PAR7 (SC520_PAR0 + (0x04 * 7))
+#define SC520_PAR8 (SC520_PAR0 + (0x04 * 8))
+#define SC520_PAR9 (SC520_PAR0 + (0x04 * 9))
+#define SC520_PAR10 (SC520_PAR0 + (0x04 * 10))
+#define SC520_PAR11 (SC520_PAR0 + (0x04 * 11))
+#define SC520_PAR12 (SC520_PAR0 + (0x04 * 12))
+#define SC520_PAR13 (SC520_PAR0 + (0x04 * 13))
+#define SC520_PAR14 (SC520_PAR0 + (0x04 * 14))
+#define SC520_PAR15 (SC520_PAR0 + (0x04 * 15))
+
+/*
+ * PARs for maximum allowable 256MB of SDRAM @ 0x00000000
+ * Two PARs are required due to maximum PAR size of 128MB
+ * These are used in the SDRAM sizing code to disable caching
+ *
+ * 111 0 0 0 1 11111111111 00000000000000 }- 0xe3ffc000
+ * 111 0 0 0 1 11111111111 00100000000000 }- 0xe3ffc800
+ * \ / | | | | \----+----/ \-----+------/
+ * | | | | | | +---------- Start at 0x00000000
+ * | | | | | | 0x08000000
+ * | | | | | +----------------------- 128MB Region Size
+ * | | | | | ((2047 + 1) * 64kB)
+ * | | | | +------------------------------ 64kB Page Size
+ * | | | +-------------------------------- Writes Enabled
+ * | | +---------------------------------- Caching Enabled
+ * | +------------------------------------ Execution Enabled
+ * +--------------------------------------- SDRAM
+ */
+#define SC520_SDRAM1_PAR 0xe3ffc000
+#define SC520_SDRAM2_PAR 0xe3ffc800
+
+#define SC520_PAR_WRITE_DIS 0x04000000
+#define SC520_PAR_CACHE_DIS 0x08000000
+#define SC520_PAR_EXEC_DIS 0x10000000
+
+/*
+ * Programmable Address Regions to cover 256MB SDRAM (Maximum supported)
+ * required for DRAM sizing code
+ */
+
+/* MMCR Register bits (not all of them :) ) */
+
+/* SSI Stuff */
+#define CTL_CLK_SEL_4 0x00 /* Nominal Bit Rate = 8 MHz */
+#define CTL_CLK_SEL_8 0x10 /* Nominal Bit Rate = 4 MHz */
+#define CTL_CLK_SEL_16 0x20 /* Nominal Bit Rate = 2 MHz */
+#define CTL_CLK_SEL_32 0x30 /* Nominal Bit Rate = 1 MHz */
+#define CTL_CLK_SEL_64 0x40 /* Nominal Bit Rate = 512 KHz */
+#define CTL_CLK_SEL_128 0x50 /* Nominal Bit Rate = 256 KHz */
+#define CTL_CLK_SEL_256 0x60 /* Nominal Bit Rate = 128 KHz */
+#define CTL_CLK_SEL_512 0x70 /* Nominal Bit Rate = 64 KHz */
+
+#define TC_INT_ENB 0x08 /* Transaction Complete Interrupt Enable */
+#define PHS_INV_ENB 0x04 /* SSI Inverted Phase Mode Enable */
+#define CLK_INV_ENB 0x02 /* SSI Inverted Clock Mode Enable */
+#define MSBF_ENB 0x01 /* SSI Most Significant Bit First Mode Enable */
+
+#define SSICMD_CMD_SEL_XMITRCV 0x03 /* Simultaneous Transmit / Receive Transaction */
+#define SSICMD_CMD_SEL_RCV 0x02 /* Receive Transaction */
+#define SSICMD_CMD_SEL_XMIT 0x01 /* Transmit Transaction */
+#define SSISTA_BSY 0x02 /* SSI Busy */
+#define SSISTA_TC_INT 0x01 /* SSI Transaction Complete Interrupt */
+
+/* BITS for SC520_ADDDECCTL: */
+#define WPV_INT_ENB 0x80 /* Write-Protect Violation Interrupt Enable */
+#define IO_HOLE_DEST_PCI 0x10 /* I/O Hole Access Destination */
+#define RTC_DIS 0x04 /* RTC Disable */
+#define UART2_DIS 0x02 /* UART2 Disable */
+#define UART1_DIS 0x01 /* UART1 Disable */
+
+/*
+ * Defines used for SDRAM Sizing (number of columns and rows)
+ * Refer to section 10.6.4 - SDRAM Sizing Algorithm in the
+ * Elan SC520 Microcontroller User's Manual (Order #22004B)
+ */
+#define CACHELINESZ 0x00000010
+
+#define COL11_ADR 0x0e001e00
+#define COL10_ADR 0x0e000e00
+#define COL09_ADR 0x0e000600
+#define COL08_ADR 0x0e000200
+#define COL11_DATA 0x0b0b0b0b
+#define COL10_DATA 0x0a0a0a0a
+#define COL09_DATA 0x09090909
+#define COL08_DATA 0x08080808
+
+#define ROW14_ADR 0x0f000000
+#define ROW13_ADR 0x07000000
+#define ROW12_ADR 0x03000000
+#define ROW11_ADR 0x01000000
+#define ROW10_ADR 0x00000000
+#define ROW14_DATA 0x3f3f3f3f
+#define ROW13_DATA 0x1f1f1f1f
+#define ROW12_DATA 0x0f0f0f0f
+#define ROW11_DATA 0x07070707
+#define ROW10_DATA 0xaaaaaaaa
+
+/* 0x28000000 - 0x3fffffff is used by the flash banks */
+
+/* 0x40000000 - 0xffffffff is not adressable by the SC520 */
+
+/* priority numbers used for interrupt channel mappings */
+#define SC520_IRQ_DISABLED 0
+#define SC520_IRQ0 1
+#define SC520_IRQ1 2
+#define SC520_IRQ2 4 /* same as IRQ9 */
+#define SC520_IRQ3 11
+#define SC520_IRQ4 12
+#define SC520_IRQ5 13
+#define SC520_IRQ6 21
+#define SC520_IRQ7 22
+#define SC520_IRQ8 3
+#define SC520_IRQ9 4
+#define SC520_IRQ10 5
+#define SC520_IRQ11 6
+#define SC520_IRQ12 7
+#define SC520_IRQ13 8
+#define SC520_IRQ14 9
+#define SC520_IRQ15 10
+
+#endif
diff --git a/arch/x86/include/asm/ic/ssi.h b/arch/x86/include/asm/ic/ssi.h
new file mode 100644
index 0000000000..bd48eab161
--- /dev/null
+++ b/arch/x86/include/asm/ic/ssi.h
@@ -0,0 +1,34 @@
+/*
+ * (C) Copyright 2008
+ * Graeme Russ <graeme.russ@gmail.com>.
+ *
+ * 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
+ */
+
+#ifndef _ASM_IC_SSI_H_
+#define _ASM_IC_SSI_H_ 1
+
+int ssi_set_interface(int, int, int, int);
+void ssi_chip_select(int);
+u8 ssi_txrx_byte(u8);
+void ssi_tx_byte(u8);
+u8 ssi_rx_byte(void);
+
+
+#endif
diff --git a/arch/x86/include/asm/interrupt.h b/arch/x86/include/asm/interrupt.h
new file mode 100644
index 0000000000..be52fe40d0
--- /dev/null
+++ b/arch/x86/include/asm/interrupt.h
@@ -0,0 +1,46 @@
+/*
+ * (C) Copyright 2009
+ * Graeme Russ, graeme.russ@gmail.com
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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
+ */
+
+#ifndef __ASM_INTERRUPT_H_
+#define __ASM_INTERRUPT_H_ 1
+
+#include <asm/types.h>
+
+/* arch/x86/cpu/interrupts.c */
+void set_vector(u8 intnum, void *routine);
+
+/* arch/x86/lib/interupts.c */
+void disable_irq(int irq);
+void enable_irq(int irq);
+
+/* Architecture specific functions */
+void mask_irq(int irq);
+void unmask_irq(int irq);
+void specific_eoi(int irq);
+
+extern char exception_stack[];
+
+#endif
diff --git a/arch/x86/include/asm/io.h b/arch/x86/include/asm/io.h
new file mode 100644
index 0000000000..9b757d489e
--- /dev/null
+++ b/arch/x86/include/asm/io.h
@@ -0,0 +1,237 @@
+#ifndef _ASM_IO_H
+#define _ASM_IO_H
+
+/*
+ * This file contains the definitions for the x86 IO instructions
+ * inb/inw/inl/outb/outw/outl and the "string versions" of the same
+ * (insb/insw/insl/outsb/outsw/outsl). You can also use "pausing"
+ * versions of the single-IO instructions (inb_p/inw_p/..).
+ *
+ * This file is not meant to be obfuscating: it's just complicated
+ * to (a) handle it all in a way that makes gcc able to optimize it
+ * as well as possible and (b) trying to avoid writing the same thing
+ * over and over again with slight variations and possibly making a
+ * mistake somewhere.
+ */
+
+/*
+ * Thanks to James van Artsdalen for a better timing-fix than
+ * the two short jumps: using outb's to a nonexistent port seems
+ * to guarantee better timings even on fast machines.
+ *
+ * On the other hand, I'd like to be sure of a non-existent port:
+ * I feel a bit unsafe about using 0x80 (should be safe, though)
+ *
+ * Linus
+ */
+
+ /*
+ * Bit simplified and optimized by Jan Hubicka
+ * Support of BIGMEM added by Gerhard Wichert, Siemens AG, July 1999.
+ *
+ * isa_memset_io, isa_memcpy_fromio, isa_memcpy_toio added,
+ * isa_read[wl] and isa_write[wl] fixed
+ * - Arnaldo Carvalho de Melo <acme@conectiva.com.br>
+ */
+
+#define IO_SPACE_LIMIT 0xffff
+
+
+#ifdef __KERNEL__
+
+
+/*
+ * readX/writeX() are used to access memory mapped devices. On some
+ * architectures the memory mapped IO stuff needs to be accessed
+ * differently. On the x86 architecture, we just read/write the
+ * memory location directly.
+ */
+
+#define readb(addr) (*(volatile unsigned char *) (addr))
+#define readw(addr) (*(volatile unsigned short *) (addr))
+#define readl(addr) (*(volatile unsigned int *) (addr))
+#define __raw_readb readb
+#define __raw_readw readw
+#define __raw_readl readl
+
+#define writeb(b,addr) (*(volatile unsigned char *) (addr) = (b))
+#define writew(b,addr) (*(volatile unsigned short *) (addr) = (b))
+#define writel(b,addr) (*(volatile unsigned int *) (addr) = (b))
+#define __raw_writeb writeb
+#define __raw_writew writew
+#define __raw_writel writel
+
+#define memset_io(a,b,c) memset((a),(b),(c))
+#define memcpy_fromio(a,b,c) memcpy((a),(b),(c))
+#define memcpy_toio(a,b,c) memcpy((a),(b),(c))
+
+/*
+ * ISA space is 'always mapped' on a typical x86 system, no need to
+ * explicitly ioremap() it. The fact that the ISA IO space is mapped
+ * to PAGE_OFFSET is pure coincidence - it does not mean ISA values
+ * are physical addresses. The following constant pointer can be
+ * used as the IO-area pointer (it can be iounmapped as well, so the
+ * analogy with PCI is quite large):
+ */
+#define isa_readb(a) readb((a))
+#define isa_readw(a) readw((a))
+#define isa_readl(a) readl((a))
+#define isa_writeb(b,a) writeb(b,(a))
+#define isa_writew(w,a) writew(w,(a))
+#define isa_writel(l,a) writel(l,(a))
+#define isa_memset_io(a,b,c) memset_io((a),(b),(c))
+#define isa_memcpy_fromio(a,b,c) memcpy_fromio((a),(b),(c))
+#define isa_memcpy_toio(a,b,c) memcpy_toio((a),(b),(c))
+
+
+static inline int check_signature(unsigned long io_addr,
+ const unsigned char *signature, int length)
+{
+ int retval = 0;
+ do {
+ if (readb(io_addr) != *signature)
+ goto out;
+ io_addr++;
+ signature++;
+ length--;
+ } while (length);
+ retval = 1;
+out:
+ return retval;
+}
+
+/**
+ * isa_check_signature - find BIOS signatures
+ * @io_addr: mmio address to check
+ * @signature: signature block
+ * @length: length of signature
+ *
+ * Perform a signature comparison with the ISA mmio address io_addr.
+ * Returns 1 on a match.
+ *
+ * This function is deprecated. New drivers should use ioremap and
+ * check_signature.
+ */
+
+
+static inline int isa_check_signature(unsigned long io_addr,
+ const unsigned char *signature, int length)
+{
+ int retval = 0;
+ do {
+ if (isa_readb(io_addr) != *signature)
+ goto out;
+ io_addr++;
+ signature++;
+ length--;
+ } while (length);
+ retval = 1;
+out:
+ return retval;
+}
+
+#endif /* __KERNEL__ */
+
+#ifdef SLOW_IO_BY_JUMPING
+#define __SLOW_DOWN_IO "\njmp 1f\n1:\tjmp 1f\n1:"
+#else
+#define __SLOW_DOWN_IO "\noutb %%al,$0x80"
+#endif
+
+#ifdef REALLY_SLOW_IO
+#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO __SLOW_DOWN_IO
+#else
+#define __FULL_SLOW_DOWN_IO __SLOW_DOWN_IO
+#endif
+
+
+/*
+ * Talk about misusing macros..
+ */
+#define __OUT1(s,x) \
+static inline void out##s(unsigned x value, unsigned short port) {
+
+#define __OUT2(s,s1,s2) \
+__asm__ __volatile__ ("out" #s " %" s1 "0,%" s2 "1"
+
+
+#define __OUT(s,s1,x) \
+__OUT1(s,x) __OUT2(s,s1,"w") : : "a" (value), "Nd" (port)); } \
+__OUT1(s##_p,x) __OUT2(s,s1,"w") __FULL_SLOW_DOWN_IO : : "a" (value), "Nd" (port));}
+
+#define __IN1(s) \
+static inline RETURN_TYPE in##s(unsigned short port) { RETURN_TYPE _v;
+
+#define __IN2(s,s1,s2) \
+__asm__ __volatile__ ("in" #s " %" s2 "1,%" s1 "0"
+
+#define __IN(s,s1,i...) \
+__IN1(s) __IN2(s,s1,"w") : "=a" (_v) : "Nd" (port) ,##i ); return _v; } \
+__IN1(s##_p) __IN2(s,s1,"w") __FULL_SLOW_DOWN_IO : "=a" (_v) : "Nd" (port) ,##i ); return _v; }
+
+#define __INS(s) \
+static inline void ins##s(unsigned short port, void * addr, unsigned long count) \
+{ __asm__ __volatile__ ("rep ; ins" #s \
+: "=D" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
+
+#define __OUTS(s) \
+static inline void outs##s(unsigned short port, const void * addr, unsigned long count) \
+{ __asm__ __volatile__ ("rep ; outs" #s \
+: "=S" (addr), "=c" (count) : "d" (port),"0" (addr),"1" (count)); }
+
+#define RETURN_TYPE unsigned char
+__IN(b,"")
+#undef RETURN_TYPE
+#define RETURN_TYPE unsigned short
+__IN(w,"")
+#undef RETURN_TYPE
+#define RETURN_TYPE unsigned int
+__IN(l,"")
+#undef RETURN_TYPE
+
+__OUT(b,"b",char)
+__OUT(w,"w",short)
+__OUT(l,,int)
+
+__INS(b)
+__INS(w)
+__INS(l)
+
+__OUTS(b)
+__OUTS(w)
+__OUTS(l)
+
+static inline void sync(void)
+{
+}
+
+/*
+ * Given a physical address and a length, return a virtual address
+ * that can be used to access the memory range with the caching
+ * properties specified by "flags".
+ */
+#define MAP_NOCACHE (0)
+#define MAP_WRCOMBINE (0)
+#define MAP_WRBACK (0)
+#define MAP_WRTHROUGH (0)
+
+static inline void *
+map_physmem(phys_addr_t paddr, unsigned long len, unsigned long flags)
+{
+ return (void *)paddr;
+}
+
+/*
+ * Take down a mapping set up by map_physmem().
+ */
+static inline void unmap_physmem(void *vaddr, unsigned long flags)
+{
+
+}
+
+static inline phys_addr_t virt_to_phys(void * vaddr)
+{
+ return (phys_addr_t)(vaddr);
+}
+
+#endif
diff --git a/arch/x86/include/asm/ioctl.h b/arch/x86/include/asm/ioctl.h
new file mode 100644
index 0000000000..b279fe06df
--- /dev/null
+++ b/arch/x86/include/asm/ioctl.h
@@ -0,0 +1 @@
+#include <asm-generic/ioctl.h>
diff --git a/arch/x86/include/asm/ist.h b/arch/x86/include/asm/ist.h
new file mode 100644
index 0000000000..7e5dff1de0
--- /dev/null
+++ b/arch/x86/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/x86/include/asm/pci.h b/arch/x86/include/asm/pci.h
new file mode 100644
index 0000000000..050a2bb868
--- /dev/null
+++ b/arch/x86/include/asm/pci.h
@@ -0,0 +1,34 @@
+
+
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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
+ */
+
+#ifndef _PCI_I386_H_
+#define _PCI_I386_H_ 1
+
+void pci_setup_type1(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data);
+int pci_enable_legacy_video_ports(struct pci_controller* hose);
+int pci_shadow_rom(pci_dev_t dev, unsigned char *dest);
+void pci_remove_rom_window(struct pci_controller* hose, u32 addr);
+u32 pci_get_rom_window(struct pci_controller* hose, int size);
+#endif
diff --git a/arch/x86/include/asm/posix_types.h b/arch/x86/include/asm/posix_types.h
new file mode 100644
index 0000000000..5529f32702
--- /dev/null
+++ b/arch/x86/include/asm/posix_types.h
@@ -0,0 +1,80 @@
+#ifndef __ARCH_I386_POSIX_TYPES_H
+#define __ARCH_I386_POSIX_TYPES_H
+
+/*
+ * This file is generally used by user-level software, so you need to
+ * be a little careful about namespace pollution etc. Also, we cannot
+ * assume GCC is being used.
+ */
+
+typedef unsigned short __kernel_dev_t;
+typedef unsigned long __kernel_ino_t;
+typedef unsigned short __kernel_mode_t;
+typedef unsigned short __kernel_nlink_t;
+typedef long __kernel_off_t;
+typedef int __kernel_pid_t;
+typedef unsigned short __kernel_ipc_pid_t;
+typedef unsigned short __kernel_uid_t;
+typedef unsigned short __kernel_gid_t;
+typedef unsigned int __kernel_size_t;
+typedef int __kernel_ssize_t;
+typedef int __kernel_ptrdiff_t;
+typedef long __kernel_time_t;
+typedef long __kernel_suseconds_t;
+typedef long __kernel_clock_t;
+typedef int __kernel_daddr_t;
+typedef char * __kernel_caddr_t;
+typedef unsigned short __kernel_uid16_t;
+typedef unsigned short __kernel_gid16_t;
+typedef unsigned int __kernel_uid32_t;
+typedef unsigned int __kernel_gid32_t;
+
+typedef unsigned short __kernel_old_uid_t;
+typedef unsigned short __kernel_old_gid_t;
+
+#ifdef __GNUC__
+typedef long long __kernel_loff_t;
+#endif
+
+typedef struct {
+#if defined(__KERNEL__) || defined(__USE_ALL)
+ int val[2];
+#else /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+ int __val[2];
+#endif /* !defined(__KERNEL__) && !defined(__USE_ALL) */
+} __kernel_fsid_t;
+
+#if defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2)
+
+#undef __FD_SET
+#define __FD_SET(fd,fdsetp) \
+ __asm__ __volatile__("btsl %1,%0": \
+ "=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
+
+#undef __FD_CLR
+#define __FD_CLR(fd,fdsetp) \
+ __asm__ __volatile__("btrl %1,%0": \
+ "=m" (*(__kernel_fd_set *) (fdsetp)):"r" ((int) (fd)))
+
+#undef __FD_ISSET
+#define __FD_ISSET(fd,fdsetp) (__extension__ ({ \
+ unsigned char __result; \
+ __asm__ __volatile__("btl %1,%2 ; setb %0" \
+ :"=q" (__result) :"r" ((int) (fd)), \
+ "m" (*(__kernel_fd_set *) (fdsetp))); \
+ __result; }))
+
+#undef __FD_ZERO
+#define __FD_ZERO(fdsetp) \
+do { \
+ int __d0, __d1; \
+ __asm__ __volatile__("cld ; rep ; stosl" \
+ :"=m" (*(__kernel_fd_set *) (fdsetp)), \
+ "=&c" (__d0), "=&D" (__d1) \
+ :"a" (0), "1" (__FDSET_LONGS), \
+ "2" ((__kernel_fd_set *) (fdsetp)) : "memory"); \
+} while (0)
+
+#endif /* defined(__KERNEL__) || !defined(__GLIBC__) || (__GLIBC__ < 2) */
+
+#endif
diff --git a/arch/x86/include/asm/processor-flags.h b/arch/x86/include/asm/processor-flags.h
new file mode 100644
index 0000000000..7a3e836eb2
--- /dev/null
+++ b/arch/x86/include/asm/processor-flags.h
@@ -0,0 +1,100 @@
+#ifndef _ASM_X86_PROCESSOR_FLAGS_H
+#define _ASM_X86_PROCESSOR_FLAGS_H
+/* Various flags defined: can be included from assembler. */
+
+/*
+ * EFLAGS bits
+ */
+#define X86_EFLAGS_CF 0x00000001 /* Carry Flag */
+#define X86_EFLAGS_PF 0x00000004 /* Parity Flag */
+#define X86_EFLAGS_AF 0x00000010 /* Auxillary carry Flag */
+#define X86_EFLAGS_ZF 0x00000040 /* Zero Flag */
+#define X86_EFLAGS_SF 0x00000080 /* Sign Flag */
+#define X86_EFLAGS_TF 0x00000100 /* Trap Flag */
+#define X86_EFLAGS_IF 0x00000200 /* Interrupt Flag */
+#define X86_EFLAGS_DF 0x00000400 /* Direction Flag */
+#define X86_EFLAGS_OF 0x00000800 /* Overflow Flag */
+#define X86_EFLAGS_IOPL 0x00003000 /* IOPL mask */
+#define X86_EFLAGS_NT 0x00004000 /* Nested Task */
+#define X86_EFLAGS_RF 0x00010000 /* Resume Flag */
+#define X86_EFLAGS_VM 0x00020000 /* Virtual Mode */
+#define X86_EFLAGS_AC 0x00040000 /* Alignment Check */
+#define X86_EFLAGS_VIF 0x00080000 /* Virtual Interrupt Flag */
+#define X86_EFLAGS_VIP 0x00100000 /* Virtual Interrupt Pending */
+#define X86_EFLAGS_ID 0x00200000 /* CPUID detection flag */
+
+/*
+ * Basic CPU control in CR0
+ */
+#define X86_CR0_PE 0x00000001 /* Protection Enable */
+#define X86_CR0_MP 0x00000002 /* Monitor Coprocessor */
+#define X86_CR0_EM 0x00000004 /* Emulation */
+#define X86_CR0_TS 0x00000008 /* Task Switched */
+#define X86_CR0_ET 0x00000010 /* Extension Type */
+#define X86_CR0_NE 0x00000020 /* Numeric Error */
+#define X86_CR0_WP 0x00010000 /* Write Protect */
+#define X86_CR0_AM 0x00040000 /* Alignment Mask */
+#define X86_CR0_NW 0x20000000 /* Not Write-through */
+#define X86_CR0_CD 0x40000000 /* Cache Disable */
+#define X86_CR0_PG 0x80000000 /* Paging */
+
+/*
+ * Paging options in CR3
+ */
+#define X86_CR3_PWT 0x00000008 /* Page Write Through */
+#define X86_CR3_PCD 0x00000010 /* Page Cache Disable */
+
+/*
+ * Intel CPU features in CR4
+ */
+#define X86_CR4_VME 0x00000001 /* enable vm86 extensions */
+#define X86_CR4_PVI 0x00000002 /* virtual interrupts flag enable */
+#define X86_CR4_TSD 0x00000004 /* disable time stamp at ipl 3 */
+#define X86_CR4_DE 0x00000008 /* enable debugging extensions */
+#define X86_CR4_PSE 0x00000010 /* enable page size extensions */
+#define X86_CR4_PAE 0x00000020 /* enable physical address extensions */
+#define X86_CR4_MCE 0x00000040 /* Machine check enable */
+#define X86_CR4_PGE 0x00000080 /* enable global pages */
+#define X86_CR4_PCE 0x00000100 /* enable performance counters at ipl 3 */
+#define X86_CR4_OSFXSR 0x00000200 /* enable fast FPU save and restore */
+#define X86_CR4_OSXMMEXCPT 0x00000400 /* enable unmasked SSE exceptions */
+#define X86_CR4_VMXE 0x00002000 /* enable VMX virtualization */
+#define X86_CR4_OSXSAVE 0x00040000 /* enable xsave and xrestore */
+
+/*
+ * x86-64 Task Priority Register, CR8
+ */
+#define X86_CR8_TPR 0x0000000F /* task priority register */
+
+/*
+ * AMD and Transmeta use MSRs for configuration; see <asm/msr-index.h>
+ */
+
+/*
+ * NSC/Cyrix CPU configuration register indexes
+ */
+#define CX86_PCR0 0x20
+#define CX86_GCR 0xb8
+#define CX86_CCR0 0xc0
+#define CX86_CCR1 0xc1
+#define CX86_CCR2 0xc2
+#define CX86_CCR3 0xc3
+#define CX86_CCR4 0xe8
+#define CX86_CCR5 0xe9
+#define CX86_CCR6 0xea
+#define CX86_CCR7 0xeb
+#define CX86_PCR1 0xf0
+#define CX86_DIR0 0xfe
+#define CX86_DIR1 0xff
+#define CX86_ARR_BASE 0xc4
+#define CX86_RCR_BASE 0xdc
+
+#ifdef __KERNEL__
+#ifdef CONFIG_VM86
+#define X86_VM_MASK X86_EFLAGS_VM
+#else
+#define X86_VM_MASK 0 /* No VM86 support */
+#endif
+#endif
+
+#endif /* _ASM_X86_PROCESSOR_FLAGS_H */
diff --git a/arch/x86/include/asm/processor.h b/arch/x86/include/asm/processor.h
new file mode 100644
index 0000000000..22a129813c
--- /dev/null
+++ b/arch/x86/include/asm/processor.h
@@ -0,0 +1,32 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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
+ */
+
+#ifndef __ASM_PROCESSOR_H_
+#define __ASM_PROCESSOR_H_ 1
+
+#define GDT_ENTRY_32BIT_CS 2
+#define GDT_ENTRY_32BIT_DS (GDT_ENTRY_32BIT_CS + 1)
+#define GDT_ENTRY_16BIT_CS (GDT_ENTRY_32BIT_DS + 1)
+#define GDT_ENTRY_16BIT_DS (GDT_ENTRY_16BIT_CS + 1)
+
+#endif
diff --git a/arch/x86/include/asm/ptrace.h b/arch/x86/include/asm/ptrace.h
new file mode 100644
index 0000000000..a727dbfb05
--- /dev/null
+++ b/arch/x86/include/asm/ptrace.h
@@ -0,0 +1,90 @@
+#ifndef _I386_PTRACE_H
+#define _I386_PTRACE_H
+
+#include <asm/types.h>
+
+#define EBX 0
+#define ECX 1
+#define EDX 2
+#define ESI 3
+#define EDI 4
+#define EBP 5
+#define EAX 6
+#define DS 7
+#define ES 8
+#define FS 9
+#define GS 10
+#define ORIG_EAX 11
+#define EIP 12
+#define CS 13
+#define EFL 14
+#define UESP 15
+#define SS 16
+#define FRAME_SIZE 17
+
+/* this struct defines the way the registers are stored on the
+ stack during a system call. */
+
+struct pt_regs {
+ long ebx;
+ long ecx;
+ long edx;
+ long esi;
+ long edi;
+ long ebp;
+ long eax;
+ int xds;
+ int xes;
+ int xfs;
+ int xgs;
+ long orig_eax;
+ long eip;
+ int xcs;
+ long eflags;
+ long esp;
+ int xss;
+} __attribute__ ((packed));
+
+struct irq_regs {
+ /* Pushed by irq_common_entry */
+ long ebx;
+ long ecx;
+ long edx;
+ long esi;
+ long edi;
+ long ebp;
+ long esp;
+ long eax;
+ long xds;
+ long xes;
+ long xfs;
+ long xgs;
+ long xss;
+ /* Pushed by vector handler (irq_<num>) */
+ long irq_id;
+ /* Pushed by cpu in response to interrupt */
+ long eip;
+ long xcs;
+ long eflags;
+} __attribute__ ((packed));
+
+/* Arbitrarily choose the same ptrace numbers as used by the Sparc code. */
+#define PTRACE_GETREGS 12
+#define PTRACE_SETREGS 13
+#define PTRACE_GETFPREGS 14
+#define PTRACE_SETFPREGS 15
+#define PTRACE_GETFPXREGS 18
+#define PTRACE_SETFPXREGS 19
+
+#define PTRACE_SETOPTIONS 21
+
+/* options set using PTRACE_SETOPTIONS */
+#define PTRACE_O_TRACESYSGOOD 0x00000001
+
+#ifdef __KERNEL__
+#define user_mode(regs) ((VM_MASK & (regs)->eflags) || (3 & (regs)->xcs))
+#define instruction_pointer(regs) ((regs)->eip)
+extern void show_regs(struct pt_regs *);
+#endif
+
+#endif
diff --git a/arch/x86/include/asm/realmode.h b/arch/x86/include/asm/realmode.h
new file mode 100644
index 0000000000..9177e4ec0d
--- /dev/null
+++ b/arch/x86/include/asm/realmode.h
@@ -0,0 +1,32 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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
+ */
+
+#ifndef __ASM_REALMODE_H_
+#define __ASM_REALMODE_H_
+#include <asm/ptrace.h>
+
+int bios_setup(void);
+int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out);
+int enter_realmode_int(u8 lvl, struct pt_regs *in, struct pt_regs *out);
+
+#endif
diff --git a/arch/x86/include/asm/string.h b/arch/x86/include/asm/string.h
new file mode 100644
index 0000000000..3643a79fdf
--- /dev/null
+++ b/arch/x86/include/asm/string.h
@@ -0,0 +1,32 @@
+#ifndef __ASM_I386_STRING_H
+#define __ASM_I386_STRING_H
+
+/*
+ * We don't do inline string functions, since the
+ * optimised inline asm versions are not small.
+ */
+#undef __HAVE_ARCH_STRNCPY
+extern char *strncpy(char *__dest, __const__ char *__src, __kernel_size_t __n);
+
+#undef __HAVE_ARCH_STRRCHR
+extern char * strrchr(const char * s, int c);
+
+#undef __HAVE_ARCH_STRCHR
+extern char * strchr(const char * s, int c);
+
+#undef __HAVE_ARCH_MEMCPY
+extern void * memcpy(void *, const void *, __kernel_size_t);
+
+#undef __HAVE_ARCH_MEMMOVE
+extern void * memmove(void *, const void *, __kernel_size_t);
+
+#undef __HAVE_ARCH_MEMCHR
+extern void * memchr(const void *, int, __kernel_size_t);
+
+#undef __HAVE_ARCH_MEMSET
+extern void * memset(void *, int, __kernel_size_t);
+
+#undef __HAVE_ARCH_MEMZERO
+extern void memzero(void *ptr, __kernel_size_t n);
+
+#endif
diff --git a/arch/x86/include/asm/types.h b/arch/x86/include/asm/types.h
new file mode 100644
index 0000000000..9a40e383eb
--- /dev/null
+++ b/arch/x86/include/asm/types.h
@@ -0,0 +1,53 @@
+#ifndef __ASM_I386_TYPES_H
+#define __ASM_I386_TYPES_H
+
+typedef unsigned short umode_t;
+
+/*
+ * __xx is ok: it doesn't pollute the POSIX namespace. Use these in the
+ * header files exported to user space
+ */
+
+typedef __signed__ char __s8;
+typedef unsigned char __u8;
+
+typedef __signed__ short __s16;
+typedef unsigned short __u16;
+
+typedef __signed__ int __s32;
+typedef unsigned int __u32;
+
+#if defined(__GNUC__)
+__extension__ typedef __signed__ long long __s64;
+__extension__ typedef unsigned long long __u64;
+#endif
+
+/*
+ * These aren't exported outside the kernel to avoid name space clashes
+ */
+#ifdef __KERNEL__
+
+typedef signed char s8;
+typedef unsigned char u8;
+
+typedef signed short s16;
+typedef unsigned short u16;
+
+typedef signed int s32;
+typedef unsigned int u32;
+
+typedef signed long long s64;
+typedef unsigned long long u64;
+
+#define BITS_PER_LONG 32
+
+/* Dma addresses are 32-bits wide. */
+
+typedef u32 dma_addr_t;
+
+typedef unsigned long phys_addr_t;
+typedef unsigned long phys_size_t;
+
+#endif /* __KERNEL__ */
+
+#endif
diff --git a/arch/x86/include/asm/u-boot-x86.h b/arch/x86/include/asm/u-boot-x86.h
new file mode 100644
index 0000000000..944e1a2005
--- /dev/null
+++ b/arch/x86/include/asm/u-boot-x86.h
@@ -0,0 +1,59 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se.
+ *
+ * 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
+ */
+
+#ifndef _U_BOOT_I386_H_
+#define _U_BOOT_I386_H_ 1
+
+/* cpu/.../cpu.c */
+int x86_cpu_init_r(void);
+int cpu_init_r(void);
+int x86_cpu_init_f(void);
+int cpu_init_f(void);
+
+/* cpu/.../timer.c */
+void timer_isr(void *);
+typedef void (timer_fnc_t) (void);
+int register_timer_isr (timer_fnc_t *isr_func);
+
+/* Architecture specific - can be in arch/x86/cpu/, arch/x86/lib/, or $(BOARD)/ */
+int timer_init(void);
+int dram_init_f(void);
+
+/* cpu/.../interrupts.c */
+int cpu_init_interrupts(void);
+
+/* board/.../... */
+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);
+
+/* arch/x86/lib/... */
+int video_bios_init(void);
+int video_init(void);
+
+
+#endif /* _U_BOOT_I386_H_ */
diff --git a/arch/x86/include/asm/u-boot.h b/arch/x86/include/asm/u-boot.h
new file mode 100644
index 0000000000..a43b3aaded
--- /dev/null
+++ b/arch/x86/include/asm/u-boot.h
@@ -0,0 +1,61 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Alex Zuepke <azu@sysgo.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
+ *
+ ********************************************************************
+ * NOTE: This header file defines an interface to U-Boot. Including
+ * this (unmodified) header file in another file is considered normal
+ * use of U-Boot, and does *not* fall under the heading of "derived
+ * work".
+ ********************************************************************
+ */
+
+#ifndef _U_BOOT_H_
+#define _U_BOOT_H_ 1
+
+typedef struct bd_info {
+ unsigned long bi_memstart; /* start of DRAM memory */
+ phys_size_t bi_memsize; /* size of DRAM memory in bytes */
+ unsigned long bi_flashstart; /* start of FLASH memory */
+ unsigned long bi_flashsize; /* size of FLASH memory */
+ unsigned long bi_flashoffset; /* reserved area for startup monitor */
+ unsigned long bi_sramstart; /* start of SRAM memory */
+ unsigned long bi_sramsize; /* size of SRAM memory */
+ unsigned long bi_bootflags; /* boot / reboot flag (for LynxOS) */
+ unsigned long bi_ip_addr; /* IP Address */
+ unsigned short bi_ethspeed; /* Ethernet speed in Mbps */
+ unsigned long bi_intfreq; /* Internal Freq, in MHz */
+ unsigned long bi_busfreq; /* Bus Freq, in MHz */
+ unsigned int bi_baudrate; /* Console Baudrate */
+ unsigned long bi_boot_params; /* where this board expects params */
+ struct /* RAM configuration */
+ {
+ ulong start;
+ ulong size;
+ }bi_dram[CONFIG_NR_DRAM_BANKS];
+} bd_t;
+
+#endif /* _U_BOOT_H_ */
diff --git a/arch/x86/include/asm/unaligned.h b/arch/x86/include/asm/unaligned.h
new file mode 100644
index 0000000000..6cecbbb211
--- /dev/null
+++ b/arch/x86/include/asm/unaligned.h
@@ -0,0 +1 @@
+#include <asm-generic/unaligned.h>
diff --git a/arch/x86/include/asm/video/edid.h b/arch/x86/include/asm/video/edid.h
new file mode 100644
index 0000000000..928c342b33
--- /dev/null
+++ b/arch/x86/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/x86/include/asm/zimage.h b/arch/x86/include/asm/zimage.h
new file mode 100644
index 0000000000..b6266e456a
--- /dev/null
+++ b/arch/x86/include/asm/zimage.h
@@ -0,0 +1,74 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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
+ */
+
+#ifndef _ASM_ZIMAGE_H_
+#define _ASM_ZIMAGE_H_
+
+/* linux i386 zImage/bzImage header. Offsets relative to
+ * the start of the image */
+
+#define CMD_LINE_MAGIC_OFF 0x020 /* Magic 0xa33f if the offset below is valid */
+#define CMD_LINE_OFFSET_OFF 0x022 /* Offset to comandline */
+#define SETUP_SECTS_OFF 0x1F1 /* The size of the setup in sectors */
+#define ROOT_FLAGS_OFF 0x1F2 /* If set, the root is mounted readonly */
+#define VID_MODE_OFF 0x1FA /* Video mode control */
+#define ROOT_DEV_OFF 0x1FC /* Default root device number */
+#define BOOT_FLAG_OFF 0x1FE /* 0xAA55 magic number */
+#define HEADER_OFF 0x202 /* Magic signature "HdrS" */
+#define VERSION_OFF 0x206 /* Boot protocol version supported */
+#define REALMODE_SWTCH_OFF 0x208 /* Boot loader hook (see below) */
+#define START_SYS_OFF 0x20C /* Points to kernel version string */
+#define TYPE_OF_LOADER_OFF 0x210 /* Boot loader identifier */
+#define LOADFLAGS_OFF 0x211 /* Boot protocol option flags */
+#define SETUP_MOVE_SIZE_OFF 0x212 /* Move to high memory size (used with hooks) */
+#define CODE32_START_OFF 0x214 /* Boot loader hook (see below) */
+#define RAMDISK_IMAGE_OFF 0x218 /* initrd load address (set by boot loader) */
+#define RAMDISK_SIZE_OFF 0x21C /* initrd size (set by boot loader) */
+#define HEAP_END_PTR_OFF 0x224 /* Free memory after setup end */
+#define CMD_LINE_PTR_OFF 0x228 /* 32-bit pointer to the kernel command line */
+
+
+#define HEAP_FLAG 0x80
+#define BIG_KERNEL_FLAG 0x01
+
+/* magic numbers */
+#define KERNEL_MAGIC 0xaa55
+#define KERNEL_V2_MAGIC 0x53726448
+#define COMMAND_LINE_MAGIC 0xA33F
+
+/* limits */
+#define BZIMAGE_MAX_SIZE 15*1024*1024 /* 15MB */
+#define ZIMAGE_MAX_SIZE 512*1024 /* 512k */
+#define SETUP_MAX_SIZE 32768
+
+#define SETUP_START_OFFSET 0x200
+#define BZIMAGE_LOAD_ADDR 0x100000
+#define ZIMAGE_LOAD_ADDR 0x10000
+
+void *load_zimage(char *image, unsigned long kernel_size,
+ unsigned long initrd_addr, unsigned long initrd_size,
+ int auto_boot);
+
+void boot_zimage(void *setup_base);
+
+#endif
diff --git a/arch/x86/lib/Makefile b/arch/x86/lib/Makefile
new file mode 100644
index 0000000000..71e94f76f3
--- /dev/null
+++ b/arch/x86/lib/Makefile
@@ -0,0 +1,59 @@
+#
+# (C) Copyright 2002-2006
+# 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
+#
+
+include $(TOPDIR)/config.mk
+
+LIB = $(obj)lib$(ARCH).o
+
+SOBJS-y += bios.o
+SOBJS-y += bios_pci.o
+SOBJS-y += realmode_switch.o
+
+COBJS-y += bios_setup.o
+COBJS-y += board.o
+COBJS-y += bootm.o
+COBJS-y += interrupts.o
+COBJS-$(CONFIG_SYS_PCAT_INTERRUPTS) += pcat_interrupts.o
+COBJS-$(CONFIG_SYS_GENERIC_TIMER) += pcat_timer.o
+COBJS-$(CONFIG_PCI) += pci.o
+COBJS-$(CONFIG_PCI) += pci_type1.o
+COBJS-y += realmode.o
+COBJS-y += timer.o
+COBJS-y += video_bios.o
+COBJS-y += video.o
+COBJS-y += zimage.o
+
+SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c)
+OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y))
+
+$(LIB): $(obj).depend $(OBJS)
+ $(call cmd_link_o_target, $(OBJS))
+
+#########################################################################
+
+# defines $(obj).depend target
+include $(SRCTREE)/rules.mk
+
+sinclude $(obj).depend
+
+#########################################################################
diff --git a/arch/x86/lib/bios.S b/arch/x86/lib/bios.S
new file mode 100644
index 0000000000..660a244394
--- /dev/null
+++ b/arch/x86/lib/bios.S
@@ -0,0 +1,531 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+/*
+ * Based on msbios.c from rolo 1.6:
+ *----------------------------------------------------------------------
+ * (C) Copyright 2000
+ * Sysgo Real-Time Solutions GmbH
+ * Klein-Winternheim, Germany
+ *----------------------------------------------------------------------
+ */
+
+#include "bios.h"
+
+/*
+ * During it's initialization phase, before switching to protected
+ * mode, the Linux Kernel makes a few BIOS calls. This won't work
+ * if the board does not have a BIOS.
+ *
+ * This is a very minimalisic BIOS that supplies just enough
+ * functionality to keep the Linux Kernel happy. It is NOT
+ * a general purpose replacement for a real BIOS !!
+ */
+
+.section .bios, "ax"
+.code16
+.org 0
+ /* a call to f000:0 should warmboot */
+ jmp realmode_reset
+
+.globl rm_int00
+.hidden rm_int00
+.type rm_int00, @function
+rm_int00:
+ pushw $0
+ jmp any_interrupt16
+.globl rm_int01
+.hidden rm_int01
+.type rm_int01, @function
+rm_int01:
+ pushw $1
+ jmp any_interrupt16
+.globl rm_int02
+.hidden rm_int02
+.type rm_int02, @function
+rm_int02:
+ pushw $2
+ jmp any_interrupt16
+.globl rm_int03
+.hidden rm_int03
+.type rm_int03, @function
+rm_int03:
+ pushw $3
+ jmp any_interrupt16
+.globl rm_int04
+.hidden rm_int04
+.type rm_int04, @function
+rm_int04:
+ pushw $4
+ jmp any_interrupt16
+.globl rm_int05
+.hidden rm_int05
+.type rm_int05, @function
+rm_int05:
+ pushw $5
+ jmp any_interrupt16
+.globl rm_int06
+.hidden rm_int06
+.type rm_int06, @function
+rm_int06:
+ pushw $6
+ jmp any_interrupt16
+.globl rm_int07
+.hidden rm_int07
+.type rm_int07, @function
+rm_int07:
+ pushw $7
+ jmp any_interrupt16
+.globl rm_int08
+.hidden rm_int08
+.type rm_int08, @function
+rm_int08:
+ pushw $8
+ jmp any_interrupt16
+.globl rm_int09
+.hidden rm_int09
+.type rm_int09, @function
+rm_int09:
+ pushw $9
+ jmp any_interrupt16
+.globl rm_int0a
+.hidden rm_int0a
+.type rm_int0a, @function
+rm_int0a:
+ pushw $10
+ jmp any_interrupt16
+.globl rm_int0b
+.hidden rm_int0b
+.type rm_int0b, @function
+rm_int0b:
+ pushw $11
+ jmp any_interrupt16
+.globl rm_int0c
+.hidden rm_int0c
+.type rm_int0c, @function
+rm_int0c:
+ pushw $12
+ jmp any_interrupt16
+.globl rm_int0d
+.hidden rm_int0d
+.type rm_int0d, @function
+rm_int0d:
+ pushw $13
+ jmp any_interrupt16
+.globl rm_int0e
+.hidden rm_int0e
+.type rm_int0e, @function
+rm_int0e:
+ pushw $14
+ jmp any_interrupt16
+.globl rm_int0f
+.hidden rm_int0f
+.type rm_int0f, @function
+rm_int0f:
+ pushw $15
+ jmp any_interrupt16
+.globl rm_int10
+.hidden rm_int10
+.type rm_int10, @function
+rm_int10:
+ pushw $16
+ jmp any_interrupt16
+.globl rm_int11
+.hidden rm_int11
+.type rm_int11, @function
+rm_int11:
+ pushw $17
+ jmp any_interrupt16
+.globl rm_int12
+.hidden rm_int12
+.type rm_int12, @function
+rm_int12:
+ pushw $18
+ jmp any_interrupt16
+.globl rm_int13
+.hidden rm_int13
+.type rm_int13, @function
+rm_int13:
+ pushw $19
+ jmp any_interrupt16
+.globl rm_int14
+.hidden rm_int14
+.type rm_int14, @function
+rm_int14:
+ pushw $20
+ jmp any_interrupt16
+.globl rm_int15
+.hidden rm_int15
+.type rm_int15, @function
+rm_int15:
+ pushw $21
+ jmp any_interrupt16
+.globl rm_int16
+.hidden rm_int16
+.type rm_int16, @function
+rm_int16:
+ pushw $22
+ jmp any_interrupt16
+.globl rm_int17
+.hidden rm_int17
+.type rm_int17, @function
+rm_int17:
+ pushw $23
+ jmp any_interrupt16
+.globl rm_int18
+.hidden rm_int18
+.type rm_int18, @function
+rm_int18:
+ pushw $24
+ jmp any_interrupt16
+.globl rm_int19
+.hidden rm_int19
+.type rm_int19, @function
+rm_int19:
+ pushw $25
+ jmp any_interrupt16
+.globl rm_int1a
+.hidden rm_int1a
+.type rm_int1a, @function
+rm_int1a:
+ pushw $26
+ jmp any_interrupt16
+.globl rm_int1b
+.hidden rm_int1b
+.type rm_int1b, @function
+rm_int1b:
+ pushw $27
+ jmp any_interrupt16
+.globl rm_int1c
+.hidden rm_int1c
+.type rm_int1c, @function
+rm_int1c:
+ pushw $28
+ jmp any_interrupt16
+.globl rm_int1d
+.hidden rm_int1d
+.type rm_int1d, @function
+rm_int1d:
+ pushw $29
+ jmp any_interrupt16
+.globl rm_int1e
+.hidden rm_int1e
+.type rm_int1e, @function
+rm_int1e:
+ pushw $30
+ jmp any_interrupt16
+.globl rm_int1f
+.hidden rm_int1f
+.type rm_int1f, @function
+rm_int1f:
+ pushw $31
+ jmp any_interrupt16
+.globl rm_def_int
+.hidden rm_def_int
+.type rm_def_int, @function
+rm_def_int:
+ iret
+
+
+ /*
+ * All interrupt jumptable entries jump to here
+ * after pushing the interrupt vector number onto the
+ * stack.
+ */
+any_interrupt16:
+ MAKE_BIOS_STACK
+
+gs movw OFFS_VECTOR(%bp), %ax
+ cmpw $0x10, %ax
+ je Lint_10h
+ cmpw $0x11, %ax
+ je Lint_11h
+ cmpw $0x12, %ax
+ je Lint_12h
+ cmpw $0x13, %ax
+ je Lint_13h
+ cmpw $0x15, %ax
+ je Lint_15h
+ cmpw $0x16, %ax
+ je Lint_16h
+ cmpw $0x1a, %ax
+ je Lint_1ah
+ movw $0xffff, %ax
+ jmp Lout
+Lint_10h: /* VGA BIOS services */
+ call bios_10h
+ jmp Lout
+Lint_11h:
+ call bios_11h
+ jmp Lout
+Lint_12h:
+ call bios_12h
+ jmp Lout
+Lint_13h: /* BIOS disk services */
+ call bios_13h
+ jmp Lout
+Lint_15h: /* Misc. BIOS services */
+ call bios_15h
+ jmp Lout
+Lint_16h: /* keyboard services */
+ call bios_16h
+ jmp Lout
+Lint_1ah: /* PCI bios */
+ call bios_1ah
+ jmp Lout
+Lout:
+ cmpw $0, %ax
+ je Lhandeled
+
+ /* Insert code for unhandeled INTs here.
+ *
+ * ROLO prints a message to the console
+ * (we could do that but then we're in 16bit mode
+ * so we'll have to get back into 32bit mode
+ * to use the console I/O routines (if we do this
+ * we shuls make int 0x10 and int 0x16 work as well))
+ */
+Lhandeled:
+ RESTORE_CALLERS_STACK
+ addw $2,%sp /* dump vector number */
+ iret /* return from interrupt */
+
+
+/*
+ ************************************************************
+ * BIOS interrupt 10h -- VGA services
+ ************************************************************
+ */
+bios_10h:
+gs movw OFFS_AX(%bp), %ax
+ shrw $8, %ax
+ cmpw $0x3, %ax
+ je Lcur_pos
+ cmpw $0xf, %ax
+ je Lvid_state
+ cmpw $0x12, %ax
+ je Lvid_cfg
+ movw $0xffff, %ax
+ ret
+Lcur_pos: /* Read Cursor Position and Size */
+gs movw $0, OFFS_CX(%bp)
+gs movw $0, OFFS_DX(%bp)
+ xorw %ax, %ax
+ ret
+Lvid_state: /* Get Video State */
+gs movw $(80 << 8|0x03), OFFS_AX(%bp) /* 80 columns, 80x25, 16 colors */
+gs movw $0, OFFS_BX(%bp)
+ xorw %ax, %ax
+ ret
+Lvid_cfg: /* Video Subsystem Configuration (EGA/VGA) */
+gs movw $0x10, OFFS_BX(%bp) /* indicate CGA/MDA/HGA */
+ xorw %ax, %ax
+ ret
+
+
+/*
+ ************************************************************
+ * BIOS interrupt 11h -- Equipment determination
+ ************************************************************
+ */
+
+bios_11h:
+cs movw bios_equipment, %ax
+gs movw %ax, OFFS_AX(%bp)
+ xorw %ax, %ax
+ ret
+
+
+/*
+ ************************************************************
+ * BIOS interrupt 12h -- Get Memory Size
+ ************************************************************
+ */
+bios_12h:
+cs movw ram_in_64kb_chunks, %ax
+ cmpw $0xa, %ax
+ ja b12_more_than_640k
+ shlw $6, %ax
+ jmp b12_return
+b12_more_than_640k:
+ movw $0x280, %ax
+b12_return:
+gs movw %ax, OFFS_AX(%bp) /* return number of kilobytes in ax */
+
+gs movw OFFS_FLAGS(%bp), %ax
+ andw $0xfffe, %ax /* clear carry -- function succeeded */
+gs movw %ax, OFFS_FLAGS(%bp)
+
+ xorw %ax, %ax
+ ret
+
+
+/*
+ ************************************************************
+ * BIOS interrupt 13h -- Disk services
+ ************************************************************
+ */
+bios_13h:
+gs movw OFFS_AX(%bp), %ax
+ shrw $8, %ax
+ cmpw $0x15, %ax
+ je Lfunc_15h
+ movw $0xffff, %ax
+ ret
+Lfunc_15h:
+gs movw OFFS_AX(%bp), %ax
+ andw $0xff, %ax /* return AH=0->drive not present */
+gs movw %ax, OFFS_AX(%bp)
+ xorw %ax, %ax
+ ret
+
+
+/*
+ ***********************************************************
+ * BIOS interrupt 15h -- Miscellaneous services
+ ***********************************************************
+ */
+bios_15h:
+gs movw OFFS_AX(%bp), %ax
+ shrw $8, %ax
+ cmpw $0xc0, %ax
+ je Lfunc_c0h
+ cmpw $0xe8, %ax
+ je Lfunc_e8h
+ cmpw $0x88, %ax
+ je Lfunc_88h
+ movw $0xffff, %ax
+ ret
+
+Lfunc_c0h: /* Return System Configuration Parameters (PS2 only) */
+gs movw OFFS_FLAGS(%bp), %ax
+ orw $1, %ax /* return carry -- function not supported */
+gs movw %ax, OFFS_FLAGS(%bp)
+ xorw %ax, %ax
+ ret
+
+Lfunc_e8h:
+gs movw OFFS_AX(%bp), %ax
+ andw $0xff, %ax
+ cmpw $1, %ax
+ je Lfunc_e801h
+gs movw OFFS_FLAGS(%bp), %ax
+ orw $1, %ax /* return carry -- function not supported */
+gs movw %ax, OFFS_FLAGS(%bp)
+ xorw %ax, %ax
+ ret
+
+Lfunc_e801h: /* Get memory size for >64M Configurations */
+cs movw ram_in_64kb_chunks, %ax
+ cmpw $0x100, %ax
+ ja e801_more_than_16mb
+ shlw $6, %ax /* multiply by 64 */
+ subw $0x400, %ax /* 1st meg does not count */
+
+gs movw %ax, OFFS_AX(%bp) /* return memory size between 1M and 16M in 1kb chunks in AX and CX */
+gs movw %ax, OFFS_CX(%bp)
+gs movw $0, OFFS_BX(%bp) /* set BX and DX to 0*/
+gs movw $0, OFFS_DX(%bp)
+gs movw OFFS_FLAGS(%bp), %ax
+ andw $0xfffe, %ax /* clear carry -- function succeeded */
+gs movw %ax, OFFS_FLAGS(%bp)
+ xorw %ax, %ax
+ ret
+
+e801_more_than_16mb:
+ subw $0x100, %ax /* subtract 16MB */
+
+gs movw $0x3c00, OFFS_AX(%bp) /* return 0x3c00 (16MB-1MB) in AX and CX */
+gs movw $0x3c00, OFFS_CX(%bp)
+gs movw %ax, OFFS_BX(%bp) /* set BX and DX to number of 64kb chunks above 16MB */
+gs movw %ax, OFFS_DX(%bp)
+
+gs movw OFFS_FLAGS(%bp), %ax
+ andw $0xfffe, %ax /* clear carry -- function succeeded */
+gs movw %ax, OFFS_FLAGS(%bp)
+ xorw %ax, %ax
+ ret
+
+Lfunc_88h:
+cs movw ram_in_64kb_chunks, %ax
+ cmpw $0x100, %ax
+ jna b88_not_more_than16
+ movw $0x100, %ax
+b88_not_more_than16:
+ shlw $6, %ax
+ subw $0x400, %ax /* 1st meg does not count */
+
+gs movw %ax, OFFS_AX(%bp) /* return number of kilobytes between 16MB and 16MB in ax */
+
+gs movw OFFS_FLAGS(%bp), %ax
+ andw $0xfffe, %ax /* clear carry -- function succeeded */
+gs movw %ax, OFFS_FLAGS(%bp)
+
+ xorw %ax, %ax
+ ret
+
+
+/*
+ ************************************************************
+ * BIOS interrupt 16h -- keyboard services
+ ************************************************************
+ */
+bios_16h:
+gs movw OFFS_AX(%bp), %ax
+ shrw $8, %ax
+ cmpw $0x03, %ax
+ je Lfunc_03h
+ movw $0xffff, %ax
+ ret
+Lfunc_03h:
+ xorw %ax, %ax /* do nothing -- function not supported */
+ ret
+
+/*
+ ************************************************************
+ * BIOS interrupt 1ah -- PCI bios
+ ************************************************************
+ */
+bios_1ah:
+gs movw OFFS_AX(%bp), %ax
+ cmpb $0xb1, %ah
+ je Lfunc_b1h
+ movw $0xffff, %ax
+ ret
+Lfunc_b1h:
+ call realmode_pci_bios
+ xorw %ax, %ax /* do nothing -- function not supported */
+ ret
+
+
+.globl ram_in_64kb_chunks
+.hidden ram_in_64kb_chunks
+.type ram_in_64kb_chunks, @function
+ram_in_64kb_chunks:
+ .word 0
+
+.globl bios_equipment
+.hidden bios_equipment
+.type bios_equipment, @function
+bios_equipment:
+ .word 0
diff --git a/arch/x86/lib/bios.h b/arch/x86/lib/bios.h
new file mode 100644
index 0000000000..3c8d61a6f4
--- /dev/null
+++ b/arch/x86/lib/bios.h
@@ -0,0 +1,92 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+#ifndef _BIOS_H_
+#define _BIOS_H_
+
+#define OFFS_ES 0 /* 16bit */
+#define OFFS_GS 2 /* 16bit */
+#define OFFS_DS 4 /* 16bit */
+#define OFFS_EDI 6 /* 32bit */
+#define OFFS_DI 6 /* low 16 bits of EDI */
+#define OFFS_ESI 10 /* 32bit */
+#define OFFS_SI 10 /* low 16 bits of ESI */
+#define OFFS_EBP 14 /* 32bit */
+#define OFFS_BP 14 /* low 16 bits of EBP */
+#define OFFS_ESP 18 /* 32bit */
+#define OFFS_SP 18 /* low 16 bits of ESP */
+#define OFFS_EBX 22 /* 32bit */
+#define OFFS_BX 22 /* low 16 bits of EBX */
+#define OFFS_BL 22 /* low 8 bits of BX */
+#define OFFS_BH 23 /* high 8 bits of BX */
+#define OFFS_EDX 26 /* 32bit */
+#define OFFS_DX 26 /* low 16 bits of EBX */
+#define OFFS_DL 26 /* low 8 bits of BX */
+#define OFFS_DH 27 /* high 8 bits of BX */
+#define OFFS_ECX 30 /* 32bit */
+#define OFFS_CX 30 /* low 16 bits of EBX */
+#define OFFS_CL 30 /* low 8 bits of BX */
+#define OFFS_CH 31 /* high 8 bits of BX */
+#define OFFS_EAX 34 /* 32bit */
+#define OFFS_AX 34 /* low 16 bits of EBX */
+#define OFFS_AL 34 /* low 8 bits of BX */
+#define OFFS_AH 35 /* high 8 bits of BX */
+#define OFFS_VECTOR 38 /* 16bit */
+#define OFFS_IP 40 /* 16bit */
+#define OFFS_CS 42 /* 16bit */
+#define OFFS_FLAGS 44 /* 16bit */
+
+#define SEGMENT 0x40
+#define STACK 0x800 /* stack at 0x40:0x800 -> 0x800 */
+
+/* save general registers */
+/* save some segments */
+/* save callers stack segment .. */
+/* ... in gs */
+ /* setup my segments */
+ /* setup BIOS stackpointer */
+
+#define MAKE_BIOS_STACK \
+ pushal; \
+ pushw %ds; \
+ pushw %gs; \
+ pushw %es; \
+ pushw %ss; \
+ popw %gs; \
+ movw $SEGMENT, %ax; \
+ movw %ax, %ds; \
+ movw %ax, %es; \
+ movw %ax, %ss; \
+ movw %sp, %bp; \
+ movw $STACK, %sp
+
+#define RESTORE_CALLERS_STACK \
+ pushw %gs; /* restore callers stack segment */ \
+ popw %ss; \
+ movw %bp, %sp; /* restore stackpointer */ \
+ popw %es; /* restore segment selectors */ \
+ popw %gs; \
+ popw %ds; \
+ popal /* restore GP registers */
+
+#endif
diff --git a/arch/x86/lib/bios_pci.S b/arch/x86/lib/bios_pci.S
new file mode 100644
index 0000000000..9e412e5e4c
--- /dev/null
+++ b/arch/x86/lib/bios_pci.S
@@ -0,0 +1,413 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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
+ */
+
+/*
+ * x86 realmode assembly implementation of a PCI BIOS
+ * for platforms that use one PCI hose and configuration
+ * access type 1. (The common case for low-end PC's)
+ */
+
+#include "bios.h"
+
+#define PCI_BIOS_DEBUG
+
+.section .bios, "ax"
+.code16
+.globl realmode_pci_bios_call_entry
+.hidden realmode_pci_bios_call_entry
+.type realmode_pci_bios_call_entry, @function
+realmode_pci_bios_call_entry:
+ MAKE_BIOS_STACK
+ call realmode_pci_bios
+ RESTORE_CALLERS_STACK
+ ret
+
+
+.globl realmode_pci_bios
+realmode_pci_bios:
+gs movw OFFS_AX(%bp), %ax
+ cmpb $1, %al
+ je pci_bios_present
+ cmpb $2, %al
+ je pci_bios_find_device
+ cmpb $3, %al
+ je pci_bios_find_class
+ cmpb $6, %al
+ je pci_bios_generate_special_cycle
+ cmpb $8, %al
+ je pci_bios_read_cfg_byte
+ cmpb $9, %al
+ je pci_bios_read_cfg_word
+ cmpb $10, %al
+ je pci_bios_read_cfg_dword
+ cmpb $11, %al
+ je pci_bios_write_cfg_byte
+ cmpb $12, %al
+ je pci_bios_write_cfg_word
+ cmpb $13, %al
+ je pci_bios_write_cfg_dword
+ cmpb $14, %al
+ je pci_bios_get_irq_routing
+ cmpb $15, %al
+ je pci_bios_set_irq
+ jmp unknown_function
+
+/*****************************************************************************/
+
+pci_bios_present:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_present
+#endif
+ movl $0x20494350, %eax
+gs movl %eax, OFFS_EDX(%bp)
+ movb $0x01, %al
+gs movb %al, OFFS_AL(%bp) /* We support cfg type 1 */
+ movw $0x0210, %ax /* version 2.10 */
+gs movw %ax, OFFS_BX(%bp)
+cs movb pci_last_bus, %al /* last bus number */
+gs movb %al, OFFS_CL(%bp)
+ jmp clear_carry
+
+/*****************************************************************************/
+
+/* device 0-31, function 0-7 */
+pci_bios_find_device:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_find_device
+#endif
+gs movw OFFS_CX(%bp), %di
+ shll $16, %edi
+gs movw OFFS_DX(%bp), %di /* edi now holds device in upper 16
+ * bits and vendor in lower 16 bits */
+gs movw OFFS_SI(%bp), %si
+ xorw %bx, %bx /* start at bus 0 dev 0 function 0 */
+pfd_loop:
+ xorw %ax, %ax /* dword 0 is vendor/device */
+ call __pci_bios_select_register
+ movw $0xcfc, %dx
+ inl %dx, %eax
+ cmpl %edi, %eax /* our device ? */
+ je pfd_found_one
+pfd_next_dev:
+ /* check for multi function devices */
+ movw %bx, %ax
+ andw $3, %ax
+ jnz pfd_function_not_zero
+ movw $0x000c, %ax
+ call __pci_bios_select_register
+ movw $0xcfe, %dx
+ inb %dx, %al
+ andb $0x80, %al
+ jz pfd_not_multi_function
+pfd_function_not_zero:
+ incw %bx /* next function, overflows in to
+ * device number, then bus number */
+ jmp pfd_check_bus
+
+pfd_not_multi_function:
+ andw $0xfff8, %bx /* remove function bits */
+ addw $0x0008, %bx /* next device, overflows in to bus number */
+pfd_check_bus:
+cs movb pci_last_bus, %ah
+ cmpb %ah, %bh
+ ja pfd_not_found
+ jmp pfd_loop
+pfd_found_one:
+ decw %si
+ js pfd_done
+ jmp pfd_next_dev
+
+pfd_done:
+gs movw %bx, OFFS_BX(%bp)
+ jmp clear_carry
+
+pfd_not_found:
+ movb $0x86, %ah /* device not found */
+ jmp set_carry
+
+/*****************************************************************************/
+
+pci_bios_find_class:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_find_class
+#endif
+gs movl OFFS_ECX(%bp), %edi
+ andl $0x00ffffff, %edi /* edi now holds class-code in lower 24 bits */
+gs movw OFFS_SI(%bp), %si
+ xorw %bx, %bx /* start at bus 0 dev 0 function 0 */
+pfc_loop:
+ movw $8, %ax /* dword 8 is class-code high 24bits */
+ call __pci_bios_select_register
+ movw $0xcfc, %dx
+ inl %dx, %eax
+ shrl $8, %eax
+ andl $0x00ffffff, %eax
+ cmpl %edi, %eax /* our device ? */
+ je pfc_found_one
+pfc_next_dev:
+ /* check for multi function devices */
+ andw $3, %bx
+ jnz pfc_function_not_zero
+ movw $0x000c, %ax
+ call __pci_bios_select_register
+ movw $0xcfe, %dx
+ inb %dx, %al
+ andb $0x80, %al
+ jz pfc_not_multi_function
+pfc_function_not_zero:
+ incw %bx /* next function, overflows in to
+ * device number, then bus number */
+ jmp pfc_check_bus
+
+pfc_not_multi_function:
+ andw $0xfff8, %bx /* remove function bits */
+ addw $0x0008, %bx /* next device, overflows in to bus number */
+pfc_check_bus:
+cs movb pci_last_bus, %ah
+ cmpb %ah, %bh
+ ja pfc_not_found
+ jmp pfc_loop
+pfc_found_one:
+ decw %si
+ js pfc_done
+ jmp pfc_next_dev
+
+pfc_done:
+gs movw %bx, OFFS_BX(%bp)
+ jmp clear_carry
+
+pfc_not_found:
+ movb $0x86, %ah /* device not found */
+ jmp set_carry
+
+/*****************************************************************************/
+
+pci_bios_generate_special_cycle:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_generate_special_cycle
+#endif
+ movb $0x81, %ah /* function not supported */
+ jmp set_carry
+
+/*****************************************************************************/
+
+pci_bios_read_cfg_byte:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_read_cfg_byte
+#endif
+ call pci_bios_select_register
+gs movw OFFS_DI(%bp), %dx
+ andw $3, %dx
+ addw $0xcfc, %dx
+ inb %dx, %al
+gs movb %al, OFFS_CL(%bp)
+ jmp clear_carry
+
+/*****************************************************************************/
+
+pci_bios_read_cfg_word:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_read_cfg_word
+#endif
+ call pci_bios_select_register
+gs movw OFFS_DI(%bp), %dx
+ andw $2, %dx
+ addw $0xcfc, %dx
+ inw %dx, %ax
+gs movw %ax, OFFS_CX(%bp)
+ jmp clear_carry
+
+
+/*****************************************************************************/
+
+pci_bios_read_cfg_dword:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_read_cfg_dword
+#endif
+ call pci_bios_select_register
+ movw $0xcfc, %dx
+ inl %dx, %eax
+gs movl %eax, OFFS_ECX(%bp)
+ jmp clear_carry
+
+/*****************************************************************************/
+
+pci_bios_write_cfg_byte:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_write_cfg_byte
+#endif
+ call pci_bios_select_register
+gs movw OFFS_DI(%bp), %dx
+gs movb OFFS_CL(%bp), %al
+ andw $3, %dx
+ addw $0xcfc, %dx
+ outb %al, %dx
+ jmp clear_carry
+
+/*****************************************************************************/
+
+pci_bios_write_cfg_word:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_write_cfg_word
+#endif
+ call pci_bios_select_register
+gs movw OFFS_DI(%bp), %dx
+gs movw OFFS_CX(%bp), %ax
+ andw $2, %dx
+ addw $0xcfc, %dx
+ outw %ax, %dx
+ jmp clear_carry
+
+/*****************************************************************************/
+
+pci_bios_write_cfg_dword:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_write_cfg_dword
+#endif
+ call pci_bios_select_register
+gs movl OFFS_ECX(%bp), %eax
+ movw $0xcfc, %dx
+ outl %eax, %dx
+ jmp clear_carry
+
+/*****************************************************************************/
+
+pci_bios_get_irq_routing:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_get_irq_routing
+#endif
+ movb $0x81, %ah /* function not supported */
+ jmp set_carry
+
+/*****************************************************************************/
+
+pci_bios_set_irq:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_set_irq
+#endif
+ movb $0x81, %ah /* function not supported */
+ jmp set_carry
+
+/*****************************************************************************/
+
+unknown_function:
+#ifdef PCI_BIOS_DEBUG
+cs incl num_pci_bios_unknown_function
+#endif
+ movb $0x81, %ah /* function not supported */
+ jmp set_carry
+
+/*****************************************************************************/
+
+pci_bios_select_register:
+gs movw OFFS_BX(%bp), %bx
+gs movw OFFS_DI(%bp), %ax
+/* destroys eax, dx */
+__pci_bios_select_register: /* BX holds device id, AX holds register index */
+ pushl %ebx
+ andl $0xfc, %eax
+ andl $0xffff, %ebx
+ shll $8, %ebx
+ orl %ebx, %eax
+ orl $0x80000000, %eax
+ movw $0xcf8, %dx
+ outl %eax, %dx
+ popl %ebx
+ ret
+
+
+clear_carry:
+gs movw OFFS_FLAGS(%bp), %ax
+ andw $0xfffe, %ax /* clear carry -- function succeeded */
+gs movw %ax, OFFS_FLAGS(%bp)
+ xorw %ax, %ax
+gs movb %ah, OFFS_AH(%bp)
+ ret
+
+set_carry:
+gs movb %ah, OFFS_AH(%bp)
+gs movw OFFS_FLAGS(%bp), %ax
+ orw $1, %ax /* return carry -- function not supported */
+gs movw %ax, OFFS_FLAGS(%bp)
+ movw $-1, %ax
+ ret
+
+/*****************************************************************************/
+
+.globl pci_last_bus
+pci_last_bus:
+ .byte 0
+
+#ifdef PCI_BIOS_DEBUG
+.globl num_pci_bios_present
+num_pci_bios_present:
+ .long 0
+
+.globl num_pci_bios_find_device
+num_pci_bios_find_device:
+ .long 0
+
+.globl num_pci_bios_find_class
+num_pci_bios_find_class:
+ .long 0
+
+.globl num_pci_bios_generate_special_cycle
+num_pci_bios_generate_special_cycle:
+ .long 0
+
+.globl num_pci_bios_read_cfg_byte
+num_pci_bios_read_cfg_byte:
+ .long 0
+
+.globl num_pci_bios_read_cfg_word
+num_pci_bios_read_cfg_word:
+ .long 0
+
+.globl num_pci_bios_read_cfg_dword
+num_pci_bios_read_cfg_dword:
+ .long 0
+
+.globl num_pci_bios_write_cfg_byte
+num_pci_bios_write_cfg_byte:
+ .long 0
+
+.globl num_pci_bios_write_cfg_word
+num_pci_bios_write_cfg_word:
+ .long 0
+
+.globl num_pci_bios_write_cfg_dword
+num_pci_bios_write_cfg_dword:
+ .long 0
+
+.globl num_pci_bios_get_irq_routing
+num_pci_bios_get_irq_routing:
+ .long 0
+
+.globl num_pci_bios_set_irq
+num_pci_bios_set_irq:
+ .long 0
+
+.globl num_pci_bios_unknown_function
+num_pci_bios_unknown_function:
+ .long 0
+#endif
diff --git a/arch/x86/lib/bios_setup.c b/arch/x86/lib/bios_setup.c
new file mode 100644
index 0000000000..6949b35069
--- /dev/null
+++ b/arch/x86/lib/bios_setup.c
@@ -0,0 +1,241 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+/*
+ * Partly based on msbios.c from rolo 1.6:
+ *----------------------------------------------------------------------
+ * (C) Copyright 2000
+ * Sysgo Real-Time Solutions GmbH
+ * Klein-Winternheim, Germany
+ *----------------------------------------------------------------------
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/realmode.h>
+#include <asm/io.h>
+
+DECLARE_GLOBAL_DATA_PTR;
+
+#define NUMVECTS 256
+
+#define BIOS_DATA ((char*)0x400)
+#define BIOS_DATA_SIZE 256
+#define BIOS_BASE ((char*)0xf0000)
+#define BIOS_CS 0xf000
+
+extern ulong __bios_start;
+extern ulong __bios_size;
+
+/* these are defined in a 16bit segment and needs
+ * to be accessed with the RELOC_16_xxxx() macros below
+ */
+extern u16 ram_in_64kb_chunks;
+extern u16 bios_equipment;
+extern u8 pci_last_bus;
+
+extern void *rm_int00;
+extern void *rm_int01;
+extern void *rm_int02;
+extern void *rm_int03;
+extern void *rm_int04;
+extern void *rm_int05;
+extern void *rm_int06;
+extern void *rm_int07;
+extern void *rm_int08;
+extern void *rm_int09;
+extern void *rm_int0a;
+extern void *rm_int0b;
+extern void *rm_int0c;
+extern void *rm_int0d;
+extern void *rm_int0e;
+extern void *rm_int0f;
+extern void *rm_int10;
+extern void *rm_int11;
+extern void *rm_int12;
+extern void *rm_int13;
+extern void *rm_int14;
+extern void *rm_int15;
+extern void *rm_int16;
+extern void *rm_int17;
+extern void *rm_int18;
+extern void *rm_int19;
+extern void *rm_int1a;
+extern void *rm_int1b;
+extern void *rm_int1c;
+extern void *rm_int1d;
+extern void *rm_int1e;
+extern void *rm_int1f;
+extern void *rm_def_int;
+
+extern void *realmode_reset;
+extern void *realmode_pci_bios_call_entry;
+
+static int set_jmp_vector(int entry_point, void *target)
+{
+ if (entry_point & ~0xffff) {
+ return -1;
+ }
+
+ if (((u32)target-0xf0000) & ~0xffff) {
+ return -1;
+ }
+ printf("set_jmp_vector: 0xf000:%04x -> %p\n",
+ entry_point, target);
+
+ /* jmp opcode */
+ writeb(0xea, 0xf0000 + entry_point);
+
+ /* offset */
+ writew(((u32)target-0xf0000), 0xf0000 + entry_point + 1);
+
+ /* segment */
+ writew(0xf000, 0xf0000 + entry_point + 3);
+
+ return 0;
+}
+
+
+/*
+ ************************************************************
+ * Install an interrupt vector
+ ************************************************************
+ */
+
+static void setvector(int vector, u16 segment, void *handler)
+{
+ u16 *ptr = (u16*)(vector*4);
+ ptr[0] = ((u32)handler - (segment << 4))&0xffff;
+ ptr[1] = segment;
+
+#if 0
+ printf("setvector: int%02x -> %04x:%04x\n",
+ vector, ptr[1], ptr[0]);
+#endif
+}
+
+#define RELOC_16_LONG(seg, off) *(u32*)(seg << 4 | (u32)&off)
+#define RELOC_16_WORD(seg, off) *(u16*)(seg << 4 | (u32)&off)
+#define RELOC_16_BYTE(seg, off) *(u8*)(seg << 4 | (u32)&off)
+
+int bios_setup(void)
+{
+ ulong bios_start = (ulong)&__bios_start + gd->reloc_off;
+ ulong bios_size = (ulong)&__bios_size;
+
+ static int done=0;
+ int vector;
+#ifdef CONFIG_PCI
+ struct pci_controller *pri_hose;
+#endif
+ if (done) {
+ return 0;
+ }
+ done = 1;
+
+ if (bios_size > 65536) {
+ printf("BIOS too large (%ld bytes, max is 65536)\n",
+ bios_size);
+ return -1;
+ }
+
+ memcpy(BIOS_BASE, (void*)bios_start, bios_size);
+
+ /* clear bda */
+ memset(BIOS_DATA, 0, BIOS_DATA_SIZE);
+
+ /* enter some values to the bda */
+ writew(0x3f8, BIOS_DATA); /* com1 addr */
+ writew(0x2f8, BIOS_DATA+2); /* com2 addr */
+ writew(0x3e8, BIOS_DATA+4); /* com3 addr */
+ writew(0x2e8, BIOS_DATA+6); /* com4 addr */
+ writew(0x278, BIOS_DATA+8); /* lpt1 addr */
+ /*
+ * The kernel wants to read the base memory size
+ * from 40:13. Put a zero there to avoid an error message
+ */
+ writew(0, BIOS_DATA+0x13); /* base memory size */
+
+
+ /* setup realmode interrupt vectors */
+ for (vector = 0; vector < NUMVECTS; vector++) {
+ setvector(vector, BIOS_CS, &rm_def_int);
+ }
+
+ setvector(0x00, BIOS_CS, &rm_int00);
+ setvector(0x01, BIOS_CS, &rm_int01);
+ setvector(0x02, BIOS_CS, &rm_int02);
+ setvector(0x03, BIOS_CS, &rm_int03);
+ setvector(0x04, BIOS_CS, &rm_int04);
+ setvector(0x05, BIOS_CS, &rm_int05);
+ setvector(0x06, BIOS_CS, &rm_int06);
+ setvector(0x07, BIOS_CS, &rm_int07);
+ setvector(0x08, BIOS_CS, &rm_int08);
+ setvector(0x09, BIOS_CS, &rm_int09);
+ setvector(0x0a, BIOS_CS, &rm_int0a);
+ setvector(0x0b, BIOS_CS, &rm_int0b);
+ setvector(0x0c, BIOS_CS, &rm_int0c);
+ setvector(0x0d, BIOS_CS, &rm_int0d);
+ setvector(0x0e, BIOS_CS, &rm_int0e);
+ setvector(0x0f, BIOS_CS, &rm_int0f);
+ setvector(0x10, BIOS_CS, &rm_int10);
+ setvector(0x11, BIOS_CS, &rm_int11);
+ setvector(0x12, BIOS_CS, &rm_int12);
+ setvector(0x13, BIOS_CS, &rm_int13);
+ setvector(0x14, BIOS_CS, &rm_int14);
+ setvector(0x15, BIOS_CS, &rm_int15);
+ setvector(0x16, BIOS_CS, &rm_int16);
+ setvector(0x17, BIOS_CS, &rm_int17);
+ setvector(0x18, BIOS_CS, &rm_int18);
+ setvector(0x19, BIOS_CS, &rm_int19);
+ setvector(0x1a, BIOS_CS, &rm_int1a);
+ setvector(0x1b, BIOS_CS, &rm_int1b);
+ setvector(0x1c, BIOS_CS, &rm_int1c);
+ setvector(0x1d, BIOS_CS, &rm_int1d);
+ setvector(0x1e, BIOS_CS, &rm_int1e);
+ setvector(0x1f, BIOS_CS, &rm_int1f);
+
+ set_jmp_vector(0xfff0, &realmode_reset);
+ set_jmp_vector(0xfe6e, &realmode_pci_bios_call_entry);
+
+ /* fill in data area */
+ RELOC_16_WORD(0xf000, ram_in_64kb_chunks) = gd->ram_size >> 16;
+ RELOC_16_WORD(0xf000, bios_equipment) = 0; /* FixMe */
+
+ /* If we assume only one PCI hose, this PCI hose
+ * will own PCI bus #0, and the last PCI bus of
+ * that PCI hose will be the last PCI bus in the
+ * system.
+ * (This, ofcause break on multi hose systems,
+ * but our PCI BIOS only support one hose anyway)
+ */
+#ifdef CONFIG_PCI
+ pri_hose = pci_bus_to_hose(0);
+ if (NULL != pri_hose) {
+ /* fill in last pci bus number for use by the realmode
+ * PCI BIOS */
+ RELOC_16_BYTE(0xf000, pci_last_bus) = pri_hose->last_busno;
+ }
+#endif
+ return 0;
+}
diff --git a/arch/x86/lib/board.c b/arch/x86/lib/board.c
new file mode 100644
index 0000000000..df54222211
--- /dev/null
+++ b/arch/x86/lib/board.c
@@ -0,0 +1,480 @@
+/*
+ * (C) Copyright 2008-2011
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * (C) Copyright 2002
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.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
+ */
+
+#include <common.h>
+#include <watchdog.h>
+#include <command.h>
+#include <stdio_dev.h>
+#include <timestamp.h>
+#include <version.h>
+#include <malloc.h>
+#include <net.h>
+#include <ide.h>
+#include <serial.h>
+#include <asm/u-boot-x86.h>
+#include <elf.h>
+
+#ifdef CONFIG_BITBANGMII
+#include <miiphy.h>
+#endif
+
+/*
+ * Pointer to initial global data area
+ *
+ * Here we initialize it.
+ */
+#undef XTRN_DECLARE_GLOBAL_DATA_PTR
+#define XTRN_DECLARE_GLOBAL_DATA_PTR /* empty = allocate here */
+DECLARE_GLOBAL_DATA_PTR = (gd_t *) (CONFIG_SYS_INIT_GD_ADDR);
+
+
+/* Exports from the Linker Script */
+extern ulong __text_start;
+extern ulong __data_end;
+extern ulong __rel_dyn_start;
+extern ulong __rel_dyn_end;
+extern ulong __bss_start;
+extern ulong __bss_end;
+
+const char version_string[] =
+ U_BOOT_VERSION" (" U_BOOT_DATE " - " U_BOOT_TIME ")";
+
+/************************************************************************
+ * Init Utilities *
+ ************************************************************************
+ * Some of this code should be moved into the core functions,
+ * or dropped completely,
+ * but let's get it working (again) first...
+ */
+static int init_baudrate (void)
+{
+ char tmp[64]; /* long enough for environment variables */
+ int i = getenv_f("baudrate", tmp, 64);
+
+ gd->baudrate = (i != 0)
+ ? (int) simple_strtoul (tmp, NULL, 10)
+ : CONFIG_BAUDRATE;
+
+ return (0);
+}
+
+static int display_banner (void)
+{
+
+ printf ("\n\n%s\n\n", version_string);
+/*
+ printf ("U-Boot code: %08lX -> %08lX data: %08lX -> %08lX\n"
+ " BSS: %08lX -> %08lX stack: %08lX -> %08lX\n",
+ i386boot_start, i386boot_romdata_start-1,
+ i386boot_romdata_dest, i386boot_romdata_dest+i386boot_romdata_size-1,
+ i386boot_bss_start, i386boot_bss_start+i386boot_bss_size-1,
+ i386boot_bss_start+i386boot_bss_size,
+ i386boot_bss_start+i386boot_bss_size+CONFIG_SYS_STACK_SIZE-1);
+
+*/
+
+ return (0);
+}
+
+static int display_dram_config (void)
+{
+ int i;
+
+ puts ("DRAM Configuration:\n");
+
+ for (i=0; i<CONFIG_NR_DRAM_BANKS; i++) {
+ printf ("Bank #%d: %08lx ", i, gd->bd->bi_dram[i].start);
+ print_size (gd->bd->bi_dram[i].size, "\n");
+ }
+
+ return (0);
+}
+
+static void display_flash_config (ulong size)
+{
+ puts ("Flash: ");
+ print_size (size, "\n");
+}
+
+/*
+ * Breath some life into the board...
+ *
+ * Initialize an SMC for serial comms, and carry out some hardware
+ * tests.
+ *
+ * The first part of initialization is running from Flash memory;
+ * its main purpose is to initialize the RAM so that we
+ * can relocate the monitor code to RAM.
+ */
+
+/*
+ * All attempts to come up with a "common" initialization sequence
+ * that works for all boards and architectures failed: some of the
+ * requirements are just _too_ different. To get rid of the resulting
+ * mess of board dependend #ifdef'ed code we now make the whole
+ * initialization sequence configurable to the user.
+ *
+ * The requirements for any new initalization function is simple: it
+ * receives a pointer to the "global data" structure as it's only
+ * argument, and returns an integer return code, where 0 means
+ * "continue" and != 0 means "fatal error, hang the system".
+ */
+typedef int (init_fnc_t) (void);
+
+static int calculate_relocation_address(void);
+static int copy_uboot_to_ram(void);
+static int clear_bss(void);
+static int do_elf_reloc_fixups(void);
+
+init_fnc_t *init_sequence_f[] = {
+ cpu_init_f,
+ board_early_init_f,
+ env_init,
+ init_baudrate,
+ serial_init,
+ console_init_f,
+ dram_init_f,
+ calculate_relocation_address,
+ copy_uboot_to_ram,
+ clear_bss,
+ do_elf_reloc_fixups,
+
+ NULL,
+};
+
+init_fnc_t *init_sequence_r[] = {
+ cpu_init_r, /* basic cpu dependent setup */
+ board_early_init_r, /* basic board dependent setup */
+ dram_init, /* configure available RAM banks */
+ interrupt_init, /* set up exceptions */
+ timer_init,
+ display_banner,
+ display_dram_config,
+
+ NULL,
+};
+
+gd_t *gd;
+
+static int calculate_relocation_address(void)
+{
+ void *text_start = &__text_start;
+ void *bss_end = &__bss_end;
+ void *dest_addr;
+ ulong rel_offset;
+
+ /* Calculate destination RAM Address and relocation offset */
+ dest_addr = (void *)gd->ram_size;
+ dest_addr -= CONFIG_SYS_STACK_SIZE;
+ dest_addr -= (bss_end - text_start);
+ rel_offset = dest_addr - text_start;
+
+ gd->start_addr_sp = gd->ram_size;
+ gd->relocaddr = (ulong)dest_addr;
+ gd->reloc_off = rel_offset;
+
+ return 0;
+}
+
+static int copy_uboot_to_ram(void)
+{
+ ulong *dst_addr = (ulong *)gd->relocaddr;
+ ulong *src_addr = (ulong *)&__text_start;
+ ulong *end_addr = (ulong *)&__data_end;
+
+ while (src_addr < end_addr)
+ *dst_addr++ = *src_addr++;
+
+ return 0;
+}
+
+static int clear_bss(void)
+{
+ void *bss_start = &__bss_start;
+ void *bss_end = &__bss_end;
+
+ ulong *dst_addr = (ulong *)(bss_start + gd->reloc_off);
+ ulong *end_addr = (ulong *)(bss_end + gd->reloc_off);;
+
+ while (dst_addr < end_addr)
+ *dst_addr++ = 0x00000000;
+
+ return 0;
+}
+
+static int do_elf_reloc_fixups(void)
+{
+ Elf32_Rel *re_src = (Elf32_Rel *)(&__rel_dyn_start);
+ Elf32_Rel *re_end = (Elf32_Rel *)(&__rel_dyn_end);
+
+ do {
+ if (re_src->r_offset >= CONFIG_SYS_TEXT_BASE)
+ if (*(Elf32_Addr *)(re_src->r_offset + gd->reloc_off) >= CONFIG_SYS_TEXT_BASE)
+ *(Elf32_Addr *)(re_src->r_offset + gd->reloc_off) += gd->reloc_off;
+ } while (re_src++ < re_end);
+
+ return 0;
+}
+
+/* Load U-Boot into RAM, initialize BSS, perform relocation adjustments */
+void board_init_f(ulong boot_flags)
+{
+ init_fnc_t **init_fnc_ptr;
+
+ gd->flags = boot_flags;
+
+ for (init_fnc_ptr = init_sequence_f; *init_fnc_ptr; ++init_fnc_ptr) {
+ if ((*init_fnc_ptr)() != 0)
+ hang();
+ }
+
+ gd->flags |= GD_FLG_RELOC;
+
+ /* Enter the relocated U-Boot! */
+ relocate_code(gd->start_addr_sp, gd, gd->relocaddr);
+
+ /* NOTREACHED - relocate_code() does not return */
+ while(1);
+}
+
+void board_init_r(gd_t *id, ulong dest_addr)
+{
+ char *s;
+ ulong size;
+ static bd_t bd_data;
+ static gd_t gd_data;
+ init_fnc_t **init_fnc_ptr;
+
+ show_boot_progress(0x21);
+
+ /* Global data pointer is now writable */
+ gd = &gd_data;
+ memcpy(gd, id, sizeof(gd_t));
+
+ /* compiler optimization barrier needed for GCC >= 3.4 */
+ __asm__ __volatile__("": : :"memory");
+
+ gd->bd = &bd_data;
+ memset (gd->bd, 0, sizeof (bd_t));
+ show_boot_progress(0x22);
+
+ gd->baudrate = CONFIG_BAUDRATE;
+
+ mem_malloc_init((((ulong)dest_addr - CONFIG_SYS_MALLOC_LEN)+3)&~3,
+ CONFIG_SYS_MALLOC_LEN);
+
+ for (init_fnc_ptr = init_sequence_r; *init_fnc_ptr; ++init_fnc_ptr) {
+ if ((*init_fnc_ptr)() != 0)
+ hang ();
+ }
+ show_boot_progress(0x23);
+
+#ifdef CONFIG_SERIAL_MULTI
+ serial_initialize();
+#endif
+ /* configure available FLASH banks */
+ size = flash_init();
+ display_flash_config(size);
+ show_boot_progress(0x24);
+
+ show_boot_progress(0x25);
+
+ /* initialize environment */
+ env_relocate ();
+ show_boot_progress(0x26);
+
+
+#ifdef CONFIG_CMD_NET
+ /* IP Address */
+ bd_data.bi_ip_addr = getenv_IPaddr ("ipaddr");
+#endif
+
+#if defined(CONFIG_PCI)
+ /*
+ * Do pci configuration
+ */
+ pci_init();
+#endif
+
+ show_boot_progress(0x27);
+
+
+ stdio_init ();
+
+ jumptable_init ();
+
+ /* Initialize the console (after the relocation and devices init) */
+ console_init_r();
+
+#ifdef CONFIG_MISC_INIT_R
+ /* miscellaneous platform dependent initialisations */
+ misc_init_r();
+#endif
+
+#if defined(CONFIG_CMD_PCMCIA) && !defined(CONFIG_CMD_IDE)
+ WATCHDOG_RESET();
+ puts ("PCMCIA:");
+ pcmcia_init();
+#endif
+
+#if defined(CONFIG_CMD_KGDB)
+ WATCHDOG_RESET();
+ puts("KGDB: ");
+ kgdb_init();
+#endif
+
+ /* enable exceptions */
+ enable_interrupts();
+ show_boot_progress(0x28);
+
+#ifdef CONFIG_STATUS_LED
+ status_led_set (STATUS_LED_BOOT, STATUS_LED_BLINKING);
+#endif
+
+ udelay(20);
+
+ set_timer (0);
+
+ /* Initialize from environment */
+ if ((s = getenv ("loadaddr")) != NULL) {
+ load_addr = simple_strtoul (s, NULL, 16);
+ }
+#if defined(CONFIG_CMD_NET)
+ if ((s = getenv ("bootfile")) != NULL) {
+ copy_filename (BootFile, s, sizeof (BootFile));
+ }
+#endif
+
+ WATCHDOG_RESET();
+
+#if defined(CONFIG_CMD_IDE)
+ WATCHDOG_RESET();
+ puts("IDE: ");
+ ide_init();
+#endif
+
+#if defined(CONFIG_CMD_SCSI)
+ WATCHDOG_RESET();
+ puts("SCSI: ");
+ scsi_init();
+#endif
+
+#if defined(CONFIG_CMD_DOC)
+ WATCHDOG_RESET();
+ puts("DOC: ");
+ doc_init();
+#endif
+
+#ifdef CONFIG_BITBANGMII
+ bb_miiphy_init();
+#endif
+#if defined(CONFIG_CMD_NET)
+#if defined(CONFIG_NET_MULTI)
+ WATCHDOG_RESET();
+ puts("Net: ");
+#endif
+ eth_initialize(gd->bd);
+#endif
+
+#if ( defined(CONFIG_CMD_NET)) && (0)
+ WATCHDOG_RESET();
+# ifdef DEBUG
+ puts ("Reset Ethernet PHY\n");
+# endif
+ reset_phy();
+#endif
+
+#ifdef CONFIG_LAST_STAGE_INIT
+ WATCHDOG_RESET();
+ /*
+ * Some parts can be only initialized if all others (like
+ * Interrupts) are up and running (i.e. the PC-style ISA
+ * keyboard).
+ */
+ last_stage_init();
+#endif
+
+
+#ifdef CONFIG_POST
+ post_run (NULL, POST_RAM | post_bootmode_get(0));
+#endif
+
+
+ show_boot_progress(0x29);
+
+ /* main_loop() can return to retry autoboot, if so just run it again. */
+ for (;;) {
+ main_loop();
+ }
+
+ /* NOTREACHED - no way out of command loop except booting */
+}
+
+void hang (void)
+{
+ puts ("### ERROR ### Please RESET the board ###\n");
+ for (;;);
+}
+
+unsigned long do_go_exec (ulong (*entry)(int, char * const []), int argc, char * const argv[])
+{
+ unsigned long ret = 0;
+ char **argv_tmp;
+
+ /*
+ * x86 does not use a dedicated register to pass the pointer to
+ * the global_data, so it is instead passed as argv[-1]. By using
+ * argv[-1], the called 'Application' can use the contents of
+ * argv natively. However, to safely use argv[-1] a new copy of
+ * argv is needed with the extra element
+ */
+ argv_tmp = malloc(sizeof(char *) * (argc + 1));
+
+ if (argv_tmp) {
+ argv_tmp[0] = (char *)gd;
+
+ memcpy(&argv_tmp[1], argv, (size_t)(sizeof(char *) * argc));
+
+ ret = (entry) (argc, &argv_tmp[1]);
+ free(argv_tmp);
+ }
+
+ return ret;
+}
+
+void setup_pcat_compatibility(void)
+ __attribute__((weak, alias("__setup_pcat_compatibility")));
+
+void __setup_pcat_compatibility(void)
+{
+}
diff --git a/arch/x86/lib/bootm.c b/arch/x86/lib/bootm.c
new file mode 100644
index 0000000000..a21a21f1f7
--- /dev/null
+++ b/arch/x86/lib/bootm.c
@@ -0,0 +1,97 @@
+/*
+ * (C) Copyright 2002
+ * Sysgo Real-Time Solutions, GmbH <www.elinos.com>
+ * Marius Groeger <mgroeger@sysgo.de>
+ *
+ * Copyright (C) 2001 Erik Mouw (J.A.K.Mouw@its.tudelft.nl)
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <command.h>
+#include <image.h>
+#include <u-boot/zlib.h>
+#include <asm/byteorder.h>
+#include <asm/zimage.h>
+
+/*cmd_boot.c*/
+int do_bootm_linux(int flag, int argc, char * const argv[], bootm_headers_t *images)
+{
+ void *base_ptr;
+ ulong os_data, os_len;
+ image_header_t *hdr;
+
+#if defined(CONFIG_FIT)
+ const void *data;
+ size_t len;
+#endif
+
+ if ((flag != 0) && (flag != BOOTM_STATE_OS_GO))
+ return 1;
+
+ if (images->legacy_hdr_valid) {
+ hdr = images->legacy_hdr_os;
+ if (image_check_type (hdr, IH_TYPE_MULTI)) {
+ /* if multi-part image, we need to get first subimage */
+ image_multi_getimg (hdr, 0, &os_data, &os_len);
+ } else {
+ /* otherwise get image data */
+ os_data = image_get_data (hdr);
+ os_len = image_get_data_size (hdr);
+ }
+#if defined(CONFIG_FIT)
+ } else if (images->fit_uname_os) {
+ ret = fit_image_get_data (images->fit_hdr_os,
+ images->fit_noffset_os, &data, &len);
+ if (ret) {
+ puts ("Can't get image data/size!\n");
+ goto error;
+ }
+ os_data = (ulong)data;
+ os_len = (ulong)len;
+#endif
+ } else {
+ puts ("Could not find kernel image!\n");
+ goto error;
+ }
+
+ base_ptr = load_zimage ((void*)os_data, os_len,
+ images->rd_start, images->rd_end - images->rd_start, 0);
+
+ if (NULL == base_ptr) {
+ printf ("## Kernel loading failed ...\n");
+ goto error;
+
+ }
+
+#ifdef DEBUG
+ printf ("## Transferring control to Linux (at address %08x) ...\n",
+ (u32)base_ptr);
+#endif
+
+ /* we assume that the kernel is in place */
+ printf("\nStarting kernel ...\n\n");
+
+ boot_zimage(base_ptr);
+ /* does not return */
+
+error:
+ return 1;
+}
diff --git a/arch/x86/lib/interrupts.c b/arch/x86/lib/interrupts.c
new file mode 100644
index 0000000000..a2c598f9a4
--- /dev/null
+++ b/arch/x86/lib/interrupts.c
@@ -0,0 +1,161 @@
+/*
+ * (C) Copyright 2009
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2007
+ * Daniel Hellstrom, Gaisler Research, <daniel@gaisler.com>
+ *
+ * (C) Copyright 2006
+ * Detlev Zundel, DENX Software Engineering, <dzu@denx.de>
+ *
+ * (C) Copyright -2003
+ * Wolfgang Denk, DENX Software Engineering, <wd@denx.de>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * (C) Copyright 2001
+ * Josh Huber, Mission Critical Linux, Inc, <huber@mclx.com>
+ *
+ * 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 file contains the high-level API for the interrupt sub-system
+ * of the x86 port of U-Boot. Most of the functionality has been
+ * shamelessly stolen from the leon2 / leon3 ports of U-Boot.
+ * Daniel Hellstrom, Detlev Zundel, Wolfgang Denk and Josh Huber are
+ * credited for the corresponding work on those ports. The original
+ * interrupt handling routines for the x86 port were written by
+ * Daniel Engström
+ */
+
+#include <common.h>
+#include <asm/interrupt.h>
+
+struct irq_action {
+ interrupt_handler_t *handler;
+ void *arg;
+ unsigned int count;
+};
+
+static struct irq_action irq_handlers[CONFIG_SYS_NUM_IRQS] = { {0} };
+static int spurious_irq_cnt = 0;
+static int spurious_irq = 0;
+
+void irq_install_handler(int irq, interrupt_handler_t *handler, void *arg)
+{
+ int status;
+
+ if (irq < 0 || irq >= CONFIG_SYS_NUM_IRQS) {
+ printf("irq_install_handler: bad irq number %d\n", irq);
+ return;
+ }
+
+ if (irq_handlers[irq].handler != NULL)
+ printf("irq_install_handler: 0x%08lx replacing 0x%08lx\n",
+ (ulong) handler,
+ (ulong) irq_handlers[irq].handler);
+
+ status = disable_interrupts ();
+
+ irq_handlers[irq].handler = handler;
+ irq_handlers[irq].arg = arg;
+ irq_handlers[irq].count = 0;
+
+ unmask_irq(irq);
+
+ if (status)
+ enable_interrupts();
+
+ return;
+}
+
+void irq_free_handler(int irq)
+{
+ int status;
+
+ if (irq < 0 || irq >= CONFIG_SYS_NUM_IRQS) {
+ printf("irq_free_handler: bad irq number %d\n", irq);
+ return;
+ }
+
+ status = disable_interrupts ();
+
+ mask_irq(irq);
+
+ irq_handlers[irq].handler = NULL;
+ irq_handlers[irq].arg = NULL;
+
+ if (status)
+ enable_interrupts();
+
+ return;
+}
+
+void do_irq(int hw_irq)
+{
+ int irq = hw_irq - 0x20;
+
+ if (irq < 0 || irq >= CONFIG_SYS_NUM_IRQS) {
+ printf("do_irq: bad irq number %d\n", irq);
+ return;
+ }
+
+ if (irq_handlers[irq].handler) {
+ mask_irq(irq);
+
+ irq_handlers[irq].handler(irq_handlers[irq].arg);
+ irq_handlers[irq].count++;
+
+ unmask_irq(irq);
+ specific_eoi(irq);
+
+ } else {
+ if ((irq & 7) != 7) {
+ spurious_irq_cnt++;
+ spurious_irq = irq;
+ }
+ }
+}
+
+#if defined(CONFIG_CMD_IRQ)
+int do_irqinfo(cmd_tbl_t *cmdtp, int flag, int argc, char * const argv[])
+{
+ int irq;
+
+ printf("Spurious IRQ: %u, last unknown IRQ: %d\n",
+ spurious_irq_cnt, spurious_irq);
+
+ printf ("Interrupt-Information:\n");
+ printf ("Nr Routine Arg Count\n");
+
+ for (irq = 0; irq <= CONFIG_SYS_NUM_IRQS; irq++) {
+ if (irq_handlers[irq].handler != NULL) {
+ printf ("%02d %08lx %08lx %d\n",
+ irq,
+ (ulong)irq_handlers[irq].handler,
+ (ulong)irq_handlers[irq].arg,
+ irq_handlers[irq].count);
+ }
+ }
+
+ return 0;
+}
+#endif
diff --git a/arch/x86/lib/pcat_interrupts.c b/arch/x86/lib/pcat_interrupts.c
new file mode 100644
index 0000000000..364c435837
--- /dev/null
+++ b/arch/x86/lib/pcat_interrupts.c
@@ -0,0 +1,132 @@
+/*
+ * (C) Copyright 2009
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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 file provides the interrupt handling functionality for systems
+ * based on the standard PC/AT architecture using two cascaded i8259
+ * Programmable Interrupt Controllers.
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/i8259.h>
+#include <asm/ibmpc.h>
+#include <asm/interrupt.h>
+
+#if CONFIG_SYS_NUM_IRQS != 16
+#error "CONFIG_SYS_NUM_IRQS must equal 16 if CONFIG_SYS_NUM_IRQS is defined"
+#endif
+
+int interrupt_init(void)
+{
+ u8 i;
+
+ disable_interrupts();
+
+ /* Mask all interrupts */
+ outb(0xff, MASTER_PIC + IMR);
+ outb(0xff, SLAVE_PIC + IMR);
+
+ /* Master PIC */
+ /* Place master PIC interrupts at INT20 */
+ /* ICW3, One slave PIC is present */
+ outb(ICW1_SEL|ICW1_EICW4, MASTER_PIC + ICW1);
+ outb(0x20, MASTER_PIC + ICW2);
+ outb(IR2, MASTER_PIC + ICW3);
+ outb(ICW4_PM, MASTER_PIC + ICW4);
+
+ for (i = 0; i < 8; i++)
+ outb(OCW2_SEOI | i, MASTER_PIC + OCW2);
+
+ /* Slave PIC */
+ /* Place slave PIC interrupts at INT28 */
+ /* Slave ID */
+ outb(ICW1_SEL|ICW1_EICW4, SLAVE_PIC + ICW1);
+ outb(0x28, SLAVE_PIC + ICW2);
+ outb(0x02, SLAVE_PIC + ICW3);
+ outb(ICW4_PM, SLAVE_PIC + ICW4);
+
+ for (i = 0; i < 8; i++)
+ outb(OCW2_SEOI | i, SLAVE_PIC + OCW2);
+
+ /*
+ * Enable cascaded interrupts by unmasking the cascade IRQ pin of
+ * the master PIC
+ */
+ unmask_irq (2);
+
+ enable_interrupts();
+
+ return 0;
+}
+
+void mask_irq(int irq)
+{
+ int imr_port;
+
+ if (irq >= CONFIG_SYS_NUM_IRQS)
+ return;
+
+ if (irq > 7)
+ imr_port = SLAVE_PIC + IMR;
+ else
+ imr_port = MASTER_PIC + IMR;
+
+ outb(inb(imr_port) | (1 << (irq & 7)), imr_port);
+}
+
+void unmask_irq(int irq)
+{
+ int imr_port;
+
+ if (irq >= CONFIG_SYS_NUM_IRQS)
+ return;
+
+ if (irq > 7)
+ imr_port = SLAVE_PIC + IMR;
+ else
+ imr_port = MASTER_PIC + IMR;
+
+ outb(inb(imr_port) & ~(1 << (irq & 7)), imr_port);
+}
+
+void specific_eoi(int irq)
+{
+ if (irq >= CONFIG_SYS_NUM_IRQS)
+ return;
+
+ if (irq > 7) {
+ /*
+ * IRQ is on the slave - Issue a corresponding EOI to the
+ * slave PIC and an EOI for IRQ2 (the cascade interrupt)
+ * on the master PIC
+ */
+ outb(OCW2_SEOI | (irq & 7), SLAVE_PIC + OCW2);
+ irq = SEOI_IR2;
+ }
+
+ outb(OCW2_SEOI | irq, MASTER_PIC + OCW2);
+}
diff --git a/arch/x86/lib/pcat_timer.c b/arch/x86/lib/pcat_timer.c
new file mode 100644
index 0000000000..1911c6c19d
--- /dev/null
+++ b/arch/x86/lib/pcat_timer.c
@@ -0,0 +1,107 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/i8254.h>
+#include <asm/ibmpc.h>
+#include <asm/interrupt.h>
+
+#define TIMER0_VALUE 0x04aa /* 1kHz 1.9318MHz / 1000 */
+#define TIMER2_VALUE 0x0a8e /* 440Hz */
+
+static int timer_init_done = 0;
+
+int timer_init(void)
+{
+ /* initialize timer 0 and 2
+ *
+ * Timer 0 is used to increment system_tick 1000 times/sec
+ * Timer 1 was used for DRAM refresh in early PC's
+ * Timer 2 is used to drive the speaker
+ * (to stasrt a beep: write 3 to port 0x61,
+ * to stop it again: write 0)
+ */
+ outb (PIT_CMD_CTR0 | PIT_CMD_BOTH | PIT_CMD_MODE2,
+ PIT_BASE + PIT_COMMAND);
+ outb (TIMER0_VALUE & 0xff, PIT_BASE + PIT_T0);
+ outb (TIMER0_VALUE >> 8, PIT_BASE + PIT_T0);
+
+ outb (PIT_CMD_CTR2 | PIT_CMD_BOTH | PIT_CMD_MODE3,
+ PIT_BASE + PIT_COMMAND);
+ outb (TIMER2_VALUE & 0xff, PIT_BASE + PIT_T2);
+ outb (TIMER2_VALUE >> 8, PIT_BASE + PIT_T2);
+
+ irq_install_handler (0, timer_isr, NULL);
+ unmask_irq (0);
+
+ timer_init_done = 1;
+
+ return 0;
+}
+
+static u16 read_pit(void)
+{
+ u8 low;
+
+ outb (PIT_CMD_LATCH, PIT_BASE + PIT_COMMAND);
+ low = inb (PIT_BASE + PIT_T0);
+
+ return ((inb (PIT_BASE + PIT_T0) << 8) | low);
+}
+
+/* this is not very exact */
+void __udelay (unsigned long usec)
+{
+ int counter;
+ int wraps;
+
+ if (timer_init_done)
+ {
+ counter = read_pit ();
+ wraps = usec / 1000;
+ usec = usec % 1000;
+
+ usec *= 1194;
+ usec /= 1000;
+ usec += counter;
+
+ while (usec > 1194) {
+ usec -= 1194;
+ wraps++;
+ }
+
+ while (1) {
+ int new_count = read_pit ();
+
+ if (((new_count < usec) && !wraps) || wraps < 0)
+ break;
+
+ if (new_count > counter)
+ wraps--;
+
+ counter = new_count;
+ }
+ }
+
+}
diff --git a/arch/x86/lib/pci.c b/arch/x86/lib/pci.c
new file mode 100644
index 0000000000..e791e88bd4
--- /dev/null
+++ b/arch/x86/lib/pci.c
@@ -0,0 +1,150 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+
+#undef PCI_ROM_SCAN_VERBOSE
+
+int pci_shadow_rom(pci_dev_t dev, unsigned char *dest)
+{
+ struct pci_controller *hose;
+ int res = -1;
+ int i;
+
+ u32 rom_addr;
+ u32 addr_reg;
+ u32 size;
+
+ u16 vendor;
+ u16 device;
+ u32 class_code;
+
+ hose = pci_bus_to_hose(PCI_BUS(dev));
+#if 0
+ printf("pci_shadow_rom() asked to shadow device %x to %x\n",
+ dev, (u32)dest);
+#endif
+ pci_read_config_word(dev, PCI_VENDOR_ID, &vendor);
+ pci_read_config_word(dev, PCI_DEVICE_ID, &device);
+ pci_read_config_dword(dev, PCI_CLASS_REVISION, &class_code);
+
+ class_code &= 0xffffff00;
+ class_code >>= 8;
+
+ debug("PCI Header Vendor %04x device %04x class %06x\n",
+ vendor, device, class_code);
+
+ /* Enable the rom addess decoder */
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, (u32)PCI_ROM_ADDRESS_MASK);
+ pci_read_config_dword(dev, PCI_ROM_ADDRESS, &addr_reg);
+
+ if (!addr_reg) {
+ /* register unimplemented */
+ printf("pci_chadow_rom: device do not seem to have a rom\n");
+ return -1;
+ }
+
+ size = (~(addr_reg&PCI_ROM_ADDRESS_MASK))+1;
+
+ debug("ROM is %d bytes\n", size);
+
+ rom_addr = pci_get_rom_window(hose, size);
+
+ debug("ROM mapped at %x\n", rom_addr);
+
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS,
+ pci_phys_to_mem(dev, rom_addr)
+ |PCI_ROM_ADDRESS_ENABLE);
+
+
+ for (i=rom_addr;i<rom_addr+size; i+=512) {
+
+
+ if (readw(i) == 0xaa55) {
+ u32 pci_data;
+#ifdef PCI_ROM_SCAN_VERBOSE
+ printf("ROM signature found\n");
+#endif
+ pci_data = readw(0x18+i);
+ pci_data += i;
+
+ if (0==memcmp((void*)pci_data, "PCIR", 4)) {
+#ifdef PCI_ROM_SCAN_VERBOSE
+ printf("Fount PCI rom image at offset %d\n", i-rom_addr);
+ printf("Vendor %04x device %04x class %06x\n",
+ readw(pci_data+4), readw(pci_data+6),
+ readl(pci_data+0x0d)&0xffffff);
+ printf("%s\n",
+ (readw(pci_data+0x15) &0x80)?
+ "Last image":"More images follow");
+ switch (readb(pci_data+0x14)) {
+ case 0:
+ printf("X86 code\n");
+ break;
+ case 1:
+ printf("Openfirmware code\n");
+ break;
+ case 2:
+ printf("PARISC code\n");
+ break;
+ }
+ printf("Image size %d\n", readw(pci_data+0x10) * 512);
+#endif
+ /* FixMe: I think we should compare the class code
+ * bytes as well but I have no reference on the
+ * exact order of these bytes in the PCI ROM header */
+ if (readw(pci_data+4) == vendor &&
+ readw(pci_data+6) == device &&
+ /* (readl(pci_data+0x0d)&0xffffff) == class_code && */
+ readb(pci_data+0x14) == 0 /* x86 code image */ ) {
+#ifdef PCI_ROM_SCAN_VERBOSE
+ printf("Suitable ROM image found, copying\n");
+#endif
+ memmove(dest, (void*)rom_addr, readw(pci_data+0x10) * 512);
+ res = 0;
+ break;
+
+ }
+ if (readw(pci_data+0x15) &0x80) {
+ break;
+ }
+ }
+ }
+
+ }
+
+#ifdef PCI_ROM_SCAN_VERBOSE
+ if (res) {
+ printf("No suitable image found\n");
+ }
+#endif
+ /* disable PAR register and PCI device ROM address devocer */
+ pci_remove_rom_window(hose, rom_addr);
+
+ pci_write_config_dword(dev, PCI_ROM_ADDRESS, 0);
+
+ return res;
+}
diff --git a/arch/x86/lib/pci_type1.c b/arch/x86/lib/pci_type1.c
new file mode 100644
index 0000000000..8ce5b33e3d
--- /dev/null
+++ b/arch/x86/lib/pci_type1.c
@@ -0,0 +1,66 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+/*
+ * Support for type PCI configuration cycles.
+ * based on pci_indirect.c
+ */
+#include <common.h>
+#include <asm/io.h>
+#include <pci.h>
+
+#define cfg_read(val, addr, op) *val = op((int)(addr))
+#define cfg_write(val, addr, op) op((val), (int)(addr))
+
+#define TYPE1_PCI_OP(rw, size, type, op, mask) \
+static int \
+type1_##rw##_config_##size(struct pci_controller *hose, \
+ pci_dev_t dev, int offset, type val) \
+{ \
+ outl(dev | (offset & 0xfc) | 0x80000000, (int)hose->cfg_addr); \
+ cfg_##rw(val, hose->cfg_data + (offset & mask), op); \
+ return 0; \
+}
+
+
+TYPE1_PCI_OP(read, byte, u8 *, inb, 3)
+TYPE1_PCI_OP(read, word, u16 *, inw, 2)
+TYPE1_PCI_OP(read, dword, u32 *, inl, 0)
+
+TYPE1_PCI_OP(write, byte, u8, outb, 3)
+TYPE1_PCI_OP(write, word, u16, outw, 2)
+TYPE1_PCI_OP(write, dword, u32, outl, 0)
+
+void pci_setup_type1(struct pci_controller* hose, u32 cfg_addr, u32 cfg_data)
+{
+ pci_set_ops(hose,
+ type1_read_config_byte,
+ type1_read_config_word,
+ type1_read_config_dword,
+ type1_write_config_byte,
+ type1_write_config_word,
+ type1_write_config_dword);
+
+ hose->cfg_addr = (unsigned int *) cfg_addr;
+ hose->cfg_data = (unsigned char *) cfg_data;
+}
diff --git a/arch/x86/lib/realmode.c b/arch/x86/lib/realmode.c
new file mode 100644
index 0000000000..5be827c66b
--- /dev/null
+++ b/arch/x86/lib/realmode.c
@@ -0,0 +1,96 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/ptrace.h>
+#include <asm/realmode.h>
+
+#define REALMODE_MAILBOX ((char*)0xe00)
+
+extern ulong __realmode_start;
+extern ulong __realmode_size;
+extern char realmode_enter;
+
+int realmode_setup(void)
+{
+ ulong realmode_start = (ulong)&__realmode_start + gd->reloc_off;
+ ulong realmode_size = (ulong)&__realmode_size;
+
+ /* copy the realmode switch code */
+ if (realmode_size > (REALMODE_MAILBOX - (char *)REALMODE_BASE)) {
+ printf("realmode switch too large (%ld bytes, max is %d)\n",
+ realmode_size,
+ (REALMODE_MAILBOX - (char *)REALMODE_BASE));
+ return -1;
+ }
+
+ memcpy((char *)REALMODE_BASE, (void *)realmode_start, realmode_size);
+ asm("wbinvd\n");
+
+ return 0;
+}
+
+int enter_realmode(u16 seg, u16 off, struct pt_regs *in, struct pt_regs *out)
+{
+
+ /* setup out thin bios emulation */
+ if (bios_setup())
+ return -1;
+
+ if (realmode_setup())
+ return -1;
+
+ in->eip = off;
+ in->xcs = seg;
+ if (3>(in->esp & 0xffff)) {
+ printf("Warning: entering realmode with sp < 4 will fail\n");
+ }
+
+ memcpy(REALMODE_MAILBOX, in, sizeof(struct pt_regs));
+ asm("wbinvd\n");
+
+ __asm__ volatile (
+ "lcall $0x20,%0\n" : : "i" (&realmode_enter) );
+
+ asm("wbinvd\n");
+ memcpy(out, REALMODE_MAILBOX, sizeof(struct pt_regs));
+
+ return out->eax;
+}
+
+
+/* This code is supposed to access a realmode interrupt
+ * it does currently not work for me */
+int enter_realmode_int(u8 lvl, struct pt_regs *in, struct pt_regs *out)
+{
+ /* place two instructions at 0x700 */
+ writeb(0xcd, 0x700); /* int $lvl */
+ writeb(lvl, 0x701);
+ writeb(0xcb, 0x702); /* lret */
+ asm("wbinvd\n");
+
+ enter_realmode(0x00, 0x700, in, out);
+
+ return out->eflags&1;
+}
diff --git a/arch/x86/lib/realmode_switch.S b/arch/x86/lib/realmode_switch.S
new file mode 100644
index 0000000000..fce4eccab0
--- /dev/null
+++ b/arch/x86/lib/realmode_switch.S
@@ -0,0 +1,221 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, daniel@omicron.se
+ *
+ * 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
+ */
+
+/* 32bit -> 16bit -> 32bit mode switch code */
+
+/*
+ * Stack frame at 0xe00
+ * e00 ebx;
+ * e04 ecx;
+ * e08 edx;
+ * e0c esi;
+ * e10 edi;
+ * e14 ebp;
+ * e18 eax;
+ * e1c ds;
+ * e20 es;
+ * e24 fs;
+ * e28 gs;
+ * e2c orig_eax;
+ * e30 eip;
+ * e34 cs;
+ * e38 eflags;
+ * e3c esp;
+ * e40 ss;
+ */
+
+#define a32 .byte 0x67; /* address size prefix 32 */
+#define o32 .byte 0x66; /* operand size prefix 32 */
+
+.section .realmode, "ax"
+.code16
+ /* 16bit protected mode code here */
+.globl realmode_enter
+realmode_enter:
+o32 pusha
+o32 pushf
+ cli
+ sidt saved_idt
+ sgdt saved_gdt
+ movl %esp, %eax
+ movl %eax, saved_protected_mode_esp
+
+ movl $0x10, %eax
+ movl %eax, %esp
+ movw $0x28, %ax
+ movw %ax, %ds
+ movw %ax, %es
+ movw %ax, %fs
+ movw %ax, %gs
+
+ lidt realmode_idt_ptr
+ movl %cr0, %eax /* Go back into real mode by */
+ andl $0x7ffffffe, %eax /* clearing PE to 0 */
+ movl %eax, %cr0
+ ljmp $0x0,$do_realmode /* switch to real mode */
+
+do_realmode: /* realmode code from here */
+ movw %cs,%ax
+ movw %ax,%ds
+ movw %ax,%es
+ movw %ax,%fs
+ movw %ax,%gs
+
+ /* create a temporary stack */
+
+ movw $0xc0, %ax
+ movw %ax, %ss
+ movw $0x200, %ax
+ movw %ax, %sp
+
+ popl %ebx
+ popl %ecx
+ popl %edx
+ popl %esi
+ popl %edi
+ popl %ebp
+ popl %eax
+ movl %eax, temp_eax
+ popl %eax
+ movw %ax, %ds
+ popl %eax
+ movw %ax, %es
+ popl %eax
+ movw %ax, %fs
+ popl %eax
+ movw %ax, %gs
+ popl %eax /* orig_eax */
+ popl %eax
+cs movw %ax, temp_ip
+ popl %eax
+cs movw %ax, temp_cs
+o32 popf
+ popl %eax
+ popw %ss
+ movl %eax, %esp
+cs movl temp_eax, %eax
+ wbinvd /* self-modifying code,
+ * better flush the cache */
+
+ .byte 0x9a /* lcall */
+temp_ip:
+ .word 0 /* new ip */
+temp_cs:
+ .word 0 /* new cs */
+realmode_ret:
+ /* save eax, esp and ss */
+cs movl %eax, saved_eax
+ movl %esp, %eax
+cs movl %eax, saved_esp
+ movw %ss, %ax
+cs movw %ax, saved_ss
+
+ /* restore the stack, note that we set sp to 0x244;
+ * pt_regs is 0x44 bytes long and we push the structure
+ * backwards on to the stack, bottom first */
+
+ movw $0xc0, %ax
+ movw %ax, %ss
+ movw $0x244, %ax
+ movw %ax, %sp
+
+ xorl %eax,%eax
+cs movw saved_ss, %ax
+ pushl %eax
+cs movl saved_esp, %eax
+ pushl %eax
+o32 pushf
+ xorl %eax,%eax
+cs movw temp_cs, %ax
+ pushl %eax
+cs movw temp_ip, %ax
+ pushl %eax
+ pushl $0
+ movw %gs, %ax
+ pushl %eax
+ movw %fs, %ax
+ pushl %eax
+ movw %es, %ax
+ pushl %eax
+ movw %ds, %ax
+ pushl %eax
+ movl saved_eax, %eax
+ pushl %eax
+ pushl %ebp
+ pushl %edi
+ pushl %esi
+ pushl %edx
+ pushl %ecx
+ pushl %ebx
+
+o32 cs lidt saved_idt
+o32 cs lgdt saved_gdt /* Set GDTR */
+
+ movl %cr0, %eax /* Go back into protected mode */
+ orl $1,%eax /* reset PE to 1 */
+ movl %eax, %cr0
+ jmp next_line /* flush prefetch queue */
+next_line:
+ movw $return_ptr, %ax
+ movw %ax,%bp
+o32 cs ljmp *(%bp)
+
+.code32
+protected_mode:
+ movl $0x18,%eax /* reload GDT[3] */
+ movw %ax,%fs /* reset FS */
+ movw %ax,%ds /* reset DS */
+ movw %ax,%gs /* reset GS */
+ movw %ax,%es /* reset ES */
+ movw %ax,%ss /* reset SS */
+ movl saved_protected_mode_esp, %eax
+ movl %eax, %esp
+ popf
+ popa
+ ret
+
+temp_eax:
+ .long 0
+
+saved_ss:
+ .word 0
+saved_esp:
+ .long 0
+saved_eax:
+ .long 0
+
+realmode_idt_ptr:
+ .word 0x400
+ .word 0x0, 0x0
+
+saved_gdt:
+ .word 0, 0, 0, 0
+saved_idt:
+ .word 0, 0, 0, 0
+
+saved_protected_mode_esp:
+ .long 0
+
+return_ptr:
+ .long protected_mode
+ .word 0x10
diff --git a/arch/x86/lib/timer.c b/arch/x86/lib/timer.c
new file mode 100644
index 0000000000..8fc68cdcb8
--- /dev/null
+++ b/arch/x86/lib/timer.c
@@ -0,0 +1,110 @@
+/*
+ * (C) Copyright 2008,2009
+ * Graeme Russ, <graeme.russ@gmail.com>
+ *
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <malloc.h>
+#include <asm/io.h>
+#include <asm/i8254.h>
+#include <asm/ibmpc.h>
+
+struct timer_isr_function {
+ struct timer_isr_function *next;
+ timer_fnc_t *isr_func;
+};
+
+static struct timer_isr_function *first_timer_isr = NULL;
+static volatile unsigned long system_ticks = 0;
+
+/*
+ * register_timer_isr() allows multiple architecture and board specific
+ * functions to be called every millisecond. Keep the execution time of
+ * each function as low as possible
+ */
+int register_timer_isr (timer_fnc_t *isr_func)
+{
+ struct timer_isr_function *new_func;
+ struct timer_isr_function *temp;
+ int flag;
+
+ new_func = malloc(sizeof(struct timer_isr_function));
+
+ if (new_func == NULL)
+ return 1;
+
+ new_func->isr_func = isr_func;
+ new_func->next = NULL;
+
+ /*
+ * Don't allow timer interrupts while the
+ * linked list is being modified
+ */
+ flag = disable_interrupts ();
+
+ if (first_timer_isr == NULL) {
+ first_timer_isr = new_func;
+ } else {
+ temp = first_timer_isr;
+ while (temp->next != NULL)
+ temp = temp->next;
+ temp->next = new_func;
+ }
+
+ if (flag)
+ enable_interrupts ();
+
+ return 0;
+}
+
+/*
+ * timer_isr() MUST be the registered interrupt handler for
+ */
+void timer_isr(void *unused)
+{
+ struct timer_isr_function *temp = first_timer_isr;
+
+ system_ticks++;
+
+ /* Execute each registered function */
+ while (temp != NULL) {
+ temp->isr_func ();
+ temp = temp->next;
+ }
+}
+
+void reset_timer (void)
+{
+ system_ticks = 0;
+}
+
+ulong get_timer (ulong base)
+{
+ return (system_ticks - base);
+}
+
+void set_timer (ulong t)
+{
+ system_ticks = t;
+}
diff --git a/arch/x86/lib/video.c b/arch/x86/lib/video.c
new file mode 100644
index 0000000000..b29075c490
--- /dev/null
+++ b/arch/x86/lib/video.c
@@ -0,0 +1,229 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <stdio_dev.h>
+#include <i8042.h>
+#include <asm/ptrace.h>
+#include <asm/realmode.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+
+/* basic textmode I/O from linux kernel */
+static char *vidmem = (char *)0xb8000;
+static int vidport;
+static int lines, cols;
+static int orig_x, orig_y;
+
+static void beep(int dur)
+{
+ int i;
+
+ outb_p(3, 0x61);
+ for (i = 0; i < 10*dur; i++)
+ udelay(1000);
+
+ outb_p(0, 0x61);
+}
+
+static void scroll(void)
+{
+ int i;
+
+ memcpy(vidmem, vidmem + cols * 2, (lines - 1) * cols * 2);
+ for (i = (lines - 1) * cols * 2; i < lines * cols * 2; i += 2)
+ vidmem[i] = ' ';
+}
+
+static void __video_putc(const char c, int *x, int *y)
+{
+ if (c == '\n') {
+ (*x) = 0;
+ if (++(*y) >= lines) {
+ scroll();
+ (*y)--;
+ }
+ } else if (c == '\b') {
+ if ((*x) != 0) {
+ --(*x);
+ vidmem[((*x) + cols * (*y)) * 2] = ' ';
+ }
+ } else if (c == '\r') {
+ (*x) = 0;
+
+ } else if (c == '\a') {
+ beep(3);
+
+ } else if (c == '\t') {
+ __video_putc(' ', x, y);
+ __video_putc(' ', x, y);
+ __video_putc(' ', x, y);
+ __video_putc(' ', x, y);
+ __video_putc(' ', x, y);
+ __video_putc(' ', x, y);
+ __video_putc(' ', x, y);
+ __video_putc(' ', x, y);
+ } else if (c == '\v') {
+ switch ((*x) % 8) {
+ case 0:
+ __video_putc(' ', x, y);
+ case 7:
+ __video_putc(' ', x, y);
+ case 6:
+ __video_putc(' ', x, y);
+ case 5:
+ __video_putc(' ', x, y);
+ case 4:
+ __video_putc(' ', x, y);
+ case 3:
+ __video_putc(' ', x, y);
+ case 2:
+ __video_putc(' ', x, y);
+ case 1:
+ __video_putc(' ', x, y);
+ }
+ } else if (c == '\f') {
+ int i;
+ for (i = 0; i < lines * cols * 2; i += 2)
+ vidmem[i] = 0;
+ (*x) = 0;
+ (*y) = 0;
+ } else {
+ vidmem[((*x) + cols * (*y)) * 2] = c;
+ if (++(*x) >= cols) {
+ (*x) = 0;
+ if (++(*y) >= lines) {
+ scroll();
+ (*y)--;
+ }
+ }
+ }
+}
+
+static void video_putc(const char c)
+{
+ int x,y,pos;
+
+ x = orig_x;
+ y = orig_y;
+
+ __video_putc(c, &x, &y);
+
+ orig_x = x;
+ orig_y = y;
+
+ pos = (x + cols * y) * 2; /* Update cursor position */
+ outb_p(14, vidport);
+ outb_p(0xff & (pos >> 9), vidport+1);
+ outb_p(15, vidport);
+ outb_p(0xff & (pos >> 1), vidport+1);
+}
+
+static void video_puts(const char *s)
+{
+ int x,y,pos;
+ char c;
+
+ x = orig_x;
+ y = orig_y;
+
+ while ((c = *s++) != '\0')
+ __video_putc(c, &x, &y);
+
+ orig_x = x;
+ orig_y = y;
+
+ pos = (x + cols * y) * 2; /* Update cursor position */
+ outb_p(14, vidport);
+ outb_p(0xff & (pos >> 9), vidport+1);
+ outb_p(15, vidport);
+ outb_p(0xff & (pos >> 1), vidport+1);
+}
+
+int video_init(void)
+{
+ u16 pos;
+
+ static struct stdio_dev vga_dev;
+ static struct stdio_dev kbd_dev;
+
+ vidmem = (char *) 0xb8000;
+ vidport = 0x3d4;
+
+ lines = 25;
+ cols = 80;
+
+ outb_p(14, vidport);
+ pos = inb_p(vidport+1);
+ pos <<= 8;
+ outb_p(15, vidport);
+ pos |= inb_p(vidport+1);
+
+ orig_x = pos%cols;
+ orig_y = pos/cols;
+
+#if 0
+ printf("pos %x %d %d\n", pos, orig_x, orig_y);
+#endif
+ if (orig_y > lines)
+ orig_x = orig_y =0;
+
+ memset(&vga_dev, 0, sizeof(vga_dev));
+ strcpy(vga_dev.name, "vga");
+ vga_dev.ext = 0;
+ vga_dev.flags = DEV_FLAGS_OUTPUT | DEV_FLAGS_SYSTEM;
+ vga_dev.putc = video_putc; /* 'putc' function */
+ vga_dev.puts = video_puts; /* 'puts' function */
+ vga_dev.tstc = NULL; /* 'tstc' function */
+ vga_dev.getc = NULL; /* 'getc' function */
+
+ if (stdio_register(&vga_dev) == 0)
+ return 1;
+
+ if (i8042_kbd_init())
+ return 1;
+
+ memset(&kbd_dev, 0, sizeof(kbd_dev));
+ strcpy(kbd_dev.name, "kbd");
+ kbd_dev.ext = 0;
+ kbd_dev.flags = DEV_FLAGS_INPUT | DEV_FLAGS_SYSTEM;
+ kbd_dev.putc = NULL; /* 'putc' function */
+ kbd_dev.puts = NULL; /* 'puts' function */
+ kbd_dev.tstc = i8042_tstc; /* 'tstc' function */
+ kbd_dev.getc = i8042_getc; /* 'getc' function */
+
+ if (stdio_register(&kbd_dev) == 0)
+ return 1;
+
+ return 0;
+}
+
+
+int drv_video_init(void)
+{
+ if (video_bios_init())
+ return 1;
+
+ return video_init();
+}
diff --git a/arch/x86/lib/video_bios.c b/arch/x86/lib/video_bios.c
new file mode 100644
index 0000000000..6bc4335743
--- /dev/null
+++ b/arch/x86/lib/video_bios.c
@@ -0,0 +1,222 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+#include <common.h>
+#include <pci.h>
+#include <malloc.h>
+#include <asm/ptrace.h>
+#include <asm/realmode.h>
+#include <asm/io.h>
+#include <asm/pci.h>
+
+#undef PCI_BIOS_DEBUG
+#undef VGA_BIOS_DEBUG
+
+#ifdef VGA_BIOS_DEBUG
+#define PRINTF(fmt,args...) printf (fmt ,##args)
+#else
+#define PRINTF(fmt,args...)
+#endif
+
+#ifdef CONFIG_PCI
+
+#ifdef PCI_BIOS_DEBUG
+#define RELOC_16(seg, off) *(u32*)(seg << 4 | (u32)&off)
+extern u32 num_pci_bios_present;
+extern u32 num_pci_bios_find_device;
+extern u32 num_pci_bios_find_class;
+extern u32 num_pci_bios_generate_special_cycle;
+extern u32 num_pci_bios_read_cfg_byte;
+extern u32 num_pci_bios_read_cfg_word;
+extern u32 num_pci_bios_read_cfg_dword;
+extern u32 num_pci_bios_write_cfg_byte;
+extern u32 num_pci_bios_write_cfg_word;
+extern u32 num_pci_bios_write_cfg_dword;
+extern u32 num_pci_bios_get_irq_routing;
+extern u32 num_pci_bios_set_irq;
+extern u32 num_pci_bios_unknown_function;
+
+void print_bios_bios_stat(void)
+{
+ printf("16 bit functions:\n");
+ printf("pci_bios_present: %d\n", RELOC_16(0xf000, num_pci_bios_present));
+ printf("pci_bios_find_device: %d\n", RELOC_16(0xf000, num_pci_bios_find_device));
+ printf("pci_bios_find_class: %d\n", RELOC_16(0xf000, num_pci_bios_find_class));
+ printf("pci_bios_generate_special_cycle: %d\n", RELOC_16(0xf000, num_pci_bios_generate_special_cycle));
+ printf("pci_bios_read_cfg_byte: %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_byte));
+ printf("pci_bios_read_cfg_word: %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_word));
+ printf("pci_bios_read_cfg_dword: %d\n", RELOC_16(0xf000, num_pci_bios_read_cfg_dword));
+ printf("pci_bios_write_cfg_byte: %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_byte));
+ printf("pci_bios_write_cfg_word: %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_word));
+ printf("pci_bios_write_cfg_dword: %d\n", RELOC_16(0xf000, num_pci_bios_write_cfg_dword));
+ printf("pci_bios_get_irq_routing: %d\n", RELOC_16(0xf000, num_pci_bios_get_irq_routing));
+ printf("pci_bios_set_irq: %d\n", RELOC_16(0xf000, num_pci_bios_set_irq));
+ printf("pci_bios_unknown_function: %d\n", RELOC_16(0xf000, num_pci_bios_unknown_function));
+
+}
+#endif
+
+#ifdef CONFIG_VIDEO
+
+#define PCI_CLASS_VIDEO 3
+#define PCI_CLASS_VIDEO_STD 0
+#define PCI_CLASS_VIDEO_PROG_IF_VGA 0
+
+static struct pci_device_id supported[] = {
+ {PCI_VIDEO_VENDOR_ID, PCI_VIDEO_DEVICE_ID},
+ {}
+};
+
+static u32 probe_pci_video(void)
+{
+ pci_dev_t devbusfn;
+
+ if ((devbusfn = pci_find_devices(supported, 0) != -1)) {
+ u32 old;
+ u32 addr;
+
+ /* PCI video device detected */
+ printf("Found PCI VGA device at %02x.%02x.%x\n",
+ PCI_BUS(devbusfn), PCI_DEV(devbusfn), PCI_FUNC(devbusfn));
+
+ /* Enable I/O decoding as well, PCI viudeo boards
+ * support I/O accesses, but they provide no
+ * bar register for this since the ports are fixed.
+ */
+ pci_write_config_word(devbusfn, PCI_COMMAND, PCI_COMMAND_MEMORY | PCI_COMMAND_IO | PCI_COMMAND_MASTER);
+
+ /* Test the ROM decoder, do the device support a rom? */
+ pci_read_config_dword(devbusfn, PCI_ROM_ADDRESS, &old);
+ pci_write_config_dword(devbusfn, PCI_ROM_ADDRESS, (u32)PCI_ROM_ADDRESS_MASK);
+ pci_read_config_dword(devbusfn, PCI_ROM_ADDRESS, &addr);
+ pci_write_config_dword(devbusfn, PCI_ROM_ADDRESS, old);
+
+ if (!addr) {
+ printf("PCI VGA have no ROM?\n");
+ return 0;
+ }
+
+ /* device have a rom */
+ if (pci_shadow_rom(devbusfn, (void*)0xc0000)) {
+ printf("Shadowing of PCI VGA BIOS failed\n");
+ return 0;
+ }
+
+ /* Now enable lagacy VGA port access */
+ if (pci_enable_legacy_video_ports(pci_bus_to_hose(PCI_BUS(devbusfn)))) {
+ printf("PCI VGA enable failed\n");
+ return 0;
+ }
+
+
+ /* return the pci device info, that we'll need later */
+ return PCI_BUS(devbusfn) << 8 |
+ PCI_DEV(devbusfn) << 3 | (PCI_FUNC(devbusfn)&7);
+ }
+
+ return 0;
+}
+
+static int probe_isa_video(void)
+{
+ u32 ptr;
+ char *buf;
+
+ if (0 == (ptr = isa_map_rom(0xc0000, 0x8000))) {
+ return -1;
+ }
+ if (NULL == (buf=malloc(0x8000))) {
+ isa_unmap_rom(ptr);
+ return -1;
+ }
+ if (readw(ptr) != 0xaa55) {
+ free(buf);
+ isa_unmap_rom(ptr);
+ return -1;
+ }
+
+ /* shadow the rom */
+ memcpy(buf, (void*)ptr, 0x8000);
+ isa_unmap_rom(ptr);
+ memcpy((void*)0xc0000, buf, 0x8000);
+
+ free(buf);
+
+ return 0;
+}
+
+int video_bios_init(void)
+{
+ struct pt_regs regs;
+
+ /* clear the video bios area in case we warmbooted */
+ memset((void*)0xc0000, 0, 0x8000);
+ memset(&regs, 0, sizeof(struct pt_regs));
+
+ if (probe_isa_video()) {
+ /* No ISA board found, try the PCI bus */
+ regs.eax = probe_pci_video();
+ }
+
+ /* Did we succeed in mapping any video bios */
+ if (readw(0xc0000) == 0xaa55) {
+ int size;
+ int i;
+ u8 sum;
+
+ PRINTF("Found video bios signature\n");
+ size = 512*readb(0xc0002);
+ PRINTF("size %d\n", size);
+ sum=0;
+ for (i=0;i<size;i++) {
+ sum += readb(0xc0000 + i);
+ }
+ PRINTF("Checksum is %sOK\n",sum?"NOT ":"");
+ if (sum) {
+ return 1;
+ }
+
+ /* some video bioses (ATI Mach64) seem to think that
+ * the original int 10 handler is always at
+ * 0xf000:0xf065 , place an iret instruction there
+ */
+ writeb(0xcf, 0xff065);
+
+ regs.esp = 0x8000;
+ regs.xss = 0x2000;
+ enter_realmode(0xc000, 3, &regs, &regs);
+ PRINTF("INT 0x10 vector after: %04x:%04x\n",
+ readw(0x42), readw(0x40));
+ PRINTF("BIOS returned %scarry\n", regs.eflags & 1?"":"NOT ");
+#ifdef PCI_BIOS_DEBUG
+ print_bios_bios_stat();
+#endif
+ return (regs.eflags & 1);
+
+ }
+
+ return 1;
+
+}
+#endif
+#endif
diff --git a/arch/x86/lib/zimage.c b/arch/x86/lib/zimage.c
new file mode 100644
index 0000000000..cc4b40e64c
--- /dev/null
+++ b/arch/x86/lib/zimage.c
@@ -0,0 +1,296 @@
+/*
+ * (C) Copyright 2002
+ * Daniel Engström, Omicron Ceti AB, <daniel@omicron.se>
+ *
+ * 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
+ */
+
+/*
+ * Linux x86 zImage and bzImage loading
+ *
+ * based on the procdure described in
+ * linux/Documentation/i386/boot.txt
+ */
+
+#include <common.h>
+#include <asm/io.h>
+#include <asm/ptrace.h>
+#include <asm/zimage.h>
+#include <asm/realmode.h>
+#include <asm/byteorder.h>
+#include <asm/bootparam.h>
+#include <asm/ic/sc520.h>
+
+/*
+ * Memory lay-out:
+ *
+ * relative to setup_base (which is 0x90000 currently)
+ *
+ * 0x0000-0x7FFF Real mode kernel
+ * 0x8000-0x8FFF Stack and heap
+ * 0x9000-0x90FF Kernel command line
+ */
+#define DEFAULT_SETUP_BASE 0x90000
+#define COMMAND_LINE_OFFSET 0x9000
+#define HEAP_END_OFFSET 0x8e00
+
+#define COMMAND_LINE_SIZE 2048
+
+static void build_command_line(char *command_line, int auto_boot)
+{
+ char *env_command_line;
+
+ command_line[0] = '\0';
+
+ env_command_line = getenv("bootargs");
+
+ /* set console= argument if we use a serial console */
+ if (NULL == strstr(env_command_line, "console=")) {
+ if (0==strcmp(getenv("stdout"), "serial")) {
+
+ /* We seem to use serial console */
+ sprintf(command_line, "console=ttyS0,%s ",
+ getenv("baudrate"));
+ }
+ }
+
+ if (auto_boot) {
+ strcat(command_line, "auto ");
+ }
+
+ if (NULL != env_command_line) {
+ strcat(command_line, env_command_line);
+ }
+
+
+ printf("Kernel command line: \"%s\"\n", command_line);
+}
+
+void *load_zimage(char *image, unsigned long kernel_size,
+ unsigned long initrd_addr, unsigned long initrd_size,
+ int auto_boot)
+{
+ void *setup_base;
+ int setup_size;
+ int bootproto;
+ 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 != 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 == 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 == hdr->setup_sects) {
+ printf("Setup Sectors = 0 (defaulting to 4)\n");
+ setup_size = 5 * 512;
+ } else {
+ 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) && (hdr->loadflags & BIG_KERNEL_FLAG);
+
+ /* 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;
+ *(u16*)(setup_base + CMD_LINE_OFFSET_OFF) = COMMAND_LINE_OFFSET;
+
+ /* A very old kernel MUST have its real-mode code
+ * loaded at 0x90000 */
+
+ if ((u32)setup_base != 0x90000) {
+ /* Copy the real-mode kernel */
+ memmove((void*)0x90000, setup_base, setup_size);
+ /* Copy the command line */
+ memmove((void*)0x99000, setup_base+COMMAND_LINE_OFFSET,
+ COMMAND_LINE_SIZE);
+
+ setup_base = (void*)0x90000; /* Relocated */
+ }
+
+ /* It is recommended to clear memory up to the 32K mark */
+ 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) {
+ 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);
+
+ hdr->ramdisk_image = initrd_addr;
+ hdr->ramdisk_size = initrd_size;
+ }
+ }
+
+ if (bootproto >= 0x0201) {
+ hdr->heap_end_ptr = HEAP_END_OFFSET;
+ hdr->loadflags |= HEAP_FLAG;
+ }
+
+ if (bootproto >= 0x0202) {
+ 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;
+
+ hdr->setup_move_size = 0x9100;
+ }
+
+ if (bootproto >= 0x0204)
+ kernel_size = hdr->syssize * 16;
+ else
+ kernel_size -= setup_size;
+
+
+ if (big_image) {
+ if ((kernel_size) > BZIMAGE_MAX_SIZE) {
+ printf("Error: bzImage kernel too big! (size: %ld, max: %d)\n",
+ kernel_size, BZIMAGE_MAX_SIZE);
+ return 0;
+ }
+
+ } else if ((kernel_size) > ZIMAGE_MAX_SIZE) {
+ printf("Error: zImage kernel too big! (size: %ld, max: %d)\n",
+ kernel_size, ZIMAGE_MAX_SIZE);
+ return 0;
+ }
+
+ /* build command line at COMMAND_LINE_OFFSET */
+ 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);
+
+
+ memmove(load_address, image + setup_size, kernel_size);
+
+ /* ready for booting */
+ return setup_base;
+}
+
+void boot_zimage(void *setup_base)
+{
+ struct pt_regs regs;
+
+ memset(&regs, 0, sizeof(struct pt_regs));
+ regs.xds = (u32)setup_base >> 4;
+ 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 * const argv[])
+{
+ void *base_ptr;
+ void *bzImage_addr = NULL;
+ char *s;
+ ulong bzImage_size = 0;
+
+ disable_interrupts();
+
+ /* Setup board for maximum PC/AT Compatibility */
+ setup_pcat_compatibility();
+
+ if (argc >= 2)
+ /* argv[1] holds the address of the bzImage */
+ s = argv[1];
+ else
+ s = getenv("fileaddr");
+
+ if (s)
+ bzImage_addr = (void *)simple_strtoul(s, NULL, 16);
+
+ if (argc >= 3)
+ /* argv[2] holds the size of the bzImage */
+ 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, 2, 0, do_zboot,
+ "Boot bzImage",
+ ""
+);
OpenPOWER on IntegriCloud