> -----Original Message-----
> From: David Woodhouse [mailto:[EMAIL PROTECTED]]
> Sent: Tuesday, April 24, 2001 2:33 PM
> To: [EMAIL PROTECTED]
> Cc: Vipin Malik; Alex Lennon; [EMAIL PROTECTED]; jffs-dev;
> [EMAIL PROTECTED]
> Subject: Re: Elan SC520 - problem with MTD
>
>
>
>
>
> [EMAIL PROTECTED] said:
> > I have some code that does the basic SC520 initialization
> right after
> > reset and I am now trying to initialize the Super I/O chip (I have
> > just received the chip manual from Acerlabs). After that, I need to
> > figure out a way to setup the set up the PCI bridge... Another thing
> > that is still missing in my code is a proper RAM size detection.
>
> > So any working code you might have along these lines -no matter how
> > ugly- would probably be helpful to me.
I have a system with the Elan520 evaluation board working completely from flash.
Here is some of the code used. It is based on AMD codekits, check their website
to verify latest news.
//==============================================================================
// FILE : ram_sizer.S
// =============================================================================
//
// It will then intialize the SDRAM
//
// ============================================================================
#include "asm.hs"
#include "elan520sc.hs"
.code32
.text
//============================================================================
// Automatic RAM configuration
//============================================================================
.code32
.globl sizemem
.align 4
sizemem:
xorw %ax, %ax
movl $DBCTL, %edi //
movb %al, (%edi) // disable write buffer/read-ahead buffer
movl $ECCCTL, %edi //
movb %al, (%edi) // disable ECC
movl $DRCTMCTL, %edi //
movb $0x1E, %al // Set SDRAM timing for slowest
movb %al, (%edi) // speed.
//
// setup loop to do 4 external banks starting with bank 3
//
movl $0x0ff000000, %eax // enable last bank and setup
movl $DRCBENDADR, %edi // ending address register
movl %eax, (%edi) // for max ram in last bank
movl $DRCCFG, %edi // setup
movw $0x0bbbb, %ax // dram config register for
movw %ax, (%edi) // all banks with max cols and max banks
//
// 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) // Test Mode and NOP command select
movl $CACHELINESZ, %esi // just a dummy address to write for
movw %ax, (%esi) // NOP cmd to take effect
//
// 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 $0x02, %al // All banks precharge
movb %al, (%edi) //
movw %ax, (%esi) // write needed for cmd to take effect
//
// issue 2 auto refreshes to all banks
//
movb $0x04, %al // Auto refresh cmd
movb %al, (%edi) //
movw $2, %cx
refresh1:
movw %ax, (%esi) // write needed for cmd to take effect
loop refresh1
//
// issue LOAD MODE REGISTER command
//
movb $0x03, %al // Load mode register cmd
movb %al, (%edi) //
movw %ax, (%esi) // write needed for cmd to take effect
//
// issue 8 more auto refreshes to all banks
//
movb $0x04, %al // Auto refresh cmd
movb %al, (%edi) //
movw $8, %cx
refresh2:
movw %ax, (%esi) // write needed for cmd to take effect
loop refresh2
//
// 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
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
cmpl %ebx, %eax // check for AA pattern
movl $ROW14_ADR, %esi // set address back to max row wrap addr
movl (%esi), %eax // read actual number of rows @ row14 adr
jz only2 // if pattern == AA, we only have 2
banks
movw $0x0008, %di // value for 4 banks in DI
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!
only2:
//
// validate row mask
//
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
shr $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
movb %bl, %dh
xchgw %cx, %ax
shrb %cl, %dh
incb %dh // ending addr is 1 greater than
real end
xchgw %cx, %ax
//
// issue all banks precharge
//
bad_reint:
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) // write needed for cmd to take effect
//
// update ENDING ADDRESS REGISTER
//
movl $DRCBENDADR, %edi // DRAM ending address register
movl %ecx, %ebx
movb %dh, %fs:(%ebx, %edi) // write ending address for this bank
//
// 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 $0x0ff, %al
movb %al, %fs:(%ebx, %edi) // enable next bank for max
ending addr
//
// 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) // write needed for cmd to take
effect
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 $0x07f, %al
nottoomuch:
movb %al, %ah
orb $0x80, %al
movb %al, (%edi)
emptybank:
incl %edi
loop cleanuplp
movl $DRCCTL, %edi // DRAM Control register
movb $0x18, %al // Enable refresh and NORMAL
mode
movb %al, (%edi) // and 15.6 usec refresh rate
// get ram size from "DRC BankEndAddress"
// ecx counter
// esi pointer to BankEndAddress
movl $0x3, %ecx
movl $DRCBENDADR, %esi // DRAM ending address register
.Lcaltotalram:
movl (%esi), %edx
movl %ecx, %ebx // save counter
shl $3, %ecx // multipy counter to get number of
bits
shr %cl, %edx // place into lower byte the
bank_reg[counter]
movl %ebx, %ecx // restore counter
test $128, %edx // bank enabled ?
jz .LBankDisabled
// theorically edx by 4Meg == ramsize
andl $127, %edx // get bank ending address
movl %edx, %eax
shl $22, %eax // multiply by 4Megs 0x400000
jmp .LTotalSizeDone
.LBankDisabled:
loop .Lcaltotalram
.LTotalSizeDone: // eax dram size in bytes
//--- Ram Sizing FINISHES return with %ebp address
jmp *%ebp // return thanks to ebp
.align 4
bad_ram:
xor %edx, %edx
xorl %edi, %edi
jmp bad_reint
//========================================================================================
*********************************************************************************
from start32.S
*********************************************************************************
.equiv gdt_table_size, 5 * SIZE_GDT_ENTRY // gdt_table_end - gdt_table
.code32
.text
.global _start_32
//----------------------------------------------------------------------
_start_32:
// now reload all of the segment registers with descriptor 0x18
xorl %eax, %eax // clear eax (porque movw ax, fs se traduce a
movl ??)
movw $SEG32_DS, %ax // set segment base to descriptor 0x018
movw %ax, %fs
movw %ax, %ds // use DS
movw %ax, %gs // use GS
movw %ax, %es // use ES
movw %ax, %ss // use ES
//---- output a 3 to led 680, segments changed
movw $0x0680, %dx
movw $0x04, %ax
outw %ax, %dx
DELAY_LOOP
//-----------------------------------------------------------------------
// all accesses to data from now on are now done in 32 bit
// mode. As a result, we don't need the CBAR alias anymore.
// to prevent any possible problems with the alias interfering
// with any loaded code or data, we turn off the CBAR alias here.
//-----------------------------------------------------------------------
movw $CBAR, %dx // set the new MMCR base to 0df00:0h
movl $0x0CB, %eax // that is: cancel the alias
outl %eax, %dx // 32 bit register
//-----------------------------------------------------------------------
// Now that we have access to 32 bit memory space, we
// setup the SDRAM controller and initialize the SDRAM.
// perform dynamic DRAM sizing
//-----------------------------------------------------------------------
movl $dram_done, %ebp // return address (we still don't have a stack)
jmp sizemem // jump to the dram dynamic sizing routine
dram_done:
movl %eax, %ebp // !!!! now EBP contains TOTAL RAM SIZE in bytes
//------------------- output a 4 to led 680, dram done
movw $0x0680, %dx
movw $0x04, %ax
outw %ax, %dx
//-----------------------------------------------------------
// -------------------- Ram Parameters init ------------------------ JB
movl $ECCCTL, %edi // ECC Control
movl $0x0, %eax
movb %al, (%edi) // disable RAM ECC (in fact, it already was)
movl $DRCTMCTL, %edi // SDram Timing Control
movb (RamTimings), %al // CAS Latency 3T, RAS Precharge Delay 3T, RAS
to CAS delay 3T => 000 1 01 01
movb %al, (%edi)
//------------------- output a 5 to led 680, dram configured
movw $0x0680, %dx
movw $0x05, %ax
outw %ax, %dx
movb (RamTestDisabled), %al
testb %al, %al
jnz test_stack
.equ VAL_5A, 0x5A5A5A5A
.equ VAL_A5, 0xA5A5A5A5
//--------------- RAM test (cache disabled but memory at full-speed) --------
cld
//--- write 0x5A5A5A5A to RAM
movl $0x0, %edi // destination
movl %ebp, %ecx
shr $2, %ecx // RAM doubleword size (div 4)
movl $VAL_5A, %eax
rep stosl
//------------------- output a 6 to led 680, dram to 5A written
movw $0x0680, %dx
movw $0x06, %ax
outw %ax, %dx
//--- verify that RAM is 0x5A5A5A5A
movl $0x0, %edi // scan destination
movl %ebp, %ecx
shr $2, %ecx // RAM doubleword size
movl $VAL_5A, %eax
repe scasl // repeat while equal
jne ram_test_err
//------------------- output a 7 to led 680, dram 5A test done
movw $0x0680, %dx
movw $0x07, %ax
outw %ax, %dx
//--- write 0xA5A5A5A5 to RAM
movl $0x0, %edi // destination
movl %ebp, %ecx
shr $2, %ecx // RAM doubleword size (div 4)
movl $VAL_A5, %eax
rep stosl
//------------------- output a 8 to led 680, dram to A5 written
movw $0x0680, %dx
movw $0x08, %ax
outw %ax, %dx
//--- verify RAM to 0xA5A5A5A5
movl $0x0, %edi // scan destination
movl %ebp, %ecx
shr $2, %ecx // RAM doubleword size
movl $VAL_A5, %eax
repe scasl // repeat while equal
jne ram_test_err
//------- output a 9 to led 680, dram to A5 done
movw $0x0680, %dx
movw $0x09, %ax
outw %ax, %dx
test_stack:
...
*********************************************************************************
Juan Bertran
UNIDESA
Pi i Margall 201
08224 - Terrassa
SPAIN
e-mail: [EMAIL PROTECTED]