uboot/arch/i386/cpu/sc520/sc520_asm.S
<<
>>
Prefs
   1/*
   2 * (C) Copyright 2002
   3 * Daniel Engström, Omicron Ceti AB <daniel@omicron.se>.
   4 *
   5 * See file CREDITS for list of people who contributed to this
   6 * project.
   7 *
   8 * This program is free software; you can redistribute it and/or
   9 * modify it under the terms of the GNU General Public License as
  10 * published by the Free Software Foundation; either version 2 of
  11 * the License, or (at your option) any later version.
  12 *
  13 * This program is distributed in the hope that it will be useful,
  14 * but WITHOUT ANY WARRANTY; without even the implied warranty of
  15 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.  See the
  16 * GNU General Public License for more details.
  17 *
  18 * You should have received a copy of the GNU General Public License
  19 * along with this program; if not, write to the Free Software
  20 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
  21 * MA 02111-1307 USA
  22 */
  23
  24/* This file is largely based on code obtned from AMD. AMD's original
  25 * copyright is included below
  26 */
  27
  28/*              TITLE   SIZER - Aspen DRAM Sizing Routine.
  29 * =============================================================================
  30 *
  31 *  Copyright 1999 Advanced Micro Devices, Inc.
  32 * You may redistribute this program and/or modify this program under the terms
  33 * of the GNU General Public License as published by the Free Software Foundation;
  34 * either version 2 of the License, or (at your option) any later version.
  35 *
  36 *  This program is distributed WITHOUT ANY WARRANTY; WITHOUT EVEN THE IMPLIED
  37 * WARRANTY OF MERCHANTABILITY OR FITNESS FOR A PARTICULAR PURPOSE. See the GNU
  38 * General Public License for more details.
  39 *
  40 * You should have received a copy of the GNU General Public License along with
  41 * this program; if not, write to the Free Software Foundation, Inc.,
  42 * 59 Temple Place, Suite 330, Boston, MA 02111-1307 USA.
  43 *
  44 * THE MATERIALS ARE PROVIDED "AS IS" WITHOUT ANY EXPRESS OR IMPLIED WARRANTY
  45 * OF ANY KIND INCLUDING WARRANTIES OF MERCHANTABILITY, NONINFRINGEMENT OF
  46 * THIRD-PARTY INTELLECTUAL PROPERTY, OR FITNESS FOR ANY PARTICULAR PURPOSE.
  47 * IN NO EVENT SHALL AMD OR ITS SUPPLIERS BE LIABLE FOR ANY DAMAGES WHATSOEVER
  48 * (INCLUDING, WITHOUT LIMITATION, DAMAGES FOR LOSS OF PROFITS, BUSINESS
  49 * INTERRUPTION, LOSS OF INFORMATION) ARISING OUT OF THE USE OF OR INABILITY
  50 * TO USE THE MATERIALS, EVEN IF AMD HAS BEEN ADVISED OF THE POSSIBILITY OF
  51 * SUCH DAMAGES.  BECAUSE SOME JURSIDICTIONS PROHIBIT THE EXCLUSION OR
  52 * LIMITATION OF LIABILITY FOR CONSEQUENTIAL OR INCIDENTAL DAMAGES, THE ABOVE
  53 * LIMITATION MAY NOT APPLY TO YOU.
  54 *
  55 * AMD does not assume any responsibility for any errors that may appear in
  56 * the Materials nor any responsibility to support or update the Materials.
  57 * AMD retains the right to make changes to its test specifications at any
  58 * time, without notice.
  59 * ==============================================================================
  60 */
  61
  62/*
  63 ******************************************************************************
  64 *
  65 *  FILE        : sizer.asm - SDRAM DIMM Sizing Algorithm
  66 *
  67 *
  68 *
  69 *  FUNCTIONS   : sizemem() - jumped to, not called.  To be executed after
  70 *                reset to determine the size of the SDRAM DIMMs. Initializes
  71 *               the memory subsystem.
  72 *
  73 *
  74 *  AUTHOR      : Buddy Fey - Original.
  75 *
  76 *
  77 *  DESCRIPTION : Performs sizing on SDRAM DIMMs on ASPEN processor.
  78 *                NOTE: This is a small memory model version
  79 *
  80 *
  81 *  INPUTS      : BP contains return address offset
  82 *               CACHE is assumed to be disabled.
  83 *               The FS segment limit has already been set to big real mode
  84 *               (full 32-bit addressing capability)
  85 *
  86 *
  87 *  OUTPUTS     : None
  88 *
  89 *
  90 *  REG USE     :  ax,bx,cx,dx,di,si,bp, fs
  91 *
  92 *
  93 *  REVISION    : See PVCS info below
  94 *
  95 *
  96 *  TEST PLAN CROSS REFERENCE:
  97 *
  98 *
  99 * $Workfile: $
 100 * $Revision: 1.2 $
 101 * $Date: 1999/09/22 12:49:33 $
 102 * $Author: chipf $
 103 * $Log: sizer.asm $
 104 * Revision 1.2  1999/09/22 12:49:33  chipf
 105 * Add legal header
 106 *
 107 *******************************************************************************
 108 */
 109
 110
 111/*******************************************************************************
 112 *       FUNCTIONAL DESCRIPTION:
 113 * This routine is called to autodetect the geometry of the DRAM.
 114 *
 115 * This routine is called to determine the number of column bits for the DRAM
 116 * devices in this external bank. This routine assumes that the external bank
 117 * has been configured for an 11-bit column and for 4 internal banks. This gives
 118 * us the maximum address reach in memory. By writing a test value to the max
 119 * address and locating where it aliases to, we can determine the number of valid
 120 * column bits.
 121 *
 122 * This routine is called to determine the number of internal banks each DRAM
 123 * device has. The external bank (under test) is configured for maximum reach
 124 * with 11-bit columns and 4 internal banks. This routine will write to a max
 125 * address (BA1 and BA0 = 1) and then read from an address with BA1=0 to see if
 126 * that column is a "don't care". If BA1 does not affect write/read of data,
 127 * then this device has only 2 internal banks.
 128 *
 129 * This routine is called to determine the ending address for this external
 130 * bank of SDRAM. We write to a max address with a data value and then disable
 131 * row address bits looking for "don't care" locations. Each "don't care" bit
 132 * represents a dividing of the maximum density (128M) by 2. By dividing the
 133 * maximum of 32 4M chunks in an external bank down by all the "don't care" bits
 134 * determined during sizing, we set the proper density.
 135 *
 136 * WARNINGS.
 137 * bp must be preserved because it is used for return linkage.
 138 *
 139 * EXIT
 140 * nothing returned - but the memory subsystem is enabled
 141 *******************************************************************************
 142 */
 143
 144#include <config.h>
 145
 146.section .text
 147.equ            DRCCTL,     0x0fffef010   /* DRAM control register */
 148.equ            DRCTMCTL,   0x0fffef012   /* DRAM timing control register */
 149.equ            DRCCFG,     0x0fffef014   /* DRAM bank configuration register */
 150.equ            DRCBENDADR, 0x0fffef018   /* DRAM bank ending address register */
 151.equ            ECCCTL,     0x0fffef020   /* DRAM ECC control register */
 152.equ            ECCINT,     0x0fffefd18   /* DRAM ECC nmi-INT mapping */
 153.equ            DBCTL,      0x0fffef040   /* DRAM buffer control register */
 154
 155.equ            CACHELINESZ, 0x00000010   /* size of our cache line (read buffer) */
 156.equ            COL11_ADR,  0x0e001e00    /* 11 col addrs */
 157.equ            COL10_ADR,  0x0e000e00    /* 10 col addrs */
 158.equ            COL09_ADR,  0x0e000600    /*  9 col addrs */
 159.equ            COL08_ADR,  0x0e000200    /*  8 col addrs */
 160.equ            ROW14_ADR,  0x0f000000    /* 14 row addrs */
 161.equ            ROW13_ADR,  0x07000000    /* 13 row addrs */
 162.equ            ROW12_ADR,  0x03000000    /* 12 row addrs */
 163.equ            ROW11_ADR,  0x01000000    /* 11 row addrs/also bank switch */
 164.equ            ROW10_ADR,  0x00000000    /* 10 row addrs/also bank switch */
 165.equ            COL11_DATA, 0x0b0b0b0b    /* 11 col addrs */
 166.equ            COL10_DATA, 0x0a0a0a0a    /* 10 col data */
 167.equ            COL09_DATA, 0x09090909    /*  9 col data */
 168.equ            COL08_DATA, 0x08080808    /*  8 col data */
 169.equ            ROW14_DATA, 0x3f3f3f3f    /* 14 row data (MASK) */
 170.equ            ROW13_DATA, 0x1f1f1f1f    /* 13 row data (MASK) */
 171.equ            ROW12_DATA, 0x0f0f0f0f    /* 12 row data (MASK) */
 172.equ            ROW11_DATA, 0x07070707    /* 11 row data/also bank switch (MASK) */
 173.equ            ROW10_DATA, 0xaaaaaaaa    /* 10 row data/also bank switch (MASK) */
 174
 175
 176 /*
 177  * initialize dram controller registers
 178  */
 179.globl mem_init
 180mem_init:
 181        xorw    %ax,%ax
 182        movl    $DBCTL, %edi
 183        movb     %al, (%edi)             /* disable write buffer */
 184
 185        movl    $ECCCTL, %edi
 186        movb     %al, (%edi)             /* disable ECC */
 187
 188        movl    $DRCTMCTL, %edi
 189        movb    $0x1E,%al                /* Set SDRAM timing for slowest */
 190        movb     %al, (%edi)
 191
 192 /*
 193  * setup loop to do 4 external banks starting with bank 3
 194  */
 195        movl    $0xff000000,%eax         /* enable last bank and setup */
 196        movl    $DRCBENDADR, %edi        /* ending address register */
 197        movl     %eax, (%edi)
 198
 199        movl    $DRCCFG, %edi            /* setup */
 200        movw    $0xbbbb,%ax              /* dram config register for  */
 201        movw    %ax, (%edi)
 202
 203 /*
 204  * issue a NOP to all DRAMs
 205  */
 206        movl    $DRCCTL, %edi            /* setup DRAM control register with */
 207        movb    $0x1,%al                 /* Disable refresh,disable write buffer */
 208        movb     %al, (%edi)
 209        movl    $CACHELINESZ, %esi       /* just a dummy address to write for */
 210        movw     %ax, (%esi)
 211 /*
 212  * delay for 100 usec? 200?
 213  * ******this is a cludge for now *************
 214  */
 215        movw    $100,%cx
 216sizdelay:
 217        loop    sizdelay                 /* we need 100 usec here */
 218 /***********************************************/
 219
 220 /*
 221  * issue all banks precharge
 222  */
 223        movb    $0x2,%al                 /* All banks precharge */
 224        movb     %al, (%edi)
 225        movw     %ax, (%esi)
 226
 227 /*
 228  * issue 2 auto refreshes to all banks
 229  */
 230        movb    $0x4,%al                 /* Auto refresh cmd */
 231        movb     %al, (%edi)
 232        movw    $2,%cx
 233refresh1:
 234        movw     %ax, (%esi)
 235        loop    refresh1
 236
 237 /*
 238  * issue LOAD MODE REGISTER command
 239  */
 240        movb    $0x3,%al                 /* Load mode register cmd */
 241        movb     %al, (%edi)
 242        movw     %ax, (%esi)
 243
 244 /*
 245  * issue 8 more auto refreshes to all banks
 246  */
 247        movb    $0x4,%al                 /* Auto refresh cmd */
 248        movb     %al, (%edi)
 249        movw    $8,%cx
 250refresh2:
 251        movw     %ax, (%esi)
 252        loop    refresh2
 253
 254 /*
 255  * set control register to NORMAL mode
 256  */
 257        movb    $0x0,%al                 /* Normal mode value */
 258        movb     %al, (%edi)
 259
 260 /*
 261  * size dram starting with external bank 3 moving to external bank 0
 262  */
 263        movl    $0x3,%ecx                /* start with external bank 3 */
 264
 265nextbank:
 266
 267 /*
 268  * write col 11 wrap adr
 269  */
 270        movl    $COL11_ADR, %esi         /* set address to max col (11) wrap addr */
 271        movl    $COL11_DATA, %eax        /* pattern for max supported columns(11) */
 272        movl    %eax, (%esi)             /* write max col pattern at max col adr */
 273        movl    (%esi), %ebx             /* optional read */
 274        cmpl    %ebx,%eax                /* to verify write */
 275        jnz     bad_ram                  /* this ram is bad */
 276 /*
 277  * write col 10 wrap adr
 278  */
 279
 280        movl    $COL10_ADR, %esi         /* set address to 10 col wrap address */
 281        movl    $COL10_DATA, %eax        /* pattern for 10 col wrap */
 282        movl    %eax, (%esi)             /* write 10 col pattern @ 10 col wrap adr */
 283        movl    (%esi), %ebx             /* optional read */
 284        cmpl    %ebx,%eax                /* to verify write */
 285        jnz     bad_ram                  /* this ram is bad */
 286 /*
 287  * write col 9 wrap adr
 288  */
 289        movl    $COL09_ADR, %esi         /* set address to 9 col wrap address */
 290        movl    $COL09_DATA, %eax        /* pattern for 9 col wrap */
 291        movl    %eax, (%esi)             /* write 9 col pattern @ 9 col wrap adr */
 292        movl    (%esi), %ebx             /* optional read */
 293        cmpl    %ebx,%eax                /* to verify write */
 294        jnz     bad_ram                  /* this ram is bad */
 295 /*
 296  * write col 8 wrap adr
 297  */
 298        movl    $COL08_ADR, %esi         /* set address to min(8) col wrap address */
 299        movl    $COL08_DATA, %eax        /* pattern for min (8) col wrap */
 300        movl    %eax, (%esi)             /* write min col pattern @ min col adr */
 301        movl    (%esi), %ebx             /* optional read */
 302        cmpl    %ebx,%eax                /* to verify write */
 303        jnz     bad_ram                  /* this ram is bad */
 304 /*
 305  * write row 14 wrap adr
 306  */
 307        movl    $ROW14_ADR, %esi         /* set address to max row (14) wrap addr */
 308        movl    $ROW14_DATA, %eax        /* pattern for max supported rows(14) */
 309        movl    %eax, (%esi)             /* write max row pattern at max row adr */
 310        movl    (%esi), %ebx             /* optional read */
 311        cmpl    %ebx,%eax                /* to verify write */
 312        jnz     bad_ram                  /* this ram is bad */
 313 /*
 314  * write row 13 wrap adr
 315  */
 316        movl    $ROW13_ADR, %esi         /* set address to 13 row wrap address */
 317        movl    $ROW13_DATA, %eax        /* pattern for 13 row wrap */
 318        movl    %eax, (%esi)             /* write 13 row pattern @ 13 row wrap adr */
 319        movl    (%esi), %ebx             /* optional read */
 320        cmpl    %ebx,%eax                /* to verify write */
 321        jnz     bad_ram                  /* this ram is bad */
 322 /*
 323  * write row 12 wrap adr
 324  */
 325        movl    $ROW12_ADR, %esi         /* set address to 12 row wrap address */
 326        movl    $ROW12_DATA, %eax        /* pattern for 12 row wrap */
 327        movl    %eax, (%esi)             /* write 12 row pattern @ 12 row wrap adr */
 328        movl    (%esi), %ebx             /* optional read */
 329        cmpl    %ebx,%eax                /* to verify write */
 330        jnz     bad_ram                  /* this ram is bad */
 331 /*
 332  * write row 11 wrap adr
 333  */
 334        movl    $ROW11_ADR, %edi         /* set address to 11 row wrap address */
 335        movl    $ROW11_DATA, %eax        /* pattern for 11 row wrap */
 336        movl    %eax, (%edi)             /* write 11 row pattern @ 11 row wrap adr */
 337        movl    (%edi), %ebx             /* optional read */
 338        cmpl    %ebx,%eax                /* to verify write */
 339        jnz     bad_ram                  /* this ram is bad */
 340 /*
 341  * write row 10 wrap adr --- this write is really to determine number of banks
 342  */
 343        movl    $ROW10_ADR, %edi         /* set address to 10 row wrap address */
 344        movl    $ROW10_DATA, %eax        /* pattern for 10 row wrap (AA) */
 345        movl    %eax, (%edi)             /* write 10 row pattern @ 10 row wrap adr */
 346        movl    (%edi), %ebx             /* optional read */
 347        cmpl    %ebx,%eax                /* to verify write */
 348        jnz     bad_ram                  /* this ram is bad */
 349 /*
 350  * read data @ row 12 wrap adr to determine  * banks,
 351  * and read data @ row 14 wrap adr to determine  * rows.
 352  * if data @ row 12 wrap adr is not AA, 11 or 12 we have bad RAM.
 353  * if data @ row 12 wrap == AA, we only have 2 banks, NOT 4
 354  * if data @ row 12 wrap == 11 or 12, we have 4 banks,
 355  */
 356        xorw    %di,%di                  /* value for 2 banks in DI */
 357        movl    (%esi), %ebx             /* read from 12 row wrap to check banks
 358                                          * (esi is setup from the write to row 12 wrap) */
 359        cmpl    %ebx,%eax                /* check for AA pattern  (eax holds the aa pattern) */
 360        jz      only2                    /* if pattern == AA, we only have 2 banks */
 361
 362        /* 4 banks */
 363
 364        movw    $8,%di                   /* value for 4 banks in DI (BNK_CNT bit) */
 365        cmpl    $ROW11_DATA, %ebx        /* only other legitimate values are 11 */
 366        jz      only2
 367        cmpl    $ROW12_DATA, %ebx        /* and 12 */
 368        jnz     bad_ram                  /* its bad if not 11 or 12! */
 369
 370        /* fall through */
 371only2:
 372 /*
 373  * validate row mask
 374  */
 375        movl    $ROW14_ADR, %esi         /* set address back to max row wrap addr */
 376        movl    (%esi), %eax             /* read actual number of rows @ row14 adr */
 377
 378        cmpl    $ROW11_DATA, %eax        /* row must be greater than 11 pattern */
 379        jb      bad_ram
 380
 381        cmpl    $ROW14_DATA, %eax        /* and row must be less than 14 pattern */
 382        ja      bad_ram
 383
 384        cmpb    %ah,%al                  /* verify all 4 bytes of dword same */
 385        jnz     bad_ram
 386        movl    %eax,%ebx
 387        shrl    $16,%ebx
 388        cmpw    %bx,%ax
 389        jnz     bad_ram
 390 /*
 391  * read col 11 wrap adr for real column data value
 392  */
 393        movl    $COL11_ADR, %esi         /* set address to max col (11) wrap addr */
 394        movl    (%esi), %eax             /* read real col number at max col adr */
 395 /*
 396  * validate column data
 397  */
 398        cmpl    $COL08_DATA, %eax        /* col must be greater than 8 pattern */
 399        jb      bad_ram
 400
 401        cmpl    $COL11_DATA, %eax        /* and row must be less than 11 pattern */
 402        ja      bad_ram
 403
 404        subl    $COL08_DATA, %eax        /* normalize column data to zero */
 405        jc      bad_ram
 406        cmpb    %ah,%al                  /* verify all 4 bytes of dword equal */
 407        jnz     bad_ram
 408        movl    %eax,%edx
 409        shrl    $16,%edx
 410        cmpw    %dx,%ax
 411        jnz     bad_ram
 412 /*
 413  * merge bank and col data together
 414  */
 415        addw    %di,%dx                  /* merge of bank and col info in dl */
 416 /*
 417  * fix ending addr mask based upon col info
 418  */
 419        movb    $3,%al
 420        subb    %dh,%al                  /* dh contains the overflow from the bank/col merge  */
 421        movb    %bl,%dh                  /* bl contains the row mask (aa, 07, 0f, 1f or 3f) */
 422        xchgw   %cx,%ax                  /* cx = ax = 3 or 2 depending on 2 or 4 bank device */
 423        shrb    %cl,%dh                  /*  */
 424        incb    %dh                      /* ending addr is 1 greater than real end */
 425        xchgw   %cx,%ax                  /* cx is bank number again */
 426 /*
 427  * issue all banks precharge
 428  */
 429bad_reint:
 430        movl    $DRCCTL, %esi            /* setup DRAM control register with */
 431        movb    $0x2,%al                 /* All banks precharge */
 432        movb     %al, (%esi)
 433        movl    $CACHELINESZ, %esi       /* address to init read buffer */
 434        movw     %ax, (%esi)
 435
 436 /*
 437  * update ENDING ADDRESS REGISTER
 438  */
 439        movl    $DRCBENDADR, %edi        /* DRAM ending address register */
 440        movl    %ecx,%ebx
 441        addl    %ebx, %edi
 442        movb    %dh, (%edi)
 443 /*
 444  * update CONFIG REGISTER
 445  */
 446        xorb    %dh,%dh
 447        movw    $0x00f,%bx
 448        movw    %cx,%ax
 449        shlw    $2,%ax
 450        xchgw   %cx,%ax
 451        shlw    %cl,%dx
 452        shlw    %cl,%bx
 453        notw    %bx
 454        xchgw   %cx,%ax
 455        movl    $DRCCFG, %edi
 456        mov     (%edi), %ax
 457        andw    %bx,%ax
 458        orw     %dx,%ax
 459        movw    %ax, (%edi)
 460        jcxz    cleanup
 461
 462        decw    %cx
 463        movl    %ecx,%ebx
 464        movl    $DRCBENDADR, %edi        /* DRAM ending address register */
 465        movb    $0xff,%al
 466        addl    %ebx, %edi
 467        movb    %al, (%edi)
 468 /*
 469  * set control register to NORMAL mode
 470  */
 471        movl    $DRCCTL, %esi            /* setup DRAM control register with */
 472        movb    $0x0,%al                 /* Normal mode value */
 473        movb    %al, (%esi)
 474        movl    $CACHELINESZ, %esi       /* address to init read buffer */
 475        movw    %ax, (%esi)
 476        jmp     nextbank
 477
 478cleanup:
 479        movl    $DRCBENDADR, %edi        /* DRAM ending address register  */
 480        movw    $4,%cx
 481        xorw    %ax,%ax
 482cleanuplp:
 483        movb   (%edi), %al
 484        orb     %al,%al
 485        jz      emptybank
 486
 487        addb    %ah,%al
 488        jns     nottoomuch
 489
 490        movb    $0x7f,%al
 491nottoomuch:
 492        movb    %al,%ah
 493        orb     $0x80,%al
 494        movb    %al, (%edi)
 495emptybank:
 496        incl    %edi
 497        loop    cleanuplp
 498
 499#if defined CONFIG_SYS_SDRAM_DRCTMCTL
 500        /* just have your hardware desinger _GIVE_ you what you need here! */
 501        movl    $DRCTMCTL, %edi
 502        movb    $CONFIG_SYS_SDRAM_DRCTMCTL,%al
 503        movb    %al, (%edi)
 504#else
 505#if defined(CONFIG_SYS_SDRAM_CAS_LATENCY_2T) || defined(CONFIG_SYS_SDRAM_CAS_LATENCY_3T)
 506        /* set the CAS latency now since it is hard to do
 507         * when we run from the RAM */
 508        movl    $DRCTMCTL, %edi          /* DRAM timing register */
 509        movb    (%edi), %al
 510#ifdef CONFIG_SYS_SDRAM_CAS_LATENCY_2T
 511        andb    $0xef, %al
 512#endif
 513#ifdef CONFIG_SYS_SDRAM_CAS_LATENCY_3T
 514        orb     $0x10, %al
 515#endif
 516        movb    %al, (%edi)
 517#endif
 518#endif
 519        movl    $DRCCTL, %edi            /* DRAM Control register */
 520        movb    $0x3,%al                 /* Load mode register cmd */
 521        movb     %al, (%edi)
 522        movw     %ax, (%esi)
 523
 524
 525        movl    $DRCCTL, %edi            /* DRAM Control register */
 526        movb    $0x18,%al                /*  Enable refresh and NORMAL mode */
 527        movb    %al, (%edi)
 528
 529        jmp     dram_done
 530
 531bad_ram:
 532        xorl    %edx,%edx
 533        xorl    %edi,%edi
 534        jmp     bad_reint
 535
 536dram_done:
 537
 538#if CONFIG_SYS_SDRAM_ECC_ENABLE
 539        /*
 540         * We are in the middle of an existing 'call' - Need to store the
 541         * existing return address before making another 'call'
 542         */
 543        movl    %ebp, %ebx
 544
 545        /* Get the memory size */
 546        movl    $init_ecc, %ebp
 547        jmpl    get_mem_size
 548
 549init_ecc:
 550        /* Restore the orignal return address */
 551        movl    %ebx, %ebp
 552
 553        /* A nominal memory test: just a byte at each address line */
 554        movl    %eax, %ecx
 555        shrl    $0x1, %ecx
 556        movl    $0x1, %edi
 557memtest0:
 558        movb    $0xa5, (%edi)
 559        cmpb    $0xa5, (%edi)
 560        jne     out
 561        shrl    $1, %ecx
 562        andl    %ecx,%ecx
 563        jz      set_ecc
 564        shll    $1, %edi
 565        jmp     memtest0
 566
 567set_ecc:
 568        /* clear all ram with a memset */
 569        movl    %eax, %ecx
 570        xorl    %esi, %esi
 571        xorl    %edi, %edi
 572        xorl    %eax, %eax
 573        shrl    $2, %ecx
 574        cld
 575        rep     stosl
 576                        /* enable read, write buffers */
 577        movb    $0x11, %al
 578        movl    $DBCTL, %edi
 579        movb    %al, (%edi)
 580                        /* enable NMI mapping for ECC */
 581        movl    $ECCINT, %edi
 582        mov     $0x10, %al
 583        movb    %al, (%edi)
 584                        /* Turn on ECC */
 585        movl    $ECCCTL, %edi
 586        mov     $0x05, %al
 587        movb    %al, (%edi)
 588#endif
 589
 590out:
 591        jmp     *%ebp
 592
 593/*
 594 * Read and decode the sc520 DRCBENDADR MMCR and return the number of
 595 * available ram bytes in %eax
 596 */
 597.globl get_mem_size
 598get_mem_size:
 599        movl    $DRCBENDADR, %edi        /* DRAM ending address register  */
 600
 601bank0:  movl    (%edi), %eax
 602        movl    %eax, %ecx
 603        andl    $0x00000080, %ecx
 604        jz      bank1
 605        andl    $0x0000007f, %eax
 606        shll    $22, %eax
 607        movl    %eax, %ebx
 608
 609bank1:  movl    (%edi), %eax
 610        movl    %eax, %ecx
 611        andl    $0x00008000, %ecx
 612        jz      bank2
 613        andl    $0x00007f00, %eax
 614        shll    $14, %eax
 615        movl    %eax, %ebx
 616
 617bank2:  movl    (%edi), %eax
 618        movl    %eax, %ecx
 619        andl    $0x00800000, %ecx
 620        jz      bank3
 621        andl    $0x007f0000, %eax
 622        shll    $6, %eax
 623        movl    %eax, %ebx
 624
 625bank3:  movl    (%edi), %eax
 626        movl    %eax, %ecx
 627        andl    $0x80000000, %ecx
 628        jz      done
 629        andl    $0x7f000000, %eax
 630        shrl    $2, %eax
 631        movl    %eax, %ebx
 632
 633done:
 634        movl    %ebx, %eax
 635        jmp     *%ebp
 636