diff options
Diffstat (limited to 'roms/u-boot-sam460ex/arch/i386/cpu')
-rw-r--r-- | roms/u-boot-sam460ex/arch/i386/cpu/Makefile | 50 | ||||
-rw-r--r-- | roms/u-boot-sam460ex/arch/i386/cpu/config.mk | 26 | ||||
-rw-r--r-- | roms/u-boot-sam460ex/arch/i386/cpu/cpu.c | 92 | ||||
-rw-r--r-- | roms/u-boot-sam460ex/arch/i386/cpu/interrupts.c | 647 | ||||
-rw-r--r-- | roms/u-boot-sam460ex/arch/i386/cpu/resetvec.S | 37 | ||||
-rw-r--r-- | roms/u-boot-sam460ex/arch/i386/cpu/sc520/Makefile | 56 | ||||
-rw-r--r-- | roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520.c | 201 | ||||
-rw-r--r-- | roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_asm.S | 635 | ||||
-rw-r--r-- | roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_pci.c | 142 | ||||
-rw-r--r-- | roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_ssi.c | 95 | ||||
-rw-r--r-- | roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_timer.c | 89 | ||||
-rw-r--r-- | roms/u-boot-sam460ex/arch/i386/cpu/start.S | 272 | ||||
-rw-r--r-- | roms/u-boot-sam460ex/arch/i386/cpu/start16.S | 101 |
13 files changed, 2443 insertions, 0 deletions
diff --git a/roms/u-boot-sam460ex/arch/i386/cpu/Makefile b/roms/u-boot-sam460ex/arch/i386/cpu/Makefile new file mode 100644 index 000000000..bb0a48f86 --- /dev/null +++ b/roms/u-boot-sam460ex/arch/i386/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).a + +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) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +######################################################################### diff --git a/roms/u-boot-sam460ex/arch/i386/cpu/config.mk b/roms/u-boot-sam460ex/arch/i386/cpu/config.mk new file mode 100644 index 000000000..16a160d2f --- /dev/null +++ b/roms/u-boot-sam460ex/arch/i386/cpu/config.mk @@ -0,0 +1,26 @@ +# +# (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 +# + +PLATFORM_RELFLAGS += + +PLATFORM_CPPFLAGS += -march=i386 -Werror diff --git a/roms/u-boot-sam460ex/arch/i386/cpu/cpu.c b/roms/u-boot-sam460ex/arch/i386/cpu/cpu.c new file mode 100644 index 000000000..3010519e7 --- /dev/null +++ b/roms/u-boot-sam460ex/arch/i386/cpu/cpu.c @@ -0,0 +1,92 @@ +/* + * (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 + */ + +/* + * CPU specific code + */ + +#include <common.h> +#include <command.h> +#include <asm/interrupt.h> + +int cpu_init_f(void) +{ + /* initialize FPU, reset EM, set MP and NE */ + asm ("fninit\n" \ + "movl %cr0, %eax\n" \ + "andl $~0x4, %eax\n" \ + "orl $0x22, %eax\n" \ + "movl %eax, %cr0\n" ); + + return 0; +} + +int cpu_init_r(void) +{ + /* Initialize core interrupt and exception functionality of CPU */ + cpu_init_interrupts (); + return 0; +} + +int do_reset(cmd_tbl_t *cmdtp, int flag, int argc, char *argv[]) +{ + printf ("resetting ...\n"); + udelay(50000); /* wait 50 ms */ + disable_interrupts(); + reset_cpu(0); + + /*NOTREACHED*/ + return 0; +} + +void flush_cache (unsigned long dummy1, unsigned long dummy2) +{ + asm("wbinvd\n"); + return; +} + +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 i386 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/roms/u-boot-sam460ex/arch/i386/cpu/interrupts.c b/roms/u-boot-sam460ex/arch/i386/cpu/interrupts.c new file mode 100644 index 000000000..51023f3a8 --- /dev/null +++ b/roms/u-boot-sam460ex/arch/i386/cpu/interrupts.c @@ -0,0 +1,647 @@ +/* + * (C) Copyright 2008 + * 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> + +#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 serialization + */ +static unsigned long __force_order; + +static inline unsigned long read_cr0(void) +{ + unsigned long val; + asm volatile("mov %%cr0,%0\n\t" : "=r" (val), "=m" (__force_order)); + return val; +} + +static inline unsigned long read_cr2(void) +{ + unsigned long val; + asm volatile("mov %%cr2,%0\n\t" : "=r" (val), "=m" (__force_order)); + return val; +} + +static inline unsigned long read_cr3(void) +{ + unsigned long val; + asm volatile("mov %%cr3,%0\n\t" : "=r" (val), "=m" (__force_order)); + return val; +} + +static inline unsigned long read_cr4(void) +{ + unsigned long val; + asm volatile("mov %%cr4,%0\n\t" : "=r" (val), "=m" (__force_order)); + return val; +} + +static inline unsigned long get_debugreg(int regno) +{ + unsigned long val = 0; /* Damn you, gcc! */ + + switch (regno) { + case 0: + asm("mov %%db0, %0" :"=r" (val)); + break; + case 1: + asm("mov %%db1, %0" :"=r" (val)); + break; + case 2: + asm("mov %%db2, %0" :"=r" (val)); + break; + case 3: + asm("mov %%db3, %0" :"=r" (val)); + break; + case 6: + asm("mov %%db6, %0" :"=r" (val)); + break; + case 7: + asm("mov %%db7, %0" :"=r" (val)); + break; + default: + val = 0; + } + return val; +} + +void dump_regs(struct pt_regs *regs) +{ + unsigned long cr0 = 0L, cr2 = 0L, cr3 = 0L, cr4 = 0L; + unsigned long d0, d1, d2, d3, d6, d7; + + printf("EIP: %04x:[<%08lx>] EFLAGS: %08lx\n", + (u16)regs->xcs, regs->eip, regs->eflags); + + printf("EAX: %08lx EBX: %08lx ECX: %08lx EDX: %08lx\n", + regs->eax, regs->ebx, regs->ecx, regs->edx); + printf("ESI: %08lx EDI: %08lx EBP: %08lx ESP: %08lx\n", + regs->esi, regs->edi, regs->ebp, regs->esp); + printf(" DS: %04x ES: %04x FS: %04x GS: %04x SS: %04x\n", + (u16)regs->xds, (u16)regs->xes, (u16)regs->xfs, (u16)regs->xgs, (u16)regs->xss); + + cr0 = read_cr0(); + cr2 = read_cr2(); + cr3 = read_cr3(); + cr4 = read_cr4(); + + printf("CR0: %08lx CR2: %08lx CR3: %08lx CR4: %08lx\n", + cr0, cr2, cr3, cr4); + + d0 = get_debugreg(0); + d1 = get_debugreg(1); + d2 = get_debugreg(2); + d3 = get_debugreg(3); + + printf("DR0: %08lx DR1: %08lx DR2: %08lx DR3: %08lx\n", + d0, d1, d2, d3); + + d6 = get_debugreg(6); + d7 = get_debugreg(7); + printf("DR6: %08lx DR7: %08lx\n", + d6, d7); +} + +struct idt_entry { + u16 base_low; + u16 selector; + 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&0x200); /* IE flags is bit 9 */ +} + +/* IRQ Low-Level Service Routine */ +__isr__ irq_llsr(struct pt_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->orig_eax) { + 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->orig_eax); + } +} + +/* + * 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 + */ +asm(".globl irq_common_entry\n" \ + ".hidden irq_common_entry\n" \ + ".type irq_common_entry, @function\n" \ + "irq_common_entry:\n" \ + "cld\n" \ + "pushl %gs\n" \ + "pushl %fs\n" \ + "pushl %es\n" \ + "pushl %ds\n" \ + "pushl %eax\n" \ + "pushl %ebp\n" \ + "pushl %edi\n" \ + "pushl %esi\n" \ + "pushl %edx\n" \ + "pushl %ecx\n" \ + "pushl %ebx\n" \ + "mov %esp, %eax\n" \ + "pushl %ebp\n" \ + "movl %esp,%ebp\n" \ + "pushl %eax\n" \ + "call irq_llsr\n" \ + "popl %eax\n" \ + "leave\n"\ + "popl %ebx\n" \ + "popl %ecx\n" \ + "popl %edx\n" \ + "popl %esi\n" \ + "popl %edi\n" \ + "popl %ebp\n" \ + "popl %eax\n" \ + "popl %ds\n" \ + "popl %es\n" \ + "popl %fs\n" \ + "popl %gs\n" \ + "add $4, %esp\n" \ + "iret\n" \ + DECLARE_INTERRUPT(0) \ + DECLARE_INTERRUPT(1) \ + 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/roms/u-boot-sam460ex/arch/i386/cpu/resetvec.S b/roms/u-boot-sam460ex/arch/i386/cpu/resetvec.S new file mode 100644 index 000000000..d9222dd2f --- /dev/null +++ b/roms/u-boot-sam460ex/arch/i386/cpu/resetvec.S @@ -0,0 +1,37 @@ +/* + * U-boot - i386 Startup Code + * + * Copyright (c) 2002 Omicron Ceti AB, Daniel Engström <denaiel@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/roms/u-boot-sam460ex/arch/i386/cpu/sc520/Makefile b/roms/u-boot-sam460ex/arch/i386/cpu/sc520/Makefile new file mode 100644 index 000000000..87835b2c2 --- /dev/null +++ b/roms/u-boot-sam460ex/arch/i386/cpu/sc520/Makefile @@ -0,0 +1,56 @@ +# +# (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).a + +COBJS-$(CONFIG_SYS_SC520) += sc520.o +COBJS-$(CONFIG_SYS_SC520_SSI) += sc520_ssi.o +COBJS-$(CONFIG_SYS_SC520_TIMER) += sc520_timer.o +COBJS-$(CONFIG_PCI) += sc520_pci.o + +SOBJS-$(CONFIG_SYS_SC520) += sc520_asm.o + +SRCS := $(SOBJS-y:.o=.S) $(COBJS-y:.o=.c) +OBJS := $(addprefix $(obj),$(SOBJS-y) $(COBJS-y)) + +all: $(obj).depend $(LIB) + +$(LIB): $(OBJS) + $(AR) $(ARFLAGS) $@ $(OBJS) + +######################################################################### + +# defines $(obj).depend target +include $(SRCTREE)/rules.mk + +sinclude $(obj).depend + +#########################################################################
\ No newline at end of file diff --git a/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520.c b/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520.c new file mode 100644 index 000000000..519bfd8b0 --- /dev/null +++ b/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520.c @@ -0,0 +1,201 @@ +/* + * (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 + */ + +/* stuff specific for the sc520, + * but idependent of implementation */ + +#include <common.h> +#include <asm/io.h> +#include <asm/ic/sc520.h> + +DECLARE_GLOBAL_DATA_PTR; + +/* + * utility functions for boards based on the AMD sc520 + * + * void init_sc520(void) + * unsigned long init_sc520_dram(void) + */ + +volatile sc520_mmcr_t *sc520_mmcr = (sc520_mmcr_t *)0xfffef000; + +void init_sc520(void) +{ + /* Set the UARTxCTL register at it's slower, + * baud clock giving us a 1.8432 MHz reference + */ + writeb(0x07, &sc520_mmcr->uart1ctl); + writeb(0x07, &sc520_mmcr->uart2ctl); + + /* first set the timer pin mapping */ + writeb(0x72, &sc520_mmcr->clksel); /* no clock frequency selected, use 1.1892MHz */ + + /* enable PCI bus arbitrer */ + writeb(0x02, &sc520_mmcr->sysarbctl); /* enable concurrent mode */ + + writeb(0x1f, &sc520_mmcr->sysarbmenb); /* enable external grants */ + writeb(0x04, &sc520_mmcr->hbctl); /* enable posted-writes */ + + if (CONFIG_SYS_SC520_HIGH_SPEED) { + writeb(0x02, &sc520_mmcr->cpuctl); /* set it to 133 MHz and write back */ + gd->cpu_clk = 133000000; + printf("## CPU Speed set to 133MHz\n"); + } else { + writeb(0x01, &sc520_mmcr->cpuctl); /* set it to 100 MHz and write back */ + printf("## CPU Speed set to 100MHz\n"); + 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"); + + /* turn on the SDRAM write buffer */ + writeb(0x11, &sc520_mmcr->dbctl); + + /* turn on the cache and disable write through */ + asm("movl %%cr0, %%eax\n" + "andl $0x9fffffff, %%eax\n" + "movl %%eax, %%cr0\n" : : : "eax"); +} + +unsigned long init_sc520_dram(void) +{ + bd_t *bd = gd->bd; + + u32 dram_present=0; + u32 dram_ctrl; + +#ifdef CONFIG_SYS_SDRAM_DRCTMCTL + /* these memory control registers are set up in the assember part, + * in sc520_asm.S, during 'mem_init'. If we muck with them here, + * after we are running a stack in RAM, we have troubles. Besides, + * these refresh and delay values are better ? simply specified + * outright in the include/configs/{cfg} file since the HW designer + * simply dictates it. + */ +#else + u8 tmp; + u8 val; + + int cas_precharge_delay = CONFIG_SYS_SDRAM_PRECHARGE_DELAY; + int refresh_rate = CONFIG_SYS_SDRAM_REFRESH_RATE; + int ras_cas_delay = CONFIG_SYS_SDRAM_RAS_CAS_DELAY; + + /* set SDRAM speed here */ + + refresh_rate/=78; + if (refresh_rate<=1) { + val = 0; /* 7.8us */ + } else if (refresh_rate==2) { + val = 1; /* 15.6us */ + } else if (refresh_rate==3 || refresh_rate==4) { + val = 2; /* 31.2us */ + } else { + val = 3; /* 62.4us */ + } + + tmp = (readb(&sc520_mmcr->drcctl) & 0xcf) | (val<<4); + writeb(tmp, &sc520_mmcr->drcctl); + + val = readb(&sc520_mmcr->drctmctl) & 0xf0; + + if (cas_precharge_delay==3) { + val |= 0x04; /* 3T */ + } else if (cas_precharge_delay==4) { + val |= 0x08; /* 4T */ + } else if (cas_precharge_delay>4) { + val |= 0x0c; + } + + if (ras_cas_delay > 3) { + val |= 2; + } else { + val |= 1; + } + writeb(val, &c520_mmcr->drctmctl); +#endif + + /* We read-back the configuration of the dram + * controller that the assembly code wrote */ + dram_ctrl = readl(&sc520_mmcr->drcbendadr); + + bd->bi_dram[0].start = 0; + if (dram_ctrl & 0x80) { + /* bank 0 enabled */ + dram_present = bd->bi_dram[1].start = (dram_ctrl & 0x7f) << 22; + bd->bi_dram[0].size = bd->bi_dram[1].start; + + } else { + bd->bi_dram[0].size = 0; + bd->bi_dram[1].start = bd->bi_dram[0].start; + } + + if (dram_ctrl & 0x8000) { + /* bank 1 enabled */ + dram_present = bd->bi_dram[2].start = (dram_ctrl & 0x7f00) << 14; + bd->bi_dram[1].size = bd->bi_dram[2].start - bd->bi_dram[1].start; + } else { + bd->bi_dram[1].size = 0; + bd->bi_dram[2].start = bd->bi_dram[1].start; + } + + if (dram_ctrl & 0x800000) { + /* bank 2 enabled */ + dram_present = bd->bi_dram[3].start = (dram_ctrl & 0x7f0000) << 6; + bd->bi_dram[2].size = bd->bi_dram[3].start - bd->bi_dram[2].start; + } else { + bd->bi_dram[2].size = 0; + bd->bi_dram[3].start = bd->bi_dram[2].start; + } + + if (dram_ctrl & 0x80000000) { + /* bank 3 enabled */ + dram_present = (dram_ctrl & 0x7f000000) >> 2; + bd->bi_dram[3].size = dram_present - bd->bi_dram[3].start; + } else { + bd->bi_dram[3].size = 0; + } + + +#if 0 + printf("Configured %d bytes of dram\n", dram_present); +#endif + gd->ram_size = dram_present; + + return dram_present; +} + +#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/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_asm.S b/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_asm.S new file mode 100644 index 000000000..fff56c00b --- /dev/null +++ b/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_asm.S @@ -0,0 +1,635 @@ +/* + * (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 is largely based on code obtned from AMD. AMD's original + * copyright is included below + */ + +/* TITLE SIZER - Aspen DRAM Sizing Routine. + * ============================================================================= + * + * Copyright 1999 Advanced Micro Devices, Inc. + * You may redistribute this program and/or modify this program under the terms + * of the GNU General Public License as published by the Free Software Foundation; + * either version 2 of the License, or (at your option) any later version. + * + * This program is distributed WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED + * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU + * General Public License for more details. + * + * You should have received a copy of the GNU General Public License along with + * this program; if not, write to the Free Software Foundation, Inc., + * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA. + * + * THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY + * OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT OF + * THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY PARTICULAR PURPOSE. + * IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER + * (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS + * INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR INABILITY + * TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY OF + * SUCH DAMAGES. BECAUSE SOME JURSIDICTIONS PROHIBIT THE EXCLUSION OR + * LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE + * LIMITATION MAY NOT APPLY TO YOU. + * + * AMD does not assume any responsibility for any errors that may appear in + * the Materials nor any responsibility to support or update the Materials. + * AMD retains the right to make changes to its test specifications at any + * time, without notice. + * ============================================================================== + */ + +/* + ****************************************************************************** + * + * FILE : sizer.asm - SDRAM DIMM Sizing Algorithm + * + * + * + * FUNCTIONS : sizemem() - jumped to, not called. To be executed after + * reset to determine the size of the SDRAM DIMMs. Initializes + * the memory subsystem. + * + * + * AUTHOR : Buddy Fey - Original. + * + * + * DESCRIPTION : Performs sizing on SDRAM DIMMs on ASPEN processor. + * NOTE: This is a small memory model version + * + * + * INPUTS : BP contains return address offset + * CACHE is assumed to be disabled. + * The FS segment limit has already been set to big real mode + * (full 32-bit addressing capability) + * + * + * OUTPUTS : None + * + * + * REG USE : ax,bx,cx,dx,di,si,bp, fs + * + * + * REVISION : See PVCS info below + * + * + * TEST PLAN CROSS REFERENCE: + * + * + * $Workfile: $ + * $Revision: 1.2 $ + * $Date: 1999/09/22 12:49:33 $ + * $Author: chipf $ + * $Log: sizer.asm $ + * Revision 1.2 1999/09/22 12:49:33 chipf + * Add legal header + * + ******************************************************************************* + */ + + +/******************************************************************************* + * FUNCTIONAL DESCRIPTION: + * This routine is called to autodetect the geometry of the DRAM. + * + * This routine is called to determine the number of column bits for the DRAM + * devices in this external bank. This routine assumes that the external bank + * has been configured for an 11-bit column and for 4 internal banks. This gives + * us the maximum address reach in memory. By writing a test value to the max + * address and locating where it aliases to, we can determine the number of valid + * column bits. + * + * This routine is called to determine the number of internal banks each DRAM + * device has. The external bank (under test) is configured for maximum reach + * with 11-bit columns and 4 internal banks. This routine will write to a max + * address (BA1 and BA0 = 1) and then read from an address with BA1=0 to see if + * that column is a "don't care". If BA1 does not affect write/read of data, + * then this device has only 2 internal banks. + * + * This routine is called to determine the ending address for this external + * bank of SDRAM. We write to a max address with a data value and then disable + * row address bits looking for "don't care" locations. Each "don't care" bit + * represents a dividing of the maximum density (128M) by 2. By dividing the + * maximum of 32 4M chunks in an external bank down by all the "don't care" bits + * determined during sizing, we set the proper density. + * + * WARNINGS. + * bp must be preserved because it is used for return linkage. + * + * EXIT + * nothing returned - but the memory subsystem is enabled + ******************************************************************************* + */ + +#include <config.h> + +.section .text +.equ DRCCTL, 0x0fffef010 /* DRAM control register */ +.equ DRCTMCTL, 0x0fffef012 /* DRAM timing control register */ +.equ DRCCFG, 0x0fffef014 /* DRAM bank configuration register */ +.equ DRCBENDADR, 0x0fffef018 /* DRAM bank ending address register */ +.equ ECCCTL, 0x0fffef020 /* DRAM ECC control register */ +.equ ECCINT, 0x0fffefd18 /* DRAM ECC nmi-INT mapping */ +.equ DBCTL, 0x0fffef040 /* DRAM buffer control register */ + +.equ CACHELINESZ, 0x00000010 /* size of our cache line (read buffer) */ +.equ COL11_ADR, 0x0e001e00 /* 11 col addrs */ +.equ COL10_ADR, 0x0e000e00 /* 10 col addrs */ +.equ COL09_ADR, 0x0e000600 /* 9 col addrs */ +.equ COL08_ADR, 0x0e000200 /* 8 col addrs */ +.equ ROW14_ADR, 0x0f000000 /* 14 row addrs */ +.equ ROW13_ADR, 0x07000000 /* 13 row addrs */ +.equ ROW12_ADR, 0x03000000 /* 12 row addrs */ +.equ ROW11_ADR, 0x01000000 /* 11 row addrs/also bank switch */ +.equ ROW10_ADR, 0x00000000 /* 10 row addrs/also bank switch */ +.equ COL11_DATA, 0x0b0b0b0b /* 11 col addrs */ +.equ COL10_DATA, 0x0a0a0a0a /* 10 col data */ +.equ COL09_DATA, 0x09090909 /* 9 col data */ +.equ COL08_DATA, 0x08080808 /* 8 col data */ +.equ ROW14_DATA, 0x3f3f3f3f /* 14 row data (MASK) */ +.equ ROW13_DATA, 0x1f1f1f1f /* 13 row data (MASK) */ +.equ ROW12_DATA, 0x0f0f0f0f /* 12 row data (MASK) */ +.equ ROW11_DATA, 0x07070707 /* 11 row data/also bank switch (MASK) */ +.equ ROW10_DATA, 0xaaaaaaaa /* 10 row data/also bank switch (MASK) */ + + + /* + * initialize dram controller registers + */ +.globl mem_init +mem_init: + xorw %ax,%ax + movl $DBCTL, %edi + movb %al, (%edi) /* disable write buffer */ + + movl $ECCCTL, %edi + movb %al, (%edi) /* disable ECC */ + + movl $DRCTMCTL, %edi + movb $0x1E,%al /* Set SDRAM timing for slowest */ + movb %al, (%edi) + + /* + * setup loop to do 4 external banks starting with bank 3 + */ + movl $0xff000000,%eax /* enable last bank and setup */ + movl $DRCBENDADR, %edi /* ending address register */ + movl %eax, (%edi) + + movl $DRCCFG, %edi /* setup */ + movw $0xbbbb,%ax /* dram config register for */ + movw %ax, (%edi) + + /* + * issue a NOP to all DRAMs + */ + movl $DRCCTL, %edi /* setup DRAM control register with */ + movb $0x1,%al /* Disable refresh,disable write buffer */ + movb %al, (%edi) + movl $CACHELINESZ, %esi /* just a dummy address to write for */ + movw %ax, (%esi) + /* + * delay for 100 usec? 200? + * ******this is a cludge for now ************* + */ + movw $100,%cx +sizdelay: + loop sizdelay /* we need 100 usec here */ + /***********************************************/ + + /* + * issue all banks precharge + */ + movb $0x2,%al /* All banks precharge */ + movb %al, (%edi) + movw %ax, (%esi) + + /* + * issue 2 auto refreshes to all banks + */ + movb $0x4,%al /* Auto refresh cmd */ + movb %al, (%edi) + movw $2,%cx +refresh1: + movw %ax, (%esi) + loop refresh1 + + /* + * issue LOAD MODE REGISTER command + */ + movb $0x3,%al /* Load mode register cmd */ + movb %al, (%edi) + movw %ax, (%esi) + + /* + * issue 8 more auto refreshes to all banks + */ + movb $0x4,%al /* Auto refresh cmd */ + movb %al, (%edi) + movw $8,%cx +refresh2: + movw %ax, (%esi) + loop refresh2 + + /* + * set control register to NORMAL mode + */ + movb $0x0,%al /* Normal mode value */ + movb %al, (%edi) + + /* + * size dram starting with external bank 3 moving to external bank 0 + */ + movl $0x3,%ecx /* start with external bank 3 */ + +nextbank: + + /* + * write col 11 wrap adr + */ + movl $COL11_ADR, %esi /* set address to max col (11) wrap addr */ + movl $COL11_DATA, %eax /* pattern for max supported columns(11) */ + movl %eax, (%esi) /* write max col pattern at max col adr */ + movl (%esi), %ebx /* optional read */ + cmpl %ebx,%eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + /* + * write col 10 wrap adr + */ + + movl $COL10_ADR, %esi /* set address to 10 col wrap address */ + movl $COL10_DATA, %eax /* pattern for 10 col wrap */ + movl %eax, (%esi) /* write 10 col pattern @ 10 col wrap adr */ + movl (%esi), %ebx /* optional read */ + cmpl %ebx,%eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + /* + * write col 9 wrap adr + */ + movl $COL09_ADR, %esi /* set address to 9 col wrap address */ + movl $COL09_DATA, %eax /* pattern for 9 col wrap */ + movl %eax, (%esi) /* write 9 col pattern @ 9 col wrap adr */ + movl (%esi), %ebx /* optional read */ + cmpl %ebx,%eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + /* + * write col 8 wrap adr + */ + movl $COL08_ADR, %esi /* set address to min(8) col wrap address */ + movl $COL08_DATA, %eax /* pattern for min (8) col wrap */ + movl %eax, (%esi) /* write min col pattern @ min col adr */ + movl (%esi), %ebx /* optional read */ + cmpl %ebx,%eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + /* + * write row 14 wrap adr + */ + movl $ROW14_ADR, %esi /* set address to max row (14) wrap addr */ + movl $ROW14_DATA, %eax /* pattern for max supported rows(14) */ + movl %eax, (%esi) /* write max row pattern at max row adr */ + movl (%esi), %ebx /* optional read */ + cmpl %ebx,%eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + /* + * write row 13 wrap adr + */ + movl $ROW13_ADR, %esi /* set address to 13 row wrap address */ + movl $ROW13_DATA, %eax /* pattern for 13 row wrap */ + movl %eax, (%esi) /* write 13 row pattern @ 13 row wrap adr */ + movl (%esi), %ebx /* optional read */ + cmpl %ebx,%eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + /* + * write row 12 wrap adr + */ + movl $ROW12_ADR, %esi /* set address to 12 row wrap address */ + movl $ROW12_DATA, %eax /* pattern for 12 row wrap */ + movl %eax, (%esi) /* write 12 row pattern @ 12 row wrap adr */ + movl (%esi), %ebx /* optional read */ + cmpl %ebx,%eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + /* + * write row 11 wrap adr + */ + movl $ROW11_ADR, %edi /* set address to 11 row wrap address */ + movl $ROW11_DATA, %eax /* pattern for 11 row wrap */ + movl %eax, (%edi) /* write 11 row pattern @ 11 row wrap adr */ + movl (%edi), %ebx /* optional read */ + cmpl %ebx,%eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + /* + * write row 10 wrap adr --- this write is really to determine number of banks + */ + movl $ROW10_ADR, %edi /* set address to 10 row wrap address */ + movl $ROW10_DATA, %eax /* pattern for 10 row wrap (AA) */ + movl %eax, (%edi) /* write 10 row pattern @ 10 row wrap adr */ + movl (%edi), %ebx /* optional read */ + cmpl %ebx,%eax /* to verify write */ + jnz bad_ram /* this ram is bad */ + /* + * read data @ row 12 wrap adr to determine * banks, + * and read data @ row 14 wrap adr to determine * 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, + */ + xorw %di,%di /* value for 2 banks in DI */ + movl (%esi), %ebx /* read from 12 row wrap to check banks + * (esi is setup from the write to row 12 wrap) */ + cmpl %ebx,%eax /* check for AA pattern (eax holds the aa pattern) */ + jz only2 /* if pattern == AA, we only have 2 banks */ + + /* 4 banks */ + + movw $8,%di /* value for 4 banks in DI (BNK_CNT bit) */ + cmpl $ROW11_DATA, %ebx /* only other legitimate values are 11 */ + jz only2 + cmpl $ROW12_DATA, %ebx /* and 12 */ + jnz bad_ram /* its bad if not 11 or 12! */ + + /* fall through */ +only2: + /* + * validate row mask + */ + movl $ROW14_ADR, %esi /* set address back to max row wrap addr */ + movl (%esi), %eax /* read actual number of rows @ row14 adr */ + + cmpl $ROW11_DATA, %eax /* row must be greater than 11 pattern */ + jb bad_ram + + cmpl $ROW14_DATA, %eax /* and row must be less than 14 pattern */ + ja bad_ram + + cmpb %ah,%al /* verify all 4 bytes of dword same */ + jnz bad_ram + movl %eax,%ebx + shrl $16,%ebx + cmpw %bx,%ax + jnz bad_ram + /* + * read col 11 wrap adr for real column data value + */ + movl $COL11_ADR, %esi /* set address to max col (11) wrap addr */ + movl (%esi), %eax /* read real col number at max col adr */ + /* + * validate column data + */ + cmpl $COL08_DATA, %eax /* col must be greater than 8 pattern */ + jb bad_ram + + cmpl $COL11_DATA, %eax /* and row must be less than 11 pattern */ + ja bad_ram + + subl $COL08_DATA, %eax /* normalize column data to zero */ + jc bad_ram + cmpb %ah,%al /* verify all 4 bytes of dword equal */ + jnz bad_ram + movl %eax,%edx + shrl $16,%edx + cmpw %dx,%ax + jnz bad_ram + /* + * merge bank and col data together + */ + addw %di,%dx /* merge of bank and col info in dl */ + /* + * fix ending addr mask based upon col info + */ + movb $3,%al + subb %dh,%al /* dh contains the overflow from the bank/col merge */ + movb %bl,%dh /* bl contains the row mask (aa, 07, 0f, 1f or 3f) */ + xchgw %cx,%ax /* cx = ax = 3 or 2 depending on 2 or 4 bank device */ + shrb %cl,%dh /* */ + incb %dh /* ending addr is 1 greater than real end */ + xchgw %cx,%ax /* cx is bank number again */ + /* + * issue all banks precharge + */ +bad_reint: + movl $DRCCTL, %esi /* setup DRAM control register with */ + movb $0x2,%al /* All banks precharge */ + movb %al, (%esi) + movl $CACHELINESZ, %esi /* address to init read buffer */ + movw %ax, (%esi) + + /* + * update ENDING ADDRESS REGISTER + */ + movl $DRCBENDADR, %edi /* DRAM ending address register */ + movl %ecx,%ebx + addl %ebx, %edi + movb %dh, (%edi) + /* + * update CONFIG REGISTER + */ + xorb %dh,%dh + movw $0x00f,%bx + movw %cx,%ax + shlw $2,%ax + xchgw %cx,%ax + shlw %cl,%dx + shlw %cl,%bx + notw %bx + xchgw %cx,%ax + movl $DRCCFG, %edi + mov (%edi), %ax + andw %bx,%ax + orw %dx,%ax + movw %ax, (%edi) + jcxz cleanup + + decw %cx + movl %ecx,%ebx + movl $DRCBENDADR, %edi /* DRAM ending address register */ + movb $0xff,%al + addl %ebx, %edi + movb %al, (%edi) + /* + * set control register to NORMAL mode + */ + movl $DRCCTL, %esi /* setup DRAM control register with */ + movb $0x0,%al /* Normal mode value */ + movb %al, (%esi) + movl $CACHELINESZ, %esi /* address to init read buffer */ + movw %ax, (%esi) + jmp nextbank + +cleanup: + movl $DRCBENDADR, %edi /* DRAM ending address register */ + movw $4,%cx + xorw %ax,%ax +cleanuplp: + movb (%edi), %al + orb %al,%al + jz emptybank + + addb %ah,%al + jns nottoomuch + + movb $0x7f,%al +nottoomuch: + movb %al,%ah + orb $0x80,%al + movb %al, (%edi) +emptybank: + incl %edi + loop cleanuplp + +#if defined CONFIG_SYS_SDRAM_DRCTMCTL + /* just have your hardware desinger _GIVE_ you what you need here! */ + movl $DRCTMCTL, %edi + movb $CONFIG_SYS_SDRAM_DRCTMCTL,%al + movb %al, (%edi) +#else +#if defined(CONFIG_SYS_SDRAM_CAS_LATENCY_2T) || defined(CONFIG_SYS_SDRAM_CAS_LATENCY_3T) + /* set the CAS latency now since it is hard to do + * when we run from the RAM */ + movl $DRCTMCTL, %edi /* DRAM timing register */ + movb (%edi), %al +#ifdef CONFIG_SYS_SDRAM_CAS_LATENCY_2T + andb $0xef, %al +#endif +#ifdef CONFIG_SYS_SDRAM_CAS_LATENCY_3T + orb $0x10, %al +#endif + movb %al, (%edi) +#endif +#endif + movl $DRCCTL, %edi /* DRAM Control register */ + movb $0x3,%al /* Load mode register cmd */ + movb %al, (%edi) + movw %ax, (%esi) + + + movl $DRCCTL, %edi /* DRAM Control register */ + movb $0x18,%al /* Enable refresh and NORMAL mode */ + movb %al, (%edi) + + jmp dram_done + +bad_ram: + xorl %edx,%edx + xorl %edi,%edi + jmp bad_reint + +dram_done: + +#if CONFIG_SYS_SDRAM_ECC_ENABLE + /* + * We are in the middle of an existing 'call' - Need to store the + * existing return address before making another 'call' + */ + movl %ebp, %ebx + + /* Get the memory size */ + movl $init_ecc, %ebp + jmpl get_mem_size + +init_ecc: + /* Restore the orignal return address */ + movl %ebx, %ebp + + /* 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 $1, %ecx + andl %ecx,%ecx + jz set_ecc + shll $1, %edi + jmp memtest0 + +set_ecc: + /* clear all ram with a memset */ + movl %eax, %ecx + xorl %esi, %esi + xorl %edi, %edi + xorl %eax, %eax + shrl $2, %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 + mov $0x10, %al + movb %al, (%edi) + /* Turn on ECC */ + movl $ECCCTL, %edi + mov $0x05, %al + movb %al, (%edi) +#endif + +out: + jmp *%ebp + +/* + * Read and decode the sc520 DRCBENDADR MMCR and return the number of + * available ram bytes in %eax + */ +.globl get_mem_size +get_mem_size: + movl $DRCBENDADR, %edi /* DRAM ending address register */ + +bank0: movl (%edi), %eax + movl %eax, %ecx + andl $0x00000080, %ecx + jz bank1 + andl $0x0000007f, %eax + shll $22, %eax + movl %eax, %ebx + +bank1: movl (%edi), %eax + movl %eax, %ecx + andl $0x00008000, %ecx + jz bank2 + andl $0x00007f00, %eax + shll $14, %eax + movl %eax, %ebx + +bank2: movl (%edi), %eax + movl %eax, %ecx + andl $0x00800000, %ecx + jz bank3 + andl $0x007f0000, %eax + shll $6, %eax + movl %eax, %ebx + +bank3: movl (%edi), %eax + movl %eax, %ecx + andl $0x80000000, %ecx + jz done + andl $0x7f000000, %eax + shrl $2, %eax + movl %eax, %ebx + +done: + movl %ebx, %eax + jmp *%ebp diff --git a/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_pci.c b/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_pci.c new file mode 100644 index 000000000..b91773435 --- /dev/null +++ b/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_pci.c @@ -0,0 +1,142 @@ +/* + * (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 + */ + +/* stuff specific for the sc520, but independent of implementation */ + +#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; + +# if 1 + printf("set_irq(): map INT%c to IRQ%d\n", pci_pin + 'A', irq); +#endif + 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/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_ssi.c b/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_ssi.c new file mode 100644 index 000000000..6e5e34630 --- /dev/null +++ b/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_ssi.c @@ -0,0 +1,95 @@ +/* + * (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 + */ + +/* stuff specific for the sc520, but independent of implementation */ + +#include <common.h> +#include <asm/io.h> +#include <asm/ic/ssi.h> +#include <asm/ic/sc520.h> + +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/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_timer.c b/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_timer.c new file mode 100644 index 000000000..d5617e91f --- /dev/null +++ b/roms/u-boot-sam460ex/arch/i386/cpu/sc520/sc520_timer.c @@ -0,0 +1,89 @@ +/* + * (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 + */ + +/* stuff specific for the sc520, but independent of implementation */ + +#include <common.h> +#include <asm/io.h> +#include <asm/interrupt.h> +#include <asm/ic/sc520.h> + +void sc520_timer_isr(void) +{ + /* Ack the GP Timer Interrupt */ + 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/roms/u-boot-sam460ex/arch/i386/cpu/start.S b/roms/u-boot-sam460ex/arch/i386/cpu/start.S new file mode 100644 index 000000000..7def8def8 --- /dev/null +++ b/roms/u-boot-sam460ex/arch/i386/cpu/start.S @@ -0,0 +1,272 @@ +/* + * U-boot - i386 Startup Code + * + * Copyright (c) 2002 Omicron Ceti AB, Daniel Engström <denaiel@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> + + +.section .text +.code32 +.globl _start +.type _start, @function +.globl _i386boot_start +_i386boot_start: + /* + * This is the fail safe 32-bit bootstrap entry point. The + * following code is not executed from a cold-reset (actually, a + * lot of it is, but from real-mode after cold reset. It is + * repeated here to put the board into a state as close to cold + * reset as necessary) + */ + cli + cld + + /* Turn of cache (this might require a 486-class CPU) */ + movl %cr0, %eax + orl $0x60000000,%eax + movl %eax, %cr0 + wbinvd + + /* Tell 32-bit code it is being entered from an in-RAM copy */ + movw $0x0000, %bx +_start: + /* This is the 32-bit cold-reset entry point */ + + movl $0x18,%eax /* Load our segement registes, the + * gdt have already been loaded by start16.S */ + movw %ax,%fs + movw %ax,%ds + movw %ax,%gs + movw %ax,%es + movw %ax,%ss + + /* Clear the interupt vectors */ + lidt blank_idt_ptr + + /* + * Skip low-level board and memory initialization if not starting + * from cold-reset. This allows us to do a fail safe boot-strap + * into a new build of U-Boot from a known-good boot flash + */ + movw $0x0001, %ax + cmpw %ax, %bx + jne mem_init_ret + + /* We call a few functions in the board support package + * since we have no stack yet we'll have to use %ebp + * to store the return address */ + + /* Early platform init (setup gpio, etc ) */ + mov $early_board_init_ret, %ebp + jmp early_board_init +early_board_init_ret: + + /* The __port80 entry-point should be usabe by now */ + /* so we try to indicate progress */ + movw $0x01, %ax + movl $.progress0, %ebp + jmp show_boot_progress_asm +.progress0: + + /* size memory */ + mov $mem_init_ret, %ebp + jmp mem_init +mem_init_ret: + + /* fetch memory size (into %eax) */ + mov $get_mem_size_ret, %ebp + jmp get_mem_size +get_mem_size_ret: + + /* + * We are now in 'Flat Protected Mode' and we know how much memory + * the board has. The (temporary) Global Descriptor Table is not + * in a 'Safe' place (it is either in Flash which can be erased or + * reprogrammed or in a fail-safe boot-strap image which could be + * over-written). + * + * Move the final gdt to a safe place (top of RAM) and load it. + * This is not a trivial excercise - the lgdt instruction does not + * have a register operand (memory only) and we may well be + * running from Flash, so self modifying code will not work here. + * To overcome this, we copy a stub into upper memory along with + * the GDT. + */ + + /* Reduce upper memory limit by (Stub + GDT Pointer + GDT) */ + subl $(end_gdt_setup - start_gdt_setup), %eax + + /* Copy the GDT and Stub */ + movl $start_gdt_setup, %esi + movl %eax, %edi + movl $(end_gdt_setup - start_gdt_setup), %ecx + shrl $2, %ecx + cld + rep movsl + + /* write the lgdt 'parameter' */ + subl $(jmp_instr - start_gdt_setup - 4), %ebp + addl %eax, %ebp + movl $(gdt_ptr - start_gdt_setup), %ebx + addl %eax, %ebx + movl %ebx, (%ebp) + + /* write the gdt address into the pointer */ + movl $(gdt_addr - start_gdt_setup), %ebp + addl %eax, %ebp + movl $(gdt - start_gdt_setup), %ebx + addl %eax, %ebx + movl %ebx, (%ebp) + + /* Save the return address */ + movl $load_gdt_ret, %ebp + + /* Load the new (safe) Global Descriptor Table */ + jmp *%eax + +load_gdt_ret: + /* Check we have enough memory for stack */ + movl $CONFIG_SYS_STACK_SIZE, %ecx + cmpl %ecx, %eax + jae mem_ok + + /* indicate (lack of) progress */ + movw $0x81, %ax + movl $.progress0a, %ebp + jmp show_boot_progress_asm +.progress0a: + jmp die +mem_ok: + /* Set stack pointer to upper memory limit*/ + movl %eax, %esp + + /* indicate progress */ + movw $0x02, %ax + movl $.progress1, %ebp + jmp show_boot_progress_asm +.progress1: + + /* Test the stack */ + pushl $0 + popl %eax + cmpl $0, %eax + jne no_stack + push $0x55aa55aa + popl %ebx + cmpl $0x55aa55aa, %ebx + je stack_ok + +no_stack: + /* indicate (lack of) progress */ + movw $0x82, %ax + movl $.progress1a, %ebp + jmp show_boot_progress_asm +.progress1a: + jmp die + + +stack_ok: + /* indicate progress */ + movw $0x03, %ax + movl $.progress2, %ebp + jmp show_boot_progress_asm +.progress2: + + wbinvd + + /* Get upper memory limit */ + movl %esp, %ecx + subl $CONFIG_SYS_STACK_SIZE, %ecx + + /* Create a Stack Frame */ + pushl %ebp + movl %esp, %ebp + + /* stack_limit parameter */ + pushl %ecx + call board_init_f /* Enter, U-boot! */ + + /* indicate (lack of) progress */ + movw $0x85, %ax + movl $.progress4a, %ebp + jmp show_boot_progress_asm +.progress4a: + +die: hlt + jmp die + hlt + +blank_idt_ptr: + .word 0 /* limit */ + .long 0 /* base */ + +.align 4 +start_gdt_setup: + lgdt gdt_ptr +jmp_instr: + jmp *%ebp + +.align 4 +gdt_ptr: + .word 0x30 /* limit (48 bytes = 6 GDT entries) */ +gdt_addr: + .long gdt /* base */ + + /* The GDT table ... + * + * Selector Type + * 0x00 NULL + * 0x08 Unused + * 0x10 32bit code + * 0x18 32bit data/stack + * 0x20 16bit code + * 0x28 16bit data/stack + */ + +.align 4 +gdt: + .word 0, 0, 0, 0 /* NULL */ + .word 0, 0, 0, 0 /* unused */ + + .word 0xFFFF /* 4Gb - (0x100000*0x1000 = 4Gb) */ + .word 0 /* base address = 0 */ + .word 0x9B00 /* code read/exec */ + .word 0x00CF /* granularity = 4096, 386 (+5th nibble of limit) */ + + .word 0xFFFF /* 4Gb - (0x100000*0x1000 = 4Gb) */ + .word 0x0 /* base address = 0 */ + .word 0x9300 /* data read/write */ + .word 0x00CF /* granularity = 4096, 386 (+5th nibble of limit) */ + + .word 0xFFFF /* 64kb */ + .word 0 /* base address = 0 */ + .word 0x9b00 /* data read/write */ + .word 0x0010 /* granularity = 1 (+5th nibble of limit) */ + + .word 0xFFFF /* 64kb */ + .word 0 /* base address = 0 */ + .word 0x9300 /* data read/write */ + .word 0x0010 /* granularity = 1 (+5th nibble of limit) */ +end_gdt_setup: diff --git a/roms/u-boot-sam460ex/arch/i386/cpu/start16.S b/roms/u-boot-sam460ex/arch/i386/cpu/start16.S new file mode 100644 index 000000000..3e8b2cc5c --- /dev/null +++ b/roms/u-boot-sam460ex/arch/i386/cpu/start16.S @@ -0,0 +1,101 @@ +/* + * U-boot - i386 Startup Code + * + * Copyright (c) 2002, 2003 Omicron Ceti AB, Daniel Engström <denaiel@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 + */ + + +#define BOOT_SEG 0xffff0000 /* linear segment of boot code */ +#define a32 .byte 0x67; +#define o32 .byte 0x66; + +.section .start16, "ax" +.code16 +.globl start16 +start16: + /* First we let the BSP do some early initialization + * this code have to map the flash to its final position + */ + mov $board_init16_ret, %bp + jmp board_init16 +board_init16_ret: + + /* Turn of cache (this might require a 486-class CPU) */ + movl %cr0, %eax + orl $0x60000000,%eax + movl %eax, %cr0 + wbinvd + + /* load the temporary Global Descriptor Table */ +o32 cs lgdt gdt_ptr + + /* Now, we enter protected mode */ + movl %cr0, %eax + orl $1,%eax + movl %eax, %cr0 + + /* Flush the prefetch queue */ + jmp ff +ff: + /* Tell 32-bit code it is being entered from hard-reset */ + movw $0x0001, %bx + + /* Finally jump to the 32bit initialization code */ + movw $code32start, %ax + movw %ax,%bp +o32 cs ljmp *(%bp) + + /* 48-bit far pointer */ +code32start: + .long _start /* offset */ + .word 0x10 /* segment */ + +/* + * 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) */ |