diff options
Diffstat (limited to 'arch/i386/cpu')
-rw-r--r-- | arch/i386/cpu/cpu.c | 57 | ||||
-rw-r--r-- | arch/i386/cpu/interrupts.c | 28 | ||||
-rw-r--r-- | arch/i386/cpu/sc520/sc520.c | 54 | ||||
-rw-r--r-- | arch/i386/cpu/sc520/sc520_asm.S | 668 | ||||
-rw-r--r-- | arch/i386/cpu/start.S | 225 | ||||
-rw-r--r-- | arch/i386/cpu/start16.S | 18 |
6 files changed, 488 insertions, 562 deletions
diff --git a/arch/i386/cpu/cpu.c b/arch/i386/cpu/cpu.c index bd6aced8737..ae40384f099 100644 --- a/arch/i386/cpu/cpu.c +++ b/arch/i386/cpu/cpu.c @@ -37,6 +37,61 @@ #include <command.h> #include <asm/interrupt.h> +/* Constructor for a conventional segment GDT (or LDT) entry */ +/* This is a macro so it can be used in initializers */ +#define GDT_ENTRY(flags, base, limit) \ + ((((base) & 0xff000000ULL) << (56-24)) | \ + (((flags) & 0x0000f0ffULL) << 40) | \ + (((limit) & 0x000f0000ULL) << (48-16)) | \ + (((base) & 0x00ffffffULL) << 16) | \ + (((limit) & 0x0000ffffULL))) + +/* Simple and small GDT entries for booting only */ + +#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) + +/* + * Set up the GDT + */ + +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 cpu_init_f(void) { /* initialize FPU, reset EM, set MP and NE */ @@ -51,6 +106,8 @@ int cpu_init_f(void) int cpu_init_r(void) { + reload_gdt(); + /* Initialize core interrupt and exception functionality of CPU */ cpu_init_interrupts (); return 0; diff --git a/arch/i386/cpu/interrupts.c b/arch/i386/cpu/interrupts.c index 51023f3a86f..e4d0868cde3 100644 --- a/arch/i386/cpu/interrupts.c +++ b/arch/i386/cpu/interrupts.c @@ -104,7 +104,7 @@ static inline unsigned long get_debugreg(int regno) return val; } -void dump_regs(struct pt_regs *regs) +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; @@ -225,7 +225,7 @@ int disable_interrupts(void) } /* IRQ Low-Level Service Routine */ -__isr__ irq_llsr(struct pt_regs *regs) +void irq_llsr(struct irq_regs *regs) { /* * For detailed description of each exception, refer to: @@ -234,7 +234,7 @@ __isr__ irq_llsr(struct pt_regs *regs) * Order Number: 253665-029US, November 2008 * Table 6-1. Exceptions and Interrupts */ - switch (regs->orig_eax) { + switch (regs->irq_id) { case 0x00: printf("Divide Error (Division by zero)\n"); dump_regs(regs); @@ -340,7 +340,7 @@ __isr__ irq_llsr(struct pt_regs *regs) default: /* Hardware or User IRQ */ - do_irq(regs->orig_eax); + do_irq(regs->irq_id); } } @@ -352,17 +352,30 @@ __isr__ irq_llsr(struct pt_regs *regs) * 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" \ @@ -370,12 +383,7 @@ asm(".globl irq_common_entry\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" \ @@ -383,10 +391,12 @@ asm(".globl irq_common_entry\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) \ diff --git a/arch/i386/cpu/sc520/sc520.c b/arch/i386/cpu/sc520/sc520.c index 519bfd8b0c2..7acd471d963 100644 --- a/arch/i386/cpu/sc520/sc520.c +++ b/arch/i386/cpu/sc520/sc520.c @@ -41,7 +41,8 @@ volatile sc520_mmcr_t *sc520_mmcr = (sc520_mmcr_t *)0xfffef000; void init_sc520(void) { - /* Set the UARTxCTL register at it's slower, + /* + * Set the UARTxCTL register at it's slower, * baud clock giving us a 1.8432 MHz reference */ writeb(0x07, &sc520_mmcr->uart1ctl); @@ -50,25 +51,30 @@ void init_sc520(void) /* 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 */ + /* enable PCI bus arbiter (concurrent mode) */ + writeb(0x02, &sc520_mmcr->sysarbctl); - writeb(0x1f, &sc520_mmcr->sysarbmenb); /* enable external grants */ - writeb(0x04, &sc520_mmcr->hbctl); /* enable posted-writes */ + /* enable external grants */ + writeb(0x1f, &sc520_mmcr->sysarbmenb); + + /* enable posted-writes */ + writeb(0x04, &sc520_mmcr->hbctl); if (CONFIG_SYS_SC520_HIGH_SPEED) { - writeb(0x02, &sc520_mmcr->cpuctl); /* set it to 133 MHz and write back */ + /* set it to 133 MHz and write back */ + writeb(0x02, &sc520_mmcr->cpuctl); 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 */ + /* set it to 100 MHz and write back */ + writeb(0x01, &sc520_mmcr->cpuctl); printf("## CPU Speed set to 100MHz\n"); gd->cpu_clk = 100000000; } /* wait at least one millisecond */ - asm("movl $0x2000,%%ecx\n" + asm("movl $0x2000, %%ecx\n" "0: pushl %%ecx\n" "popl %%ecx\n" "loop 0b\n": : : "ecx"); @@ -107,15 +113,15 @@ unsigned long init_sc520_dram(void) /* 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 */ + 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 */ + val = 3; /* 62.4us */ } tmp = (readb(&sc520_mmcr->drcctl) & 0xcf) | (val<<4); @@ -124,9 +130,9 @@ unsigned long init_sc520_dram(void) val = readb(&sc520_mmcr->drctmctl) & 0xf0; if (cas_precharge_delay==3) { - val |= 0x04; /* 3T */ + val |= 0x04; /* 3T */ } else if (cas_precharge_delay==4) { - val |= 0x08; /* 4T */ + val |= 0x08; /* 4T */ } else if (cas_precharge_delay>4) { val |= 0x0c; } @@ -139,8 +145,10 @@ unsigned long init_sc520_dram(void) writeb(val, &c520_mmcr->drctmctl); #endif - /* We read-back the configuration of the dram - * controller that the assembly code wrote */ + /* + * 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; @@ -148,7 +156,6 @@ unsigned long init_sc520_dram(void) /* 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; @@ -179,11 +186,6 @@ unsigned long init_sc520_dram(void) } 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; diff --git a/arch/i386/cpu/sc520/sc520_asm.S b/arch/i386/cpu/sc520/sc520_asm.S index fff56c00b4f..63c14b7eb0e 100644 --- a/arch/i386/cpu/sc520/sc520_asm.S +++ b/arch/i386/cpu/sc520/sc520_asm.S @@ -172,396 +172,373 @@ .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 */ + /* Preserve Boot Flags */ + movl %ebx, %ebp - movl $ECCCTL, %edi - movb %al, (%edi) /* disable ECC */ + /* initialize dram controller registers */ + xorw %ax, %ax + movl $DBCTL, %edi + movb %al, (%edi) /* disable write buffer */ - movl $DRCTMCTL, %edi - movb $0x1E,%al /* Set SDRAM timing for slowest */ - movb %al, (%edi) + movl $ECCCTL, %edi + movb %al, (%edi) /* disable ECC */ - /* - * 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 $DRCTMCTL, %edi + movb $0x1e, %al /* Set SDRAM timing for slowest */ + movb %al, (%edi) - movl $DRCCFG, %edi /* setup */ - movw $0xbbbb,%ax /* dram config register for */ - movw %ax, (%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) - /* - * 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 */ - /***********************************************/ + movl $DRCCFG, %edi /* setup */ + movw $0xbbbb, %ax /* dram config register for */ + movw %ax, (%edi) - /* - * issue all banks precharge - */ - movb $0x2,%al /* All banks precharge */ - movb %al, (%edi) - movw %ax, (%esi) + /* issue a NOP to all DRAMs */ + movl $DRCCTL, %edi /* setup DRAM control register with */ + movb $0x01, %al /* Disable refresh,disable write buffer */ + movb %al, (%edi) + movl $CACHELINESZ, %esi /* just a dummy address to write for */ + 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 + /* delay for 100 usec? */ + movw $100, %cx +sizdelay: + loop sizdelay - /* - * issue LOAD MODE REGISTER command - */ - movb $0x3,%al /* Load mode register cmd */ - movb %al, (%edi) - movw %ax, (%esi) + /* issue all banks precharge */ + movb $0x02, %al + 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 + /* issue 2 auto refreshes to all banks */ + movb $0x04, %al /* Auto refresh cmd */ + movb %al, (%edi) + movw $0x02, %cx +refresh1: + movw %ax, (%esi) + loop refresh1 + + /* issue LOAD MODE REGISTER command */ + movb $0x03, %al /* Load mode register cmd */ + movb %al, (%edi) + movw %ax, (%esi) + + /* issue 8 more auto refreshes to all banks */ + movb $0x04, %al /* Auto refresh cmd */ + movb %al, (%edi) + movw $0x0008, %cx refresh2: - movw %ax, (%esi) - loop refresh2 + movw %ax, (%esi) + loop refresh2 - /* - * set control register to NORMAL mode - */ - movb $0x0,%al /* Normal mode value */ - movb %al, (%edi) + /* set control register to NORMAL mode */ + movb $0x00, %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 */ + /* + * 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 - */ + /* 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 */ - 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 */ + /* + * 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! */ + movw $0x008, %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 */ + 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 $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 + 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 $0x03, %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 */ - 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) + /* + * issue all banks precharge + */ + movl $DRCCTL, %esi /* setup DRAM control register with */ + movb $0x02, %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 + /* + * 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 + movb %dh, (%edi) + + /* + * update CONFIG REGISTER + */ + xorb %dh, %dh + movw $0x000f, %bx + movw %cx, %ax + shlw $2, %ax + xchgw %cx, %ax + shlw %cl, %dx + shlw %cl, %bx + notw %bx + xchgw %cx, %ax + movl $DRCCFG, %edi + movw (%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 + movb %al, (%edi) + + /* + * set control register to NORMAL mode + */ + movl $DRCCTL, %esi /* setup DRAM control register with */ + movb $0x00, %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 + movl $DRCBENDADR, %edi /* DRAM ending address register */ + movw $0x04, %cx + xorw %ax, %ax cleanuplp: - movb (%edi), %al - orb %al,%al - jz emptybank + movb (%edi), %al + orb %al, %al + jz emptybank - addb %ah,%al - jns nottoomuch + addb %ah, %al + jns nottoomuch - movb $0x7f,%al + movb $0x7f, %al nottoomuch: - movb %al,%ah - orb $0x80,%al - movb %al, (%edi) + movb %al, %ah + orb $0x80, %al + movb %al, (%edi) emptybank: - incl %edi - loop cleanuplp + 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) + 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 + /* + * 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 + andb $0xef, %al #endif #ifdef CONFIG_SYS_SDRAM_CAS_LATENCY_3T - orb $0x10, %al + orb $0x10, %al #endif - movb %al, (%edi) + 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 $0x03, %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) + movl $DRCCTL, %edi /* DRAM Control register */ + movb $0x18, %al /* Enable refresh and NORMAL mode */ + movb %al, (%edi) - jmp dram_done + jmp dram_done bad_ram: - xorl %edx,%edx - xorl %edi,%edi - jmp bad_reint + xorl %edx, %edx + xorl %edi, %edi + jmp bad_reint dram_done: + /* Restore Boot Flags */ + movl %ebx, %ebp + jmp mem_init_ret #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 - +.globl init_ecc 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 %eax, %ecx + shrl $0x1, %ecx movl $0x1, %edi memtest0: movb $0xa5, (%edi) - cmpb $0xa5, (%edi) + cmpb $0xa5, (%edi) jne out - shrl $1, %ecx - andl %ecx,%ecx + shrl $0x1, %ecx + andl %ecx, %ecx jz set_ecc - shll $1, %edi + shll $0x1, %edi jmp memtest0 set_ecc: @@ -570,25 +547,28 @@ set_ecc: xorl %esi, %esi xorl %edi, %edi xorl %eax, %eax - shrl $2, %ecx + 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 - mov $0x10, %al - movb %al, (%edi) - /* Turn on ECC */ - movl $ECCCTL, %edi - mov $0x05, %al - movb %al, (%edi) -#endif + + /* 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 *%ebp + jmp init_ecc_ret +#endif /* * Read and decode the sc520 DRCBENDADR MMCR and return the number of @@ -596,7 +576,7 @@ out: */ .globl get_mem_size get_mem_size: - movl $DRCBENDADR, %edi /* DRAM ending address register */ + movl $DRCBENDADR, %edi /* DRAM ending address register */ bank0: movl (%edi), %eax movl %eax, %ecx @@ -604,7 +584,7 @@ bank0: movl (%edi), %eax jz bank1 andl $0x0000007f, %eax shll $22, %eax - movl %eax, %ebx + movl %eax, %edx bank1: movl (%edi), %eax movl %eax, %ecx @@ -612,7 +592,7 @@ bank1: movl (%edi), %eax jz bank2 andl $0x00007f00, %eax shll $14, %eax - movl %eax, %ebx + movl %eax, %edx bank2: movl (%edi), %eax movl %eax, %ecx @@ -620,7 +600,7 @@ bank2: movl (%edi), %eax jz bank3 andl $0x007f0000, %eax shll $6, %eax - movl %eax, %ebx + movl %eax, %edx bank3: movl (%edi), %eax movl %eax, %ecx @@ -628,8 +608,8 @@ bank3: movl (%edi), %eax jz done andl $0x7f000000, %eax shrl $2, %eax - movl %eax, %ebx + movl %eax, %edx done: - movl %ebx, %eax - jmp *%ebp + movl %edx, %eax + jmp get_mem_size_ret diff --git a/arch/i386/cpu/start.S b/arch/i386/cpu/start.S index 7def8def8b1..829468fe7ed 100644 --- a/arch/i386/cpu/start.S +++ b/arch/i386/cpu/start.S @@ -1,7 +1,7 @@ /* * U-boot - i386 Startup Code * - * Copyright (c) 2002 Omicron Ceti AB, Daniel Engström <denaiel@omicron.se> + * Copyright (c) 2002 Omicron Ceti AB, Daniel Engstr�m <denaiel@omicron.se> * * See file CREDITS for list of people who contributed to this * project. @@ -25,6 +25,7 @@ #include <config.h> #include <version.h> +#include <asm/global_data.h> .section .text @@ -45,175 +46,98 @@ _i386boot_start: /* Turn of cache (this might require a 486-class CPU) */ movl %cr0, %eax - orl $0x60000000,%eax + orl $0x60000000, %eax movl %eax, %cr0 wbinvd /* Tell 32-bit code it is being entered from an in-RAM copy */ - movw $0x0000, %bx + movw $GD_FLG_WARM_BOOT, %bx _start: /* This is the 32-bit cold-reset entry point */ - movl $0x18,%eax /* Load our segement registes, the + 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 + 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 */ + /* Skip low-level initialization if not starting from cold-reset */ + movl %ebx, %ecx + andl $GD_FLG_COLD_BOOT, %ecx + jz skip_mem_init /* Early platform init (setup gpio, etc ) */ - mov $early_board_init_ret, %ebp jmp early_board_init +.globl early_board_init_ret 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 + jmp mem_init +.globl mem_init_ret mem_init_ret: +skip_mem_init: /* fetch memory size (into %eax) */ - mov $get_mem_size_ret, %ebp - jmp get_mem_size + jmp get_mem_size +.globl get_mem_size_ret 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. - */ +#if CONFIG_SYS_SDRAM_ECC_ENABLE + /* Skip ECC initialization if not starting from cold-reset */ + movl %ebx, %ecx + andl $GD_FLG_COLD_BOOT, %ecx + jz init_ecc_ret + jmp init_ecc - /* 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 +.globl init_ecc_ret +init_ecc_ret: +#endif - /* 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 + jb 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: + movl %eax, %esp /* Test the stack */ pushl $0 - popl %eax - cmpl $0, %eax - jne no_stack + popl %ecx + cmpl $0, %ecx + jne die 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 + popl %ecx + cmpl $0x55aa55aa, %ecx + jne die + wbinvd -stack_ok: - /* indicate progress */ - movw $0x03, %ax - movl $.progress2, %ebp - jmp show_boot_progress_asm -.progress2: + /* Determine our load offset */ + call 1f +1: popl %ecx + subl $1b, %ecx - wbinvd + /* Set the upper memory limit parameter */ + subl $CONFIG_SYS_STACK_SIZE, %eax - /* Get upper memory limit */ - movl %esp, %ecx - subl $CONFIG_SYS_STACK_SIZE, %ecx + /* Reserve space for global data */ + subl $(GD_SIZE * 4), %eax - /* Create a Stack Frame */ - pushl %ebp - movl %esp, %ebp + /* %eax points to the global data structure */ + movl %esp, (GD_RAM_SIZE * 4)(%eax) + movl %ebx, (GD_FLAGS * 4)(%eax) + movl %ecx, (GD_LOAD_OFF * 4)(%eax) - /* 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 @@ -221,52 +145,3 @@ die: hlt blank_idt_ptr: .word 0 /* limit */ .long 0 /* base */ - -.align 4 -start_gdt_setup: - lgdt gdt_ptr -jmp_instr: - jmp *%ebp - -.align 4 -gdt_ptr: - .word 0x30 /* limit (48 bytes = 6 GDT entries) */ -gdt_addr: - .long gdt /* base */ - - /* The GDT table ... - * - * Selector Type - * 0x00 NULL - * 0x08 Unused - * 0x10 32bit code - * 0x18 32bit data/stack - * 0x20 16bit code - * 0x28 16bit data/stack - */ - -.align 4 -gdt: - .word 0, 0, 0, 0 /* NULL */ - .word 0, 0, 0, 0 /* unused */ - - .word 0xFFFF /* 4Gb - (0x100000*0x1000 = 4Gb) */ - .word 0 /* base address = 0 */ - .word 0x9B00 /* code read/exec */ - .word 0x00CF /* granularity = 4096, 386 (+5th nibble of limit) */ - - .word 0xFFFF /* 4Gb - (0x100000*0x1000 = 4Gb) */ - .word 0x0 /* base address = 0 */ - .word 0x9300 /* data read/write */ - .word 0x00CF /* granularity = 4096, 386 (+5th nibble of limit) */ - - .word 0xFFFF /* 64kb */ - .word 0 /* base address = 0 */ - .word 0x9b00 /* data read/write */ - .word 0x0010 /* granularity = 1 (+5th nibble of limit) */ - - .word 0xFFFF /* 64kb */ - .word 0 /* base address = 0 */ - .word 0x9300 /* data read/write */ - .word 0x0010 /* granularity = 1 (+5th nibble of limit) */ -end_gdt_setup: diff --git a/arch/i386/cpu/start16.S b/arch/i386/cpu/start16.S index ebe58358417..0a5823d3c29 100644 --- a/arch/i386/cpu/start16.S +++ b/arch/i386/cpu/start16.S @@ -22,6 +22,7 @@ * MA 02111-1307 USA */ +#include <asm/global_data.h> #define BOOT_SEG 0xffff0000 /* linear segment of boot code */ #define a32 .byte 0x67; @@ -31,16 +32,20 @@ .code16 .globl start16 start16: - /* First we let the BSP do some early initialization + /* 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 */ - mov $board_init16_ret, %bp jmp board_init16 +.globl board_init16_ret board_init16_ret: /* Turn of cache (this might require a 486-class CPU) */ movl %cr0, %eax - orl $0x60000000,%eax + orl $0x60000000, %eax movl %eax, %cr0 wbinvd @@ -50,18 +55,15 @@ o32 cs lgdt gdt_ptr /* Now, we enter protected mode */ movl %cr0, %eax - orl $1,%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 + movw %ax, %bp o32 cs ljmp *(%bp) /* 48-bit far pointer */ |