www.pudn.com > vxworks0108.rar > romInit.s


/* romInit.s - SBS Technologies VG4 ROM initialization module */

/*
DESCRIPTION
This module contains the entry code for the VxWorks bootrom.
The entry point romInit, is the first code executed on power-up.
It sets the BOOT_COLD parameter to be passed to the generic
romStart() routine.

The routine sysToMonitor() jumps to the location 4 bytes
past the beginning of romInit, to perform a "warm boot".
This entry point allows a parameter to be passed to romStart().

This code is intended to be generic across PowerPC 603/604 boards.
Hardware that requires special register setting or memory
mapping to be done immediately, may do so here.
*/

#define _ASMLANGUAGE
#include "config.h"
#include "reg.h"
#include "ppc750.h"
#include "vg4.h"
#include "mpc107.h"

#define SDRAM_SIZE 512    /* valid values : 64, 128, 256, 512 */

#define LOADREG(reg,const32) \
      addis reg,r0,HI(const32); ori reg,reg,LO(const32)

/*
 *  Use this macro to prevent reordering by as/ld and processor
 */
#define IORDER      eieio; sync

/*
 *  I2C Registers.
 */

#define MPC107_I2C_ADR      (I2C_BASE_ADRS)
#define MPC107_I2C_FDR      (I2C_BASE_ADRS + 0x0004)
#define MPC107_I2C_CCR      (I2C_BASE_ADRS + 0x0008)
#define MPC107_I2C_CSR      (I2C_BASE_ADRS + 0x000c)
#define MPC107_I2C_CDR      (I2C_BASE_ADRS + 0x0010)


#define I2C_CCR_TXAK    0x08    /* Transfer ack */
#define I2C_CSR_MCF     0x80    /* Transfer complete */
#define I2C_CSR_MBB     0x20    /* Bus busy */
#define I2C_CSR_MIF     0x02    /* Interrupt */
#define I2C_CSR_RXAK    0x01    /* No receive ack */

#define I2C_READ    1
#define I2C_WRITE   0


    /* Exported internal functions */

    .type  _romInit,@function
    .type  romInit,@function
    .type  _romInitWarm,@function
    .type  romInitWarm,@function
    .type  _romInitPmon,@function
    .type  romInitPmon,@function
    .globl  _romInit        /* start of system code */
    .globl  romInit         /* start of system code */
    .globl  _romInitWarm    /* warm boot entry point */
    .globl  romInitWarm     /* warm boot entry point */
    .globl  _romInitPmon
    .globl  romInitPmon
    .globl  romPuts
    .globl  board_led_on

#if defined (ROM_DEBUG)
    .globl  romPuts
#endif /* if defined (ROM_DEBUG)*/


    /* externals */

    .extern romStart    /* system initialization routine */

    .text
    .align 2

    /*
     * After reset, the processor fetches from ROM_BASE_ADRS + 0x100.
     * We offset the _romInit entry by 0x100 bytes to compensate.
     * In other WRS PPC BSP's, this offset was accounted for in the
     * elfHex stage of building the rom image by setting HEX_FLAGS
     * to "-a 100".  Explictly adding the space here seems more
     * straitforward, and it also helps when not using elfToHex
     * such as in a flash programmed binary image.   Therefore
     * the VG4 BSP Makefile uses HEX_FLAGS of "-a 0".
     * This also means that ROM_TEXT_ADRS must be defined
     * equivalent to ROM_BASE_ADRS + 0x100 in config.h and Makefile.
     */

    .ascii  "SBS_JMP""\0"   /* Boot Description Header ID */
    .long 0x00010000        /* Boot Description Header V1.0 */
    .long ROM_TEXT_ADRS
    .long 0x00000000        /* Boot Description Header dummy size */
    .long 0x00000000        /* Boot Description Header dummy crc */
    .space (0xe8)

/******************************************************************************
*
* romInit - entry point for VxWorks in ROM
*

* romInit
*     (
*     int startType /@ only used by 2nd entry point @/
*     )

*/

_romInit:
romInit:


    bl  cold
    nop

    /*
     * This warm boot entry point is defined as ROM_WARM_ADRS in config.h.
     * It is defined as an offset from ROM_TEXT_ADRS.  Please make sure
     * that the offset from _romInit to romInitWarm matches that specified
     * in config.h.  Since WRS is standardizing this offset to 8 bytes,
     * we insert a nop to ensure romInitWarm is a 8 byte offset from
     * ROM_TEXT_ADRS.
     */

_romInitWarm:
romInitWarm:

    nop
    nop

    /*
     * This boot entry point is used by sysToPmon(). It's treated like 
     * a vxWorks warm reboot.
     */
_romInitPmon:
romInitPmon:
    bl  warm

    /* copyright notice appears at beginning of ROM (in TEXT segment) */

    .align 2
    .ascii   "Copyright 1984-1999 Wind River Systems, Inc. "
    .ascii   "\0"__DATE__"\0"
    .ascii   "\0"__TIME__"\0"

#if defined (ADRS_MAP_PREP)
    .ascii   "MPC107 MAP A"
#else
    .ascii   "MPC107 MAP B"
#endif /* #if defined (ADRS_MAP_PREP) */
    .align 2

cold:
    li  r12, 1
    bl  start       /* skip over next instruction */


warm:
    or  r12, r3, r3 /* startType to r12 */



start:

    /* Zero-out registers: r0 & SPRGs */
    xor     r0, r0, r0
    mtspr   272, r0
    mtspr   273, r0
    mtspr   274, r0
    mtspr   275, r0

    /*
     *  Set HID0 to a known state
     *  Enable machine check input pin (EMCP) for DRAM ECC detection.
     *  Don't touch hard reset bit.
     */
    mfspr   r3, HID0
    isync
    rlwinm  r4, r3, 0, 15, 15   /* r4 has NHR bit cleared */
    addis   r4, r4, 0x8000
    sync
    isync
    mtspr   HID0, r4        /* HID0 = r4 */
    isync


    /*
     *  Set MPU/MSR to a known state
     *  Turn on FP
     */

    andi.   r3, r3, 0
    ori     r3, r3, 0x2000
    sync
    mtmsr   r3
    isync

    /* Init the floating point control/status register */

    mtfsfi  7,0x0
    mtfsfi  6,0x0
    mtfsfi  5,0x0
    mtfsfi  4,0x0
    mtfsfi  3,0x0
    mtfsfi  2,0x0
    mtfsfi  1,0x0
    mtfsfi  0,0x0
    isync

    /* Initialize the floating point data regsiters to a known state */

    bl  ifpdr_value
    .long   0x3f800000  /* 1.0 */
ifpdr_value:
    mfspr   r3,8
    lfs f0,0(r3)
    lfs f1,0(r3)
    lfs f2,0(r3)
    lfs f3,0(r3)
    lfs f4,0(r3)
    lfs f5,0(r3)
    lfs f6,0(r3)
    lfs f7,0(r3)
    lfs f8,0(r3)
    lfs f9,0(r3)
    lfs f10,0(r3)
    lfs f11,0(r3)
    lfs f12,0(r3)
    lfs f13,0(r3)
    lfs f14,0(r3)
    lfs f15,0(r3)
    lfs f16,0(r3)
    lfs f17,0(r3)
    lfs f18,0(r3)
    lfs f19,0(r3)
    lfs f20,0(r3)
    lfs f21,0(r3)
    lfs f22,0(r3)
    lfs f23,0(r3)
    lfs f24,0(r3)
    lfs f25,0(r3)
    lfs f26,0(r3)
    lfs f27,0(r3)
    lfs f28,0(r3)
    lfs f29,0(r3)
    lfs f30,0(r3)
    lfs f31,0(r3)
    sync

    /*
     *  Set MPU/MSR to a known state
     *  Turn off FP
     */

    andi.   r3, r3, 0
    sync
    mtmsr   r3
    isync


    /* Get cpu type */

    mfspr   r28, PVR
    rlwinm  r27, r28, 0, 16, 31
    rlwinm  r28, r28, 16, 16, 31


    /* Init the Segment registers */

    andi.   r3, r3, 0
    isync
    mtsr    0,r3
    isync
    mtsr    1,r3
    isync
    mtsr    2,r3
    isync
    mtsr    3,r3
    isync
    mtsr    4,r3
    isync
    mtsr    5,r3
    isync
    mtsr    6,r3
    isync
    mtsr    7,r3
    isync
    mtsr    8,r3
    isync
    mtsr    9,r3
    isync
    mtsr    10,r3
    isync
    mtsr    11,r3
    isync
    mtsr    12,r3
    isync
    mtsr    13,r3
    isync
    mtsr    14,r3
    isync
    mtsr    15,r3
    isync


    /* Invalidate all BAT entries by setting upper BAT registers to zero */

    mtspr   IBAT0U, r3
    isync
    mtspr   IBAT1U, r3
    isync
    mtspr   IBAT2U, r3
    isync
    mtspr   IBAT3U, r3
    isync
    mtspr   DBAT0U, r3
    isync
    mtspr   DBAT1U, r3
    isync
    mtspr   DBAT2U, r3
    isync
    mtspr   DBAT3U, r3
    isync

    /* Check CPU type resp. revision */

    cmplwi  r28, CPU_TYPE_750
    bne     INVAL_L1
    cmplwi  r27, CPU_REV_750_IBM
    bnl     INVAL_L1
    cmpli   cr0, r27, CPU_REV_755
    blt     INVAL_L1


    /* Disable additional BATs for 755 processor */

    mtspr   IBAT4U, r3
    isync
    mtspr   IBAT5U, r3
    isync
    mtspr   IBAT6U, r3
    isync
    mtspr   IBAT7U, r3
    isync
    mtspr   DBAT4U, r3
    isync
    mtspr   DBAT5U, r3
    isync
    mtspr   DBAT6U, r3
    isync
    mtspr   DBAT7U, r3
    isync

    /* Set HID2 to known state (755 processors) */

    andi.   r3, r3, 0
    mtspr   HID2, r3


    /* invalidate the MPU's data/instruction caches */

INVAL_L1:
    mfspr   r3,HID0

    addis   r4,r0,0x0000        /* Clear r4 */
    ori     r4,r4,0xCC00        /* Setup bit pattern for ICE/ICFI/DCE/DCFI */
    or      r3,r4,r3
    isync
    mtspr   HID0,r3             /* set ICE/ICFI/DCE/DCFI */

    addis   r4,r0,0x0000        /* Clear r4 */
    ori     r4,r4,0x0C00        /* Setup bit pattern for ICFI/DCFI */
    andc    r3,r3,r4
    isync
    mtspr   HID0,r3             /* clear ICFI/DCFI (bit 16/17) */

    addis   r4,r0,0x0000        /* Clear r4 */
    ori     r4,r4,0x3000        /* Setup bit pattern for ILOCK/DLOCK */
    andc    r3,r3,r4
    isync
    mtspr   HID0,r3             /* clear ILOCK/DLOCK (bit 18/19) */

    addis   r4,r0,0x0000        /* Clear r4 */
    ori     r4,r4,0x4000        /* Setup bit pattern for DCE */
    andc    r3,r3,r4
    isync
    mtspr   HID0,r3             /* disable data cache by clearing DCE (bit 17), */
                                /* instruction cache is already enabled */

    sync


    /*
     * Enable branch history table and branch target instruction cache.
     */
#ifndef USER_BHT_DISABLE
    ori     r3, r3, 0x0004      /* Set BHTE (bit 29) */
#endif
#ifndef USER_BTIC_DISABLE
    ori     r3, r3, 0x0020      /* Set BTIC (bit 26) */
#endif
    isync                       /* setting of ICE bit must be preceeded by isync */
    mtspr   HID0,r3
    sync
    isync                       /* setting of ICE bit must be preceeded by isync */

    b       MPC107_INIT


MPC107_INIT:

    /*
     * Below we setup the MPC107 embedded memory controller.
     * This procedure detects the current MPC107's address map 
     * configuration. Address map A conforms to the PowerPC 
     * reference platform specification (PReP). Map B conforms
     * to the PowerPC microprocessor common hardware reference 
     * platform (CHRP).
     * A board pull up/down resistor selects the map in hardware.
     * We assume that the memory map is Map A (default on VG4),
     * and attempt to read the MPC107's PCI Vendor and Device IDs.
     * If the read value is ok, then use map A, else assume map B.
     * Emulation mode address mapping is not suppported.
     * No "compatability hole" is configured.
     */

mpc107_map_test:
    lis     r1, HI(MPC107_CFG_ADDR_PREP) 	/* r1 = PCI config address register */
    ori     r1, r1, LO(MPC107_CFG_ADDR_PREP)
    lis     r2, HI(MPC107_CFG_DATA_PREP) 	/* r2 = PCI config data register */
    ori     r2, r2, LO(MPC107_CFG_DATA_PREP)

    lis     r3, CHAPARRAL_REG           /* start building new reg number */
    ori     r3, r3, MPC107_VEND_ID      /* processor configuration register 1 (0xa8) */
    stwbrx  r3, 0, r1                   /* write this value to CONFIG_ADDR */
	lwbrx   r3, 0, r2                   /* read chaparral device id */
    isync

    lis   	r4, HI(PCI_ID_CHAPARRAL)
    ori   	r4, r4, LO(PCI_ID_CHAPARRAL)
    cmpl    0, 0, r3, r4
	bne		detected_chrp
	b		detected_prep


detected_prep:
    /* Load PReP settings */
    lis     r1, HI(MPC107_CFG_ADDR_PREP) 	/* r1 = PCI config address register */
    ori     r1, r1, LO(MPC107_CFG_ADDR_PREP)
    lis     r2, HI(MPC107_CFG_DATA_PREP) 	/* r2 = PCI config data register */
    ori     r2, r2, LO(MPC107_CFG_DATA_PREP)

#if defined (ADRS_MAP_PREP)
	/* Do nothing, PReP settings already loaded */
#else
	/* Set PCI address map B (CHRP) */
    lis     r3, CHAPARRAL_REG           /* start building new reg number */
    ori     r3, r3, MPC107_PRC1         /* processor configuration register 1 (0xa8) */
    stwbrx  r3, 0, r1               /* write this value to CONFIG_ADDR */
    isync

    lwbrx   r4, 0, r2               /* load r4 from CONFIG_DATA */
	rlwinm	r4, r4, 0, 16, 14		/* adress map B: bit 16 (ADDRESS_MAP) = 0 */
    stwbrx  r4, 0, r2       
	sync

    /* Reload CHRP settings */
    lis     r1, HI(MPC107_CFG_ADDR_CHRP) 	/* r1 = PCI config address register */
    ori     r1, r1, LO(MPC107_CFG_ADDR_CHRP)
    lis     r2, HI(MPC107_CFG_DATA_CHRP) 	/* r2 = PCI config data register */
    ori     r2, r2, LO(MPC107_CFG_DATA_CHRP)

    /* Configure Address Map B Options Register */
    lis     r3, CHAPARRAL_REG       /* start building new reg number */
    ori     r3, r3, MPC107_AMBOR    /* register number 0xe0 */
    stwbrx  r3, r0, r1              /* write this value to CONFIG_ADDR */
    isync

    li      r4, 0x80                /* CPU_FD_ALIAS_EN = 1, PCI_FD_ALIAS_EN = 0*/
    stb     r4, 0(r2)               /* Store data */
    sync
#endif /* #if defined (ADRS_MAP_PREP) */
	b	mpc107_ambor


detected_chrp:
    /* Load CHRP settings */
    lis     r1, HI(MPC107_CFG_ADDR_CHRP) 	/* r1 = PCI config address register */
    ori     r1, r1, LO(MPC107_CFG_ADDR_CHRP)
    lis     r2, HI(MPC107_CFG_DATA_CHRP) 	/* r2 = PCI config data register */
    ori     r2, r2, LO(MPC107_CFG_DATA_CHRP)

#if defined (ADRS_MAP_PREP)
	/* Set PCI address map B (CHRP) */
    lis     r3, CHAPARRAL_REG           /* start building new reg number */
    ori     r3, r3, MPC107_PRC1         /* processor configuration register 1 (0xa8) */
    stwbrx  r3, 0, r1               /* write this value to CONFIG_ADDR */
    isync

    lwbrx   r4, 0, r2               /* load r4 from CONFIG_DATA */
    oris    r4, r4, 0x0001             /* adress map B: bit 16 (ADDRESS_MAP) = 1 */
    stwbrx  r4, 0, r2       
    sync

    /* Reload PReP settings */
    lis     r1, HI(MPC107_CFG_ADDR_PREP) 	/* r1 = PCI config address register */
    ori     r1, r1, LO(MPC107_CFG_ADDR_PREP)
    lis     r2, HI(MPC107_CFG_DATA_PREP) 	/* r2 = PCI config data register */
    ori     r2, r2, LO(MPC107_CFG_DATA_PREP)
#endif /* #if defined (ADRS_MAP_PREP) */
	b	mpc107_ambor


mpc107_ambor:
#if !defined (ADRS_MAP_PREP)
    /* Configure Address Map B Options Register */
    lis     r3, CHAPARRAL_REG       /* start building new reg number */
    ori     r3, r3, MPC107_AMBOR    /* register number 0xe0 */
    stwbrx  r3, r0, r1              /* write this value to CONFIG_ADDR */
    isync

    li      r4, 0x80                /* CPU_FD_ALIAS_EN = 1, PCI_FD_ALIAS_EN = 0*/
    stb     r4, 0(r2)               /* Store data */
    sync
#endif /* #if !defined (ADRS_MAP_PREP) */


    /*
     * Switch off watchdog
     */
    bl wd_off

    /*
     * Embedded utilities memory block base address
     *
     * EUMBBAR defines a local address for the I2C, I2O, DMA, EPIC, ATU
     * and other registers.
     * PCSRBAR defines the PCI address for the EUMB
     *
     * Remember that this area must be enabled in a BAT to be accessible.
     */

    lis     r3, CHAPARRAL_REG       /* start building new reg number */
    ori     r3, r3, MPC107_EUMBBAR  /* register number 0x78 */
    stwbrx  r3, r0, r1              /* write this value to CONFIG_ADDR */
    isync

    lis     r4, HI(CPU_EUMB_ADRS)   /* Local base address for EUMB */
    stwbrx  r4, r0, r2              /* write modified data to CONFIG_DATA */
    sync


    /*
     * Store memory bus speed into Timer Frequency Reporting Register (TFFR) of MPC107.
     * The value of the memory bus speed has been determined before the SDRAM
     * initialization and is still in r25.
     */

    lis     r3, ((EPIC_ADDR (EPIC_TIMER_FREQ_REG)) >> 16)
    ori     r3, r3, ((EPIC_ADDR (EPIC_TIMER_FREQ_REG)) & 0xffff)
    lis     r4, ((MEMORY_BUS_SPEED) >> 16)
    ori     r4, r4, ((MEMORY_BUS_SPEED) & 0xffff)
    stwbrx  r4, r0, r3                              /* store r4 into TFFR */


    /*
     * Make sure we're disabling RAM interface logic
     * by clearing MEMGO bit.  Needed for warm boots
     */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MCCR1    /* register number 0xf0 */
    stwbrx  r3, r0, r1          /* write this value to CONFIG_ADDR */
    isync

    lwbrx   r4, r0, r2          /* load r4 from CONFIG_DATA */
    lis r0, 0xfff7              /* MEMGO=0 */
    ori r0, r0, 0xffff

    and r4, r4, r0              /* Clear MEMGO bit */
    stwbrx  r4, r0, r2          /* write modified data to CONFIG_DATA */

    /*
     * This section of code inits the MPC107's PCI Interface Registers
     */
INIT_PCI:
    lis r3, CHAPARRAL_REG   /* start building new reg number */
    ori r3, r3, MPC107_PCI_CMD  /* register number 0x0004 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync

    lhbrx   r4, 0, r2           /* load r4 from CONFIG_DATA */
    lis r0, 0x0000
    ori r0, r0, 0xfca0
    and r4, r4, r0              /* Preserve reserve bits */
    lis r0, 0x0000
    ori r0, r0, 0x0106          /* Enable bus master function and memory space access */
    or  r4, r4, r0              /* sets the desired bits */
    sthbrx  r4, 0, r2           /* write modfd data to CONFIG_DATA */

    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_PCI_STAT /* register number 0x0006 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */

    li  r3, 0x0002
    lhbrx   r4, r3, r2          /* load r4 from CONFIG_DATA */
    ori r4, r4, 0xff80          /* ones clears all bits in PCI_STAT */
    sthbrx  r4, r3, r2          /* write mdfd data to CONFIG_DATA */

    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_PRC1     /* processor configuration register 1 (0xa8) */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync

    lwbrx   r4, 0, r2           /* load r4 from CONFIG_DATA */
    lis     r0, 0xff39
    ori     r0, r0, 0x0300
    and     r4, r4, r0          /* Preserve reserved bits (includes memory map bit) */
    lis     r0, 0x0004          /* 603e, 7xx, 74xx processor type */

#ifdef PREFETCH_ENABLE
    ori r0, r0, 0x1294
                                /* prefetch reads (speculative PCI reads) */
                                /* snoop looping enabled */
                                /* Flash write enabled */
#else
    ori r0, r0, 0x1290
                                /* no prefetch reads, */
                                /* snoop looping enabled */
                                /* Flash write enabled */
#endif
    or  r4, r4, r0
    stwbrx  r4, 0, r2

    /* Make sure we disable reporting of parity errors until  */
    /* memory has been scrubed.  Enabling of reporting occurs */
    /* in sysHwInit().                  */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_EER1     /* register number 0xc0 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
    lbz r4, 0(r2)               /* Load data */
    andi.   r4, r4, 0xFB        /* Disable single-bit ECC error trigger exceeded reporting */
/*  ori     r4, r4, 0x04 */     /* Enable single-bit ECC error trigger exceeded reporting */
    stb r4, 0(r2)               /* Store data */

    /* Disable multibit ECC erorrs for SDRAM */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_EER2     /* register number 0xc4 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
    lbz r4, 0(r2)               /* Load data */
    andi.   r4, r4, 0xF7        /* Disable multibit ECC error (must be disabled for SDRAM) */
    stb r4, 0(r2)               /* Store data */

    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3,MPC107_MCCR1     /* register number 0xf0 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
    lwbrx   r4, 0, r2           /* load r4 from CONFIG_DATA */

    /* REDUCE WAIT STATES FOR ROM ACCESSES */
#ifdef MPC107_66 /* 66 MHz */
    lis r0, 0x0480              /* ROMNAL: 0 , ROMFAL: 9*/
#else /* 100 MHz */
    lis r0, 0x0780              /* ROMNAL: 0 , ROMFAL: 15*/
#endif

/*  oris    r0, r0, 0x0004 */   /* Self-refresh enable       */
/*  oris    r0, r0, 0x0001 */   /* Parity check      */

#if SDRAM_SIZE == 512
    ori r0, r0, 0x000a          /* 2 banks with 13 row bits (SDRAM) */
#elif SDRAM_SIZE == 256
    ori r0, r0, 0x0002          /* 1 bank with 13 row bits (SDRAM) */
#else/* 64, 128 MB */
    ori r0, r0, 0x0000          /* 1 bank with 12 row bits (SDRAM) */
#endif

    and r4, r4, r0              /* clears the desired bits */
    or  r4, r4, r0              /* sets the desired bits */
    stwbrx  r4, 0, r2           /* write mdfd data to CONFIG_DATA */

    lis r3, CHAPARRAL_REG       /* start building new register number */
    ori r3, r3, MPC107_MCCR2    /* register number 0xf4 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync

    lis r4, 0x0000
#ifdef MPC107_66 /* 66 MHz */
    oris    r4, r4, 0x6000      /* TS_WAIT_TIMER = 4 clocks (for 55 ns) */
#else /* 100 MHz */
    oris    r4, r4, 0xa000      /* TS_WAIT_TIMER = 6 clocks (for 55 ns) */
#endif
    oris    r4, r4, 0x0008      /* SDRAM inline writes */
    oris    r4, r4, 0x0004      /* SDRAM inline reads */


#ifdef MPC107_66 /* 66 MHz */
    ori     r4, r4, 0x0920      /* Refresh:  66 MHz mem bus */
#else /* 100 MHz */             /*           649 - 65 (10% security) = 584 */
    ori     r4, r4, 0x0f30      /* Refresh: 100 MHz mem bus */
#endif                          /*          1080 - 108 (10% security) = 972  */
/*  ori     r4, r4, 0x0002 */   /* Reserve a page */
    ori     r4, r4, 0x0001      /* RWM parity */
    stwbrx  r4, 0, r2           /* write mdfd data to CONFIG_DATA */

    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MCCR3    /* register number 0xf8 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
    lwbrx   r4, 0, r2           /* load r4 from CONFIG_DATA */

    lis r0, 0x000f              /* Bits 31 .. 20 used for SDRAM */
    ori r0, r0, 0xffff
    and r4, r4, r0

    lis     r0, 0x7000          /* BSTOPRE_M = 7 (see A/N) */
#ifdef MPC107_66 /* 66 MHz */
    oris    r0, r0, 0x0540      /* REFREC    = 5 clocks */
                                /* RDLAT     = 4 clocks (CAS latency + 1 for registered buffer mode) */
                                /*                      (CAS latency + 2 for in-line buffer mode) */
#else /* 100 MHz */
    oris    r0, r0, 0x0750      /* REFREC    = 7 clocks */
                                /* RDLAT     = 5 clocks (CAS latency + 1 for registered buffer mode) */
                                /*                      (CAS latency + 2 for in-line buffer mode) */
#endif

    or  r4, r4, r0              /* sets the desired bits */
    stwbrx  r4, 0, r2           /* write mdfd data to CONFIG_DATA */


    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MCCR4        /* register number 0xfc */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
    lwbrx   r4, 0, r2           /* load r4 from CONFIG_DATA */

    lis r0, 0x0083
    and r4, r4, r0
#ifdef MPC107_66 /* 66 MHz */
    lis     r0, 0x2000          /* PRETOACT = 2 clocks              */
    oris    r0, r0, 0x0462      /* ACTOPRE  = 4 clocks              */
                                /* Enable Inline ECC/Parity         */
                                /* Enable Extended ROM (RCS2/RCS3)  */
                                /* BSTOPRE_U = 0 (see A/N)          */
                                /* RCS1 is 8-bits                   */
    ori     r0, r0, 0x2239      /* CAS Latency (CL=2) (see RDLAT)   */
                                /* Sequential wrap/4-beat burst     */
                                /* ACTORW  = 3 clocks               */
                                /* BSTOPRE_L = 9 (see A/N)          */
#else /* 100 MHz */
    lis     r0, 0x2000          /* PRETOACT = 2 clocks              */
    oris    r0, r0, 0x0562      /* ACTOPRE  = 5 clocks              */
                                /* Enable Inline ECC/Parity         */
                                /* Enable Extended ROM (RCS2/RCS3)  */
                                /* BSTOPRE_U = 0 (see A/N)          */
                                /* RCS1 is 8-bits                   */
    ori     r0, r0, 0x3239      /* CAS Latency (CL=3) (see RDLAT)   */
                                /* Sequential wrap/4-beat burst     */
                                /* ACTORW  = 3 clocks               */
                                /* BSTOPRE_L = 9 (see A/N)          */
#endif

    or  r4, r4, r0              /* sets the desired bits */
    stwbrx  r4, 0, r2           /* write mdfd data to CONFIG_DATA */

    /* Disable all memory banks first */
    li  r0, 0x0000              /* Disable all 8 banks of DRAM */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MBEN     /* register number 0xa0 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
    stb r0, 0(r2)               /* write mdfd data to CONFIG_DATA */

    /* Set starting address, banks 0-3 */
    xor r4, r4, r4
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MSAR1    /* register number 0x80 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
#if SDRAM_SIZE >= 256
    addis   r4, r0, 0x8000
    ori r4, r4, 0x0000
#elif SDRAM_SIZE == 128
    addis   r4, r0, 0x8000
    ori r4, r4, 0x8000
#else /* default: SDRAM_SIZE == 64 */
    addis   r4, r0, 0xc080
    ori r4, r4, 0x4000
#endif
    stwbrx  r4, 0, r2

    /* Set starting address, banks 4-7 */
    xor r4, r4, r4
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MSAR2    /* register number 0x84 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
#if SDRAM_SIZE >= 256
    addis   r4, r0, 0xc080
    ori r4, r4, 0x4000
#elif SDRAM_SIZE == 128
    addis   r4, r0, 0x8000
    ori r4, r4, 0x8000
#else /* default: SDRAM_SIZE == 64 */
    addis   r4, r0, 0x0000
    ori r4, r4, 0x8000
#endif
    stwbrx  r4, 0, r2

    /* Set extended starting address, banks 0-3 */
    lis r3, CHAPARRAL_REG       /* Starting address of extended memory is 0 */
    ori r3, r3, MPC107_EMSAR1   /* register number 0x88 */
    stwbrx  r3, 0, r1
    isync
#if SDRAM_SIZE >= 256
    addis   r4, r0, 0x0202
    ori r4, r4, 0x0100
#elif SDRAM_SIZE == 128
    addis   r4, r0, 0x0101
    ori r4, r4, 0x0000
#else /* default: SDRAM_SIZE == 64 */
    addis   r4, r0, 0x0000
    ori r4, r4, 0x0000
#endif
    stwbrx  r4, 0, r2

    /* Set extended starting address, banks 4-7 */
    lis r3, CHAPARRAL_REG       /* Starting address of extended memory is 0 */
    ori r3, r3, MPC107_EMSAR2   /* register number 0x8c */
    stwbrx  r3, 0, r1
    isync
#if SDRAM_SIZE >= 256
    addis   r4, r0, 0x0303
    ori r4, r4, 0x0303
#elif SDRAM_SIZE == 128
    addis   r4, r0, 0x0303
    ori r4, r4, 0x0202
#else /* default: SDRAM_SIZE == 64 */
    addis   r4, r0, 0x0302
    ori r4, r4, 0x0101
#endif
    stwbrx  r4, 0, r2

    /* Set ending address, banks 0-3 */
    lis r4, 0
    ori r4, r4, 0x003f          /* 64 MB */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MEAR1    /* register number 0x90 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
#if SDRAM_SIZE >= 256
    addis   r4, r0, 0xff7f
    ori r4, r4, 0xffff
#elif SDRAM_SIZE == 128
    addis   r4, r0, 0xff7f
    ori r4, r4, 0xff7f
#else /* default: SDRAM_SIZE == 64 */
    addis   r4, r0, 0xffbf
    ori r4, r4, 0x7f3f
#endif
    stwbrx  r4, 0, r2

    /* Set ending address, banks 4-7 */
    xor r4, r4, r4
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MEAR2    /* register number 0x94 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
#if SDRAM_SIZE >= 256
    addis   r4, r0, 0xffbf
    ori r4, r4, 0x7f3f
#elif SDRAM_SIZE == 128
    addis   r4, r0, 0xff7f
    ori r4, r4, 0xff7f
#else /* default: SDRAM_SIZE == 64 */
    addis   r4, r0, 0xffff
    ori r4, r4, 0xff7f
#endif
    stwbrx  r4, 0, r2

    /* Set extended ending address, banks 0-3 */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_EMEAR1   /* register number 98 */
    stwbrx  r3, 0, r1
    isync
#if SDRAM_SIZE >= 256
    addis   r4, r0, 0x0202
    ori r4, r4, 0x0100
#elif SDRAM_SIZE == 128
    addis   r4, r0, 0x0101
    ori r4, r4, 0x0000
#else /* default: SDRAM_SIZE == 64 */
    addis   r4, r0, 0x0000
    ori r4, r4, 0x0000
#endif
    stwbrx  r4, 0, r2

    /* Set extended ending address, banks 4-7 */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_EMEAR2   /* register number 9c */
    stwbrx  r3, 0, r1
    isync
#if SDRAM_SIZE >= 256
    addis   r4, r0, 0x0303
    ori r4, r4, 0x0303
#elif SDRAM_SIZE == 128
    addis   r4, r0, 0x0303
    ori r4, r4, 0x0202
#else /* default: SDRAM_SIZE == 64 */
    addis   r4, r0, 0x0302
    ori r4, r4, 0x0101
#endif
    stwbrx  r4, 0, r2

    /* Set memory bank enable */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MBEN     /* register number 0xa0 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync

    li  r4, 0x01                /* Enable bank 0 */
#if SDRAM_SIZE >= 512
    ori r4, r4, 0x02            /* Enable bank 1 */
#endif
    stb r4, 0(r2)               /* Enable bank(s) of memory */


    /* Set memory page mode */
    lis r3, CHAPARRAL_REG               /* start building new reg number */
    ori r3, r3, REG_BASE(MPC107_MPMR)   /* register number 0xa3 */
    stwbrx  r3, 0, r1                   /* write this value to CONFIG_ADDR */
    isync

#ifdef MPC107_66 /* 66 MHz */
    li  r4, 0x55                /* ( 6600 - 1112 - 2) / 64 =  85 = 0x55 */
#else /* 100 MHz */
    li  r4, 0x8A                /* (10000 - 1112 - 2) / 64 = 138 = 0x8A */
#endif
    stb r4, REG_OFF(MPC107_MPMR)(r2)        /* Set Memory Page Mode */


    /*
     * Output driver control register
     */
    lis r3, CHAPARRAL_REG               /* start building new reg number */
    ori r3, r3, REG_BASE(MPC107_ODCR)   /* register number 73 */
    stwbrx  r3, 0, r1
    isync

    li  r0, 0

    ori r0, r0, 0x80            /* PCI I/O: 50 ohms (else 25ohm) */
    ori r0, r0, 0x40            /* CPU I/O: 40 ohms (else 20ohm) */

/*  ori r0, r0, 0x30  */        /* Mem I/O:  8 ohms */
    ori r0, r0, 0x20            /* Mem I/O: 13 ohms */
/*  ori r0, r0, 0x10  */        /* Mem I/O: 20 ohms */
/*  ori r0, r0, 0x00  */        /* Mem I/O: 40 ohms */

/*  ori r0, r0, 0x0c  */        /* PCIClk:  8 ohms */
    ori r0, r0, 0x08            /* PCIClk: 13 ohms */
/*  ori r0, r0, 0x04  */        /* PCIClk: 20 ohms */
/*  ori r0, r0, 0x00  */        /* PCIClk: 40 ohms */

/*  ori r0, r0, 0x03  */        /* MemClk:  8 ohms */
    ori r0, r0, 0x02            /* MemClk: 13 ohms */
/*  ori r0, r0, 0x01  */        /* MemClk: 20 ohms */
/*  ori r0, r0, 0x00  */        /* MemClk: 40 ohms */

    stb     r0, REG_OFF(MPC107_ODCR)(r2)            /* New settings. */
    sync
    isync


    /*
     * Clock driver control register
     */
    lis r3, CHAPARRAL_REG               /* start building new reg number */
    ori r3, r3, REG_BASE(MPC107_CDCR)   /* register number 0x74 */
    stwbrx  r3, 0, r1
    isync

    lis     r0, 0
/*  ori     r0, r0, 0x8000 */   /* PCI_SYNC_OUT: disabled */
/*  ori     r0, r0, 0x7c00 */   /* PCI_CLK(0:4): disabled */

/*  ori     r0, r0, 0x0300 */   /* CPU_CLK(0:1):  8 ohms */
    ori     r0, r0, 0x0200      /* CPU_CLK(0:1): 13 ohms */
/*  ori     r0, r0, 0x0100 */   /* CPU_CLK(0:1): 20 ohms */
/*  ori     r0, r0, 0x0000 */   /* CPU_CLK(0:1): 40 ohms */

/*  ori     r0, r0, 0x0080 */   /* SDRAM_SYNC_OUT: disabled */
/*  ori     r0, r0, 0x0078 */   /* SDRAM_CLK(0:3): disabled */
/*  ori     r0, r0, 0x0004 */   /* CPU_CLK0: disabled */
    ori     r0, r0, 0x0002      /* CPU_CLK1: disabled */
    ori     r0, r0, 0x0001      /* CPU_CLK2: disabled */

    sthbrx  r0, REG_OFF(MPC107_CDCR),(r2)            /* New settings. */
    sync

    /*
     * Miscellaneeous driver control register
     */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MDCR     /* register number 0x76 */
    stwbrx  r3, 0, r1
    isync

    lbz r4, 2(r2)               /* load r4 from CONFIG_DATA */
    li      r0, 0x001f          /* bit 4-0 reserved */
    and r4, r4, r0
/*  ori     r4, r4, 0x80 */     /* MCP: 1=open-drain, 0=output */
/*  ori     r4, r4, 0x40 */     /* SRESET: 1=open-drain, 0=output */
/*  ori     r4, r4, 0x20 */     /* QACK: 1=high-Z, 0=output */

    stb     r4, 2(r2)           /* New settings. */
    sync


    /*
        DRAM SHOULD NOW BE CONFIGURED AND ENABLED -
        MUST WAIT BEFORE ACCESSING
    */

memgo:
    li  r0, 0x2000
    mtctr   r0

wait1:
    bdnz    wait1

    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MCCR1    /* register number 0xf0 */
    stwbrx  r3, r0, r1          /* write this value to CONFIG_ADDR */
    isync

    lwbrx   r4, r0, r2          /* load r4 from CONFIG_DATA */
    lis r0, 0x0008              /* MEMGO=1 */
    ori r0, r0, 0x0000
    or  r4, r4, r0              /* set the MEMGO bit */
    stwbrx  r4, r0, r2          /* write mdfd data to CONFIG_DATA */

    li  r0, 0x2000              /* approx decimal 8000 */
    mtctr   r0

wait2:
    bdnz    wait2





/*
 *  Determine and set up final memory configuration.
 *  VG4 has up to two memory banks.
 */

spd_init:
    bl  i2c_init

    /* get module bank density */
    li  3, 0x1f
    bl  i2c_read
    ori r4, r3, 0
    cmpwi   r4, 255
    bne get_banks
    xor r19, r19, r19
    ori r19, r19, 64
    b   use_default

get_banks:
    /* get number of module banks */
    cmpwi   r4, 128         /* bug in SPD EEPROM for 512MB */
    beq     no_bank
    li  3, 0x05
    bl      i2c_read
    mullw.  r4,r4,r3
no_bank:
    mulli   r19,r4,4


    /* r19 now holds the memory size in MB */
    bl  memInit2

use_default:
   /*
     * M1543C southbridge initialization
     */

INIT_M1543C:

    /*
     * Address definition for programmable chip select (1553, Z8536, Z85230)
     */
    lis     r3, CHAPARRAL_REG   /* start building new reg number */
    ori     r3, r3, (PCI_DEV_NO_M1543C << 11)
    ori     r3, r3, REG_BASE(M1543C_PCSAD) /* register number 0x55 */
    stwbrx  r3,  0, r1          /* write this value to CONFIG_ADDR */
    isync

    li      r4, 0x03            /* value 0x00 to register 0x55 */
    stb     r4, 1(r2)           /* write mdfd data to CONFIG_DATA */
    li      r4, 0x01            /* value 0x01 to register 0x56 */
    stb     r4, 2(r2)           /* write mdfd data to CONFIG_DATA */
    li      r4, 0x00            /* value 0x00 to register 0x57 */
    stb     r4, 3(r2)           /* write mdfd data to CONFIG_DATA */


    /*
     * General Purpose Input Definitions
     */

    /* Select address of register GPIS (0x59) in M1543C */
    lis     r3, CHAPARRAL_REG               /* start building new reg number */
    ori     r3, r3, (PCI_DEV_NO_M1543C << 11)
    ori     r3, r3, REG_BASE(M1543C_GPIS)   /* register number 0x59 */
    stwbrx  r3,  0, r1                      /* write this value to CONFIG_ADDR */
    isync

    lbz     r4, REG_OFF(M1543C_GPIS)(r2)    /* read data from CONFIG_DATA */
    ori     r4, r4, 0x09                    /* set bits 0 and 3 in register 0x59 */
    andi.   r4, r4, 0xfb                    /* reset bit 2 in register 0x59 */
    stb     r4, REG_OFF(M1543C_GPIS)(r2)    /* write mdfd data to CONFIG_DATA */


    /*
     * General Purpose Output Configuration
     */

    /* Select address of register SMIRB (0xC6) in PMU M7101 */
    lis     r3, CHAPARRAL_REG                   /* start building new reg number */
    ori     r3, r3, (PCI_DEV_NO_M1543C_PMU << 11)
    ori     r3, r3, REG_BASE(M1543C_PMU_SMIRB)  /* register number 0xC6 */
    stwbrx  r3,  0, r1                          /* write this value to CONFIG_ADDR */
    isync

    /* Select GPO[22] on pin OFF_PWR1/GPO[22] */
    /* Select GPO[23] on pin OFF_PWR2/GPO[23] */
    lbz     r4, REG_OFF(M1543C_PMU_SMIRB)(r2)   /* read from CONFIG_DATA */
    ori     r4, r4, 0x06                        /* set bits to select GPO in register 0xC6 */
    stb     r4, REG_OFF(M1543C_PMU_SMIRB)(r2)   /* write mdfd data to CONFIG_DATA */


    /*
     * Disable write access for extended flash rom and SPD eeprom
     */

    /* Select address of register DOGPOII (0xC3) in PMU M7101 */
    lis     r3, CHAPARRAL_REG   /* start building new reg number */
    ori     r3, r3, (PCI_DEV_NO_M1543C_PMU << 11)
    ori     r3, r3, REG_BASE(M1543C_PMU_DOGPOII) /* register number 0xC3 */
    stwbrx  r3,  0, r1          /* write this value to CONFIG_ADDR */
    isync

    /* Flash protection GPO[22]:  1 - write protected, 0 - write enabled */
    /* SPD eeprom protection GPO[23]:  1 - write protected, 0 - write enabled */
    lbz     r4, REG_OFF(M1543C_PMU_DOGPOII)(r2) /* read from CONFIG_DATA */
    ori     r4, r4, 0x06                        /* set bits 2 and 3 of DOGPOII*/
    stb     r4, REG_OFF(M1543C_PMU_DOGPOII)(r2) /* write mdfd data to CONFIG_DATA */

    /*
     * Set ISA clock frequency
     */
    lis     r3, CHAPARRAL_REG               /* start building new reg number */
    ori     r3, r3, (PCI_DEV_NO_M1543C << 11)
    ori     r3, r3, REG_BASE(M1543C_ISAC1)  /* register number 0x42 */
    stwbrx  r3,  0, r1                      /* write this value to CONFIG_ADDR */
    isync

    lbz     r4, REG_OFF(M1543C_ISAC1)(r2)   /* read from CONFIG_DATA */
    andi.   r4, r4, 0x0007                  /* clear ISA Clock SYSCLK Frequency Select (bit 0-2) */
    ori     r4, r4, 0x0001                  /* set clock to PCICLK/2 */
    stb     r4, REG_OFF(M1543C_ISAC1)(r2)   /* write mdfd data to CONFIG_DATA */


#ifndef STANDANLONE_FIRMWARE
    /* disable external interrupts (redundant MSR initialization) */
    mfmsr   r3                  /* load msr to parm0 */
    INT_MASK(r3, r4)            /* mask EE bit */
    mtmsr   r4                  /* LOCK INTERRUPT */
#else
    /* Disable address and data translation in MSR */
    mfmsr   r3
    lis     r4, 0xffff
    ori     r4, r4, 0xffcf
    and     r3, r3, r4
    mtmsr   r3

    isync

    /* build new BAT entries */
    lis     r3, 0xff00          /* block start: ff000000 */
    ori     r4, r3, 0x0022      /* caching inhibited, read/write */
    mtspr   IBAT0L, r4
    isync
    ori     r4, r3, 0x01ff      /* block length: 16 meg */
    mtspr   IBAT0U, r4
    isync

    lis     r3, 0xc000          /* block start: c0000000 */
    ori     r4, r3, 0x0022      /* caching inhibited, read/write */
    mtspr   DBAT0L, r4
    isync
    ori     r4, r3, 0x1fff      /* block length: 256 meg */
    mtspr   DBAT0U, r4
    isync

    lis     r3, 0x0000          /* block start: 00000000 */
    ori     r4, r3, 0x0012      /* memory coherence, read/write */
    mtspr   IBAT1L, r4
    isync
    mtspr   DBAT1L, r4
    isync
    ori     r4, r3, 0x0fff      /* block length: 128 meg */
    mtspr   IBAT1U, r4
    isync
    mtspr   DBAT1U, r4
    isync
    lis     r3, 0x8000          /* block start: 80000000 */
    ori     r4, r3, 0x0022      /* caching inhibited, read/write */
    mtspr   IBAT2L, r4
    isync
    mtspr   DBAT2L, r4
    isync
    ori     r4, r3, 0x01ff      /* block length: 16 meg */
    mtspr   IBAT2U, r4
    isync
    mtspr   DBAT2U, r4
    isync

    /* enable instruction translation in MSR */
    isync
    mfmsr   r3
    ori     r3, r3, 0x1012
    mtmsr   r3
#endif


    bl  sio_init
    
#if defined (ROM_DEBUG)
    bl      romDebugInit
#endif

#if defined(INCLUDE_DRBIT)
    slwi    r2, r19, 20             /* r19 contains sdram size in megabytes */
                                    /* r2 contains sdram size in bytes now */
    or      r5, r12, r12            /* boot type for bitTestAsm */
    bl      bitTestAsm              /* start assembly BIT module */
#else
    /* Switch off board LED */
    bl  board_led_off
#endif /* if defined(INCLUDE_DRBIT) */

#ifdef INCLUDE_ECC
/*
 *  The purpose of this section is to enable the ECC of the
 *  DRAM.  To do this, it is first necessary to initialize the
 *  ECC check bits.  The ECC check bits are initialized by
 *  initializing all of DRAM.
 *
 *  input:
 *      r19      = Total DRAM size (in Mbytes)
 *  notes:
 *      1. must run as a supervisor function
 *      2. interrupts must be masked
 *      3. address translation (MMU) disabled
 *      4. assumes ECC Control register is in a power-up state
 *
 *  registers used:
 *      r3, r4. r14, r15, r16, r17
 */
.chaparral_scrub:

    /* setup local variables */

    addi    r15, r0, 0          /* load starting addr - always zero */
    slwi    r16, r19, 20        /* r19 contains sdram size in megabytes */
                                /* r16 contains sdram size in bytes now */
#ifndef ECC_TEST
    srwi    r16, r16, 3         /* calculate number of doubles */
#else
    srwi    r16, r16, 4         /* calculate number of doubles / 2 */
#endif /* ECC_TEST */


    /* Make sure FPU is enabled; it's needed for DRAM loads and stores */

    mfmsr   r14                 /* Save current value of MSR in r14 */
    addi    r4, r0, 0x2000      /* FP bit definition */
    or      r4, r4, r14
    mtmsr   r4
    isync

    /*
     * invalidate/enable the processor data cache, one of the assumptions
     * is that address translation is disabled, the default caching mode
     * is copy-back when address translation is disabled, copy-back mode
     * is the recommended caching mode
     */
    
    bl     dCacheInval
    bl     dCacheOn

    /*
     * Loop through the entire DRAM array and initialize memory.  This has
     * the side effect of initializing the ECC check bits because they are
     * always updated when the DRAM is written.
     *
     * The data path to DRAM is the size of a cache line (128-bits), this
     * is why the data cache is enabled, the initialization of the ECC check
     * bits are optimized when a cache line write/flush occurs
     */
    
#ifdef ECC_TEST         
/*
 * Excludes 128 KBytes from scrubbing.
 * The excluded area starts at half of the memory size.
 */

chaparral_scrub_start:
    addi    r17, r15,-8         /* starting address - munged */
    mtctr   r16                 /* load number of doubles in counter */
    lis     r18, 0x1000
chaparral_scrub_iloop:
    lfdu    0, 8(r17)
    stfd    0, 0(r17)
    bdnz    chaparral_scrub_iloop /* branch till counter == 0 */
    addis   r17, r17, 0x2
    addi    r16, r16,-16384
    mtctr   r16                 /* load number of doubles in counter */
1:
    lfdu    0, 8(r17)
    stfd    0, 0(r17)
    bdnz    1b
#else
chaparral_scrub_start:
    addi    r17, r15,-8         /* starting address - munged */
    mtspr   9, r16              /* load number of doubles in counter */
chaparral_scrub_iloop:
    lfdu    0, 8(r17)
    stfd    0, 0(r17)
    bc      16, 0, chaparral_scrub_iloop /* branch till counter == 0 */
#endif /* ECC_TEST */

    eieio
    sync

    /*
     * Flush L1 data cache so that the last segment (data cache size) of 
     * DRAM is initialized.  This is done by flushing 2 x the data cache 
     * size (32K).
     */

    lis    r16, HI(0x10000/_CACHE_ALIGN_SIZE)       /* load number of cache */
    ori    r16, r16, (0x10000/_CACHE_ALIGN_SIZE)    /* lines in 64KB        */

    mtspr  9, r16               /* move to counter */
chaparral_scrub_floop:
    dcbf   r0, r17              /* flush line */
    addi   r17, r17, -(_CACHE_ALIGN_SIZE)   /* next (previous) line */
    bc     16, 0, chaparral_scrub_floop     /* branch till counter == 0 */

    eieio
    sync

    /* disable the data cache */

    bl     dCacheInval
    bl     dCacheOff

    /* Restore original value of MSR */

    mtmsr  r14
    isync

#endif /* INCLUDE_ECC */

    /* initialize the stack pointer */

    lis     sp, HIADJ(STACK_ADRS)
    addi    sp, sp, LO(STACK_ADRS)

#if FALSE /* XXX TPR SDA not supported yet */

    /* initialize r2 and r13 according to EABI standard */

    lis     r2, HIADJ(_SDA2_BASE_)
    addi    r2, r2, LO(_SDA2_BASE_)
    lis     r13, HIADJ(_SDA_BASE_)
    addi    r13, r13, LO(_SDA_BASE_)

#endif /* FALSE */

    /* go to C entry point */    
    or      r3, r12, r12                /* boot type for romStart() */
    addi    sp, sp, -FRAMEBASESZ    /* get frame stack */

    lis     r6, HIADJ(romStart)
    addi    r6, r6, LO(romStart)

    lis     r7, HIADJ(romInit)
    addi    r7, r7, LO(romInit)

    lis     r8, HIADJ(ROM_TEXT_ADRS)
    addi    r8, r8, LO(ROM_TEXT_ADRS)

    sub     r6, r6, r7
    add     r6, r6, r8

    mtlr    r6
    blr




/*
 routine: pciReadConfig
    this function reads a register from a PCI device via configuration cycle
 call:
    pciConfigRead
 return:
    register value in r3
*/
pciConfigRead:
    /* Prepare bus number */
    rlwinm  r3, r3, 16, 8, 15

    /* Prepare device number */
    rlwinm  r4, r4, 11, 16, 20

    /* Prepare function number */
    rlwinm  r5, r5, 8, 21, 23

    /* Prepare register number */
    rlwinm  r10, r6, 0, 24, 29


    /* Build configuration address in r9 */
    lis     r9, CHAPARRAL_REG   /* r0 = 0x8000 0000 BASE_ADDRESS */
    or      r9, r9, r3          /* bus number in bit 8-15 */
    or      r9, r9, r4          /* device number in bit 16-20 */
    or      r9, r9, r5          /* function number in bit 21-23 */
    or      r9, r9, r10         /* register number in bit 24-29 */
    stwbrx  r9, r0, r1          /* write this value to CONFIG_ADDR */
    isync

    /* Register offset in r6 */
    andi.   r6, r6, 0x0003      /* valid register offset: 0, 1, 2, 3 */

    /* Evaluate data size in r7 */
    andi.   r7, r7, 0x0007      /* valid data sizes: 1, 2, 4 */
    cmpli   0, 0, r7, 0x0001    /* test for byte access */
    beq     pci_read_byte
    cmpli   0, 0, r7, 0x0002    /* test for half word (16 bit) access */
    beq     pci_read_hword
    cmpli   0, 0, r7, 0x0004    /* test for word (32 bit) access */
    beq     pci_read_word
    addis   r3, r0, 0xffff
    ori     r3, r0, 0xffff
    b       pci_read_end

pci_read_byte:
    lbzx    r3, r6, r2
    b       pci_read_end

pci_read_hword:
    lhbrx   r3, r6, r2
    b       pci_read_end

pci_read_word:
    lwbrx   r3, r6, r2
    b       pci_read_end

pci_read_end:
    bclr    20,0        /* return to caller */



pciConfigWrite:
    /* Prepare bus number */
    rlwinm  r3, r3, 16, 8, 15

    /* Prepare device number */
    rlwinm  r4, r4, 11, 16, 20

    /* Prepare function number */
    rlwinm  r5, r5, 8, 21, 23

    /* Prepare register number */
    rlwinm  r10, r6, 0, 24, 29

    /* Prepare data size */
    andi.   r7, r7, 0x007


    /* Build configuration address in r9 */
    lis     r9, CHAPARRAL_REG   /* r0 = 0x8000 0000 BASE_ADDRESS */
    or      r9, r9, r3          /* bus number in bit 8-15 */
    or      r9, r9, r4          /* device number in bit 16-20 */
    or      r9, r9, r5          /* function number in bit 21-23 */
    or      r9, r9, r10         /* register number in bit 24-29 */
    stwbrx  r9, r0, r1          /* write this value to CONFIG_ADDR */
    isync

    /* Register offset in r6 */
    andi.   r6, r6, 0x0003      /* valid register offset: 0, 1, 2, 3 */

    /* Evaluate data size in r7 */
    andi.   r7, r7, 0x0007      /* valid data sizes: 1, 2, 4 */
    cmpli   0, 0, r7, 0x0001    /* test for byte access */
    beq     pci_write_byte
    cmpli   0, 0, r7, 0x0002    /* test for half word (16 bit) access */
    beq     pci_write_hword
    cmpli   0, 0, r7, 0x0004    /* test for word (32 bit) access */
    beq     pci_write_word
    b       pci_write_end


pci_write_byte:
    stbx    r8, r6, r2
    b       pci_write_end

pci_write_hword:
    sthbrx  r8, r6, r2
    b       pci_write_end

pci_write_word:
    stwbrx  r8, r6, r2
    b       pci_write_end

pci_write_end:
    bclr    20,0        /* return to caller */



board_led_off:
    /* Switch off card fail LED */
    lis     r9,  HI(VG4_PORT_LOCKR)
    ori     r9,  r9, LO(VG4_PORT_LOCKR)
    li      r11, LOCKR_UNLOCK
    stb     r11, 0(r9)              /* Unlock extended register set on VG4 */

    lis     r10, HI(VG4_PORT_LEDCR)
    ori     r10, r10,LO(VG4_PORT_LEDCR)
    li      r11, LEDCR_LED_OFF
    stb     r11, 0(r10)             /* Switch LED off (register 0x168) */

    li      r11, LOCKR_LOCK
    stb     r11, 0(r9)              /* Lock extended register set on VG4 */
    blr


board_led_on:
    /* Switch on card fail LED */
    lis     r9,  HI(VG4_PORT_LOCKR)
    ori     r9,  r9, LO(VG4_PORT_LOCKR)
    li      r11, LOCKR_UNLOCK
    stb     r11, 0(r9)              /* Unlock extended register set on VG4 */

    lis     r10, HI(VG4_PORT_LEDCR)
    ori     r10, r10,LO(VG4_PORT_LEDCR)
    li      r11, LEDCR_LED_ON
    stb     r11, 0(r10)             /* Switch LED on (register 0x168) */

    li      r11, LOCKR_LOCK
    stb     r11, 0(r9)              /* Lock extended register set on VG4 */
    blr



wd_off:
    /* Switch off watchdog */
    lis     r9,  HI(VG4_PORT_LOCKR)
    ori     r9,  r9, LO(VG4_PORT_LOCKR)
    li      r11, LOCKR_UNLOCK
    stb     r11, 0(r9)              /* Unlock extended register set on VG4 */

    lis     r10, HI(VG4_PORT_WCR)
    ori     r10, r10,LO(VG4_PORT_WCR)
    li      r11, WCR_WD_OFF
    stb     r11, 0(r10)             /* Switch watchdog off (register 0x160) */

    li      r11, LOCKR_LOCK
    stb     r11, 0(r9)              /* Lock extended register set on VG4 again */
    blr


wd_on:
    /* Switch on watchdog */
    lis     r9,  HI(VG4_PORT_LOCKR)
    ori     r9,  r9, LO(VG4_PORT_LOCKR)
    li      r11, LOCKR_UNLOCK
    stb     r11, 0(r9)              /* Unlock extended register set on VG4 */

    lis     r10, HI(VG4_PORT_WCR)
    ori     r10, r10,LO(VG4_PORT_WCR)
    li      r11, WCR_WD_ON
    stb     r11, 0(r10)             /* Switch watchdog on (register 0x160) */

    li      r11, LOCKR_LOCK
    stb     r11, 0(r9)              /* Lock extended register set on VG4 again */
    blr




/*
;
;   This function initializes the superio chip to a functional
;   state.
;
;   Upon completion, SIO resource registers are mapped as follows:
;   Resource    Enabled     Address
;   FDC         Yes         PRI     3F0-3F7
;   IDE         No
;   UART1       Yes         COM1    3F8-3FF
;   UART2       Yes         COM2    2F8-2FF
;   ||PORT      Yes         LPT1    3BC-3BE
;   KBC         Yes         060, 064
;
;
*/



sio_init:
    mflr    r13                         /* save link register */


    /*
     * Get base addr of ISA I/O space
     */
    lis     r6, HI(CPU_PCI_ISA_IO_ADRS)
    ori     r6, r6,LO(CPU_PCI_ISA_IO_ADRS)

    addi    r6, r6, M1543C_SIO_CNF_PORT /* add offset to base */
    or      r3, r6, r6                  /* make a copy */

    /*
     * Enter configuration mode
     */
    addi    r4, r0, 0x51
    stb     r4, 0(r3)                   /* write config port with configuration key */
    isync
    addi    r4, r0, 0x23
    stb     r4, 0(r3)                   /* write config port with configuration key */
    isync


    bl      check_config_mode


    /*
     * Disable all Super I/O Devices
     */

    /*
     * FDC (LUN 0x0)
     */
    addi    r4, r0, M1543C_SIO_LUN_FDC  /* select FDC LUN */
    bl      sio_disable
    /*
     * LPT (LUN 0x3)
     */
    addi    r4, r0, M1543C_SIO_LUN_LPT  /* select LPT LUN */
    bl      sio_disable
    /*
     * COM1 (LUN 0x4)
     */
    addi    r4, r0, M1543C_SIO_LUN_COM1 /* select COM1 LUN */
    bl      sio_disable
    /*
     * COM2 (LUN 0x5)
     */
    addi    r4, r0, M1543C_SIO_LUN_COM2 /* select COM2 LUN */
    bl      sio_disable
    /*
     * KBC (LUN 0x7)
     */
    addi    r4, r0, M1543C_SIO_LUN_KBC  /* select keyboard LUN */
    bl      sio_disable
    /*
     * UART3 (LUN 0xb)
     */
    addi    r4, r0, M1543C_SIO_LUN_UART3 /* select UART3 LUN */
    bl      sio_disable
    /*
     * HOTKEY (LUN 0xb)
     */
    addi    r4, r0, M1543C_SIO_LUN_HOTK /* select HOTKEY LUN */
    bl      sio_disable
    b       sio_dev_init


sio_soft_reset:
    /*
     * Soft reset of the configuration registers
     */
    addi    r4, r0, M1543C_SIO_RESET    /* reset super i/o */
    addi    r5, r0, 0x01
    bl      sio_bw


    li  r0, 0x4000
    mtctr   r0
wait_sio:
    bdnz    wait_sio


sio_dev_init:
    /*
     * Configure the desired Super I/O Devices
     */

    /*
     * FDC (LUN 0x0)
     */
    addi    r4, r0, M1543C_SIO_LUN_IDX  /* select FDC LUN */
    addi    r5, r0, M1543C_SIO_LUN_FDC
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_HIAR     /* initialize FDC address */
    addi    r5, r0, HI_ADR(M1543C_FDC_IO_ADRS)
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_LOAR
    addi    r5, r0, LO_ADR(M1543C_FDC_IO_ADRS)
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_IRQR     /* initialize FDC (irq 5) */
    addi    r5, r0, M1543C_FDC_IRQ
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_DMAR     /* initialize FDC DMA (channel 2) */
    addi    r5, r0, M1543C_FDC_DMA
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_CNFR     /* initialize FDC configuration: PS2 mode */
    addi    r5, r0, 0x88
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_ENR      /* enable FDC */
    addi    r5, r0, M1543C_SIO_LUN_ENABLE
    bl      sio_bw
    /*
     * LPT (LUN 0x3)
     */
    addi    r4, r0, M1543C_SIO_LUN_IDX  /* select LPT LUN */
    addi    r5, r0, M1543C_SIO_LUN_LPT
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_HIAR     /* initialize LPT address (0x3bc) */
    addi    r5, r0, HI_ADR(M1543C_LPT_IO_ADRS)
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_LOAR
    addi    r5, r0, LO_ADR(M1543C_LPT_IO_ADRS)
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_IRQR     /* initialize LPT irq (7) */
    addi    r5, r0, M1543C_LPT_IRQ
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_DMAR     /* initialize LPT DMA channel 3 */
    addi    r5, r0, M1543C_LPT_DMA
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_CNFR     /* initialize LPT default configuration: IRQ active low, ECP fifi treshold 0001, SPP mode*/
    addi    r5, r0, 0x8C
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_CNF2R    /* initialize LPT default configuration: ext mode, 12MHz clock, no EPP timeout interrupt, burtst mode DMAin ECP */
    addi    r5, r0, 0x85
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_ENR      /* enable LPT */
    addi    r5, r0, M1543C_SIO_LUN_ENABLE
    bl      sio_bw
    /*
     * COM1 (LUN 0x4)
     */
    addi    r4, r0, M1543C_SIO_LUN_IDX  /* select COM1 LUN */
    addi    r5, r0, M1543C_SIO_LUN_COM1
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_HIAR     /* initialize COM1 address (0x3f8) */
    addi    r5, r0, HI_ADR(M1543C_COM1_IO_ADRS)
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_LOAR
    addi    r5, r0, LO_ADR(M1543C_COM1_IO_ADRS)
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_IRQR     /* initialize COM1 irq (4) */
    addi    r5, r0, M1543C_COM1_IRQ
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_CNFR     /* initialize COM1 default configuration: normal clock source, high speed mode disabled, midi disabled */
    addi    r5, r0, 0x00
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_ENR      /* enable COM1 */
    addi    r5, r0, M1543C_SIO_LUN_ENABLE
    bl      sio_bw
    /*
     * COM2 (LUN 0x5)
     */
    addi    r4, r0, M1543C_SIO_LUN_IDX  /* select COM2 LUN */
    addi    r5, r0, M1543C_SIO_LUN_COM2
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_HIAR     /* initialize COM2 address (0x2f8) */
    addi    r5, r0, HI_ADR(M1543C_COM2_IO_ADRS)
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_LOAR
    addi    r5, r0, LO_ADR(M1543C_COM2_IO_ADRS)
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_IRQR     /* initialize COM1 irq (3) */
    addi    r5, r0, M1543C_COM2_IRQ
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_ENR      /* enable COM2 */
    addi    r5, r0, M1543C_SIO_LUN_ENABLE
    bl      sio_bw
    /*
     * KBC (LUN 0x7)
     */
    addi    r4, r0, M1543C_SIO_LUN_IDX  /* select keyboard LUN */
    addi    r5, r0, M1543C_SIO_LUN_KBC
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_IRQR     /* initialize keyboard irq (1) */
    addi    r5, r0, M1543C_KBC_IRQ
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_ENR      /* enable keyboard */
    addi    r5, r0, M1543C_SIO_LUN_ENABLE
    bl      sio_bw



    /*
     * Enable all desired Super I/O Devices
     */

    /*
     * FDC (LUN 0x0)
     */
    addi    r4, r0, M1543C_SIO_LUN_FDC  /* select FDC LUN */
    bl      sio_enable
    /*
     * LPT (LUN 0x3)
     */
    addi    r4, r0, M1543C_SIO_LUN_LPT  /* select LPT LUN */
    bl      sio_enable
    /*
     * COM1 (LUN 0x4)
     */
    addi    r4, r0, M1543C_SIO_LUN_COM1 /* select COM1 LUN */
    bl      sio_enable
    /*
     * COM2 (LUN 0x5)
     */
    addi    r4, r0, M1543C_SIO_LUN_COM2 /* select COM2 LUN */
    bl      sio_enable
    /*
     * KBC (LUN 0x7)
     */
    addi    r4, r0, M1543C_SIO_LUN_KBC  /* select keyboard LUN */
    bl      sio_enable



    /*
     * Exit configuration mode
     */
    addi    r4, r0, 0xbb
    stb     r4, 0(r3)                   /* write config port with exit key */
    isync
    mtlr    r13                         /* restore link register */
    blr


/*
; routine: sio_enable
;   this function enables one device of the SIO chip
; call:
;   sio_enable(r3=sioaddr, r4=device LUN)
; return:
;   none
*/
sio_enable:
    mflr    r14                         /* save link register */
    or      r5, r4, r4                  /* copy device LUN from r4 to r5 */
    addi    r4, r0, M1543C_SIO_LUN_IDX  /* select index register */
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_ENR      /* enable device */
    addi    r5, r0, M1543C_SIO_LUN_ENABLE
    bl      sio_bw
    mtlr    r14                         /* restore link register */
    blr

/*
; routine: sio_disable
;   this function disables one device of the SIO chip
; call:
;   sio_disable(r3=sioaddr, r4=device LUN)
; return:
;   none
*/
sio_disable:
    mflr    r14                         /* save link register */
    or      r5, r4, r4                  /* copy device LUN from r4 to r5 */
    addi    r4, r0, M1543C_SIO_LUN_IDX  /* select index register */
    bl      sio_bw
    addi    r4, r0, M1543C_SIO_ENR      /* disable device */
    addi    r5, r0, M1543C_SIO_LUN_DISABLE
    bl      sio_bw
    mtlr    r14                         /* restore link register */
    blr

/*
; routine: sio_bw
;   this function writes a register to the SIO chip
; call:
;   sio_bw(sioaddr, regnum, value)
; return:
;   none
*/
sio_bw:
    stb     r4, 0(r3)                   /* write register offset to index port */
    eieio
    isync
    stb     r5, 1(r3)                   /* write value to data port */
    eieio
    isync
    bclr    20,0                        /* return to caller */
/*
; routine: sio_br
;   this function reads a register from the SIO chip
; call:
;   sioInit(sioaddr, regnum)
; return:
;   register value
*/
sio_br:
    stb     r4, 0(r3)                   /* write index register with register offset */
    eieio
    isync
    lbz     r3, 1(r3)                   /* retrieve specified reg offset contents */
    eieio
    isync
    bclr    20, 0                       /* return to caller */


check_config_mode:
    mflr    r14                         /* save link register */
    mr      r3, r6                      /* r6 contains config port fo super i/o */
    addi    r4, r0, 0x20                /* read device identification registers 0x20 */
    bl      sio_br
    cmpli   0, 0, r3, 0x43              /* compare with ALI defined value */
    bne     error_loop

    mr      r3, r6                      /* r6 contains config port fo super i/o */
    addi    r4, r0, 0x21                /* read device identification registers 0x21 */
    bl      sio_br
    cmpli   0, 0, r3, 0x15              /* compare with ALI defined value */
    bne     error_loop

    mr      r3, r6                      /* r6 contains config port fo super i/o */
    mtlr    r14                         /* restore link register */
    blr                                 /* return to calling function */


error_loop:
    bl      board_led_on
    lis     r0, 0x400
    mtctr   r0
    bdnz .
    bl      board_led_off
    mtctr   r0
    bdnz .
    b       error_loop

/*
 *  I2C code for reading out the contents of the SPD eeprom.
 *  Very rudimentary and not intended to be general purpose!
 *  Reads one byte at specified offset.
 */

    .globl  i2c_init
i2c_init:
    lis 9, HIADJ(MPC107_I2C_ADR)
    addi    10, 9, LO(MPC107_I2C_CCR)
    lwbrx   3, 0, 10
    andi.   3, 3, ~I2C_CCR_MEN & 0xffff /* Disable */
    stwbrx  3, 0, 10
    addi    10, 9, LO(MPC107_I2C_FDR)
    lwbrx   3, 0, 10
    lis 0, 0xffff
    ori 0, 0, 0xffc0
    and 3, 3, 0
    ori 3, 3, 0x31      /* Frequency divider */
    stwbrx  3, 0, 10

    addi    10, 9, LO(MPC107_I2C_ADR)
    lwbrx   3, 0, 10
    lis 0, 0xffff
    ori 0, 0, 0xffc0
    and 3, 3, 0
    ori 3, 3, 0x02      /* Set slave address */
    stwbrx  3, 0, 10

    addi    10, 9, LO(MPC107_I2C_CCR)
    lwbrx   3, 0, 10
    ori 3, 3, 0x80      /* Master enable */
    stwbrx  3, 0, 10
    blr
/**/

/* 3 = offs */
    .globl  i2c_read
i2c_read:
    lis 9, HIADJ(MPC107_I2C_ADR)
    addi    10, 9, LO(MPC107_I2C_CSR)
    li  0, 0x0
    stwbrx  0, 0, 10        /* Clear status */
    IORDER

    addi    10, 9, LO(MPC107_I2C_CCR)
    li  0, I2C_CCR_MEN|I2C_CCR_MSTA|I2C_CCR_MTX
    stwbrx  0, 0, 10        /* Startup! */
    IORDER

    addi    10, 9, LO(MPC107_I2C_CDR)
    li  0, 0xa0         /* Write access + slave addr 0x50 */
    stwbrx  0, 0, 10
    IORDER

1:
    addi    10, 9, LO(MPC107_I2C_CSR)
    lwbrx   0, 0, 10        /* Read status */
    andi.   0, 0, I2C_CSR_MIF   /* Check interrupt MSTA */
    beq 1b          /* 0 == Nothing yet */

    li  0, 0x0
    stwbrx  0, 0, 10        /* Clear status */
    IORDER

    addi    10, 9, LO(MPC107_I2C_CDR)
    stwbrx  3, 0, 10        /* Output offset */
    IORDER

2:
    addi    10, 9, LO(MPC107_I2C_CSR)
    lwbrx   0, 0, 10        /* Read status */
    andi.   3, 0, I2C_CSR_MIF   /* Check interrupt MSTA */
    beq 2b          /* 0 == Nothing yet */

    li  0, 0x0
    stwbrx  0, 0, 10        /* Clear status */
    IORDER

    addi    10, 9, LO(MPC107_I2C_CCR)
    lwbrx   0, 0, 10
    ori 0, 0, I2C_CCR_RSTA
    stwbrx  0, 0, 10        /* Restart */
    IORDER

    addi    10, 9, LO(MPC107_I2C_CDR)
    li  0, 0xa1         /* Read access + slave addr 0x50 */
    stwbrx  0, 0, 10
    IORDER

3:
    addi    10, 9, LO(MPC107_I2C_CSR)
    lwbrx   0, 0, 10        /* Read status */
    andi.   0, 0, I2C_CSR_MIF   /* Check interrupt MSTA */
    beq 3b          /* 0 == Nothing yet */

    li  0, 0x0
    stwbrx  0, 0, 10        /* Clear status */
    IORDER

    addi    10, 9, LO(MPC107_I2C_CCR)
    lwbrx   0, 0, 10
    andi.   0, 0, ~(I2C_CCR_MTX|I2C_CCR_RSTA) & 0xffff
    ori 0, 0, I2C_CCR_TXAK
    stwbrx  0, 0, 10
    IORDER

    addi    10, 9, LO(MPC107_I2C_CDR)
    lwbrx   0, 0, 10
    IORDER


4:
    addi    10, 9, LO(MPC107_I2C_CSR)
    lwbrx   0, 0, 10        /* Read status */
    andi.   0, 0, I2C_CSR_MIF   /* Check interrupt MSTA */
    beq 4b          /* 0 == Nothing yet */


    addi    10, 9, LO(MPC107_I2C_CCR)
    lwbrx   0, 0, 10
    andi.   0, 0, ~I2C_CCR_MSTA & 0xffff
    stwbrx  0, 0, 10
    IORDER

    addi    10, 9, LO(MPC107_I2C_CDR)
    lwbrx   3, 0, 10

    lis 0, 16
    mtctr   0
1:
    bdnz    1b          /* Delay to settle */

    blr


/*
 * MemInit2
*/
memInit2:
#if defined (ADRS_MAP_PREP)
	/* reload r1 and r2 for PReP PCI configuration access */
    lis r1, HI(MPC107_CFG_ADDR_PREP) 	/* r1 = PCI config address register */
    ori r1, r1, LO(MPC107_CFG_ADDR_PREP)
    lis r2, HI(MPC107_CFG_DATA_PREP) 	/* r2 = PCI config data register */
    ori r2, r2, LO(MPC107_CFG_DATA_PREP)
#else
	/* reload r1 and r2 for CHRP PCI configuration access */
    lis r1, HI(MPC107_CFG_ADDR_CHRP) 	/* r1 = PCI config address register */
    ori r1, r1, LO(MPC107_CFG_ADDR_CHRP)
    lis r2, HI(MPC107_CFG_DATA_CHRP) 	/* r2 = PCI config data register */
    ori r2, r2, LO(MPC107_CFG_DATA_CHRP)
#endif /* defined (ADRS_MAP_PREP) */


    /*
     * Make sure we're disabling RAM interface logic
     * by clearing MEMGO bit.  Needed for warm boots
     */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MCCR1    /* register number 0xf0 */
    stwbrx  r3, r0, r1          /* write this value to CONFIG_ADDR */
    isync

    lwbrx   r4, r0, r2          /* load r4 from CONFIG_DATA */
    lis r0, 0xfff7              /* MEMGO=0 */
    ori r0, r0, 0xffff

    and r4, r4, r0              /* Clear MEMGO bit */
    stwbrx  r4, r0, r2          /* write modified data to CONFIG_DATA */


    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3,MPC107_MCCR1     /* register number 0xf0 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
    lwbrx   r4, 0, r2           /* load r4 from CONFIG_DATA */

    /* REDUCE WAIT STATES FOR ROM ACCESSES */
#ifdef MPC107_66 /* 66 MHz */
    lis r0, 0x0480              /* ROMNAL: 0 , ROMFAL: 9*/
#else /* 100 MHz */
    lis r0, 0x0780              /* ROMNAL: 0 , ROMFAL: 15*/
#endif


    cmpwi   r19,512
    bne     m1_256
    ori r0, r0, 0x000a          /* 2 banks with 13 row bits (SDRAM) */
    b       m1_done

m1_256:
    cmpwi   r19,256
    bne     m1_128
    ori r0, r0, 0x0002          /* 1 bank with 13 row bits (SDRAM) */
    b       m1_done

/* 64, 128 MB */
m1_128:
    ori r0, r0, 0x0000          /* 1 bank with 12 row bits (SDRAM) */

m1_done:
    and r4, r4, r0              /* clears the desired bits */
    or  r4, r4, r0              /* sets the desired bits */
    stwbrx  r4, 0, r2           /* write mdfd data to CONFIG_DATA */

    lis r3, CHAPARRAL_REG       /* start building new register number */
    ori r3, r3, MPC107_MCCR2    /* register number 0xf4 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync

    lis r4, 0x0000
#ifdef MPC107_66 /* 66 MHz */
    oris    r4, r4, 0x6000      /* TS_WAIT_TIMER = 4 clocks (for 55 ns) */
#else /* 100 MHz */
    oris    r4, r4, 0xa000      /* TS_WAIT_TIMER = 6 clocks (for 55 ns) */
#endif
    oris    r4, r4, 0x0008      /* SDRAM inline writes */
    oris    r4, r4, 0x0004      /* SDRAM inline reads */


#ifdef MPC107_66 /* 66 MHz */
    ori     r4, r4, 0x0920      /* Refresh:  66 MHz mem bus */
#else /* 100 MHz */             /*           649 - 65 (10% security) = 584 */
    ori     r4, r4, 0x0f30      /* Refresh: 100 MHz mem bus */
#endif                          /*          1080 - 108 (10% security) = 972  */
/*  ori     r4, r4, 0x0002 */   /* Reserve a page */
    ori     r4, r4, 0x0001      /* RWM parity */
    stwbrx  r4, 0, r2           /* write mdfd data to CONFIG_DATA */

    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MCCR3    /* register number 0xf8 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
    lwbrx   r4, 0, r2           /* load r4 from CONFIG_DATA */

    lis r0, 0x000f              /* Bits 31 .. 20 used for SDRAM */
    ori r0, r0, 0xffff
    and r4, r4, r0

    lis     r0, 0x7000          /* BSTOPRE_M = 7 (see A/N) */
#ifdef MPC107_66 /* 66 MHz */
    oris    r0, r0, 0x0540      /* REFREC    = 5 clocks */
                                /* RDLAT     = 4 clocks (CAS latency + 1 for registered buffer mode) */
                                /*                      (CAS latency + 2 for in-line buffer mode) */
#else /* 100 MHz */
    oris    r0, r0, 0x0750      /* REFREC    = 7 clocks */
                                /* RDLAT     = 5 clocks (CAS latency + 1 for registered buffer mode) */
                                /*                      (CAS latency + 2 for in-line buffer mode) */
#endif

    or  r4, r4, r0              /* sets the desired bits */
    stwbrx  r4, 0, r2           /* write mdfd data to CONFIG_DATA */


    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MCCR4        /* register number 0xfc */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
    lwbrx   r4, 0, r2           /* load r4 from CONFIG_DATA */

    lis r0, 0x0083
    and r4, r4, r0
#ifdef MPC107_66 /* 66 MHz */
    lis     r0, 0x2000          /* PRETOACT = 2 clocks              */
    oris    r0, r0, 0x0462      /* ACTOPRE  = 4 clocks              */
                                /* Enable Inline ECC/Parity         */
                                /* Enable Extended ROM (RCS2/RCS3)  */
                                /* BSTOPRE_U = 0 (see A/N)          */
                                /* RCS1 is 8-bits                   */
    ori     r0, r0, 0x2239      /* CAS Latency (CL=2) (see RDLAT)   */
                                /* Sequential wrap/4-beat burst     */
                                /* ACTORW  = 3 clocks               */
                                /* BSTOPRE_L = 9 (see A/N)          */
#else /* 100 MHz */
    lis     r0, 0x2000          /* PRETOACT = 2 clocks              */
    oris    r0, r0, 0x0562      /* ACTOPRE  = 5 clocks              */
                                /* Enable Inline ECC/Parity         */
                                /* Enable Extended ROM (RCS2/RCS3)  */
                                /* BSTOPRE_U = 0 (see A/N)          */
                                /* RCS1 is 8-bits                   */
    ori     r0, r0, 0x3239      /* CAS Latency (CL=3) (see RDLAT)   */
                                /* Sequential wrap/4-beat burst     */
                                /* ACTORW  = 3 clocks               */
                                /* BSTOPRE_L = 9 (see A/N)          */
#endif

    or  r4, r4, r0              /* sets the desired bits */
    stwbrx  r4, 0, r2           /* write mdfd data to CONFIG_DATA */

    /* Disable all memory banks first */
    li  r0, 0x0000              /* Disable all 8 banks of DRAM */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MBEN     /* register number 0xa0 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
    stb r0, 0(r2)               /* write mdfd data to CONFIG_DATA */

    /* Set starting address, banks 0-3 */
    xor r4, r4, r4
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MSAR1    /* register number 0x80 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync

/* if SDRAM_SIZE >= 256 */
    cmpwi   r19,256
    blt     m2_128
    addis   r4, r0, 0x8000
    ori r4, r4, 0x0000
    b       m2_done

/* if SDRAM_SIZE == 128 */
m2_128:
    cmpwi   r19,128
    bne     m2_64
    addis   r4, r0, 0x8000
    ori r4, r4, 0x8000
    b       m2_done

/* default: SDRAM_SIZE == 64 */
m2_64:
    addis   r4, r0, 0xc080
    ori r4, r4, 0x4000

m2_done:
    stwbrx  r4, 0, r2

    /* Set starting address, banks 4-7 */
    xor r4, r4, r4
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MSAR2    /* register number 0x84 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync

/* if SDRAM_SIZE >= 256 */
    cmpwi   r19,256
    blt     m3_128
    addis   r4, r0, 0xc080
    ori r4, r4, 0x4000
    b       m3_done

/* elif SDRAM_SIZE == 128 */
m3_128:
    cmpwi   r19,128
    bne     m3_64
    addis   r4, r0, 0x8000
    ori r4, r4, 0x8000
    b       m3_done

/* default: SDRAM_SIZE == 64 */
m3_64:
    addis   r4, r0, 0x0000
    ori r4, r4, 0x8000

m3_done:
    stwbrx  r4, 0, r2

    /* Set extended starting address, banks 0-3 */
    lis r3, CHAPARRAL_REG       /* Starting address of extended memory is 0 */
    ori r3, r3, MPC107_EMSAR1   /* register number 0x88 */
    stwbrx  r3, 0, r1
    isync

/* if SDRAM_SIZE >= 256 */
    cmpwi   r19,256
    blt     m4_128
    addis   r4, r0, 0x0202
    ori r4, r4, 0x0100
    b       m4_done

/* elif SDRAM_SIZE == 128 */
m4_128:
    cmpwi   r19,128
    bne     m4_64
    addis   r4, r0, 0x0101
    ori r4, r4, 0x0000
    b       m4_done

/* default: SDRAM_SIZE == 64 */
m4_64:
    addis   r4, r0, 0x0000
    ori r4, r4, 0x0000

m4_done:
    stwbrx  r4, 0, r2

    /* Set extended starting address, banks 4-7 */
    lis r3, CHAPARRAL_REG       /* Starting address of extended memory is 0 */
    ori r3, r3, MPC107_EMSAR2   /* register number 0x8c */
    stwbrx  r3, 0, r1
    isync

/* if SDRAM_SIZE >= 256 */
    cmpwi   r19,256
    blt     m5_128
    addis   r4, r0, 0x0303
    ori r4, r4, 0x0303
    b       m5_done

/* elif SDRAM_SIZE == 128 */
m5_128:
    cmpwi   r19,128
    bne     m5_64
    addis   r4, r0, 0x0303
    ori r4, r4, 0x0202
    b       m5_done

/* default: SDRAM_SIZE == 64 */
m5_64:
    addis   r4, r0, 0x0302
    ori r4, r4, 0x0101

m5_done:
    stwbrx  r4, 0, r2

    /* Set ending address, banks 0-3 */
    lis r4, 0
    ori r4, r4, 0x003f          /* 64 MB */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MEAR1    /* register number 0x90 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync
/* if SDRAM_SIZE >= 256 */
    cmpwi   r19,256
    blt     m6_128
    addis   r4, r0, 0xff7f
    ori r4, r4, 0xffff
    b       m6_done

/* elif SDRAM_SIZE == 128 */
m6_128:
    cmpwi   r19,128
    bne     m6_64
    addis   r4, r0, 0xff7f
    ori r4, r4, 0xff7f
    b       m6_done

/* default: SDRAM_SIZE == 64 */
m6_64:
    addis   r4, r0, 0xffbf
    ori r4, r4, 0x7f3f

m6_done:
    stwbrx  r4, 0, r2

    /* Set ending address, banks 4-7 */
    xor r4, r4, r4
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MEAR2    /* register number 0x94 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync

/*if SDRAM_SIZE >= 256 */
    cmpwi   r19,256
    blt     m7_128
    addis   r4, r0, 0xffbf
    ori r4, r4, 0x7f3f
    b       m7_done

/* elif SDRAM_SIZE == 128 */
m7_128:
    cmpwi   r19,128
    bne     m7_64
    addis   r4, r0, 0xff7f
    ori r4, r4, 0xff7f
    b       m7_done

/* default: SDRAM_SIZE == 64 */
m7_64:
    addis   r4, r0, 0xffff
    ori r4, r4, 0xff7f

m7_done:
    stwbrx  r4, 0, r2

    /* Set extended ending address, banks 0-3 */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_EMEAR1   /* register number 98 */
    stwbrx  r3, 0, r1
    isync
/* if SDRAM_SIZE >= 256 */
    cmpwi   r19,256
    blt     m8_128
    addis   r4, r0, 0x0202
    ori r4, r4, 0x0100
    b       m8_done

/* elif SDRAM_SIZE == 128 */
m8_128:
    cmpwi   r19, 128
    bne     m8_64
    addis   r4, r0, 0x0101
    ori r4, r4, 0x0000
    b       m8_done

/* default: SDRAM_SIZE == 64 */
m8_64:
    addis   r4, r0, 0x0000
    ori r4, r4, 0x0000

m8_done:
    stwbrx  r4, 0, r2

    /* Set extended ending address, banks 4-7 */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_EMEAR2   /* register number 9c */
    stwbrx  r3, 0, r1
    isync

/* if SDRAM_SIZE >= 256 */
    cmpwi   r19,256
    blt     m9_128
    addis   r4, r0, 0x0303
    ori r4, r4, 0x0303
    b       m9_end

/* elif SDRAM_SIZE == 128 */
m9_128:
    cmpwi   r19, 128
    bne     m9_64
    addis   r4, r0, 0x0303
    ori r4, r4, 0x0202
    b       m9_end

/* default: SDRAM_SIZE == 64 */
m9_64:
    addis   r4, r0, 0x0302
    ori r4, r4, 0x0101

m9_end:
    stwbrx  r4, 0, r2

    /* Set memory bank enable */
    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MBEN     /* register number 0xa0 */
    stwbrx  r3, 0, r1           /* write this value to CONFIG_ADDR */
    isync

    li  r4, 0x01                /* Enable bank 0 */
/* if SDRAM_SIZE >= 512 */
    cmpwi   r19,512
    blt     m10_1
    ori r4, r4, 0x02            /* Enable bank 1 */
m10_1:
    stb r4, 0(r2)               /* Enable bank(s) of memory */


    /* Set memory page mode */
    lis r3, CHAPARRAL_REG               /* start building new reg number */
    ori r3, r3, REG_BASE(MPC107_MPMR)   /* register number 0xa3 */
    stwbrx  r3, 0, r1                   /* write this value to CONFIG_ADDR */
    isync

#ifdef MPC107_66 /* 66 MHz */
    li  r4, 0x55                /* ( 6600 - 1112 - 2) / 64 =  85 = 0x55 */
#else /* 100 MHz */
    li  r4, 0x8A                /* (10000 - 1112 - 2) / 64 = 138 = 0x8A */
#endif
    stb r4, REG_OFF(MPC107_MPMR)(r2)        /* Set Memory Page Mode */


    /*
        DRAM SHOULD NOW BE CONFIGURED AND ENABLED -
        MUST WAIT BEFORE ACCESSING
    */

memgo2:
    li  r0, 0x2000
    mtctr   r0

wait3:
    bdnz    wait3

    lis r3, CHAPARRAL_REG       /* start building new reg number */
    ori r3, r3, MPC107_MCCR1    /* register number 0xf0 */
    stwbrx  r3, r0, r1          /* write this value to CONFIG_ADDR */
    isync

    lwbrx   r4, r0, r2          /* load r4 from CONFIG_DATA */
    lis r0, 0x0008              /* MEMGO=1 */
    ori r0, r0, 0x0000
    or  r4, r4, r0              /* set the MEMGO bit */
    stwbrx  r4, r0, r2          /* write mdfd data to CONFIG_DATA */

    li  r0, 0x2000              /* approx decimal 8000 */
    mtctr   r0

wait4:
    bdnz    wait4
    blr

/******************************************************************************
*
* dCacheOn - Turn Data Cache On
*
* void dCacheOn (void)
*/

_dCacheOn:
dCacheOn:
    /* Get cpu type */

    mfspr  r3, PVR
    rlwinm r3, r3, 16, 16, 31

    cmpli  0, 0, r3, CPU_TYPE_750
    bc     12, 2, ccdataon
    cmpli  0, 0, r3, CPU_TYPE_7400
    bc     12, 2, ccdataon
    cmpli  0, 0, r3, CPU_TYPE_7410
    bc     12, 2, ccdataon
    bclr   0x14, 0x0            /* invalid cpu type */

ccdataon:
    mfspr  r4, HID0             /* Modify HID0 to enable D cache (DCE) */
    ori    r4, r4, _PPC_HID0_DCE
    sync                        /* required before changing DCE */
    mtspr  HID0, r4
    bclr   0x14, 0x0            /* return to caller */

/******************************************************************************
*
* dCacheOff - Turn Data Cache Off
*
* void dCacheOff (void)
*/

_dCacheOff:
dCacheOff:
    /* Get cpu type */

    mfspr  r3, PVR
    rlwinm r3, r3, 16, 16, 31

    cmpli  0, 0, r3, CPU_TYPE_750
    bc     12, 2, ccDataOff
    cmpli  0, 0, r3, CPU_TYPE_7400
    bc     12, 2, ccDataOff
    cmpli  0, 0, r3, CPU_TYPE_7410
    bc     12, 2, ccDataOff
    bclr   0x14, 0x0            /* invalid cpu type */

ccDataOff:
    mfspr  r4, HID0             /* Modify HID0 to disable D cache (DCE) */
    rlwinm r4, r4, 0, _PPC_HID0_BIT_DCE+1, _PPC_HID0_BIT_DCE-1    /* clear DCE */
    sync                        /* required before changing DCE */
    mtspr  HID0, r4
    bclr   0x14, 0x0            /* return to caller */

/******************************************************************************
*
* dCacheInval - Invalidate Data Cache
*
* void dCacheInval (void)
*/

_dCacheInval:
dCacheInval:
    /* Get cpu type */

    mfspr  r3, PVR
    rlwinm r3, r3, 16, 16, 31

    cmpli  0, 0, r3, CPU_TYPE_750
    bc     12, 2, ccDataInvl
    cmpli  0, 0, r3, CPU_TYPE_7400
    bc     12, 2, ccDataInvl
    cmpli  0, 0, r3, CPU_TYPE_7410
    bc     12, 2, ccDataInvl
    bclr   0x14, 0x0            /* invalid cpu type */

    /*
     * To invalidate the Data Cache on a 750,  it's necessary
     * to set the DCFI bit while the Data Cache is enabled (DCE).
     */
    
ccDataInvl:
    addis  r3, r0, 0x0000       /* Setup bit pattern for DCFI + DCE */
    ori    r3, r3, (_PPC_HID0_DCE | _PPC_HID0_DCFI)

    mfspr  r4, HID0             /* Modify HID0 to SET DCFI + DCE bits */
    or     r4, r4, r3
    sync                        /* required before changing DCE */
    mtspr  HID0, r4

    andc   r4, r4, r3           /* Modify HID0 to CLEAR DCFI + DCE bits */
    sync                        /* required before changing DCE */
    mtspr  HID0, r4
    bclr   0x14, 0x0            /* return to caller */

#if defined(ROM_DEBUG)    
#include "rom_debug.s"
#endif