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

    .globl __pci_config_read_32
__pci_config_read_32:
    lis     r4, 0xfec0
    stwbrx   r3, r0, r4
    sync
    lis     r4, 0xfee0
    lwbrx   r3, 0, r4
    blr
    .globl __pci_config_read_16
__pci_config_read_16:
    lis     r4, 0xfec0
    andi.    r5, r3, 2
    stwbrx  r3, r0, r4
    sync
    oris     r4, r5, 0xfee0
    lhbrx    r3, r0, r4
    blr
    .globl __pci_config_read_8
__pci_config_read_8:
    lis     r4, 0xfec0
    andi.    r5, r3, 3
    stwbrx  r3, r0, r4
    sync
    oris     r4, r5, 0xfee0
    lbz      r3, 0(4)
    blr
    .globl __pci_config_write_32
__pci_config_write_32:
    lis     r5, 0xfec0
    stwbrx   r3, r0, r5
    sync
    lis      r5, 0xfee0
    stwbrx   r4, r0, r5
    sync
    blr
    .globl __pci_config_write_16
__pci_config_write_16:
    lis     r5, 0xfec0
    andi.    r6, r3, 2
    stwbrx  r3, r0, 5
    sync
    oris     r5, r6, 0xfee0
    sthbrx    r4, r0, r5
    sync
    blr
    .globl __pci_config_write_8
__pci_config_write_8:
    lis      r5, 0xfec0
    andi.    r6, r3, 3
    stwbrx   r3, r0, r5
    sync
    oris      r5, r6, 0xfee0
    stb       r4, 0(r5)
    sync
    blr
    .globl  in_8
in_8:
    oris    r3, r3, 0xfe00
    lbz     r3,0(r3)
    blr
    .globl  in_16
in_16:
    oris    r3, r3, 0xfe00
    lhbrx   r3, 0, r3
    blr
    .globl in_16_ne
in_16_ne:
    oris    r3, r3, 0xfe00
    lhzx    r3, 0, r3
    blr
    .globl  in_32
in_32:
    oris    r3, r3, 0xfe00
    lwbrx   r3, 0, r3
    blr
    .globl  out_8
out_8:
    oris    r3, r3, 0xfe00
    stb     r4, 0(r3)
    eieio
    blr
    .globl  out_16
out_16:
    oris    r3, r3, 0xfe00
    sthbrx  r4, 0, r3
    eieio
    blr
    .globl  out_16_ne
out_16_ne:
    oris    r3, r3, 0xfe00
    sth     r4, 0(r3)
    eieio
    blr
    .globl  out_32
out_32:
    oris    r3, r3, 0xfe00
    stwbrx  r4, 0, r3
    eieio
    blr
    .globl  read_8
read_8:
    lbz     r3,0(r3)
    blr
    .globl  read_16
read_16:
    lhbrx   r3, 0, r3
    blr
    .globl  read_32
read_32:
    lwbrx   r3, 0, r3
    blr
    .globl  read_32_ne
read_32_ne:
    lwz     r3, 0(r3)
    blr
    .globl  write_8
write_8:
    stb     r4, 0(r3)
    eieio
    blr
    .globl  write_16
write_16:
    sthbrx  r4, 0, r3
    eieio
    blr
    .globl  write_32
write_32:
    stwbrx  r4, 0, r3
    eieio
    blr
    .globl  write_32_ne
write_32_ne:
    stw     r4, 0(r3)
    eieio
    blr
  

.globl  early_init_f

early_init_f:
        mflr    r11
        lis     r10, 0x8000

        /* PCI Latency Timer */
        li      r4, 0x0d
        ori     r3, r10, PLTR@l
        bl      __pci_config_write_8
        
        /* Cache Line Size */
        li      r4, 0x08
        ori     r3, r10, PCLSR@l
        bl      __pci_config_write_8
        
        /* PCI Cmd */
        li      r4, 6
        ori     r3, r10, PCICR@l
        bl      __pci_config_write_16
        
#if 1
        /* PCI Stat */
        ori     r3, r10, PCISR@l
        bl      __pci_config_read_16
        ori     r4, r4, 0xffff
        ori     r3, r10, PCISR@l
        bl      __pci_config_write_16
#endif        

        /* PICR1 */
        lis     r4, 0xff14
        ori     r4, r4, 0x1b98
        ori     r3, r10, PICR1@l
        bl      __pci_config_write_32


        /* PICR2 */
        lis     r4, 0x0404
        ori     r4, r4, 0x0004
        ori     r3, r10, PICR2@l
        bl      __pci_config_write_32

	/* MIOCR1 */
        li      r4, 0x00
        ori     r3, r10, MIOCR1@l
        bl      __pci_config_write_8

	/* For the MPC8245, set register 77 to %00100000 (see Errata #15) */
	/* SDRAM_CLK_DEL (0x77)*/
        li      r4, 0x10
        ori     r3, r10, MIOCR2@l
        bl      __pci_config_write_8

        /* EUMBBAR */
        lis     r4, 0xfc00
        ori     r3, r10, EUMBBAR@l
        bl      __pci_config_write_32

	/* AMBOR */

       /* Even if Address Map B is not being used (though it should),
        * the memory DLL needs to be cleared/set/cleared before using memory.
	*/

        ori     r3, r10, AMBOR@l
        bl      __pci_config_read_8	/* get Current bits */

        andi.   r4, r4, 0xffdf
        ori     r3, r10, AMBOR@l
        bl      __pci_config_write_16	/* Clear DLL_RESET */

        ori    r4, r4, 0x0020
        ori     r3, r10, AMBOR@l
        bl      __pci_config_write_16	/* Set DLL_RESET */

        andi.   r4, r4, 0xffdf
        ori     r3, r10, AMBOR@l
        bl      __pci_config_write_16	/* Clear DLL_RESET */

	/* Preserve memgo bit */
        /* MCCR1 */

	lis     r4, 0x75a8               // Safe Local ROM = 11+3 clocks
//      lis     r4, 0x73a0               // Fast Local ROM = 7+3 clocks
//      oris    r4, r4, 0x0010           // Burst ROM/Flash enable
//      oris    r4, r4, 0x0004           // Self-refresh enable

//      ori     r4,r4,0xFFFF            // 16Mbit  2bank SDRAM
//      ori     r4,r4,0xAAAA            // 256Mbit 4bank SDRAM (8245 only)
//      ori     r4,r4,0x5555            // 64Mbit  2bank SDRAM
        ori     r4,r4,0x0000            // 64Mbit  4bank SDRAM

        ori     r3, r10, MCCR1@l
        bl      __pci_config_write_32

        /* MCCR2 */

        lis     r4,0x0000
/*      oris    r4,r4,0x4000            // TS_WAIT_TIMER = 3 clocks */
/*      oris    r4,r4,0x0400            // ASRISE = 2 clocks */
/*      oris    r4,r4,0x0040            // ASFALL = 2 clocks */
/*      oris    r4,r4,0x0010            // SDRAM Parity (else ECC) */
/*      oris    r4,r4,0x0008            // Write parity check */
/*      oris    r4,r4,0x0004            // SDRAM inline reads */


/* Select a refresh rate; it needs to match the bus speed; if too */
/* slow, data may be lost; if too fast, performance is lost.  We */
/* use the fastest value so we run at all speeds. */
/* Refresh = (15600ns/busclk) - (213 (see UM)). */

/*      ori     r4,r4,0x1d2c            // 133 MHz mem bus        = 1867 */
        ori     r4,r4,0x150c            /* 100 MHz mem bus        = 1347 */
/*      ori     r4,r4,0x10fc            //  83 MHz mem bus        = 1087 */
/*      ori     r4,r4,0x0cc4            //  66 MHz mem bus        =  817 */
/*      ori     r4,r4,0x04cc            //  33 MHz mem bus (SAFE) =  307 */

/*      ori     r4,r4,0x0002            // Reserve a page */
/*      ori     r4,r4,0x0001            // RWM parity */

        ori     r3, r10, MCCR2@l
        bl      __pci_config_write_32


        /* MCCR3 */
        lis     r4,0x7000               // BSTOPRE_M = 7 (see A/N)
        oris    r4,r4,0x0800            // REFREC    = 8 clocks
        ori     r3, r10, MCCR3@l
        bl      __pci_config_write_32

        /* MCCR4 */
        lis     r4, 0x3000              // PRETOACT = 3 clocks
        oris    r4,r4,0x0500            // ACTOPRE  = 5 clocks
        oris    r4,r4,0x0080            // Enable 8-beat burst (32-bit bus)
//      oris    r4,r4,0x0040            // Enable Inline ECC/Parity
        oris    r4,r4,0x0020            // EXTROM enabled
        oris    r4,r4,0x0010            // Registered buffers
//      oris    r4,r4,0x0000            // BSTOPRE_U = 0 (see A/N)
        oris    r4,r4,0x0002            // DBUS_SIZ[2] (8 bit on RCS1)

//      ori     r4,r4,0x8000            // Registered DIMMs
        ori     r4,r4,0x3000            // CAS Latency (CL=3) (see RDLAT)
//      ori     r4,r4,0x2000            // CAS Latency (CL=2) (see RDLAT)
//      ori     r4,r4,0x0300            // Sequential wrap/8-beat burst
        ori     r4,r4,0x0030            // ACTORW  = 3 clocks
        ori     r4,r4,0x0009            // BSTOPRE_L = 9 (see A/N)

        ori     r3, r10, MCCR4@l
        bl      __pci_config_write_32

	/* MSAR1 */
        lis     r4, 0xffffff00
        ori     r3, r10, MSAR1@l
        bl      __pci_config_write_32

	/* MSAR2 */
        lis     r4, 0xffffffff
        ori     r3, r10, MSAR2@l
        bl      __pci_config_write_32

	/* MESAR1 */
        lis     r4, 0x03030300@h
        li      r4, 0x03030300@l
        ori     r3, r10, EMSAR1@l
        bl      __pci_config_write_32

	/* MESAR2 */
        lis     r4, 0x03030303@h
        li      r4, 0x03030303@l
        ori     r3, r10, EMSAR2@l
        bl      __pci_config_write_32

	/* MEAR1 */
        lis     r4, 0xffffff7f@h
        li      r4, 0xffffff7f@l
        ori     r3, r10, MEAR1@l
        bl      __pci_config_write_32

	/* MEAR2 */
        lis     r4, 0xffffffff@h
        li      r4, 0xffffffff@l
        ori     r3, r10, MEAR2@l
        bl      __pci_config_write_32

	/* MEEAR1 */
        lis     r4, 0x03030300@h
        li      r4, 0x03030300@l
        ori     r3, r10, EMEAR1@l
        bl      __pci_config_write_32

	/* MEEAR2 */
        lis     r4, 0x03030303@h
        li      r4, 0x03030303@l
        ori     r3, r10, EMEAR2@l
        bl      __pci_config_write_32

	/* ODCR */
        li      r4, 0x1c
        ori     r3, r10, ODCR@l
        bl      __pci_config_write_8

	/* MBER */
        li      r4, 0x01
        ori     r3, r10, MBER@l
        bl      __pci_config_write_8

        /* Page CTR aka PGMAX */
        li      r4, 0x32
        ori     r3, r10, 0xa3
        bl      __pci_config_write_8
        
#if 0
	/* CLK Drive */
        ori     r4, r10, 0xfc01 /* Top bit will be ignored */
        ori     r3, r10, 0x74
        bl      __pci_config_write_16
#endif

	/* delay */ 
        lis     r7, 1
        mtctr   r7
label1: 	bdnz    label1

        /* Set memgo bit */
        /* MCCR1 */
        ori     r3, r10, MCCR1@l
        bl      __pci_config_read_32
        lis	r7, 0x0008
        or	r4, r3, r7
        ori     r3, r10, MCCR1@l
        bl      __pci_config_write_32

	/* delay again */ 
        lis     r7, 1
        mtctr   r7
label2: 	bdnz    label2

        mtlr    r11
        blr
        
