/*
 *  Memory sub-system initialization code for x200-GE-52T board.
 *
 *  Copyright (c) 2003	Wolfgang Denk <wd@denx.de>
 *
 * See file CREDITS for list of people who contributed to this
 * project.
 *
 * This program is free software; you can redistribute it and/or
 * modify it under the terms of the GNU General Public License as
 * published by the Free Software Foundation; either version 2 of
 * the License, or (at your option) any later version.
 *
 * This program is distributed in the hope that it will be useful,
 * but WITHOUT ANY WARRANTY; without even the implied warranty of
 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE.	 See the
 * GNU General Public License for more details.
 *
 * You should have received a copy of the GNU General Public License
 * along with this program; if not, write to the Free Software
 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
 * MA 02111-1307 USA
 */

#include <config.h>
#include <version.h>
#include <asm/regdef.h>
#include <asm/mipsregs.h>
#include <asm/addrspace.h>
#include <asm/cacheops.h>

#define BYTE_SEL(n)  ((n)^3)

#define X200_GE_GPIO_BASE		0x18000060
#define X200_GE_CHIPID_REG		0x18000000
#define X200_GE_CAP_REG			0x18000004
#define X200_GE_FLASH_CONTROL_REG	0x1800012c
#define X200_GE_NTLBENTRIES	32
#define X200_GE_ENUM		0x18000000 /* Beginning of core enum space */
#define X200_GE_MEMC_BASE		0x18008000
#define X200_GE_CORE_SIZE	        0x1000

#define M_C0_DCACHE_ENABLE	0x40000000 /* Dcache Enable */
#define M_C0_ICACHE_ENABLE	0x80000000 /* Icache Enable */
#define M_SR_SOFT_RESET		0x00100000 /* Soft reset */
#define M_SR_BOOT_EXCEPT_VEC	0x00400000 /* Boot exception vectors */
#define M_SBTS_RS               0x00000001 /* Reset */
#define M_SBTS_CE               0x00010000 /* ClockEnable */
#define M_SBTS_FC               0x00020000 /* ForceGatedClocks */
#define M_SBID_CR               0x0000FFF0
#define S_SBID_CR		4
#define M_SBID_RV               0x0000000F

#define K_CFG_K0COH_CACHEABLE	3
#define R_SBTMSTATELOW          0xF98
#define R_SBIDLOW               0xFF8
#define R_SBIDHIGH              0xFFC
#define K_CR_MEMC               0x80F

#define	MEMC_CONTROL		0x00
#define	MEMC_CONFIG		0x04
#define	MEMC_REFRESH		0x08
#define	MEMC_BISTSTAT		0x0c  /* unused */
#define	MEMC_MODEBUF		0x10
#define	MEMC_BKCLS		0x14  /* unused */
#define	MEMC_PRIORINV		0x18  /* unused */
#define	MEMC_DRAMTIM		0x1c
#define	MEMC_INTSTAT		0x20  /* unused */
#define	MEMC_INTMASK		0x24  /* unused */
#define	MEMC_INTINFO		0x28  /* unused */
#define	MEMC_NCDLCTL		0x30
#define	MEMC_RDNCDLCOR		0x34
#define	MEMC_WRNCDLCOR		0x38
#define	MEMC_MISCDLYCTL		0x3c
#define	MEMC_DQSGATENCDL	0x40
#define	MEMC_SPARE		0x44  /* unused */
#define	MEMC_TPADDR		0x48  /* unused */
#define	MEMC_TPDATA		0x4c  /* unused */
#define	MEMC_BARRIER		0x50  /* unused */
#define	MEMC_CORE		0x54  /* unused */

#define ICS_DLL_LOCK_VALUE       63

/* MEMC Core Init values (OCP ID 0x80f) */

/* For sdr: */
#define MEMC_SD_CONFIG_INIT	0x0004a000
#define MEMC_SD_DRAMTIM2_INIT	0x000754d8	/* CAS latency 2 */
#define MEMC_SD_DRAMTIM3_INIT	0x000754da	/* CAS latency 3 */
#define MEMC_SD_RDNCDLCOR_INIT	0x00000000
#define MEMC_SD_WRNCDLCOR_INIT	0x49351200
#define MEMC_SD1_WRNCDLCOR_INIT	0x14500200	/* For corerev 1  */
#define MEMC_SD_MISCDLYCTL_INIT	0x00061c1b
#define MEMC_SD1_MISCDLYCTL_INIT 0x00021416	/* For corerev 1  */
#define MEMC_SD_CONTROL_INIT0	0x00000002	/* SeqEn */
#define MEMC_SD_CONTROL_INIT1	0x00000008	/* PreCmd */
#define MEMC_SD_CONTROL_INIT2	0x00000004	/* RefCmd */
#define MEMC_SD_CONTROL_INIT3	0x00000010	/* MRSCmd */
#define MEMC_SD_CONTROL_INIT4	0x00000001	/* DRAMAccEn */
#define MEMC_SD_MODEBUF_INIT	0x00000000
#define MEMC_SD_REFRESH_INIT	0x0000840f


#if defined(CONFIG_SDRM64X16X1)
/* This is for 128 MB as 64M X 16 X 1 */
#define MEMC_GEOMETRY
#define MEMC_SDR_INIT           0x0013
#define MEMC_SDR_MODE           0x32
#define	MEMC_SDR_NCDL		0x00000000      /* was 0x00020032 */
#define	MEMC_SDR1_NCDL		0x00000000      /* was 0x0002020f */
#elif   defined(CONFIG_SDRM16X16X2)
/* This is for 64 MB as 16M X 16 X 2 (e.g., bcm95365rr) */
#define MEMC_GEOMETRY
#define MEMC_SDR_INIT           0x0008
#define MEMC_SDR_MODE           0x23
#define	MEMC_SDR_NCDL		0x00000000      /* was 0x00020032 */
#define	MEMC_SDR1_NCDL		0x00000000      /* was 0x0002020f */
#elif defined(CONFIG_SDRM32X16X1) /* BCM956018, BCM956014 */
/* This is for 64 MB as 32M X 16 X 1 */
#define MEMC_GEOMETRY
#define MEMC_SDR_INIT           0x0012          /* 1024 col., 16 bit i/f */
#define MEMC_SDR_MODE           0x32            /* CAS: 3, burst 4 */
#define	MEMC_SDR_NCDL		0x00000000
#define	MEMC_SDR1_NCDL          0x00000000
#elif defined(CONFIG_SDRM4X32X1)
/* This is for 16 MB as 4M X 32 X 1 */
#define MEMC_GEOMETRY
#define MEMC_SDR_INIT           0x0000
#define MEMC_SDR_MODE           0x32
#define	MEMC_SDR_NCDL		0x00000000      /* was 0x00020032 */
#define	MEMC_SDR1_NCDL          0x00000000      /* was 0x0002020f */
#elif defined(CONFIG_SDRM8X8X4)
/* Default: 32MB as 8M x 8 x 4 */
#define MEMC_GEOMETRY
#define	MEMC_SDR_INIT		0x0008
#define	MEMC_SDR_MODE		0x32
#define	MEMC_SDR_NCDL		0x00020032
#define	MEMC_SDR1_NCDL		0x0002020f	/* For corerev 1  */
#elif defined(CONFIG_SDRM32X8X4)
/* This is for 128 MB as 32M X 8 X 4 */
#define MEMC_GEOMETRY
#define MEMC_SDR_INIT           0x0010		/* 1024 columns */
#define MEMC_SDR_MODE           0x32		/* CAS 3, Burst 4 */
#define	MEMC_SDR_NCDL		0x00000000      /* was 0x00020032 */
#define	MEMC_SDR1_NCDL          0x00000000      /* was 0x0002020f */
#elif defined(CONFIG_SDRM8X16X2)
/* This is for 32 MB as 8M X 16 X 2 */
#define MEMC_GEOMETRY
#define MEMC_SDR_INIT           0x0008		/* 512 columns */
#define MEMC_SDR_MODE           0x32		/* 0x30 = CAS 3, 0x02 = Burst Length 4 */
#define	MEMC_SDR_NCDL		0x00000000      /* was 0x00020032 */
#define	MEMC_SDR1_NCDL          0x00000000      /* was 0x0002020f */
#endif


/* For ddr: */
#define MEMC_CONFIG_INIT	0x00048000
#define MEMC_DRAMTIM2_INIT	0x000754d8	/* CL = 2   */
#define MEMC_DRAMTIM25_INIT	0x000754d9	/* CL = 2.5 */
#define MEMC_DRAMTIM3_INIT	0x000754da	/* CL = 3 */
#define MEMC_RDNCDLCOR_INIT	0x00000000
#define MEMC_WRNCDLCOR_INIT	0x49351200
#define MEMC_1_WRNCDLCOR_INIT	0x14500200
#ifdef QUICK_TURN
#define MEMC_DQSGATENCDL_INIT	0x00830000
#else
#define MEMC_DQSGATENCDL_INIT	0x00030000
#endif
#define MEMC_MISCDLYCTL_INIT	0x21061c1b
#define MEMC_1_MISCDLYCTL_INIT	0x21021400
#define MEMC_NCDLCTL_INIT	0x00002001
#define MEMC_CONTROL_INIT0	0x00000002
#define MEMC_CONTROL_INIT1	0x00000008
#define MEMC_MODEBUF_INIT0	0x00004000
#define MEMC_CONTROL_INIT2	0x00000010
#define MEMC_MODEBUF_INIT1	0x00000100
#define MEMC_CONTROL_INIT3	0x00000010
#define MEMC_CONTROL_INIT4	0x00000008
#define MEMC_REFRESH_INIT_R	0x0000840f
#define MEMC_REFRESH_INIT_H	0x0000830a
#define MEMC_CONTROL_INIT5	0x00000004
#define MEMC_MODEBUF_INIT2	0x00000000
#define MEMC_CONTROL_INIT6	0x00000010
#define MEMC_CONTROL_INIT7	0x00000001

#if   defined(CONFIG_DDRM16X16X2)
/* This is for 64 MB as 16M X 16 X 2 */
#define MEMC_GEOMETRY
#define	MEMC_DDR_INIT		0x0009
#define	MEMC_DDR_MODE		0x62
#define	MEMC_DDR_NCDL		0x00000000      /* was 0005050a */
#define	MEMC_DDR1_NCDL		0x00000a0a	/* For corerev 1 */
#elif defined(CONFIG_DDRM32X16X2)
/* This is for 128 MB as 32M X 16 X 2 (e.g., bcm95836cpci) */
#define MEMC_GEOMETRY
#define	MEMC_DDR_INIT		0x0011		/* for full 128MB */
#define	MEMC_DDR_MODE		0x62
#define	MEMC_DDR_NCDL		0x00000000	/* was 0x0005050a */
#define	MEMC_DDR1_NCDL		0x00000a0a	/* For corerev 1  */
#elif defined(CONFIG_DDRM32X16X1)
/* This is for 64 MB as 32X16X1 */
#define MEMC_GEOMETRY
#define	MEMC_DDR_INIT		0x0013		/* for full 64MB */
#define	MEMC_DDR_MODE		0x62
#define	MEMC_DDR_NCDL		0x00000b0b	/* was 0x0005050a */
#define	MEMC_DDR1_NCDL		0x00000a0a	/* For corerev 1  */
#elif defined(CONFIG_DDRM64X16X1)
/* This is for 128 MB as 64X16X1 (e.g., bcm953300) */
#define MEMC_GEOMETRY
#define	MEMC_DDR_INIT		0x001b		/* for full 128MB */
#define	MEMC_DDR_MODE		0x62
#define	MEMC_DDR_NCDL		0x00000000  /* was 0x0005050a */
#define	MEMC_DDR1_NCDL		0x00000a0a	/* For corerev 1  */
#elif defined(CONFIG_DDRM16X16X1)
#define MEMC_GEOMETRY
#define	MEMC_DDR_INIT		0x000b
#define	MEMC_DDR_MODE		0x62
#define	MEMC_DDR_NCDL		0x00000000
#define	MEMC_DDR1_NCDL		0x00000a0a
#endif

#ifndef MEMC_GEOMETRY
#error "sbmemc: geometry must be defined"
#endif

#ifdef QUICK_TURN
#undef MEMC_DDR_NCDL
#define	MEMC_DDR_NCDL		0xf6f6f6f6
#endif

/* mask for sdr/ddr calibration registers */
#define MEMC_RDNCDLCOR_RD_MASK	0x000000ff
#define MEMC_WRNCDLCOR_WR_MASK	0x000000ff
#define MEMC_DQSGATENCDL_G_MASK	0x000000ff

/* masks for miscdlyctl registers */
#define MEMC_MISC_SM_MASK	0x30000000
#define MEMC_MISC_SM_SHIFT	28
#define MEMC_MISC_SD_MASK	0x0f000000
#define MEMC_MISC_SD_SHIFT	24

/* hw threshhold for calculating wr/rd for sdr memc */
#define MEMC_CD_THRESHOLD	128

/* Low bit of init register says if memc is ddr or sdr */
#define MEMC_CONFIG_DDR		0x00000001


/* */
#if defined(__ASSEMBLER__)
#define C0_BRCMCFG      $22             /* CP0: Broadcom Config */
#else
#define C0_BRCMCFG      22              /* CP0: Broadcom Config */
#endif
#ifndef C0_DIAGNOSTIC
#define C0_DIAGNOSTIC   C0_BRCMCFG      /* alias */
#endif

#define BCM53314_GPIO_BASE  0x18000060
#define BCM53314_CAP_REG    0x18000004
#define BCM53314_FLASH_CONTROL_REG  0x1800012c
#define BCM53314_EB2_CONTROL_REG  0x1800013c

#define maxIterations       t0
#define iteration           t1
#define sampleValue         t2
#define windowShiftValue    t3
#define base_ff41           t4
#define temp                t5

#ifdef __ASSEMBLER__
#define _ACAST32_
#else
#define _ACAST32_	_ATYPE_ _ATYPE32_	/* widen if necessary */
#endif
#define K0BASE 		(_ACAST32_ 0x80000000)	/* kernel unmapped cached */

/* #define PHYS_TO_K0(pa)	(K0BASE | (pa)) */
#define PHYS_TO_K1(pa)	(K1BASE | (pa))
#define K0_TO_PHYS(va)	((va) & (K0SIZE-1))
#define K1_TO_PHYS(va)	((va) & (K1SIZE-1))
#define K0_TO_K1(va)	((va) | K1SIZE)
#define K1_TO_K0(va)	((va) & ~K1SIZE)
/* */

	.set	noreorder

	.globl	lowlevel_init
	.ent	lowlevel_init
lowlevel_init:
# CPU Soft reset Clear
	li	t5, 0xb8000110
	sw	zero, 0(t5)

# Watchdog CHECK
	li	t5, 0xb8000020
	lw	t8, 0(t5)
	li	t5, 0x80000000
	and	t8, t8,t5
	beqz	t8, lowlevel_init_cpuarch
	nop
	# Hardware watchdog FIRE!!
	# save flag
	li	t5, 0xbc800000
	li	t8, 0xff5a
	sh	t8, 0x3e(t5)
	# Reset watchdog flag
	li	t5, 0xb8000020
	li	t8, 0x80000000
	lw	t8, 0(t5)
	# Reset firmware
	li	t5, 0xb8000110
	li	t8, 0x00000002
	sw	t8, 0x0(t5) # CPU Soft reset
	nop

lowlevel_init_cpuarch:

#ifndef QUICK_TURN
        #
        # Config GPIO pins for output mode.
        #
	    li	t0, 0xb8000060 /* PHYS_TO_K1(BCM53314_GPIO_BASE) */
            li  t1, 0xFF
            sb  t1, BYTE_SEL(0xc)(t0) /* GPIO Control */
	    li  t1, 0xc0
	    sb  t1, BYTE_SEL(0x4)(t0) /* GPIO output register */
            li  t1, 0x0f
            sb  t1, BYTE_SEL(8)(t0) /* GPIO out enable */
            nop
#endif

#	cpu arch check
	lui	t5,0xb800
	lw	t8,0(t5)
	andi	t8,t8,0xff0
	li	t5,784		# 0x0310
	beq	t8,t5,lowlevel_hawkeye
	nop

	# lowlevel init
	# *(0xb8000000) & 0x0ff0 == 0x0310 :	 HAWKEYE
	#                        != 0x0310 :	 RAPTOR ( 0x0210 )
lowlevel_raptor:
        # disable prefetch cache
           lui     v0, 0xff40
           lui     t1, 0x0400
           sw      t1, 4(v0)
           li      t1, 0x0000          /* Disable Prefectch for I$ & D$ */
           sw      t1, 0(v0)


        # Switch to sync mode if in async mode.
            li      t0, 0x400000
            mfc0    t1,C0_BRCMCFG,4
            and     t1, t1, t0
            beqz    t1, done_pll_r
            nop
            li      t0, 0xb8000004 /* PHYS_TO_K1(BCM53314_CAP_REG) */
            lw      t1, 0(t0)
            andi    t0, t1, 0x4
            beqz    t0, done_pll_r
            nop
            andi    t0, t1, 0x30    /* Read the clk ratio strap values */
            beqz    t0, strap_266
            nop
            beq     t0, 0x30, strap_133
            nop

            /* Strap set to either 6:4 or 9:4 ratio */
            beq     t0, 0x10, strap_300
            nop

strap_200:
            li      t0, 0x016D016D
            b       enable_dll
            nop
strap_300:
            li      t0, 0x012A00A9
            b       enable_dll
            nop
strap_266:
            li      t0, 0x00AA0055
            b       enable_dll
            nop
strap_133:
            li      t0, 0xFFFFFFFF
            b       enable_dll
            nop

enable_dll:
            li      t1, 0xff400010
            li      t2, 0x80000008
            lw      t3, 0(t1)
            or      t3, t3, t2
            sw      t3, 0(t1)

            sw      t0, 0x8(t1)

            mfc0    t2,C0_BRCMCFG,2
            ori     t2, t2, 0x8
            mtc0    t2,C0_BRCMCFG,2
            nop
            nop
            nop
            nop

start_hw_dll:
            li      t0, 0x1
            li      t1, 0xff400008  /* DLL reg address          */
            li      t3, 0x0041e021  /* setmask to be 1E         */
            lw      t2, 0(t1)
            or      t2, t2, t3
            sw      t2, 0(t1)       /* enable dll by write 1 to bit[0] */
            li      t0, 0x80        /* enable aggressive hardware mode */
            lw      t2, 0(t1)
            or      t2, t2, t0
            sw      t2, 0(t1)
            sync

DLL_LOCK_CLEAR:
            lw      t2, 0(t1)        /* check for lock */
            li      t0, 0x2
            and     t2, t2, t0
            beqz    t2, DLL_LOCK_CLEAR
            nop
            lw      t2, 0(t1)        /*  clear sticky bit */
            sw      t2, 0(t1)

            li      t3, 0xfffc1fff
            and     t2, t3, t2
            li      t3, 0x00022000   /* set mask to be 10001 */
            or      t2, t3, t2

            sw      t2, 0(t1)

            mfc0    t2,C0_BRCMCFG,2
            ori     t2, t2, 0x8
            mtc0    t2,C0_BRCMCFG,2
            nop
            nop
            nop
            nop

            li      t2, 0x000000
            mtc0    t2,C0_BRCMCFG,4
            sync

done_pll_r:
            nop

	#
	# Use CP0 Diagnostic Register to turn on the caches (I$ and D$)
	#

		mfc0	v0,C0_DIAGNOSTIC
		or	v0,0xc0000000 /* (M_BCM0_DE | M_BCM0_IE) */
		mtc0	v0,C0_DIAGNOSTIC

	b lowlevel_common_init
	nop

lowlevel_hawkeye:

        # Enable access to 0xff400000 region
            li   t0, 0x1fa0000c
            mtc0 t0, $22, 6
            nop
            li   t1, 0x1fa00000
            lw   t2, 0x14(t1)
            or   t3, t2, 0xc0000000
            sw   t3, 0x14(t1)
            li   t0, 0xff40000c
            mtc0 t0, $22, 6
            nop

       # force into async mode before running PI code

        li      t0, 0x400000
        mfc0    t1,C0_BRCMCFG,4
        or      t1, t1, t0
        mtc0    t1, C0_BRCMCFG,4


	# init  for PI code after print routine
        li      base_ff41,      0xff410000
        li      maxIterations,  2048
        li      iteration,      0

	lw   windowShiftValue, 0x48(base_ff41)
	and  windowShiftValue, windowShiftValue, 0x3ffc

        li      a0, 0x07004000
	or      a0, a0, windowShiftValue
        sw      a0, 0x48(base_ff41)
        li      a0, 0x07104000
	or      a0, a0, windowShiftValue
        sw      a0, 0x48(base_ff41)

	or      iteration, iteration, windowShiftValue
	add     maxIterations, maxIterations, windowShiftValue

1:
        bge     iteration, maxIterations, 2f

        # Looking for a rising edge.
        # Read a sample value.
            lw      sampleValue, 0x40(base_ff41)

        # The sample is in the upper 16 bits.
            srl     sampleValue, 16

        # Look at the 2 outermost bits. if the LSB is 0 and the MSB is 1, then
        # there is an edge somewhere in the sample.

            and     sampleValue, 0x41
            beq     sampleValue, 0x40, 3f

        # If rising edge not detected, request pll to move mips clk
        # write iteration to phase_cntrl_reg[5:0](pll_mips_ph)
        # Adjust the sample window.

        ## zero out the lowest 2 bit to simulate div16 vs div64 PI
            and     windowShiftValue, iteration, 0x3ffc
            or      windowShiftValue, 0x07104000  # count up
            sw      windowShiftValue, 0x48(base_ff41)


        # Delay before reading another sample.
            lw      temp, 0x40(base_ff41)
            lw      temp, 0x40(base_ff41)
	    nop
	    nop
	    nop
	    nop
            nop
            lw      temp, 0x48(base_ff41)

            addi    iteration, 4

            b       1b
            nop

2:
        # Failure
        # We exceeded our count limit, so return false
/*            EARLY_UART_DEBUG1('P','I',' ', 'F') */
/*            EARLY_UART_DEBUG1('A','I','L', ' ') */
            b       after_pi
            nop
3:

done_pll:

        nop

        # Check the contents of sampling register and fine tune clock alignment
        lw       sampleValue, 0x40(base_ff41)
        li       v1, 0x20000
        and      temp, sampleValue, v1
        bnez temp, 6f
        nop

        # Check if clock sample bit[3:2] is set, if so shift back 3 steps
        li      v1, 0xc0000
        and     temp, sampleValue, v1
        bnez    temp, 7f
        nop

        # No shift required
        b       9f
        nop

6:      li temp, 0x3
        b 8f
        nop

7:      li temp, 0x2

8:      beqz temp, 9f
        nop

        addi iteration, iteration, -4
        and  windowShiftValue, iteration, 0x3ffc
        or   windowShiftValue, 0x07100000
        sw   windowShiftValue, 0x48(base_ff41)
        addi temp, temp, -1
        b    8b
        nop

9:
        # Check the clock sampling one last time
        lw      sampleValue, 0x40(base_ff41)
        li      v1, 0xf0000
        and     temp, sampleValue, v1
        bnez    temp, done_pll
        nop

        # Success
        # Do not Turn on auto-PI mode.
        # set ph_cntr_byp(phase_cntr_reg[22] 0
        # set llmb_cntr_en(phase_cntr_reg[21]) 0
        # set ph_cntre_en(phase_cntr_reg[20]) 1
        # keep what ever is there for mips_ph_cntr_max(phase_cntr_reg[14:0])

        # enable PI scheme to drive clk crossing logic
            li     a0, 0x80000000
            sw     a0, 0x40(base_ff41)
            lw     a0, 0x40(base_ff41)

        # Search for rising edge in DLL sampling bits
            li      iteration,      1

        # Enable sync mode (clear bit 28 of CP0 reg 22 sel 4).
            li      temp, 0x0
            mtc0    temp, $22, 4

        #
        # Enable prefetch cache
        #
           lui     v0, 0xff40
           lui     t1, 0x0800
           sw      t1, 4(v0)
           li      t1, 0x0000000f          /* Enable Prefectch for I$ & D$ */
           sw      t1, 0(v0)

/*        EARLY_UART_DEBUG1('P','I','O', 'K')*/

after_pi:

/*        EARLY_UART_PRINT_MEM32(0xff410040)*/
/*        EARLY_UART_PRINT_MEM32(0xff410048)*/

        #
        # Adjust flash timing.
        #
	    li	t0, 0xb800012c /* PHYS_TO_K1(BCM53314_FLASH_CONTROL_REG) */
            li  t1, 0x01010110
            sw  t1, 0(t0)


	#
	# Use CP0 Diagnostic Register to turn on the caches (I$ and D$)
	#

		mfc0	v0,C0_DIAGNOSTIC
		or	v0,0xc0000000 /* (M_BCM0_DE | M_BCM0_IE) */
		mtc0	v0,C0_DIAGNOSTIC

        #
        # Adjust EB2 bus timing
        #
	    li	t0, 0xb800013c /* PHYS_TO_K1(BCM53314_EB2_CONTROL_REG) */
            li  t1, 0x01010110
            sw  t1, 0(t0)


lowlevel_common_init:

	/* PLD Flash window clear */
	li	t0, 0xbcc00000
	li	t1, 0
	nop
	sh	t1, 4(t0)
	nop

/* CHECK :	bcmcore_cpuinit.S  bcmcore_cp0_init */

	/* Disable Watchpoint facilities */
	mtc0	zero, CP0_WATCHLO
	mtc0	zero, CP0_WATCHHI

	/* Clear the cause register before writing the status register */
	mtc0	zero, CP0_CAUSE
	mfc0	v0, CP0_STATUS
	/* save the soft reset settings */
	and	v0, M_SR_SOFT_RESET

#ifdef DEBUG_ENV_ICE
	and	v0, ~M_SR_BOOT_EXCEPT_VEC
#else
	or	v0, M_SR_BOOT_EXCEPT_VEC
#endif
	mtc0	v0, CP0_STATUS
	/* get current CONFIG register */
	mfc0	v0, CP0_CONFIG
	/* strip out K0 bits */
	srl	v0, v0,3
	sll	v0, v0,3
	/* Make K0 cacheable */
	or	v0, v0, K_CFG_K0COH_CACHEABLE
	mtc0	v0, CP0_CONFIG
	nop

	mtc0	zero, CP0_WATCHLO
	mtc0	zero, CP0_WATCHHI
	/* Clear the EntryHi register */
	mtc0	zero, CP0_ENTRYHI
	nop

	li	v0, -1
	mtc0	v0, CP0_COMPARE
	nop

	/* clear all the TLB entries to an invalid value */
	mtc0	zero, CP0_ENTRYLO0
	nop
	mtc0	zero, CP0_ENTRYLO1
	nop
	/* sets the pagemask to 4k page size */
	mtc0	zero,CP0_PAGEMASK
	nop
	/* set to an impossible vpn */
	li	t0, KSEG1
	li	t1,(X200_GE_NTLBENTRIES-1)

	nop
1:	mtc0	t0, CP0_ENTRYHI
	nop
	mtc0	t1, CP0_INDEX
	nop
	addu	t0, 0x2000		/* inc vpn */
	tlbwi
	bnez	t1, 1b
	subu	t1, 1

	/* clear the instruction and data caches */



/* Check :	 bcmcore_l1cache.S bcmcore_l1cache_init */

	/* Size the icache */
	mfc0	t0, CP0_CONFIG,1

	/* Sets Per Way = 64 << CFG_IS */
	li	t2, 0x01c00000
	and	t2, t0
	srl	t2, 22
	li	t1, 64
	sll	t1, t2

	/* Associativity = 1 + CFG_IA */
	li	t2, 0x00070000
	and	t2, t0
	srl	t2, 16
	addiu	t2, 1

	/* Associativity * Sets Per Way */
	multu	t1, t2
	mflo	t1

	/* Line Size = 2 << CFG_IL */
	li	t2, 0x00380000
	and	t2, t0
	srl	t2, 19
	li	t0, 2
	sll	t2, t0,t2

	/* Instruction Cache Size = Associativity * Line Size * Sets Per Way */

	multu	t1,t2
	mflo	t0

	/* Zero the icache */
	mtc0	zero, CP0_TAGLO
	mtc0	zero, CP0_TAGHI
	li	t1, K0BASE

1:	sub	t0, t0,t2
	cache	Index_Store_Tag_I,0(t1)
	add	t1, t2
	bne	t0, zero,1b
	nop

	/* Size the dcache */
	mfc0	t0, CP0_CONFIG,1
	/* Sets Per Way = 64 << CFG_DS */
	li	t2, 0x0000e000
	and	t2, t0
	srl	t2, 13
	li	t1, 64
	sll	t1, t2

	/* Associativity = 1 + CFG_DA */
	li	t2, 0x00000380
	and	t2, t0
	srl	t2, 7
	addiu	t2, 1

	/* Associativity * Sets Per Way */
	multu	t1,t2
	mflo	t1

	/* Line Size = 2 << CFG_DL */
	li	t2, 0x00001c00
	and	t2, t0
	srl	t2, 10
	li	t0, 2
	sll	t2, t0,t2

	/* Data Cache Size = Associativity * Line Size * Sets Per Way */
	multu	t1,t2
	mflo	t0

	/* Zero the dcache */
	mtc0	zero, CP0_TAGLO
	mtc0	zero, CP0_TAGHI
	li	t1, K0BASE
1:	sub	t0, t0,t2
	cache	Index_Store_Tag_D,0(t1)
	add	t1, t2
	bne	t0, zero,1b
	nop




/* Check sbmemc56xxx.S board_draminit */


	/* setup the DRAM */

	/* Save return address */
	move	t6,ra

        li      v1, 0
	li	a0,KSEG1ADDR(X200_GE_MEMC_BASE)

	b	init			# No NVRAM
	li	a2, 0


init:
memc_init:
	bnez	a2,1f		# Already have the parms in t0, t1, t2, t3
	nop

        # Read strap to determine if SDR or DDR present
        li      t0, KSEG1ADDR(X200_GE_CAP_REG)
        lw      t1, 0(t0)
        andi    t0, t1, 0x02
        bnez    t0, memc_sdr_init
        nop

/*
 * Routines for initializing DDR SDRAM
 */

memc_ddr_init:
	li	t0,MEMC_DDR_INIT
	li	t1,MEMC_DDR_MODE
	li	t3,MEMC_DDR_NCDL	# If rev0, 2:
	bne	v1,1,1f
	nop
	li	t3,MEMC_DDR1_NCDL	# rev1:
1:
/* GKC for ice debugging where the unit is running from RAM */
/*	beqz	t3,szmem
	nop */
/* END - GKC for ice debugging where the unit is running from RAM */


	beqz	t3,ddr_find_ncdl	# Do we have ncdl values? (0s)
	nop
	li	t4,-1			# or ffs
	bne	t3,t4,break_ddr_ncdl
	nop

ddr_find_ncdl:

/* Register usage */
#define	pass_count	s0
#define	wrsum		s1
#define	rdsum		s2
#define	gsum		s3
#define	wrlim		s4
#define	rdlim		s5
#define	glim		s6
#define	dll		s7
#define	step		s8
#define	wr		t2
#define	rd		t3
#define	g		t4

	/* Initialize counter & accumulators */
	move	pass_count,zero
	move	wrsum,zero
	move	rdsum,zero
	move	gsum,zero

	/* Initialize with default values */
	li	wr,5
	li	rd,5
	bal	ddr_do_init
	li	g,10

	/* Read dll value */
	lw	dll,MEMC_NCDLCTL(a0)
	andi	dll,dll,0xfe
	srl	dll,dll,1

	beqz	dll,szmem		# If zero, leave the default values
	nop

	move	wrlim,dll		# dll value is lim for wr, rd and g
	move	rdlim,dll
	move	glim,dll

	addi	step,dll,15		# step = (dll + 16 - 1) / 16
	srl	step,step,4

	sub	wr,zero,dll		# Negate dll as initial value
	move	rd,wr
	move	g,wr

	/* Inner loop:	call ddr_do_init to re-initialize and the test mem */
loop:
	bal	ddr_do_init
	nop

	bal	test_mem
	nop

	beqz	v0,nextg
	nop

	/* Memory is ok */

	addi	pass_count,1
	add	wrsum,wrsum,wr
	add	rdsum,rdsum,rd
	add	gsum,gsum,g

	bne	wr,dll,1f
	nop
	sll	wrlim,dll,1
1:
	bne	rd,dll,2f
	nop
	sll	rdlim,dll,1
2:
	bne	g,dll,nextg
	nop
	sll	glim,dll,1

nextg:
	add	g,g,step
	ble	g,glim,loop
	nop
	sub	g,zero,dll
	move	glim,dll

	/* nextrd: */
	add	rd,rd,step
	ble	rd,rdlim,loop
	nop
	sub	rd,zero,dll
	move	rdlim,dll

	/* nextwr: */
	add	wr,wr,step
	ble	wr,wrlim,loop
	nop

	/* All done, calculate average values and program them */

	beqz	pass_count,1f
	nop

	div	zero,wrsum,pass_count
	mflo	wr

	div	zero,rdsum,pass_count
	mflo	rd

	div	zero,gsum,pass_count
	mflo	g

	b	ddr_got_ncdl
	nop

	/* No passing values, panic! (use defaults) */
1:
#ifdef CONFIG_MEMSDR
	li	t3,MEMC_SDR_NCDL		# If rev0, 2:
	bne	v1,1,2f
	nop
	li	t3,MEMC_SDR1_NCDL		# rev1:
#else
	li	t3,MEMC_DDR_NCDL		# If rev0, 2:
	bne	v1,1,2f
	nop
	li	t3,MEMC_DDR1_NCDL		# rev1:
#endif
2:

break_ddr_ncdl:
	andi	t4,t3,0xff			# t4:	g
	srl	t2,t3,16			# t2:	wr
	andi	t2,t2,0xff
	srl	t3,t3,8				# t3:	rd
	andi	t3,t3,0xff

ddr_got_ncdl:
	bal	ddr_do_init
	nop

	b	szmem
	nop


	/* Do an init of the memc core for ddr
	 *	a0:	memc core pointer
	 *	t0:	memc config value
	 *	t1:	memc mode value
	 *	t2:	memc wr ncdl value
	 *	t3:	memc rd ncdl value
	 *	t4:	memc g ncdl value
	 *
	 * Uses a1, t5, t7, t8, t9 (here and by calling memc_reset)
	 */
ddr_do_init:

	/* Save return address */
	move	t7,ra
#if 0
	bal	memc_reset
	li	a1,0
#endif

	/* Calc SDRAM Refresh rate */
	lui	t5,0xb800
	lw	t8,0(t5)
	andi	t8,t8,0xff0
	li	t5,784		# 0x0310
	beq	t8,t5,sdram_refresh_hawkeye
sdram_refresh_raptor:
	li	t5,MEMC_REFRESH_INIT_R
	b sdram_init_common
	nop
sdram_refresh_hawkeye:
	li	t5,MEMC_REFRESH_INIT_H
sdram_init_common:


	li	a1,MEMC_CONFIG_INIT
	or	a1,a1,t0
	sw	a1,MEMC_CONFIG(a0)

	li	a1,MEMC_DRAMTIM25_INIT		# Assume CAS latency of 2.5
	andi	t8,t1,0xf0			# Find out the CAS latency
	bne	t8,0x20,1f
	nop
	li	a1,MEMC_DRAMTIM2_INIT		# CAS latency is 2
1:
	sw	a1,MEMC_DRAMTIM(a0)

	andi	t8,t3,0xff
	sll	a1,t8,8				# Replicate rd ncdl 4 times
	or	a1,a1,t8
	sll	t8,a1,16
	or	t8,t8,a1
	li	a1,MEMC_RDNCDLCOR_INIT
	or	a1,a1,t8
	sw	a1,MEMC_RDNCDLCOR(a0)

	li	a1,MEMC_WRNCDLCOR_INIT		# If rev0, 2:
	bne	v1,1,1f
	nop
	li	a1,MEMC_1_WRNCDLCOR_INIT	# rev1
1:
	andi	t8,t2,0xff
	or	a1,a1,t8
	sw	a1,MEMC_WRNCDLCOR(a0)

	li	a1,MEMC_DQSGATENCDL_INIT
	andi	t8,t4,0xff
	or	a1,a1,t8
	sw	a1,MEMC_DQSGATENCDL(a0)

	li	a1,MEMC_MISCDLYCTL_INIT		# If rev0, 2:
	bne	v1,1,2f
	nop
	li	a1,MEMC_1_MISCDLYCTL_INIT	# rev1
2:
	sw	a1,MEMC_MISCDLYCTL(a0)

	li	a1,MEMC_NCDLCTL_INIT
	sw	a1,MEMC_NCDLCTL(a0)

	li	a1,MEMC_CONTROL_INIT0
	sw	a1,MEMC_CONTROL(a0)

	li	a1,MEMC_CONTROL_INIT1
	sw	a1,MEMC_CONTROL(a0)

	li	a1,MEMC_MODEBUF_INIT0
	sw	a1,MEMC_MODEBUF(a0)

	li	a1,MEMC_CONTROL_INIT2
	sw	a1,MEMC_CONTROL(a0)

	li	a1,MEMC_MODEBUF_INIT1
	or	a1,a1,t1
	sw	a1,MEMC_MODEBUF(a0)

	li	a1,MEMC_CONTROL_INIT3
	sw	a1,MEMC_CONTROL(a0)

	li	a1,MEMC_CONTROL_INIT4
	sw	a1,MEMC_CONTROL(a0)

	li	a1,MEMC_CONTROL_INIT5
	sw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)

	li	a1,MEMC_CONTROL_INIT5
	sw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)

#	li	a1,MEMC_REFRESH_INIT_H
#	sw	a1,MEMC_REFRESH(a0)
	sw	t5,MEMC_REFRESH(a0)

	li	a1,MEMC_MODEBUF_INIT2
	or	a1,a1,t1
	sw	a1,MEMC_MODEBUF(a0)

	li	a1,MEMC_CONTROL_INIT6
	sw	a1,MEMC_CONTROL(a0)

	li	a1,MEMC_CONTROL_INIT7
	sw	a1,MEMC_CONTROL(a0)

	jr	t7
	nop


/*
 *  Routines for initializing SDR SDRAM
 */

memc_sdr_init:
	li	t0,MEMC_SDR_INIT
	li	t1,MEMC_SDR_MODE
	li	t3,MEMC_SDR_NCDL	# If rev0, 2:
	bne	v1,1,1f
	nop
	li	t3,MEMC_SDR1_NCDL	# rev1:
1:
	beqz	t3,sdr_find_ncdl	# Do we have ncdl values?
	nop

	li	t4,-1
	bne	t3,t4,break_sdr_ncdl
	nop

sdr_find_ncdl:

/* Register usage */
#define	pass_count	s0
#define	clkdsum		s1
#define	pass_countmax	s2
#define	strmmax		s3
#define	strdmax		s4
#define	clkdmax		s5
#define	clkdlim		s6
#define	strm		t2
#define	strd		t3
#define	clkd		t4

#define	STRMLIM		4
#define	STRDLIM		16
#define	CLKDLIM		128
#define	CLKDLIM_IC	256

	/* Initialize counter & saved values */
	move	pass_countmax,zero
	move	strmmax,zero
	move	strdmax,zero
	li	clkdlim,CLKDLIM

	and	strm,t0,0x2000		# Test for internal clock (Using strm as a temp)
	beqz	strm,strmloop
	nop

	li	clkdlim,CLKDLIM_IC

	move	strm,zero		# strm loop
strmloop:
	move	strd,zero
strdloop:
	move	pass_count,zero
	move	clkdsum,zero
	move	clkd,zero

	/* Inner loop:	call sdr_do_init to re-initialize and the test mem */
clkdloop:
	bal	sdr_do_init
	nop

	bal	test_mem
	nop

	beqz	v0,failclkd
	nop

	/* Memory is ok */

	addi	pass_count,1
	add	clkdsum,clkdsum,clkd
	b	nextclkd
	nop

failclkd:
	bnez	pass_count,clkdout	# End of passing range, leave clkd loop
	nop

nextclkd:
	addi	clkd,clkd,1
	blt	clkd,clkdlim,clkdloop
	nop

clkdout:
	/* If no passing values, skip to next strm */
	beqz	pass_count,nextstrm
	nop

	/* If this is a new max, Save the values */
	ble	pass_count,pass_countmax,nextstrd
	nop

	move	pass_countmax,pass_count
	div	zero,clkdsum,pass_count
	mflo	clkdmax
	move	strdmax,strd
	move	strmmax,strm

nextstrd:
	addi	strd,strd,1
	blt	strd,STRDLIM,strdloop
	nop

nextstrm:
	addi	strm,strm,1
	blt	strm,STRMLIM,strmloop
	nop

	/* All done, program the new ncdl values */

	beqz	pass_countmax,1f
	nop

	move	clkd,clkdmax
	move	strd,strdmax
	move	strm,strmmax
	b	sdr_got_ncdl
	nop

	/* No passing values, panic! (use defaults) */
1:
#ifdef CONFIG_MEMSDR
	li	t3,MEMC_SDR_NCDL	# If rev0, 2:
	bne	v1,1,2f
	nop
	li	t3,MEMC_SDR1_NCDL	# rev1:
#else
	li	t3,MEMC_DDR_NCDL		# If rev0, 2:
	bne	v1,1,2f
	nop
	li	t3,MEMC_DDR1_NCDL		# rev1:
#endif
2:

break_sdr_ncdl:
	andi	t4,t3,0xff		# t4:	cd
	srl	t2,t3,16		# t2:	sm
	andi	t2,t2,3			#	sm is 2 bits only
	srl	t3,t3,8			# t3:	sd
	andi	t3,t3,0xf		#	sd is 4 bits

sdr_got_ncdl:
	bal	sdr_do_init
	nop

	b	szmem
	nop


	/* Do an init of the memc core for sdr
	 *	a0:	memc core pointer
	 *	t0:	memc config value
	 *	t1:	memc mode value
	 *	t2:	memc strobe mode ncdl value
	 *	t3:	memc strobe delay ncdl value
	 *	t4:	memc clock delay ncdl value
	 *
	 * Uses a1, t7, t8, t9 (here and by calling memc_reset)
	 */
sdr_do_init:

	/* Save return address */
	move	t7,ra
#if 0
	bal	memc_reset
	li	a1,0x40
#endif
	/* Initialize SDRAM */
	li	a1,MEMC_SD_CONFIG_INIT
	or	a1,a1,t0
	sw	a1,MEMC_CONFIG(a0)

	li	a1,MEMC_SD_DRAMTIM3_INIT	# Assume CAS latency of 3
	andi	t8,t1,0xf0			# Find out the CAS latency
	bne	t8,0x20,1f
	nop
	li	a1,MEMC_SD_DRAMTIM2_INIT	# CAS latency is 2
1:
	sw	a1,MEMC_DRAMTIM(a0)

	andi	t8,t4,0xff
	ble	t8,MEMC_CD_THRESHOLD,1f		# if (cd <= 128) rd = cd
	nop

	li	t8,MEMC_CD_THRESHOLD		# else rd = 128

1:						# t8 is now rd
	sll	a1,t8,8				#  .. replicate it 4 times
	or	a1,a1,t8
	sll	t8,a1,16
	or	t8,t8,a1
	li	a1,MEMC_SD_RDNCDLCOR_INIT
	or	a1,a1,t8
	sw	a1,MEMC_RDNCDLCOR(a0)

	li	a1,MEMC_SD1_WRNCDLCOR_INIT	# rev1
	beq	v1,1,1f
	nop
	li	a1,MEMC_SD_WRNCDLCOR_INIT	# rev0, 2
1:
	li	t8,0
	ble	t4,MEMC_CD_THRESHOLD,2f		# if (cd <= 128) wr = 0
	nop

	andi	t8,t4,0xff			# else wr = cd - 128
	sub	t8,t8,MEMC_CD_THRESHOLD
	andi	t8,t8,0xff

2:						# t8 is now wr, a0 is extra bits
	or	a1,a1,t8
	sw	a1,MEMC_WRNCDLCOR(a0)

	andi	t8,t2,3
	sll	a1,t8,28
	andi	t8,t3,0xf
	sll	t8,t8,24
	or	t8,t8,a1
	li	a1,MEMC_SD_MISCDLYCTL_INIT
	bne	v1,1,3f				# If rev0, 2:
	nop
	li	a1,MEMC_SD1_MISCDLYCTL_INIT	# rev1:
3:
	or	a1,a1,t8
	sw	a1,MEMC_MISCDLYCTL(a0)

	li	a1,MEMC_SD_CONTROL_INIT0
	sw	a1,MEMC_CONTROL(a0)

	li	a1,MEMC_SD_CONTROL_INIT1
	sw	a1,MEMC_CONTROL(a0)

	li	a1,MEMC_SD_CONTROL_INIT2
	sw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)

	li	a1,MEMC_SD_CONTROL_INIT2
	sw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)

	li	a1,MEMC_SD_CONTROL_INIT2
	sw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)
	lw	a1,MEMC_CONTROL(a0)

	li	a1,MEMC_SD_REFRESH_INIT
	sw	a1,MEMC_REFRESH(a0)

	li	a1,MEMC_SD_MODEBUF_INIT
	or	a1,a1,t1
	sw	a1,MEMC_MODEBUF(a0)

	li	a1,MEMC_SD_CONTROL_INIT3
	sw	a1,MEMC_CONTROL(a0)

	li	a1,MEMC_SD_CONTROL_INIT4
	sw	a1,MEMC_CONTROL(a0)

	li	t8,50
1:      nop
        nop
	bnez	t8,1b
	subu	t8,1

	jr	t7
	nop



/*
 *  Common exit code and subroutines shared by SDR and DDR initialization.
 */

	/* Determine memory size and return
	 *
	 * Somewhat simplistic, assumes size is a power of 2 and looks
	 * for aliases of location 0.
	 */
szmem:
	li	t0,KSEG1ADDR(0)
	li	t2,0xaa55beef
	sw	t2,0(t0)
	li	v0,4		/* Assume minimum of 4MB */

1:
	sll	t0,v0,20
	or	t0,KSEG1ADDR(0)
	lw	t1,0(t0)
	beq	t1,t2,done
	nop

	sll	v0,v0,1
	bne	v0,128,1b	/* Fully populated at 128MB, no alias */
	nop

done:
	jr	t6
	nop


	/*
	 * Test memory
	 *
	 * Uses arg in t2(wr/sd), t3(rd/sm) and t4(g/clkd)
	 * Returns success (1) or failure (0) in v0
	 * Uses a1, a2, a3 & t5
	 */
test_mem:
	/* Use t4 to generate a semi-random address in the second KB */
	li	a1,0xa0000000
	addi	a2,t4,255
	sll	a2,a2,2
	add	a1,a1,a2

	/* First set: 0 & its negation */
	li	a2,0
	sw	a2,0(a1)
	not	a3,a2
	sw	a3,4(a1)
	nop
	lw	t5,0(a1)
	bne	a2,t5,bad_mem
	nop
	lw	t5,4(a1)
	bne	a3,t5,bad_mem
	nop

	/* Second set: 0xaaaaaaaa & its negation */
	li	a2,0xaaaaaaaa
	sw	a2,0(a1)
	not	a3,a2
	sw	a3,4(a1)
	nop
	lw	t5,0(a1)
	bne	a2,t5,bad_mem
	nop
	lw	t5,4(a1)
	bne	a3,t5,bad_mem
	nop

	/* Third set: 0x12345678 & its negation */
	li	a2,0x12345678
	sw	a2,0(a1)
	not	a3,a2
	sw	a3,4(a1)
	nop
	lw	t5,0(a1)
	bne	a2,t5,bad_mem
	nop
	lw	t5,4(a1)
	bne	a3,t5,bad_mem
	nop

	/* Fourth set: the ncdl & its negation */
	sll	a2,t2,8
	or	a2,t3
	sll	a2,a2,8
	or	a2,t4
	sw	a2,0(a1)
	not	a3,a2
	sw	a3,4(a1)
	nop
	lw	t5,0(a1)
	bne	a2,t5,bad_mem
	nop
	lw	t5,4(a1)
	bne	a3,t5,bad_mem
	nop

	/* Fifth set: the CPU count register & its negation */
	mfc0	a2,$9
	sw	a2,0(a1)
	not	a3,a2
	sw	a3,4(a1)
	nop
	lw	t5,0(a1)
	bne	a2,t5,bad_mem
	nop
	lw	t5,4(a1)
	bne	a3,t5,bad_mem
	nop

	jr	ra
	li	v0,1

	.align 6

bad_mem:
	jr	ra
	li	v0,0


	.align 6
#if 0
memc_reset:

	/* Save return address */
	move	t9,ra

	/* run uncached */
	bal     kseg1_switch
	nop

        li      t5, 0xb8000114
        li      t8, 0x00
        sw      t8, 0(t5)
        nop
        nop
        nop
        nop
        nop
        li      t8, 0x01
        sw      t8, 0(t5)
        nop
        nop
        nop

	jr	t9
	nop
#endif

kseg1_switch:
	and     ra, ra, 0x1fffffff
	or      ra, ra, KSEG1ADDR(0)
	jr      ra
	nop

	.set	reorder

	.end lowlevel_init

.globl	x200_ge_get_cpu_cap
.ent	x200_ge_get_cpu_cap
x200_ge_get_cpu_cap:
	li	t0, KSEG1ADDR(X200_GE_CAP_REG)
	lw	v0, 0(t0)
	j	ra

	.end	x200_ge_get_cpu_cap

	.globl	x200_ge_get_chipid
	.ent	x200_ge_get_chipid
x200_ge_get_chipid:
	li	t0, KSEG1ADDR(X200_GE_CHIPID_REG)
	lw	v0, 0(t0)
	j	ra
	.end	x200_ge_get_chipid
