|  | /* | 
|  | * (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) */ | 
|  |  | 
|  | .globl mem_init | 
|  | mem_init: | 
|  | /* Preserve Boot Flags */ | 
|  | movl	%ebx, %ebp | 
|  |  | 
|  | /* initialize dram controller registers */ | 
|  | 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	$0x01, %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? */ | 
|  | movw	$100, %cx | 
|  | sizdelay: | 
|  | loop	sizdelay | 
|  |  | 
|  | /* issue all banks precharge */ | 
|  | movb	$0x02, %al | 
|  | movb	%al, (%edi) | 
|  | movw	%ax, (%esi) | 
|  |  | 
|  | /* 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 | 
|  |  | 
|  | /* 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 */ | 
|  | /* (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	$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 */ | 
|  |  | 
|  | 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	$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 */ | 
|  |  | 
|  | bad_reint: | 
|  | /* | 
|  | * 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 | 
|  | addl	%ebx, %edi | 
|  | 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	$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	$0x04, %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	$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) | 
|  |  | 
|  | jmp	dram_done | 
|  |  | 
|  | bad_ram: | 
|  | 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 | 
|  | .globl init_ecc | 
|  | init_ecc: | 
|  | /* A nominal memory test: just a byte at each address line */ | 
|  | movl	%eax, %ecx | 
|  | shrl	$0x1, %ecx | 
|  | movl	$0x1, %edi | 
|  | memtest0: | 
|  | movb	$0xa5, (%edi) | 
|  | cmpb	$0xa5, (%edi) | 
|  | jne	out | 
|  | shrl	$0x1, %ecx | 
|  | andl	%ecx, %ecx | 
|  | jz	set_ecc | 
|  | shll	$0x1, %edi | 
|  | jmp	memtest0 | 
|  |  | 
|  | set_ecc: | 
|  | /* clear all ram with a memset */ | 
|  | movl	%eax, %ecx | 
|  | xorl	%esi, %esi | 
|  | xorl	%edi, %edi | 
|  | xorl	%eax, %eax | 
|  | shrl	$0x2, %ecx | 
|  | cld | 
|  | rep	stosl | 
|  |  | 
|  | /* enable read, write buffers */ | 
|  | movb	$0x11, %al | 
|  | movl	$DBCTL, %edi | 
|  | movb	%al, (%edi) | 
|  |  | 
|  | /* enable NMI mapping for ECC */ | 
|  | movl	$ECCINT, %edi | 
|  | movb	$0x10, %al | 
|  | movb	%al, (%edi) | 
|  |  | 
|  | /* Turn on ECC */ | 
|  | movl	$ECCCTL, %edi | 
|  | movb	$0x05, %al | 
|  | movb	%al,(%edi) | 
|  |  | 
|  | out: | 
|  | jmp	init_ecc_ret | 
|  | #endif | 
|  |  | 
|  | /* | 
|  | * 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, %edx | 
|  |  | 
|  | bank1:	movl	(%edi), %eax | 
|  | movl	%eax, %ecx | 
|  | andl	$0x00008000, %ecx | 
|  | jz	bank2 | 
|  | andl	$0x00007f00, %eax | 
|  | shll	$14, %eax | 
|  | movl	%eax, %edx | 
|  |  | 
|  | bank2:	movl	(%edi), %eax | 
|  | movl	%eax, %ecx | 
|  | andl	$0x00800000, %ecx | 
|  | jz	bank3 | 
|  | andl	$0x007f0000, %eax | 
|  | shll	$6, %eax | 
|  | movl	%eax, %edx | 
|  |  | 
|  | bank3:	movl	(%edi), %eax | 
|  | movl	%eax, %ecx | 
|  | andl	$0x80000000, %ecx | 
|  | jz	done | 
|  | andl	$0x7f000000, %eax | 
|  | shrl	$2, %eax | 
|  | movl	%eax, %edx | 
|  |  | 
|  | done: | 
|  | movl	%edx, %eax | 
|  | jmp	get_mem_size_ret |