/* This file is copyright Galileo, I assume.
 * it was lifted from the early init code in Dink32
 * Small modifications (c) 2001, Josh Huber <huber@mclx.com> */
	
#include <config.h>
#include <mpc74xx.h>
#include "version.h"

#include <ppc_asm.tmpl>
#include <ppc_defs.h>

/*******************************************************************************

*
* sdramAutoConfig - SDRAM auto configuration.
*
* The SDRAM auto configuration feature is consist of two parts:
* 1) SDRAM width detection and bank parameters setting (Assembly code)
* 2) SDRAM address decoding and PCI address decoding (C code)
* This routine detects the width of the SDRAM installed in the board slots.
* This function detect all Sdram types: 16, 64, 128Mbit.
* The width of SDRAM slot 0 is stored in GT register 810.
* The width of SDRAM slot 1 is stored in GT register 814.
* The GT register 810 and 814, which is DMA register, are zero by default thus
* they are used for data storing. This SDRAM width information is retrieved
* by the C code part and used for the rest of the SDRAM initialization (PCI
* base address configuration registers and SDRAM decode registers)
*
*/

// ---------- GT defenitions --------------------------------------------
#define		INTERNAL_BASE 	0x1400
#define         CPU_CONF        0x0
#define 	SDRAM_CNFG    	0x448
#define 	SDRAM_PARA0    	0x44c
#define 	SDRAM_PARA1    	0x450
#define 	SDRAM_PARA2    	0x454
#define 	SDRAM_PARA3    	0x458
#define 	BURST_MODE     	0x478
#define 	SDRAM_MODE     	0x474
#define 	GT_DEV0_PAR    	0x45c
#define 	GT_DEV1_PAR    	0x460
#define 	GT_DEV2_PAR    	0x464
#define 	GT_DEV3_PAR    	0x468
#define 	GT_BOOT_PAR    	0x46c
#define 	BOOTCS_P_LO	0x38
#define 	BOOTCS_P_HI	0x40
#define 	BOOTCS_D_LO	0x440
#define 	BOOTCS_D_HI	0x444
#define		PCI1_MEM1_LO	0xb0
#define		PCI1_MEM1_HI	0xb8
#define 	BOOT_BASE	0xfff0
#define 	CPU_CONFIG	0x0
#define 	TIMER_COUNT0	0x850
#define 	T_C_CONTROL	0x864
#define         SCS1_0_LOW      0x008
#define         SCS1_0_HIGH     0x010
#define         SCS3_2_LOW      0x018
#define         SCS3_2_HIGH     0x020
#define         SCS1_LOW        0x208
#define         SCS1_HIGH       0x210
#define         SCS3_LOW        0x218
#define         SCS3_HIGH       0x220
				
				
#define         PCI_1_IO_LOW    0x90
#define         PCI_1_IO_HIGH   0x98
#define         PCI_1_MEM0_LOW  0xa0
#define         PCI_1_MEM0_HIGH 0xa8
#define         PCI_1_MEM1_LOW  0xb0
#define         PCI_1_MEM1_HIGH 0xb8
#define         PCI_0_TIME_OUT  0xC04
#define         PCI_1_TIME_OUT  0xC84
#define         PCI_0_BAR_EN    0xc3c
#define         PCI_1_BAR_EN    0xcbc
				
#define         MPP_CNTRL0      0xf000
#define         MPP_CNTRL1      0xf004
#define         MPP_CNTRL2      0xf008
#define         MPP_CNTRL3      0xf00c
#define         SER_PORTS_MUX   0xf010
#define         GPP_LEVEL_CNTRL 0xf110

#define         SCS_0_LOW_DECODE_ADDRESS   0x008               
#define         SCS_0_HIGH_DECODE_ADDRESS  0x010               
#define         SCS_1_LOW_DECODE_ADDRESS   0x208               
#define         SCS_1_HIGH_DECODE_ADDRESS  0x210               
#define         SCS_2_LOW_DECODE_ADDRESS   0x018              
#define         SCS_2_HIGH_DECODE_ADDRESS  0x020              
#define         SCS_3_LOW_DECODE_ADDRESS   0x218               
#define         SCS_3_HIGH_DECODE_ADDRESS  0x220               
#define         SDRAM_BANK0PARAMETERS      0x44C
#define         SDRAM_BANK2PARAMETERS      0x454         
#define         SDRAM_ADDRESS_DECODE       0x47C              
#define         SDRAM_OPERATION_MODE       0x474
// -----------------------------------------------------------------------

	/* r3: contains the NHR bit from HID0
	 * we should use this to NOT reset the SDRAM on a soft reboot
	 * [josh] XXX */
	.globl gal_low_init
gal_low_init:
	xor	r0, r0, r0

        /* SDRAM configuration - refresh_count=0x200,
                                 phisical interleaving ensable,
                                 virtual interleaving enable,
                                 non staggered refresh,
                                 standard SDRAM */
	mflr	r9 /* save away link register */
	addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, SDRAM_CNFG             
        addis	r6, r0, 0xd8e1
        ori	r6, r6, 0x0200
        lis     r7, 0x0
#ifdef REG
        lis     r7, 0x2
#endif
#ifdef HVL
        lis     r7, 0x8
#endif        
        or      r6, r6, r7
        stwbrx  r6, 0, (r5)                     // Store
	sync

_DIMM0:

     /* opening SCS[0] */
        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5, SCS1_0_LOW /* r5 holds the SCS[0] Low decode Address */
        xor     r6, r6, r6                      /* r6 <= 0 */
        stwbrx  r6, 0, (r5)                     /* ( 0x14000008 ) <= 0x0 */

        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5,SCS_0_HIGH_DECODE_ADDRESS /* r5 holds the SCS[0] High decode Address */
        xor     r6, r6, r6                      /* r6 <= 0 */
        ori     r6, r6, 0x00ff                  /* r6 <= 0xff */
        stwbrx  r6, 0, (r5)                     /* ( 0x14000010 ) <=   0xff */

     /* closing SCS[1] */
        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5, SCS_1_LOW_DECODE_ADDRESS /* r5 holds the SCS[1] Low decode Address */
        xor     r6, r6, r6                      /* r6 <= 0 */
        ori    r6, r0, 0xffff                  /* r6 <= 0x0000.07ff */
        stwbrx  r6, 0, (r5)                     /* ( 0x14000208 ) <=   0x7ff */

        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5,SCS_1_HIGH_DECODE_ADDRESS /* r5 holds the SCS[1] High decode Address */
        xor     r6, r6, r6                      /* r6 <= 0 */
        stwbrx  r6, 0, (r5)                     /* ( 0x14000210 ) <= 0x0 */

     /* closing SCS[2] */
        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5, SCS_2_LOW_DECODE_ADDRESS /* r5 holds the SCS[2]   Low decode Address */
        xor     r6, r6, r6                      /* r6 <= 0 */
        ori    r6, r0, 0xffff                  /* r6 <= 0x0000.ffff */
        stwbrx  r6, 0, (r5)                     /* ( 0x14000018 ) <=     0xffff */

        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5,SCS_2_HIGH_DECODE_ADDRESS /* r5 holds the SCS[2]   High decode Address */
        xor     r6, r6, r6                      /* r6 <= 0 */
        stwbrx  r6, 0, (r5)                     /* ( 0x14000020 ) <= 0x0 */

     /* closing SCS[3] */
        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5, SCS_3_LOW_DECODE_ADDRESS /* r5 holds the SCS[3] Low decode Address */
        xor     r6, r6, r6                      /* r6 <= 0 */
        ori    r6, r0, 0xffff                  /* r6 <= 0x0000.0ffff */
        stwbrx  r6, 0, (r5)                     /* ( 0x14000218 ) <= 0xffff */

        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5,SCS_3_HIGH_DECODE_ADDRESS /* r5 holds the SCS[3] High decode Address */
        xor     r6, r6, r6                      /* r6 <= 0 */
        stwbrx  r6, 0, (r5)                     /* ( 0x14000220 ) <= 0x0 */


      /* configurate bank0 to 256Mbit */
        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5, r5, SDRAM_BANK0PARAMETERS   /* r5 holds the Bank0 parametrs */
        lis     r6, 0x0000                      /* r6 <= 0x0 */
        ori     r6, r6, 0xc000                  /* r6 <= 0xc000 */
        stwbrx  r6, 0, (r5)                     /* ( 0x1400044c ) <= 0x0000.c000 */

      /* configuration Adrress decode 2 */
        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5, SDRAM_ADDRESS_DECODE     /* r5 holds the Sdram Address Decode */
        xor     r6, r6, r6                      /* r6 <= 0x0 */
        ori     r6, r6, 0x2                     /* r6 <= 0x2 */
        stwbrx  r6, 0, (r5)                     /* ( 0x1400047c ) <= 0x2 */

      /* configuration Sdram Operation Mode */
        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5, SDRAM_OPERATION_MODE     /* r5 holds the Sdram operation Mode */
        xor     r6, r6, r6                      /* r6 <= 0x0 */
        ori     r6, r6, 0x3                     /* r6 <= 0x3 */
        stwbrx  r6, 0, (r5)                     /* ( 0x14000474 ) <= 0x3 */

      /* A dummy writting */
        sync
        xor     r6, r6, r6                      /* r6 <= 0x0 */
        stwbrx  r6, 0, (r0)                     /* ( 0x0 ) <= 0x0 */

        sync
        xor     r5, r5, r5
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5, SDRAM_OPERATION_MODE     /* r5 holds the Sdram operation Mode */
        xor     r6, r6, r6                      /* r6 <= 0 */
        stwbrx  r6, 0, (r5)                     /* ( 0x14000474 ) <= 0x0 */

      /* write to address 0x2000000 and check if 0x0 is beeing written to */
        xor r5,r5,r5
        xor r4,r4,r4
        addis   r5, r0, 0x0                     /* r5 <= 0x0000.0000 */
        addis   r4, r0, 0x0
        ori     r4, r4, 0x10                    /* r4 <= 0x00000010 */

_1:     stwbrx  r0, 0, (r5)                     /* ( r5 ) <= 0x0 */
        addi    r5,r5,0x4                       /* r5 <= r5 + 4 */
        cmp     0, 1, r4, r5
        bne     _1                              /* If not equal, return. */

        /* the address should activate Dadr12 */
        xor r5,r5,r5
        addis   r5, r0, 0x0200
        lis     r6, 0x1111
        ori     r6, r6, 0x1111                  /* r6 <= 0x1111.1111 */
        stwbrx  r6, 0, (r5)                     /* ( 0x0200.0000 ) <= 0x1111.1111 */
        xor r5,r5,r5
        xor r4,r4,r4
        ori     r5, r0, 0x0010                  /* r5 <= 0x0000.0010 */
        ori     r4, r0, 0x1000                  /* r4 <= 0x0000.0100 */
        lis     r6, 0x2222
        ori     r6, r6, 0x2222                  /* r6 <= 0x2222.2222 */

_2:     stwbrx  r6, 0, (r5)                     /* ( r5 ) <= 0x2222.2222   */
        addi    r5,r5,0x4                       /* r5 <= r5 + 4 */
        cmp     0, 1, r4, r5                          /* Compare with  default value */
        bne     _2                              /* If not equal, then  return */
        sync

        /* check address 0x0 for duplicating. */
        xor     r6,r6,r6
        addis   r6, r0, 0x1111
        ori     r6, r6, 0x1111                  /* r6 <= 0x1111.1111 */
        lwbrx   r4, 0, (r0)                     /* r4 <= ( 0x0000.0000)*/
        cmp     0, 1, r4, r6                          /* if equal sduplication had occurred. */
        bne     _256Mbit                        /* if not equal continue jump to  _256Mbit */
        sync                                    /* recommended after  branch */

/* write to address 0x0000.1000 and checking duplication on adress 0 */


        xor     r6, r6, r6                      /* r6 <= 0x0 */
        xor     r5, r5, r5                      /* r5 <= 0x0 */
        xor     r4, r4, r4                      /* r4 <= 0x0 */
        ori     r4, r4,0x10                     /* r4 <= 0x00000010 */


_3:     stwbrx  r6, 0, (r5)                     /* ( 0x00000000 ) <= 0x0 */
        addi    r5,r5,0x4                       /* r5 <= r5 + 4 */
        cmp     0, 1, r4, r5
        bne     _3                              /* If not equal, return. */

      /* the address should activate Bank Select1 */

        sync                                    /* recommended after branch */
        lis     r5, 0x0000
        ori     r5, r5, 0x1000                  /* r5 <= 0x0000.1000 */
        lis     r6, 0x1111
        ori     r6, r6, 0x1111                  /* r6 <= 0x1111.1111 */
        stwbrx  r6, 0, (r5)                     /* ( 0x0000.1000 ) <= 0x1111.1111 */

        sync
        lis     r5, 0x0
        ori     r5, r5, 0x0010                  /* r5 <= 0x0000.0010 */
        lis     r4, 0x0
        ori     r4, r4, 0x0100                  /* r4 <= 0x0000.0100 */
        lis     r6, 0x2222
        ori     r6, r6, 0x2222                  /* r6 <= 0x2222.2222 */

_4:     stwbrx  r6, 0, (r5)                     /* ( 0x00000010 ) <=  0x2222.2222   */
        addi    r5,r5,0x4                       /* r5 <= r5 + 4 */
        cmp     0, 1, r4, r5                          /* Compare with default value */
        bne     _4                              /* If not equal, then return */

      /* check address 0x0 for duplicating. */

        sync
        xor     r4, r4, r4                      /* r4 <= 0x0 */
        xor     r5, r5, r5                      /* r5 <= 0x0 */
        lis     r6, 0x1111
        ori     r6, r6, 0x1111                  /* r6 <= 0x1111.1111 */
        lwbrx   r4, 0, (r5)                     /* r4 <= ( 0x0000.0000) */
        cmp     0, 1, r4, r6                          /* if equals      duplication had occurred. */
        beq     _16Mbit                         /* if equal jump to _16Mbit */
        sync

        /* Write to address 0x0800.0000 and check duplication on address0x00000000 */
        addis   r5,r0,0x0                       /* r5 <= 0x0 */
        addis   r4,r0,0x0
        ori     r4,r4,0x10                      /* r4 <= 0x10 */

_5:     stwbrx  r0, 0, (r5)                     /* ( r5 ) <= 0x0 */
        addi    r5,r5,0x4                       /* r5 <= r5 + 4 */
        cmp     0, 1, r4, r5                          /* Compare with default value */
        bne     _5                              /* If not equal, then return */
        sync

        /* The address should activate Dadr9 which on the column cycle*/
        /* is in active with 64 Mbit device */
        xor     r5, r5, r5
        xor     r6, r6, r6
        addis   r5, r0, 0x0800                  /* r5 <= 0x0800.0000 */
        lis     r6, 0x1111
        ori     r6, r6, 0x1111                  /* r6 <= 0x1111.1111 */
        stwbrx  r6, 0, (r5)                     /* ( 0x0800.0000 ) <= 0x1111.1111 */
        xor     r5,r5,r5
        xor     r4,r4,r4
        ori     r5, r0, 0x10                    /* r5 <= 0x10 */
        ori     r4, r0, 0x100                   /* r4 <= 0x100 */
        lis     r6, 0x2222
        ori     r6, r6, 0x2222                  /* r6 <= 0x2222.2222 */

_6:     stwbrx  r6, 0, (r5)                     /* ( r5 ) <= 0x0 */
        addi    r5,r5,0x4                       /* r5 <= r5 + 4 */
        cmp     0, 1, r4, r5                          /* Compare with default value */
        bne     _6                              /* If not equal, then return */
        sync

        lis     r6, 0x1111
        ori     r6, r6, 0x1111                  /* r6 <= 0x1111.1111 */
        lwbrx   r4, 0, (r0)                     /* r4 <= ( 0x0000.0000) */
        cmp     0, 1, r4, r6                          /* if equals duplication had occurred. */
        beq     _64Mbit                         /* if equal jump to _64Mbit */
        sync
        b       _128Mbit                        /* jump to _128Mbit */
        
_16Mbit:        // if we got here a 16Mbit memory type is present at bank 0 (and maybe in bank 1)
        lis     r5, 0x1400
        ori     r5, r5, 0x810                   // r5 <= 0x1400.0810
        ori     r6, r0, 16                      // r6 <= 16
        stwbrx  r6, 0, (r5)                     // ( 0x1400.0810 ) <= 16
        lis     r5, 0x000f
        ori     r5, r0, 0x4000                  // in _DIMM1: 0x44c <= 0x000f4000
        b       _DIMM1
        
_64Mbit:
        lis   r5, 0x1400
        ori     r5, r5, 0x810                   // r5 <= 0x1400.0810
        ori     r6, r0, 64                      // r6 <= 64
        stwbrx  r6, 0, (r5)                     // ( 0x1400.0810 ) <= 64
        lis     r5, 0x000f
        ori     r5, r0, 0x8000                  // in _DIMM1: 0x44c <= 0x000f8000
        b       _DIMM1

_128Mbit:        
        lis     r5, 0x1400
        ori     r5, r5, 0x810                   // r5 <= 0x1400.0810
        ori     r6, r0, 128                     // r6 <= 128
        stwbrx  r6, 0, (r5)                     // ( 0x1400.0810 ) <= 128
        lis     r5, 0x000f
        ori     r5, r0, 0x8000                  // in _DIMM1: 0x44c <= 0x000f8000
        b       _DIMM1

_256Mbit:        
        lis     r5, 0x1400
        ori     r5, r5, 0x810                   // r5 <= 0x1400.0810
        ori     r6, r0, 256                     // r6 <= 256
        lis     r5, 0x000f
        stwbrx  r6, 0, (r5)                     // ( 0x1400.0810 ) <= 128
        ori     r5, r0, 0xc000                  // in _DIMM1: 0x44c <= 0x000fc000
      
      
      // this section is the same as _DIMM0 it detect the type on dimm1

_DIMM1:
        addis r4, r0, INTERNAL_BASE
        ori     r4, r4, SDRAM_BANK0PARAMETERS   /* r4 holds the Bank0 parametrs register address */
        stwbrx  r5, 0, (r4)                     /* update register 0x44c due to its type Bank0 */
        addi    r4, r4, 0x4
        stwbrx  r5, 0, (r4)                     /* update register 0x450 due to its type Bank1 */

     /* Detect whether we have a 16,64,128 or 256 Mbit SDRAM on DIMM1 */

     /* Extend bank2 to 0x10000000 and Close banks 0,1 and 3      */
     /* opening SCS[2] */
        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5, SCS_2_LOW_DECODE_ADDRESS /* r5 holds the SCS[2] Low decode Address */
        ori     r6, r0, 0xff                    /* r6 <= 0xffff */
        stwbrx  r0, 0, (r5)                     /* ( 0x14000018 ) <= 0x0 */
        addi   r5, r5, 0x8
        stwbrx  r6, 0, (r5)                     /* ( 0x14000020 ) <= 0xff */

     /* closing SCS[0] */
        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5, SCS_0_LOW_DECODE_ADDRESS /* r5 holds the SCS[0] Low decode Address  */
        ori     r6, r0, 0xffff                  /* r6 <= 0xffff */
        stwbrx  r6, 0, (r5)                     /* ( 0x14000008 ) <= 0xffff */
        addi   r5, r5, 0x8
        stwbrx  r0, 0, (r5)                     /* ( 0x14000010 ) <= 0x0 */

     /* closing SCS[1] */
        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5, SCS_1_LOW_DECODE_ADDRESS /* r5 holds the SCS[1] Low decode Address */
        ori     r6, r0, 0xffff                  /* r6 <= 0xffff */
        stwbrx  r6, 0, (r5)                     /* ( 0x14000208 ) <=  0xffff */
        addi   r5, r5, 0x8
        stwbrx  r0, 0, (r5)                     /* ( 0x14000210 ) <= 0x0 */                                                                       
     /* closing SCS[3] */
        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5, SCS_3_LOW_DECODE_ADDRESS /* r5 holds the SCS[3] Low decode Address */
        ori     r6, r0, 0xffff                  /* r6 <= 0xffff */
        stwbrx  r6, 0, (r5)                     /* ( 0x14000218 ) <= 0xffff */
        addi   r5, r5, 0x8
        stwbrx  r0, 0, (r5)                     /* ( 0x14000220 ) <= 0x0 */

      /* configurate bank2 to 256Mbit */
        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5, r5, SDRAM_BANK2PARAMETERS   /* r5 holds the Bank2 parametrs */
        lis     r6, 0x0000                      /* r6 <= 0x0 */
        ori     r6, r6, 0xc000                  /* r6 <= 0xc000 */
        stwbrx  r6, 0, (r5)                     /* ( 0x1400044c ) <=  0x0000.c000 */

      /* configuration Address decode 2 */
        sync
        addis r5, r0, INTERNAL_BASE
        ori     r5,r5, SDRAM_ADDRESS_DECODE     /* r5 holds the Sdram Address Decode */
        xor     r6, r6, r6                      /* r6 <= 0x0 */
        ori     r6, r6, 0x2                     /* r6 <= 0x2 */
        stwbrx  r6, 0, (r5)                     /* ( 0x1400047c ) <= 0x2 */

      /* write to address 0x0200.0000 and check if 0x0 is beeing written too */
        xor r5,r5,r5
        xor r4,r4,r4
        addis   r5, r0, 0x0                     /* r5 <= 0x0000.0000 */
        addis   r4, r0, 0x0
        ori     r4, r4, 0x10                    /* r4 <= 0x00000010 */

_1_1:   stwbrx  r0, 0, (r5)                     /* ( r5 ) <= 0x0 */
        addi    r5,r5,0x4                       /* r5 <= r5 + 4 */
        cmp     0, 1, r4, r5
        bne     _1_1                            /* If not equal, return. */

        /* the address should activate Dadr12 */
        xor r5,r5,r5
        addis   r5, r0, 0x0200
        lis     r6, 0x1111
        ori     r6, r6, 0x1111                  /* r6 <= 0x1111.1111 */
        stwbrx  r6, 0, (r5)                     /* ( 0x0200.0000 ) <= 0x1111.1111 */
        xor r5,r5,r5
        xor r4,r4,r4
        ori     r5, r0, 0x0010                  /* r5 <= 0x0000.0010 */
        ori     r4, r0, 0x1000                  /* r4 <= 0x0000.0100 */
        lis     r6, 0x2222
        ori     r6, r6, 0x2222                  /* r6 <= 0x2222.2222 */

_2_1:   stwbrx  r6, 0, (r5)                     /* ( r5 ) <= 0x2222.2222   */
        addi    r5,r5,0x4                       /* r5 <= r5 + 4 */
        cmp     0, 1, r4, r5                          /* Compare with default value */
        bne     _2_1                            /* If not equal, then return */
        sync

        /* check address 0x0 for duplicating. */
        xor     r6,r6,r6
        addis   r6, r0, 0x1111
        ori     r6, r6, 0x1111                  /* r6 <= 0x1111.1111 */
        lwbrx   r4, 0, (r0)                     /* r4 <= ( 0x0000.0000) */
        cmp     0, 1, r4, r6                          /* if equal s     duplication had occurred. */
        bne     _256Mbit1                       /* if not equal continue jump to  _256Mbit1 */
        sync                                    /* recommended after branch */

      /* write to address 0x0000.1000 and checking duplication on adress 0 */
        xor     r6, r6, r6                      /* r6 <= 0x0 */
        xor     r5, r5, r5                      /* r5 <= 0x0 */
        xor     r4, r4, r4                      /* r4 <= 0x0 */
        ori     r4, r4,0x10                     /* r4 <= 0x00000010 */

_3_1:   stwbrx  r6, 0, (r5)                     /* ( 0x00000000 ) <= 0x0 */
        addi    r5,r5,0x4                       /* r5 <= r5 + 4 */
        cmp     0, 1, r4, r5
        bne     _3_1                            /* If not equal, return. */

      /* the address should activate Bank Select1 */

        sync                                    /* recommended after branch */
        lis     r5, 0x0000
        ori     r5, r5, 0x1000                  /* r5 <= 0x0000.1000 */
        lis     r6, 0x1111
        ori     r6, r6, 0x1111                  /* r6 <= 0x1111.1111 */
        stwbrx  r6, 0, (r5)                     /* ( 0x0000.1000 ) <= 0x1111.1111 */

        sync
        lis     r5, 0x0
        ori     r5, r5, 0x0010                  /* r5 <= 0x0000.0010 */
        lis     r4, 0x0
        ori     r4, r4, 0x0100                  /* r4 <= 0x0000.0100 */
        lis     r6, 0x2222
        ori     r6, r6, 0x2222                  /* r6 <= 0x2222.2222 */

_4_1:   stwbrx  r6, 0, (r5)                     /* ( 0x00000010 ) <= 0x2222.2222   */
        addi    r5,r5,0x4                       /* r5 <= r5 + 4 */
        cmp     0, 1, r4, r5                          /* Compare with default value */
        bne     _4_1                            /* If not equal, then return */

      /* check address 0x0 for duplicating. */

        sync
        xor     r4, r4, r4                      /* r4 <= 0x0 */
        xor     r5, r5, r5                      /* r5 <= 0x0 */
        lis     r6, 0x1111
        ori     r6, r6, 0x1111                  /* r6 <= 0x1111.1111 */
        lwbrx   r4, 0, (r5)                     /* r4 <= ( 0x0000.0000) */
        cmp     0, 1, r4, r6                          /* if equals duplication had occurred. */
        beq     _16Mbit1                        /* if equal jump to _16Mbit1 */
        sync

        /* Write to address 0x0800.0000 and check duplication on address 0x00000000 */
        addis   r5,r0,0x0                       /* r5 <= 0x0 */
        addis   r4,r0,0x0
        ori     r4,r4,0x10                      /* r4 <= 0x10 */

_5_1:   stwbrx  r0, 0, (r5)                     /* ( r5 ) <= 0x0 */
        addi    r5,r5,0x4                       /* r5 <= r5 + 4 */
        cmp     0, 1, r4, r5                          /* Compare with default value */
        bne     _5_1                            /* If not equal, then return */
        sync

        /* The address should activate Dadr9 which on the column cycle */
        /* is in active with 64 Mbit device */
        xor     r5, r5, r5
        xor     r6, r6, r6
        addis   r5, r0, 0x0800                  /* r5 <= 0x0800.0000 */
        lis     r6, 0x1111
        ori     r6, r6, 0x1111                  /* r6 <= 0x1111.1111 */
        stwbrx  r6, 0, (r5)                     /* ( 0x0800.0000 ) <=  0x1111.1111 */
        xor     r5,r5,r5
        xor     r4,r4,r4
        ori     r5, r0, 0x10                    /* r5 <= 0x10 */
        ori     r4, r0, 0x100                   /* r4 <= 0x100 */
        lis     r6, 0x2222
        ori     r6, r6, 0x2222                  /* r6 <= 0x2222.2222 */

_6_1:   stwbrx  r6, 0, (r5)                     /* ( r5 ) <= 0x0 */
        addi    r5,r5,0x4                       /* r5 <= r5 + 4 */
        cmp     0, 1, r4, r5                          /* Compare with default value */
        bne     _6_1                            /* If not equal, then return */
        sync

        lis     r6, 0x1111
        ori     r6, r6, 0x1111                  /* r6 <= 0x1111.1111 */
        lwbrx   r4, 0, (r0)                     /* r4 <= ( 0x0000.0000) */
        cmp     0, 1, r4, r6                          /* if equals duplication had occurred. */
        beq     _64Mbit1                        /* if equal jump to _64Mbit1 */
        sync
        b       _128Mbit1                       /* jump to _128Mbit1 */

_16Mbit1:        // if we got here a 16Mbit memory type is present at bank 0 (and maybe in bank 1)
        lis     r5, 0x1400
        ori     r5, r5, 0x814                   // r5 <= 0x1400814
        ori     r6, r0, 16                      // r6 <= 16
        stwbrx  r6, 0, (r5)                     // ( 0x1400.0814 ) <= 16
        lis     r5, 0x000f
        ori     r4, r0, 0x4000                  // in _init_Sdram: 0x44c <= 0x000f4000
        b       _init_Sdram
        
_64Mbit1:
        lis     r5, 0x1400
        ori     r5, r5, 0x814                   // r5 <= 0x1400814
        ori     r6, r0, 64                      // r6 <= 64
        stwbrx  r6, 0, (r5)                     // ( 0x1400.0814 ) <= 64
        lis     r5, 0x000f
        ori     r4, r0, 0x8000                  // in _init_Sdram: 0x44c <= 0x000f8000
        b       _init_Sdram

_128Mbit1:        
        lis     r5, 0x1400
        ori     r5, r5, 0x814                   // r5 <= 0x1400814
        ori     r6, r0, 128                      // r6 <= 128
        stwbrx  r6, 0, (r5)                     // ( 0x1400.0814 ) <= 128
        lis     r5, 0x000f
        ori     r4, r0, 0x8000                  // in _init_Sdram: 0x44c <= 0x000f8000
        b       _init_Sdram
        
_256Mbit1:        
        lis     r5, 0x1400
        ori     r5, r5, 0x814                   // r5 <= 0x1400814
        ori     r6, r0, 256                      // r6 <= 256
        stwbrx  r6, 0, (r5)                     // ( 0x1400.0814 ) <= 256
        lis     r5, 0x000f
        ori     r4, r0, 0xc000                  // in _init_Sdram: 0x44c <= 0x000fc000

_init_Sdram:
        lis	r5, INTERNAL_BASE
        ori     r5, r5, 0x454                   // r5 holds the Bank2 parametrs
        stwbrx  r4, 0, (r5)                     // update register 0x454 due to its type Bank2
        addi    r5, r5, 0x4
        stwbrx  r4, 0, (r5)                     // update register 0x458 due to its type Bank3
        
     // now restoring all parametrs to deafults values.
     // opening SCS[0]
        sync
	addis	r5, r0, INTERNAL_BASE
        ori     r5,r5, SCS1_0_LOW               // r5 holds the SCS[1:0] Low decode Address
        ori     r6, r0, 0xff                    // r6 <= 0xff
        stwbrx  r0, 0, (r5)                     // ( 0x14000008 ) <= 0x0
        addi    r5, r5, 0x8
        stwbrx  r6, 0, (r5)                     // ( 0x14000010 ) <= 0xff
	
     // closing SCS[1]
        sync
	addis	r5, r0, INTERNAL_BASE
        ori     r5,r5, SCS1_LOW                 // r5 holds the SCS[1:0] Low decode Address
        ori     r6, r0, 0xffff                  // r6 <= 0xffff
        stwbrx  r6, 0, (r5)                     // ( 0x14000208 ) <= 0xffff
        addi    r5, r5, 0x8
        stwbrx  r0, 0, (r5)                     // ( 0x14000210 ) <= 0x0
     
     // closing SCS[2]
        sync
	addis	r5, r0, INTERNAL_BASE
        ori     r5,r5, SCS3_2_LOW               // r5 holds the SCS[1:0] Low decode Address
        ori     r6, r0, 0xffff                  // r6 <= 0xffff
        stwbrx  r6, 0, (r5)                     // ( 0x14000008 ) <= 0xffff
        addi    r5, r5, 0x8
        stwbrx  r0, 0, (r5)                     // ( 0x14000010 ) <= 0x0
  
     // closing SCS[3]
        sync
	addis	r5, r0, INTERNAL_BASE
        ori     r5,r5, SCS3_LOW                 // r5 holds the SCS[1:0] Low decode Address
        ori     r6, r0, 0xffff                  // r6 <= 0xffff
        stwbrx  r6, 0, (r5)                     // ( 0x14000218 ) <= 0xffff
        addi    r5, r5, 0x8
        stwbrx  r0, 0, (r5)                     // ( 0x14000220 ) <= 0x0
        
// ======================  Detecting memory, Until here. ===========================       
#if 0
        /* SDRAM configuration - refresh_count=0x200,
                                 phisical interleaving disable,
                                 virtual interleaving disable,
                                 staggered refresh,
                                 standard SDRAM */
	addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, SDRAM_CNFG             
        addis	r6, r0, 0xd8e0
        ori	r6, r6, 0xc200       
        stwbrx  r6, 0, (r5)                     // Store
	sync


        /* SDRAM parameters - Bank0 */
	addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, SDRAM_PARA0             
        addis	r6, r0, 0x0000
        ori	r6, r6, 0x8000
        stwbrx  r6, 0, (r5)                     // Store
	sync
        
        /* SDRAM parameters - Bank1 */
	addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, SDRAM_PARA1             
        addis	r6, r0, 0x0000
        ori	r6, r6, 0x8000
        stwbrx  r6, 0, (r5)                     // Store
	sync
      
        /* SDRAM parameters - Bank2 */
	addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, SDRAM_PARA2             
        addis	r6, r0, 0x0000
        ori	r6, r6, 0x8000
        stwbrx  r6, 0, (r5)                     // Store
	sync
        
        /* SDRAM parameters - Bank3 */
	addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, SDRAM_PARA3             
        addis	r6, r0, 0x0000
        ori	r6, r6, 0x8000
        stwbrx  r6, 0, (r5)                     // Store
	sync

        /* configuration Sdram Operation Mode */
        sync
        addis	r5, r0, INTERNAL_BASE
        ori     r5,r5, SDRAM_MODE               // r5 holds the Sdram operation Mode
        xor     r6, r6, r6                      // r6 <= 0x0
        ori     r6, r6, 0x3                     // r6 <= 0x3
        stwbrx  r6, 0, (r5)                     // ( 0x14000474 ) <= 0x3
        
        /* A dummy write to bank0 */
        sync
        xor     r6, r6, r6                      // r6 <= 0x0
        addis   r6, r6, 0x0                     // r6 <= 0x0
        stwbrx  r0, 0, (r6)                     // ( 0x0 ) <= 0x0
        sync
        /* A dummy write to bank1 */
        sync
        xor     r6, r6, r6                      // r6 <= 0x0
        addis   r6, r6, 0x0080                  // r6 <= 0x0080.0000
        stwbrx  r0, 0, (r6)                     // ( 0x80.0000 ) <= 0x0
        sync
        /* A dummy write to bank2 */
        sync
        xor     r6, r6, r6                      // r6 <= 0x0
        addis   r6, r6, 0x0180                  // r6 <= 0x0180.0000
        stwbrx  r0, 0, (r6)                     // ( 0x180.0000 ) <= 0x0
        sync
        /* A dummy write to bank3 */
        sync
        xor     r6, r6, r6                      // r6 <= 0x0
        addis   r6, r6, 0x0200                  // r6 <= 0x0200.0000
        stwbrx  r0, 0, (r6)                     // ( 0x200.0000 ) <= 0x0
        sync
        
        /* configuration Sdram Operation Mode */
        xor     r5, r5, r5
        addis	r5, r0, INTERNAL_BASE
        ori     r5,r5, SDRAM_MODE               // r5 holds the Sdram operation Mode
        xor     r6, r6, r6                      // r6 <= 0
        stwbrx  r6, 0, (r5)                     // ( 0x14000474 ) <= 0x0
        
        /* fource 64 bit device */
	addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, 0x810             
        addis	r6, r0, 0x0
        ori	r6, r6, 64
        stwbrx  r6, 0, (r5)                     // Store
	sync
        
        /* fource 64 bit device */
	addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, 0x814             
        addis	r6, r0, 0x0
        ori	r6, r6, 64      
        stwbrx  r6, 0, (r5)                     // Store
	sync

#endif // 0
	sync

/* --\/-- GT device interface timing parameters --\/-- */
        
        /* CS0 - 32 bit SRAM-Micron MT58L256L18P1-6ns */
	addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, GT_DEV0_PAR             
        addis	r6, r0, 0xf020  
        ori	r6, r6, 0x51a9
        stwbrx  r6, 0, (r5)                     // Store
	sync

        /* CS1 - RTC-Dallas DS1501 */
	addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, GT_DEV1_PAR             
        addis	r6, r0, 0xffcf  
        ori	r6, r6, 0xffff
        stwbrx  r6, 0, (r5)                     // Store
	sync
	
        /* CS2 - UART-EXAR ST16C2552 */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, GT_DEV2_PAR             
        addis	r6, r0, 0xf005
        ori	r6, r6, 0x9bd4       
        stwbrx  r6, 0, (r5)                     // Store
	sync

        /* CS3 and BootCS width detection */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, GT_BOOT_PAR             
        lwbrx	r6,0,r5
        andis.  r6,r6,0x0030
        cmpi	0,0,r6,0x0
        bne     boot_32_bit

        /* CS3 - 32bit Flash-Intel 28F640J3A-120ns */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, GT_DEV3_PAR             
        addis	r6, r0, 0xf4a8
        ori	r6, r6, 0x241c              	
        stwbrx  r6, 0, (r5)                     // Store
	sync
        
        /* BootCS - 8bit Flash-AMD AM29LV040B-120ns */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, GT_BOOT_PAR             
        addis	r6, r0, 0xf00b
        ori	r6, r6, 0x5e7c              	
        stwbrx  r6, 0, (r5)                     // Store
	sync
	b	cont_init
	sync

#if 1
boot_32_bit:
        /* BootCS - 32bit Flash-Intel 28F640J3A-120ns */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, GT_BOOT_PAR             
        addis	r6, r0, 0xf4a8
        ori	r6, r6, 0x241c              	
        stwbrx  r6, 0, (r5)                     // Store
	sync
        
        /* CS3 - 8bit Flash-AMD AM29LV040B-120ns */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, GT_DEV3_PAR             
        addis	r6, r0, 0xf00b  
        ori	r6, r6, 0x5e7c                	
        stwbrx  r6, 0, (r5)                     // Store
	sync

/* --/\-- GT devcie interface timing parameters --/\-- */

/* --\/------ GT CPU interface parameters --------\/-- */
#define RdOOO
#define DP
#define AP
#define AACK_DELAY
#define Pipeline
#define TA_DELAY
cont_init:        
        /* CPU Configuration register */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, CPU_CONF             
        lwbrx   r6, 0, (r5)
#ifdef  RdOOO
        lis     r7, 0x0001
        or	r6, r6, r7			// Read Out Of Order enable
#else
        addis   r7, r0, 0xfffe
        ori     r7, r7, 0xffff
        and     r6, r6, r7
#endif
#ifdef  DP
        lis     r7, 0x0008
        or	r6, r6, r7			// Data Parity enable
#else
        addis   r7, r0, 0xfff7
        ori     r7, r7, 0xffff
        and     r6, r6, r7
#endif
#ifdef  AP
        lis     r7, 0x0400
        or	r6, r6, r7			// Address Parity enable
#else
        addis   r7, r0, 0xfbff
        ori     r7, r7, 0xffff
        and     r6, r6, r7
#endif
#ifdef  AACK_DELAY                
        ori	r6, r6, 0x0800              	// turn on AACK# delay
#else        
        addis   r7, r0, 0xffff
        ori     r7, r7, 0xf7ff
        and     r6, r6, r7
#endif
#ifdef Pipeline
        ori     r6, r6, 0x2000                  // Pipeline enable
#endif
#ifdef  TA_DELAY                
        ori	r6, r6, 0x8000              	// turn on TA# delay
#else        
        addis   r7, r0, 0xffff
        ori     r7, r7, 0x7fff
        and     r6, r6, r7
#endif        
        stwbrx  r6, 0, (r5)                     // Store
	sync

#if 0
	/* -albert- */
	/* set up register 0x488 */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, 0x488
	addis	r6, r0, 0xD8E8
	ori	r6, r6, 0x4200
	stwbrx	r6, 0, (r5)
#endif

        /* CPU Master Control register */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, 0x160             
        lwbrx   r6, 0, (r5)
        
        mfspr	r4, PVR
	srawi	r4,r4,16
        cmpi	0,0,r4, 0xc	 // 7400?
	bne	master_60x
        sync
        ori     r6, r6, 0x3000   // 
        stwbrx   r6, 0, (r5)     // (0x14000160) <= (0x14000160) | 0x3000
        b       cpu_interface_end
        sync

master_60x:
        lis     r8, 0xffff
        ori     r8, r8, 0xcfff
        and     r6, r6, r8       // 
        stwbrx  r6, 0, (r5)      // (0x14000160) <= (0x14000160) | 0xffffcfff        

cpu_interface_end:
/* --/\------ GT CPU interface parameters --------/\-- */
	
/* --\/------ GT PCI interface parameters --------\/-- */
        /* TimeOut 0/1 (PCI_0) */ 
        xor     r5,r5,r5
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, PCI_0_TIME_OUT          // r5 = 0x14000C04   
        xor     r6,r6,r6
        //addis	r6, r0, 0x00ff			 
        ori	r6, r6, 0xffff              	// r6 = 0x00ffffff
        stwbrx  r6, 0, (r5)                     // (0x14000C04) <=  0x0000ffff
        
        /* TimeOut 0/1 (PCI_1) */
        xor     r5,r5,r5
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, PCI_1_TIME_OUT          // r5 = 0x14000C84   
        xor     r6,r6,r6
        //addis	r6, r0, 0x00ff			 
        ori	r6, r6, 0xffff              	// r6 = 0x00ffffff
        stwbrx  r6, 0, (r5)                     // (0x14000C84) <=  0x0000ffff

        /* pci0 BAR enable */
        xor     r5,r5,r5
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, PCI_0_BAR_EN          // r5 = 0x14000c3c   
        xor     r6,r6,r6
        addis	r6, r0, 0xffff			 
        ori	r6, r6, 0xf800              	// r6 = 0x0xfffff80e
        stwbrx  r6, 0, (r5)                     // (0x14000c3c) <=  0x0xfffff80e

        /* pci1 BAR enable */
        xor     r5,r5,r5
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, PCI_1_BAR_EN          // r5 = 0x14000cbc   
        xor     r6,r6,r6
        addis	r6, r0, 0xffff			 
        ori	r6, r6, 0xf800              	// r6 = 0xfffff80e
        stwbrx  r6, 0, (r5)                     // (0x14000cbc) <=  0x0xfffff80e

/* --/\------ GT PCI interface parameters --------/\-- */

/* --\/------ GT MPP interface parameters --------\/-- */
        /* MPP control0 */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, MPP_CNTRL0             
        addis	r6, r0, 0x5354
        ori	r6, r6, 0x1717              	
        stwbrx  r6, 0, (r5)                     // Store
	sync

        /* MPP control1 */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, MPP_CNTRL1             
        addis	r6, r0, 0x4400
        ori	r6, r6, 0x9911              	
        stwbrx  r6, 0, (r5)                     // Store
	sync
        
        /* MPP control2 */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, MPP_CNTRL2             
        addis	r6, r0, 0x4009
        ori	r6, r6, 0x1818              	
        stwbrx  r6, 0, (r5)                     // Store
	sync

        /* MPP control3 */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, MPP_CNTRL3         
        addis	r6, r0, 0x0009
        ori	r6, r6, 0x0066              	
        stwbrx  r6, 0, (r5)                     // Store
	sync
        
        /* GPP Level Control - set the interrupt pins as active low */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, GPP_LEVEL_CNTRL             
        addis	r6, r0, 0x0000
        ori	r6, r6, 0x02c6              	
        stwbrx  r6, 0, (r5)                     // Store
	sync

        /* Serial Ports Multiplex - RMII */
        addis	r5, r0, INTERNAL_BASE
        ori	r5, r5, SER_PORTS_MUX             
        addis	r6, r0, 0x0000
        ori	r6, r6, 0x0102
        stwbrx  r6, 0, (r5)                     // Store
	sync
/* --/\------ GT MPP interface parameters --------/\-- */
#endif	
	mtlr	r9
	blr
