summaryrefslogtreecommitdiffstats
path: root/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S
diff options
context:
space:
mode:
Diffstat (limited to 'cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S')
-rwxr-xr-xcfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S1818
1 files changed, 1818 insertions, 0 deletions
diff --git a/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S
new file mode 100755
index 0000000..b3986ed
--- /dev/null
+++ b/cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S
@@ -0,0 +1,1818 @@
+#include "sbmips.h"
+#include "bsp_config.h"
+
+#include "bcm_cpu.h"
+#include "bcm_common.h"
+
+#include "bcm_hwdefs.h"
+#include "boardparms.h"
+#include "mipsmacros.h"
+
+#define DDR_TEST 1
+#define UBUS_SYNC_ENABLE 1
+#define LMB_SYNC_ENABLE 1
+#define MIPS_SYNC_ENABLE 1
+#define LMB_ENABLE 1
+
+/* Memory mapping table for different size DRAMs (256Mb, 512Mb, 1Gb, 2Gb) */
+ .globl dram_map_table_x8
+dram_map_table_x8:
+ // 128Mb 64B Interleaving (x8 Mode) 32MB
+ // This is just a place holder. This memory does not exist
+ _LONG_ 0x0F0E0D0C, 0x13121110, 0x17161514, 0x00000018 // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0A090805, 0x0000000B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00080706, 0x00000002, 0x00000055 // Bank CS_End Dramsize
+
+ // 256Mb 64B Interleaving (x8 Mode) 64MB
+ _LONG_ 0x100F0E0D, 0x14131211, 0x18171615, 0x00000019 // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0A090805, 0x00000C0B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00000706, 0x00000004, 0x00000066 // Bank CS_End Dramsize
+
+ // 512Mb 64B Interleaving (x8 Mode) 128MB
+ _LONG_ 0x100F0E0D, 0x14131211, 0x18171615, 0x00001A19 // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0A090805, 0x00000C0B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00000706, 0x00000008, 0x00000077 // Bank CS_End Dramsize
+
+ // 1Gb 64B Interleaving (x8 Mode) 256MB
+ _LONG_ 0x11100F0E, 0x15141312, 0x19181716, 0x00001B1A // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0B0A0905, 0x00000D0C, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00080706, 0x00000010, 0x00000088 // Bank CS_End Dramsize
+
+ .globl dram_map_table_x16
+dram_map_table_x16:
+ // 256Mb 64B Interleaving (x16 Mode) 32MB
+ _LONG_ 0x0F0E0D0C, 0x13121110, 0x17161514, 0x00000018 // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0A090805, 0x0000000B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00000706, 0x00000002, 0x00000055 // Bank CS_End Dramsize
+
+ // 512Mb 64B Interleaving (x16 Mode) 64MB
+ _LONG_ 0x100F0E0D, 0x14131211, 0x18171615, 0x00000019 // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0A090805, 0x00000C0B, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00000706, 0x00000004, 0x00000066 // Bank CS_End Dramsize
+
+ // 1Gb 64B Interleaving (x16 Mode) 128MB
+ _LONG_ 0x11100F0E, 0x15141312, 0x19181716, 0x0000001A // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0B0A0905, 0x00000D0C, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00080706, 0x00000008, 0x00000077 // Bank CS_End Dramsize
+
+ // 2Gb 64B Interleaving (x16 Mode) 256MB
+ _LONG_ 0x11100F0E, 0x15141312, 0x19181716, 0x00001B1A // Row00_0 Row00_1 Row01_0 Row01_1
+ _LONG_ 0x04000000, 0x0B0A0905, 0x00000D0C, 0x00000000 // Col00_0 Col00_1 Col01_0 Col01_1
+ _LONG_ 0x00080706, 0x00000010, 0x00000088 // Bank CS_End Dramsize
+
+ .globl dram_tRefi_table
+dram_tRefi_table: /* Refresh Interval table for different Speed DRAMs (100-200, 300-333, 400) */
+ _LONG_ 0x16, 0x49, 0x5D // 100-200 300-333 400 (MHz)
+
+ .globl dram_tRFC_table
+dram_tRFC_table: /* tRFC table for different size & Speed DRAMs (256Mb, 512Mb, 1Gb)/(200, 333, 400) */
+// 200 333 400 (MHz)
+ _LONG_ 0xF, 0x19, 0x1E // 256Mb
+ _LONG_ 0x15, 0x23, 0x2A // 512Mb
+ _LONG_ 0x1A, 0x2B, 0x33 // 1Gb
+ _LONG_ 0x28, 0x42, 0x4F // 2Gb
+
+ .globl dram_timing_table
+dram_timing_table: /* */
+// tRCD tCL tWR tWL tRP tRRD tRC tFAW tW2R tR2W tR2R tAL tRTP tW2W
+// ---------------------------------------------------------------------
+ .byte 0x03,0x04,0x03,0x03,0x03,0x02,0x11,0x00,0x01,0x01,0x00,0x02,0x02,0x00,0x00,0x00 // 200MHz
+ .byte 0x05,0x05,0x05,0x04,0x05,0x04,0x13,0x00,0x02,0x01,0x00,0x04,0x03,0x00,0x00,0x00 // 300MHz
+ .byte 0x05,0x05,0x06,0x04,0x06,0x05,0x18,0x00,0x02,0x01,0x00,0x04,0x03,0x00,0x00,0x00 // 400MHz
+
+ .globl dram_sync_table
+dram_sync_table: /* Bit vector table for Ubus sync modes and Lmb sync modes */
+#if defined(_BCM96328_)
+ _LONG_ 0x8E10FFFF, 0x8A10FFFF, 0xEDC2FFFF // UBUS Sync , LMB Sync, Mips Sync
+#elif defined(_BCM96362_)
+ _LONG_ 0xFFBFBFBF, 0x6341C101, 0xE7E5E5E5 // UBUS Sync , LMB Sync, Mips Sync
+#elif defined(_BCM96816_)
+ _LONG_ 0xC03033B5, 0x80303095, 0xFF90FFFF // UBUS Sync , LMB Sync, Mips Sync
+#endif
+ .globl dram_speed_table
+dram_speed_table: /* Memory Speed Table for different clock strap values */
+ /* 0=200Mhz 1=333MHz 2=400MHz */
+#if defined(_BCM96328_)
+ .byte 0 // 0x0
+ .byte 0 // 0x1
+ .byte 0 // 0x2
+ .byte 0 // 0x3
+ .byte 0 // 0x4
+ .byte 0 // 0x5
+ .byte 0 // 0x6
+ .byte 0 // 0x7
+ .byte 0 // 0x8
+ .byte 0 // 0x9
+ .byte 0 // 0xa
+ .byte 0 // 0xb
+ .byte 0 // 0xc
+ .byte 0 // 0xd
+ .byte 0 // 0xe
+ .byte 0 // 0xf
+ .byte 0 // 0x10
+ .byte 0 // 0x11
+ .byte 0 // 0x12
+ .byte 0 // 0x13
+ .byte 0 // 0x14
+ .byte 0 // 0x15
+ .byte 2 // 0x16
+ .byte 2 // 0x17
+ .byte 0 // 0x18
+ .byte 0 // 0x19
+ .byte 0 // 0x1a
+ .byte 0 // 0x1b
+ .byte 0 // 0x1c
+ .byte 0 // 0x1d
+ .byte 0 // 0x1e
+ .byte 1 // 0x1f
+#elif defined(_BCM96362_)
+ .byte 1 // 0x0
+ .byte 2 // 0x1
+ .byte 0 // 0x2
+ .byte 1 // 0x3
+ .byte 0 // 0x4
+ .byte 2 // 0x5
+ .byte 2 // 0x6
+ .byte 1 // 0x7
+ .byte 1 // 0x8
+ .byte 2 // 0x9
+ .byte 0 // 0xa
+ .byte 1 // 0xb
+ .byte 0 // 0xc
+ .byte 2 // 0xd
+ .byte 2 // 0xe
+ .byte 1 // 0xf
+ .byte 1 // 0x10
+ .byte 2 // 0x11
+ .byte 0 // 0x12
+ .byte 1 // 0x13
+ .byte 0 // 0x14
+ .byte 1 // 0x15 // 267MHz. Need to change tREFI if this is used.
+ .byte 2 // 0x16
+ .byte 1 // 0x17
+ .byte 1 // 0x18
+ .byte 1 // 0x19
+ .byte 0 // 0x1a
+ .byte 1 // 0x1b
+ .byte 0 // 0x1c
+ .byte 0 // 0x1d
+ .byte 2 // 0x1e
+ .byte 1 // 0x1f
+#elif defined(_BCM96816_)
+ .byte 0 // 0x0
+ .byte 1 // 0x1
+ .byte 0 // 0x2
+ .byte 0 // 0x3
+ .byte 0 // 0x4
+ .byte 1 // 0x5
+ .byte 1 // 0x6
+ .byte 1 // 0x7
+ .byte 1 // 0x8
+ .byte 1 // 0x9
+ .byte 1 // 0xa
+ .byte 2 // 0xb
+ .byte 2 // 0xc
+ .byte 2 // 0xd
+ .byte 2 // 0xe
+ .byte 2 // 0xf
+ .byte 2 // 0x10
+ .byte 2 // 0x11
+ .byte 2 // 0x12
+ .byte 2 // 0x13
+ .byte 2 // 0x14
+ .byte 0 // 0x15
+ .byte 0 // 0x16
+ .byte 1 // 0x17
+ .byte 1 // 0x18
+ .byte 1 // 0x19
+ .byte 1 // 0x1a
+ .byte 1 // 0x1b
+ .byte 2 // 0x1c
+ .byte 2 // 0x1d
+ .byte 2 // 0x1e
+ .byte 2 // 0x1f
+#endif
+
+ .globl memc_ubus_ratio_table
+memc_ubus_ratio_table: /* Memory Speed Table for different clock strap values */
+#if defined(_BCM96328_)
+// 6328 Clock Speed Table
+ .byte 3 // 0x0
+ .byte 3 // 0x1
+ .byte 3 // 0x2
+ .byte 3 // 0x3
+ .byte 3 // 0x4
+ .byte 3 // 0x5
+ .byte 3 // 0x6
+ .byte 3 // 0x7
+ .byte 3 // 0x8
+ .byte 3 // 0x9
+ .byte 3 // 0xa
+ .byte 3 // 0xb
+ .byte 3 // 0xc
+ .byte 3 // 0xd
+ .byte 3 // 0xe
+ .byte 3 // 0xf
+ .byte 3 // 0x10
+ .byte 3 // 0x11
+ .byte 0xf // 0x12
+ .byte 0xf // 0x13
+ .byte 3 // 0x14
+ .byte 9 // 0x15
+ .byte 9 // 0x16
+ .byte 9 // 0x17
+ .byte 3 // 0x18
+ .byte 3 // 0x19
+ .byte 3 // 0x1a
+ .byte 3 // 0x1b
+ .byte 0xb // 0x1c
+ .byte 0xb // 0x1d
+ .byte 0xb // 0x1e
+ .byte 3 // 0x1f
+#elif defined(_BCM96362_)
+// 6362 Clock Speed Table
+ .byte 3 // 0x0
+ .byte 3 // 0x1
+ .byte 3 // 0x2
+ .byte 3 // 0x3
+ .byte 3 // 0x4
+ .byte 3 // 0x5
+ .byte 3 // 0x6
+ .byte 3 // 0x7
+ .byte 3 // 0x8
+ .byte 3 // 0x9
+ .byte 3 // 0xa
+ .byte 3 // 0xb
+ .byte 3 // 0xc
+ .byte 3 // 0xd
+ .byte 3 // 0xe
+ .byte 3 // 0xf
+ .byte 3 // 0x10
+ .byte 3 // 0x11
+ .byte 3 // 0x12
+ .byte 3 // 0x13
+ .byte 4 // 0x14
+ .byte 4 // 0x15
+ .byte 15 // 0x16
+ .byte 3 // 0x17
+ .byte 3 // 0x18
+ .byte 3 // 0x19
+ .byte 3 // 0x1a
+ .byte 3 // 0x1b
+ .byte 3 // 0x1c
+ .byte 3 // 0x1d
+ .byte 3 // 0x1e
+ .byte 3 // 0x1f
+#elif defined(_BCM96816_)
+// 6816 Clock Speed Table
+ .byte 3 // 0x0
+ .byte 9 // 0x1
+ .byte 3 // 0x2
+ .byte 4 // 0x3
+ .byte 3 // 0x4
+ .byte 3 // 0x5
+ .byte 9 // 0x6
+ .byte 3 // 0x7
+ .byte 3 // 0x8
+ .byte 3 // 0x9
+ .byte 2 // 0xa
+ .byte 4 // 0xb
+ .byte 2 // 0xc
+ .byte 3 // 0xd
+ .byte 4 // 0xe
+ .byte 9 // 0xf
+ .byte 1 // 0x10
+ .byte 1 // 0x11
+ .byte 1 // 0x12
+ .byte 1 // 0x13
+ .byte 3 // 0x14
+ .byte 3 // 0x15
+ .byte 4 // 0x16
+ .byte 9 // 0x17
+ .byte 6 // 0x18
+ .byte 2 // 0x19
+ .byte 6 // 0x1a
+ .byte 2 // 0x1b
+ .byte 4 // 0x1c
+ .byte 3 // 0x1d
+ .byte 4 // 0x1e
+ .byte 3 // 0x1f
+#endif
+
+#if defined(_BCM96816_)
+ .globl periph_fix_table
+periph_fix_table: // Periph Clock fix vector for different clock strap values
+ _LONG_ 0xAA30A047
+#endif
+
+#define SETLEDS1(a,b,c,d) \
+ li a0,(((a)<<24)|((b)<<16)|((c)<<8)|(d)) ; \
+ bal board_setleds; \
+ nop
+
+/* *********************************************************************
+ * BOARD_EARLYINIT()
+ *
+ * Initialize board registers. This is the earliest
+ * time the BSP gets control. This routine cannot assume that
+ * memory is operational, and therefore all code in this routine
+ * must run from registers only. The $ra register must not
+ * be modified, as it contains the return address.
+ *
+ * This routine will be called from uncached space, before
+ * the caches are initialized. If you want to make
+ * subroutine calls from here, you must use the CALLKSEG1 macro.
+ *
+ * Among other things, this is where the GPIO registers get
+ * programmed to make on-board LEDs function, or other startup
+ * that has to be done before anything will work.
+ *
+ * Input parameters:
+ * a0 - Flash base address (address of MIPS reset)
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+
+LEAF(board_earlyinit)
+
+ .set noreorder
+
+ mfc0 t1, C0_BCM_CONFIG, 3
+ li t2, CP0_CMT_TPID
+ and t1, t2
+ bnez t1, 3f # if we are running on thread 1, skip init
+ nop
+
+ /**-------------------------------------------------------------**/
+ /** platform specific code **/
+ /**-------------------------------------------------------------**/
+
+#if defined(_BCM96816_)
+ /**----- Offset UBUS Clock 180 degrees -------------------------**/
+ li t2, MISC_BASE
+ lw t1, MISC_STRAP_BUS(t2)
+
+ srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT
+ andi t1, 0x1f // Mask out strap bits
+
+ move s0,ra
+ LOADREL(t2, periph_fix_table)
+ lw t2, 0(t2)
+ srl t2, t1
+ andi t2, 1
+ move ra,s0
+
+ beq t2, zero, 2f
+ nop
+
+ li t0, DDR_BASE
+ li t1, 0x00070000 // send new phase value to PLL every 8 cycles
+ sw t1, DDR_CTL_PI_UBUS_CTL(t0)
+ ori t1, 0x4080 // shift 128 steps in the positive direction to be 180 degree's offset VCO 1.6GHz
+ sw t1, DDR_CTL_PI_UBUS_CTL(t0)
+ li t1, 0x00000001
+ sw t1, DDR_CTL_PI_GCF(t0)
+
+ li t1, 0x10000 // delay
+1:
+ bnez t1, 1b
+ addi t1, -1
+
+2:
+ /**----- Set 1.2V and 2.5V Voltage regulators ------------------**/
+ li t1, GPIO_BASE
+ lw t2, GPIO_SWREG_CONFIG(t1)
+ and t2, ~GPIO_SW_VREG_SEL_MASK
+ or t2, (0x0 << GPIO_SW_VREG_SEL_SHIFT)
+ and t2, ~GPIO_LIN_VREG_ADJ_MASK
+ or t2, (0x0 << GPIO_LIN_VREG_ADJ_SHIFT)
+ sw t2, GPIO_SWREG_CONFIG(t1)
+
+ li t1, 0x10000
+1:
+ bnez t1, 1b
+ addi t1, -1
+#endif
+
+#if defined (_BCM96328_) || defined (_BCM96362_)
+ /* slow down mips clk (div 4) to unlock memory */
+ mfc0 t1, C0_BCM_CONFIG, 5
+ or t2, t1, 0x40000000
+ mtc0 t2, C0_BCM_CONFIG, 5
+ nop
+
+ mtc0 t1, C0_BCM_CONFIG, 5
+ nop
+#endif
+
+#if defined (_BCM96362_)
+ /* Adjust VREG frequency up by 50% to improve DSL performance */
+ li t2, MISC_BASE
+
+ /* First set ramp control */
+ lw t1, MISC_VREG_CONTROL0(t2)
+ or t1, (0x2 << MISC_VREG_CONTROL0_VREG_RAMP1P8_SHIFT) | (0x2 << MISC_VREG_CONTROL0_VREG_RAMP1P2_SHIFT)
+ sw t1, MISC_VREG_CONTROL0(t2)
+
+ /* wait 10ms for the setting to take effect */
+ li t8, -2000000
+ mtc0 t8, C0_COUNT
+1:
+ bltz t8, 1b
+ mfc0 t8, C0_COUNT
+
+ and t1, ~((0x7 << MISC_VREG_CONTROL0_VREG_RAMP1P8_SHIFT) | (0x7 << MISC_VREG_CONTROL0_VREG_RAMP1P2_SHIFT))
+ or t1, (0x3 << MISC_VREG_CONTROL0_VREG_ADJ_SHIFT)
+ sw t1, MISC_VREG_CONTROL0(t2)
+
+ /* Increase 2.5V regulator to provide increased range for 1.8V */
+ lw t1, MISC_VREG_CONTROL1(t2)
+ and t1, ~MISC_VREG_CONTROL1_VREG_ISEL2P5_MASK
+ or t1, (MISC_VREG_LDO_2P61 << MISC_VREG_CONTROL1_VREG_ISEL2P5_SHIFT)
+ sw t1, MISC_VREG_CONTROL1(t2)
+#endif
+
+#if 0
+ /* wait for a while to allow catch by jtag debugger */
+ li t8, -(200000000*3) /* we will count up to 0 to delay a couple of seconds */
+ /* and give the emulator a chance to catch us */
+ mtc0 t8, C0_COUNT
+catchloop:
+ bltz t8, catchloop
+ mfc0 t8, C0_COUNT
+#endif
+
+ /**----- Enable I Cache -----------------------------------------**/
+ mfc0 t1, C0_BCM_CONFIG
+ or t1, (CP0_BCM_CFG_ICSHEN | CP0_BCM_CFG_DCSHEN)
+ mtc0 t1, C0_BCM_CONFIG # Enable I Cache
+
+ // In the begining MIPS core registers are mapped to 0xbfax_xxxx
+ li t1, 0x1FA0000C # Set up CBR to 1FAx_xxxx
+ mtc0 t1, C0_BCM_CONFIG, 6
+
+ li t1, MIPS_BASE_BOOT
+ lw t2, MIPS_LMB_CR(t1)
+ or t2, 0xC0000000 # enable ffxx_xxxx space
+ sw t2, MIPS_LMB_CR(t1)
+ li t2, 0xFFF80001 # SBR FFF8_xxxx and enable
+ sw t2, MIPS_SBR(t1)
+
+ // Now map MIPS core registers to 0xFF4x_xxxx space
+ li t1, 0xFF40000C # CBR FF4x_xxxx (and reserved bits 0xc).
+ mtc0 t1, C0_BCM_CONFIG, 6
+
+#if defined(_BCM96816_)
+ /**----- Initialize EBI -----------------------------------------**/
+ li t1, MPI_BASE
+ li t2, EBI_SIZE_32M
+ or t2, a0
+ sw t2, CS0BASE(t1) # CS[0] Base
+ li t2, THREEWT|EBI_WORD_WIDE|EBI_ENABLE
+ sw t2, CS0CNTL(t1) # CS[0] Control
+#endif
+
+ /**----- Initialize Serial --------------------------------------**/
+ li t3, ((FPERIPH / 115200) / 16)
+ /*
+ # Baudword = (FPeriph)/Baud/32-1. We have to perform rounding
+ # and subtraction. Above we divided by 16 (instead of 32). If
+ # bit0 is set, we round up. However, we then subtract 1, so final
+ # result should be t3/2. If bit0 is 0, then we truncate and subtract
+ # 1, t3=t3/2-1.
+ */
+ andi t0, t3, 0x1
+ bne t0,zero,1f # do shift only (in delay slot)
+ # and jump to apply
+ srl t3,1 # do divide by 2
+ addiu t3, -1 # subtract 1
+1:
+
+ // t3 contains the UART BAUDWORD
+ li t0, UART_BASE
+ sw t3, UART0BAUD(t0) # Store BaudRate
+ li t1, BITS8SYM|ONESTOP
+ sb t1, UART0CONFIG(t0) # 8 Bits/1 Stop
+ li t1, TXEN|RXEN|BRGEN
+ sb t1, UART0CONTROL(t0) # Enable, No Parity
+ move t1, zero
+ sh t1, UART0INTMASK(t0)
+
+ .set reorder
+3:
+ j ra
+END(board_earlyinit)
+
+/* *********************************************************************
+ * BOARD_DRAMINFO
+ *
+ * Return the address of the DRAM information table
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * v0 - DRAM info table, return 0 to use default table
+ ********************************************************************* */
+LEAF(board_draminfo)
+ j ra
+END(board_draminfo)
+
+/* *********************************************************************
+ * BOARD_DRAMINIT
+ *
+ * This routine should activate memory.
+ *
+ * Input parameters:
+ * None
+ *
+ * Return value:
+ * None
+ *
+ * Registers used:
+ * can use all registers.
+ ********************************************************************* */
+LEAF(board_draminit)
+ .set noreorder
+
+ move s0,ra
+
+/***** Load DDR Base *************************************/
+ li t0, DDR_BASE
+
+/***** Disable Auto refresh ******************************/
+ li t1, 0x10000
+ sw t1, DDR_CTL_CLKS(t0)
+ SETLEDS1('-','-','-', '-')
+ SETLEDS1('P','H','Y','S')
+
+ li t1, 0x10 // Loop count value
+ li t3, 1
+
+zq_loop:
+ sub t1, t3 // Decrement count by 1
+ beq t1, zero, zq_error
+ nop
+
+ sw zero, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Reset the calibration engine
+ li t4, (1 << 26)
+ sw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Start the calibration
+
+ li t2, 0x100 // Timeout value
+
+wait_zq1:
+ beq t2, zero, zq_timeout
+ nop
+
+ lw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Read the calibration result
+ move t5, t4 // Save calibration result1
+ and t4, (1 << 28)
+ beq t4, zero, wait_zq1
+ sub t2, t3
+
+ sw zero, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Reset the calibration engine
+ li t4, (1 << 26)
+ sw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Start the calibration
+
+ li t2, 0x100 // Timeout value
+
+wait_zq2:
+ beq t2, zero, zq_timeout
+ nop
+
+ lw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Read the calibration result
+ move t6, t4 // Save calibration result1
+ and t4, (1 << 28)
+ beq t4, zero, wait_zq2
+ sub t2, t3
+
+ sw zero, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Reset the calibration engine
+ li t4, (1 << 26)
+ sw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Start the calibration
+
+ li t2, 0x100 // Timeout value
+
+wait_zq3:
+ beq t2, zero, zq_timeout
+ nop
+
+ lw t4, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Read the calibration result
+ move t7, t4 // Save calibration result1
+ and t4, (1 << 28)
+ beq t4, zero, wait_zq3
+ sub t2, t3
+
+ bne t5, t6, zq_loop
+ nop
+ bne t5, t7, zq_loop
+ nop
+ bne t6, t7, zq_loop
+ nop
+
+ b zq_done;
+ nop
+
+zq_error:
+ SETLEDS1('Z','Q','E','R')
+ b zq_done
+ nop
+
+zq_timeout:
+ SETLEDS1('Z','Q','T','O')
+ nop
+zq_done:
+ sw zero, PHY_CONTROL_REGS_ZQ_PVT_COMP_CTL(t0) // Reset the calibration engine
+
+ SETLEDS1('Z','Q','D','N')
+ nop
+
+/****** Set control pad strength to half ********/
+ lw t2, PHY_CONTROL_REGS_DRIVE_PAD_CTL(t0)
+ or t2, 0x4
+ sw t2, PHY_CONTROL_REGS_DRIVE_PAD_CTL(t0)
+
+#if defined(_BCM96816_)
+/****** Disable byte lanes 2 and 3 ********/
+ li t1, 0x800fffff
+ sw t1, PHY_BYTE_LANE_2_IDLE_PAD_CONTROL(t0)
+ sw t1, PHY_BYTE_LANE_3_IDLE_PAD_CONTROL(t0)
+#endif
+
+/****** Disable byte lane 1 clock ********/
+ li t1, 1
+ sw t1, PHY_BYTE_LANE_1_CLOCK_PAD_DISABLE(t0)
+
+ddr_x8:
+
+/****** Change the slew and receiver power to full strength in the byte lanes ********/
+ li t1, 0xFFFFFFFC
+ lw t2, PHY_BYTE_LANE_0_DRIVE_PAD_CTL(t0)
+ and t2, t2, t1
+ sw t2, PHY_BYTE_LANE_0_DRIVE_PAD_CTL(t0)
+ lw t2, PHY_BYTE_LANE_1_DRIVE_PAD_CTL(t0)
+ and t2, t2, t1
+ sw t2, PHY_BYTE_LANE_1_DRIVE_PAD_CTL(t0)
+
+/****** Hardware calibrate VDL *******/
+ li t1, 3
+ sw t1, PHY_BYTE_LANE_0_VDL_CALIBRATE(t0)
+ sw t1, PHY_BYTE_LANE_1_VDL_CALIBRATE(t0)
+
+ li t1, 0x1000
+1:
+ bnez t1, 1b
+ addi t1, -1
+
+/****** Check strap value to figure out 400MHz or 200Mhz DDR ******/
+ li t2, MISC_BASE
+ lw t1, MISC_STRAP_BUS(t2)
+
+ srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT
+ andi t1, 0x1f // Mask out strap bits
+
+ LOADREL(t2, dram_speed_table)
+
+ add t2, t1
+ lb t1, 0x00(t2)
+ beq t1, zero, ddr_clk_200
+ li t2, 1
+ beq t1, t2, ddr_clk_300
+ nop
+
+/****** Software override rd_en VDL and ADDRESS VDL ********/
+ddr_clk_450:
+ddr_clk_400:
+ li a1, 2 // Set speed to 400MHz (2)
+ b 1f
+ nop
+ddr_clk_300:
+ li a1, 1 // Set speed to 300MHz (1)
+
+/* At higher frequencies set Read_en VDL value to calibrated VDL value + 10 */
+1: li t2, 0x10000
+ lw t1, PHY_BYTE_LANE_0_VDL_STATUS(t0)
+ srl t1, 8
+ addi t1, 0xA
+ or t1, t1, t2
+ sw t1, PHY_BYTE_LANE_0_VDL_OVERRIDE_2(t0)
+ lw t1, PHY_BYTE_LANE_1_VDL_STATUS(t0)
+ srl t1, 8
+ addi t1, 0xA
+ or t1, t1, t2
+ sw t1, PHY_BYTE_LANE_1_VDL_OVERRIDE_2(t0)
+ b vdl_override_cont
+ nop
+
+ddr_clk_200:
+ li a1, 0 // Set speed to 200MHz (0)
+ li t3, 0x1f // Set maximum VDL step size for 200MHz
+ b 1f
+ nop
+
+vdl_override_cont:
+ lw t2, PHY_BYTE_LANE_0_VDL_STATUS(t0)
+ andi t3, t2, 0x1f00
+ srl t3, 8
+ addi t3, t3, 0x4 // Add Stepsize 4
+
+1: li t1, 0x110000 // Enable & Force Override
+ or t1, t3 // Fine rise and fine fall are set to 0
+
+ sw t1, PHY_CONTROL_REGS_STATIC_VDL_OVERRIDE(t0)
+ li t1, 0x0c
+ sw t1, DDR_CTL_DCMD(t0) // Set VDL
+
+ SETLEDS1('P','H','Y','E')
+
+/* Program MC Timing Registers
+
+ Read each timing parameter based on the speed and then create the
+ timing registers and program them.
+*/
+ LOADREL(t2, dram_timing_table)
+
+ li t1, 0x10 // size of dram_timing_table element
+ mult t1, a1
+ mflo t1 // dram_timing_table offset
+ add t2, t1
+
+ move t3, zero
+ lb t1, 0x00(t2) // tRCD
+ andi t1, 0xf
+ move t3, t1
+ lb t1, 0x01(t2) // tCL
+ andi t1, 0xf
+
+ move t4, t1
+ and t4, 0x7 // Make sure that only 3 bits are written to DRAM's tCL field
+ sll t4, 20
+ sw t4, DDR_CTL_DMODE_0 (t0) // Write tCL to the MRS register holder
+
+ sll t1, 4
+ or t3, t1
+ lb t1, 0x02(t2) // tWR
+ andi t1, 0xf
+
+ // Here we create the MRS register values
+ move t4, t1
+ li t5, 1
+ subu t4, t5 // tWR written to DRAM is 1 less than real tWR value
+ andi t4, 0x7
+ sll t4, 25
+ li t5, 0x01030000 // Sequential burst mode, burst of 8, reset DLL
+ or t4, t5
+ lw t5, DDR_CTL_DMODE_0 (t0)
+ or t5, t4
+ sw t5, DDR_CTL_DMODE_0 (t0) // Add tWR to the MRS register holder
+
+ sll t1, 9
+ or t3, t1
+ lb t1, 0x03(t2) // tWL
+ andi t1, 0xf
+ sll t1, 12
+ or t3, t1
+ lb t1, 0x04(t2) // tRP
+ andi t1, 0xf
+ sll t1, 16
+ or t3, t1
+ lb t1, 0x05(t2) // tRRD
+ andi t1, 0xf
+ sll t1, 20
+ or t3, t1
+ lb t1, 0x06(t2) // tRC
+ andi t1, 0x1f
+ sll t1, 24 // tRCw
+ or t3, t1
+ sw t3, DDR_CTL_TIM1_0(t0) // Program TIM1_0 register
+
+ move t3, zero
+ lb t1, 0x06(t2) // tRC
+ andi t1, 0x1f
+ or t3, t1 // tRCr
+ lb t1, 0x07(t2) // tFAW
+ andi t1, 0x3f
+ sll t1, 8
+ or t3, t1
+ li t1, 0xff // tRFC = 0xff (Set to max value first.
+ sll t1, 16 // We'll fix it after we determine dram size)
+ or t3, t1
+
+ // We skip tFIFO since it needs to be 0
+
+ lb t1, 0x08(t2) // tW2R
+ andi t1, 0x3
+ sll t1, 26
+ or t3, t1
+ lb t1, 0x09(t2) // tR2W
+ andi t1, 0x3
+ sll t1, 28
+ or t3, t1
+ lb t1, 0x0a(t2) // tR2R
+ andi t1, 0x1
+ sll t1, 30
+ or t3, t1
+ sw t3, DDR_CTL_TIM1_1(t0) // Program TIM1_1 register
+
+ move t3, zero
+ lb t1, 0x0b(t2) // tAL
+ andi t1, 0xf
+
+ // Here we create the EMRS register values
+ move t4, t1
+ andi t4, 0x7
+ sll t4, 3
+ li t5, 0x384 // RTT=75ohm, OCD Enter
+ or t4, t5
+ lw t5, DDR_CTL_DMODE_0 (t0)
+ or t5, t4
+ sw t5, DDR_CTL_DMODE_0 (t0) // Store required values in EMRS holding register
+
+ or t3, t1
+ lb t1, 0x0c(t2) // tRTP
+ andi t1, 0x7
+ sll t1, 4
+ or t3, t1
+ lb t1, 0x0d(t2) // tW2W
+ andi t1, 0x3
+ sll t1, 8
+ or t3, t1
+ sw t3, DDR_CTL_TIM2(t0) // Program TIM2 register
+
+/*
+// (tRRD is incremented by 1 due to tFAW bug for >=1Gb devices)
+ li t1, 0x18564c55 // tRCD=5,tWR=6,tCL=5,tWL=4,tRP=6,tRRD=5,tRCw=0x18
+// li t1, 0x13554a55 // tRCD=5,tWR=5,tCL=5,tWL=4,tRP=5,tRRD=5,tRCw=0x13
+ sw t1, DDR_CTL_TIM1_0(t0)
+ li t1, 0x18330018 // tR2W=1,tR2R=0,tW2R=2,tFIFO=0,tRFC=0x33,tFAW=0,tRCr=0x18
+// li t1, 0x182b0013 // tR2W=1,tR2R=0,tW2R=2,tFIFO=0,tRFC=0x2b,tFAW=0,tRCr=0x13
+ sw t1, DDR_CTL_TIM1_1(t0)
+ li t1, 0x00000034 // tAL=4 (tRCD-1), tRTP=3, tW2W=0
+ sw t1, DDR_CTL_TIM2(t0)
+*/
+
+// Set x16 mode and Page policy
+ li t1, 0x100
+ sw t1, DDR_CTL_DMODE_1(t0)
+
+// Enable ODT for writes
+ li t1, 0x104
+ sw t1, DDR_CTL_ODT(t0)
+
+/***** Turn on CKE ***************/
+ li t1, 0x35
+ sw t1, DDR_CTL_DCMD(t0)
+
+ li t1, 0x200
+2:
+ bnez t1, 2b
+ addi t1, -1
+
+/***** Set arbitor for Burst Round Robin Mode ***/
+ lw t1, DDR_CTL_ARB(t0)
+ or t1, 4 << 16
+ sw t1, DDR_CTL_ARB(t0)
+
+/***** Issue Precharge All Banks Command ***/
+ li t1, 0x32
+ sw t1, DDR_CTL_DCMD(t0)
+
+/***** Issue EMRS2 Command ***/
+ li t1, 0x0
+ lw t2, DDR_CTL_DMODE_0 (t0) // Load previous value to t2 to preserve it
+ nop
+ sw t1, DDR_CTL_DMODE_0 (t0)
+ li t1, 0x38
+ sw t1, DDR_CTL_DCMD(t0)
+
+/***** Issue EMRS3 Command***/
+ li t1, 0x0
+ sw t1, DDR_CTL_DMODE_0 (t0)
+ li t1, 0x39
+ sw t1, DDR_CTL_DCMD(t0)
+
+// Enable DLL by issuing EMRS Command
+// li t1, 0x0
+// sw t1, DDR_CTL_DMODE_0 (t0)
+ sw t2, DDR_CTL_DMODE_0 (t0) // Use the saved value back to DMODE_0 register
+ li t1, 0x30
+ sw t1, DDR_CTL_DCMD(t0)
+
+/*
+// Issue MRS Command tCL=5 tWL=4
+ li t1, 0x0b530000
+// li t1, 0x07530000 // tCL=5 tWR=5, Reset DLL, Sequential Mode, Burst Length = 8
+ sw t1, DDR_CTL_DMODE_0 (t0)
+ li t1, 0x31
+ sw t1, DDR_CTL_DCMD(t0)
+*/
+// Issue MRS Command. Set Reset DLL bit
+ li t1, 0x31
+ sw t1, DDR_CTL_DCMD(t0)
+
+// Issue Precharge All Banks Command
+ li t1, 0x32
+ sw t1, DDR_CTL_DCMD(t0)
+
+// Issue Autorefresh Command
+ li t1, 0x33
+ sw t1, DDR_CTL_DCMD(t0)
+ li t1, 0x33
+ sw t1, DDR_CTL_DCMD(t0)
+
+ li t1, 0x200
+3:
+ bnez t1, 3b
+ addi t1, -1
+
+/*
+// Clear DLL Reset by Issuing MRS Command, tCL=5 tWL=4
+ li t1, 0x0a530000
+ sw t1, DDR_CTL_DMODE_0 (t0)
+ li t1, 0x31
+ sw t1, DDR_CTL_DCMD(t0)
+*/
+
+// Issue MRS Command w/ DLL Reset bit set to 0
+ lw t1, DDR_CTL_DMODE_0 (t0)
+ li t2, 0xFEFFFFFF // Reset DLL reset bit
+ and t1, t2
+ sw t1, DDR_CTL_DMODE_0 (t0)
+ li t1, 0x31
+ sw t1, DDR_CTL_DCMD(t0)
+
+/*
+// Issue EMRS Command (Enter OCD Calibration)
+ li t1, 0x380
+ sw t1, DDR_CTL_DMODE_0 (t0)
+ li t1, 0x30
+ sw t1, DDR_CTL_DCMD(t0)
+*/
+
+// Issue EMRS Command (Enter OCD Calibration) 75 Ohm, Full strength Drive, tAL=tRCD-1
+ li t1, 0x30
+ sw t1, DDR_CTL_DCMD(t0)
+
+// Issue EMRS Command (Exit OCD Calibration)
+ lw t1, DDR_CTL_DMODE_0 (t0)
+ li t2, 0xFC7F // Reset OCD field for exit mode
+ and t1, t2
+ sw t1, DDR_CTL_DMODE_0 (t0)
+ li t1, 0x30
+ sw t1, DDR_CTL_DCMD(t0)
+
+// Check x8 or x16 DDR
+ li t1, 0x12345678
+ li t3, 0xA0000000
+ sw zero, 0(t3)
+ sw t1, 0(t3)
+ lw t2, 0(t3)
+ bne t1, t2, 3f // Failed
+ nop
+// Do the test twice. Just in case random values match...
+ li t1, 0x87654321
+ sw t1, 0(t3)
+ lw t2, 0(t3)
+ beq t1, t2, 1f // Clock lines are enabled as needed
+ nop
+
+3:
+// Memory test failed. Need to re-enable byte lane 1 clock
+ sw zero, PHY_BYTE_LANE_1_CLOCK_PAD_DISABLE(t0)
+ li t1, 0x200
+2:
+ bnez t1, 2b // Delay after enabling clocks
+ addi t1, -1
+ b ddr_x8
+ nop
+
+1:
+// Find memory size. a3 keeps the size: 0=256Mb, 1=512Mb, 2=1Gb, 3=2Gb
+// Start from 2Gb device
+ LOADREL(t7, dram_map_table_x8)
+ lw t1, PHY_BYTE_LANE_1_CLOCK_PAD_DISABLE(t0)
+ beqz t1, 1f
+ nop
+ LOADREL(t7, dram_map_table_x16)
+
+1:
+ li a3, 4
+ddr_size:
+ addi a3, -1
+
+ li t1, 0x2c // size of dram_map_table element
+ mult t1, a3
+ mflo t2 // dram_map_table offset
+ add t2, t7
+
+ lw t1, 0x00(t2) // Row00_0
+ sw t1, DDR_CTL_ROW00_0(t0)
+
+ lw t1, 0x04(t2) // Row00_1
+ sw t1, DDR_CTL_ROW00_1(t0)
+
+ lw t1, 0x08(t2) // Row01_0
+ sw t1, DDR_CTL_ROW01_0(t0)
+
+ lw t1, 0x0C(t2) // Row01_1
+ sw t1, DDR_CTL_ROW01_1(t0)
+
+ lw t1, 0x10(t2) // Col00_0
+ sw t1, DDR_CTL_COL00_0(t0)
+
+ lw t1, 0x14(t2) // Col00_1
+ sw t1, DDR_CTL_COL00_1(t0)
+
+ lw t1, 0x18(t2) // Col01_0
+ sw t1, DDR_CTL_COL01_0(t0)
+
+ lw t1, 0x1C(t2) // Col01_1
+ sw t1, DDR_CTL_COL01_1(t0)
+
+ lw t1, 0x20(t2) // Bank
+ sw t1, DDR_CTL_BNK10(t0)
+
+ li t1, 0x0 // CS_Start
+ sw t1, DDR_CTL_CSST(t0)
+
+ lw t1, 0x24(t2) // CS_End
+ sw t1, DDR_CTL_CSEND(t0)
+
+ li t1, 0x0 // CS Interleaving CFG
+ sw t1, DDR_CTL_CNFG(t0)
+
+ lw t3, 0x28(t2) // Dram Size
+ lw t1, DDR_CTL_GCFG(t0) // GCFG
+ li t2, 0xFFFFFF00
+ and t1, t1, t2 // Mask out Dram Size Fields
+ or t1, t3, t1 // insert new DRAM Size value
+ sw t1, DDR_CTL_GCFG(t0)
+ beqz a3, ddr_speed
+ nop
+
+// Check for memory aliasing
+// This assumes that the bank interleaving is below address bits 8.
+ li t1, 8
+ li t2, 24
+ add t2, a3 // Scan up to maximum memory size
+ li t3, 0xA0000000
+
+check_alias:
+ li t4, 1
+ sll t4, t1
+ add t4, t3
+
+ sw zero, 0(t3)
+ li t5, -1
+ sw t5, 0(t4)
+ lw t6, 0(t3)
+
+ beq t5, t6, ddr_size
+ nop
+
+ bne t1, t2, check_alias
+ addi t1, 1
+
+ddr_speed:
+ li t1, 3
+ lw t2, PHY_BYTE_LANE_1_CLOCK_PAD_DISABLE(t0)
+ beqz t2, 1f
+ nop
+ li t1, 2
+1:
+ blt a3, t1, tRefi_update // If smaller than 1Gb device, keep tRRD same
+ nop
+
+ lw t1, DDR_CTL_TIM1_0(t0) // Load DDR_CTL_TIM1_0 register
+ move t2, t1
+ srl t2, 20
+ andi t2, 0xf
+ addi t2, 1 // Increment ttRRD by one (software work around for a bug)
+ sll t2, 20
+ li t3, 0xFF0FFFFF
+ and t1, t3 // Clear tRRD field
+ or t1, t2 // Insert the new tRRD value
+ sw t1, DDR_CTL_TIM1_0(t0) // Store DDR_CTL_TIM1_0 register
+ nop
+
+tRefi_update:
+ LOADREL(t2, dram_tRefi_table)
+
+ li t1, 0x4 // size of dram_tRefi_table entry
+ mult t1, a1
+ mflo t1 // dram_tRefi_table offset
+ add t2, t1
+
+ lw t1, 0x0(t2) // tRefi
+ sll t1, 8
+ sw t1, DDR_CTL_CLKS(t0)
+
+ LOADREL(t2, dram_tRFC_table)
+
+ li t1, 0x4 // size of dram_tRFC_table entry
+ mult t1, a1
+ mflo t1 // dram_tRefi_table offset
+ add t2, t1 // Calculate address in the row
+
+ li t1, 0xc // size of dram_tRFC_table row
+ mult t1, a3
+ mflo t1 // dram_tRefi_table offset
+ add t2, t1 // Calculate address in the column
+
+ lw t3, 0x0(t2) // Load tRFC value
+ andi t3, 0xFF // Mask tRFC to 8-bits
+ sll t3, 16 // Move it to bit location [23:16]
+
+ lw t1, DDR_CTL_TIM1_1(t0) // Load DDR_CTL_TIM1_1 register
+ li t2, 0xFF00FFFF
+ and t1, t1, t2 // Mask out tRFC Field
+ or t1, t3, t1 // insert new tRFC value
+ sw t1, DDR_CTL_TIM1_1(t0) // Write to TIM1_1 register
+
+ SETLEDS1('D','I','N','T')
+
+/***** UBUS align to MEMC *****/
+align_memc:
+
+/*** check MEMC clk ratio to set sampling freq *****/
+ li t2, MISC_BASE
+ lw t1, MISC_STRAP_BUS(t2)
+
+ srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT
+ andi t1, 0x1f // Mask out strap bits
+
+#if defined(_BCM96816_)
+ LOADREL(t2, periph_fix_table)
+ lw t2, 0(t2)
+ srl t2, t1
+ andi t2, 1
+ bne t2, zero, 2f
+#endif
+
+ LOADREL(t2, memc_ubus_ratio_table)
+
+ add t2, t1
+ lb t1, 0x00(t2)
+ sll t4,t1,28 // Update Sampling Period Field
+
+pi_ubus:
+ li t2, 4048
+ li t3, 1
+
+ sw zero, DDR_CTL_PI_GCF(t0)
+ li t1, 0x00001c0b // send feedback command every 11 cycles
+ or t1, t1, t4
+ sw t1, DDR_CTL_PI_UBUS_SMPL(t0)
+ ori t1, 0x80 // trigger stoke signal to latch in new counter value
+ sw t1, DDR_CTL_PI_UBUS_SMPL(t0)
+ li t1, 0x00040000 // send new phase value to PLL every 5 cycles
+ sw t1, DDR_CTL_PI_UBUS_CTL(t0)
+ li t1, 0x00000001 // enable enable counter that change PLL phase
+ sw t1, DDR_CTL_PI_GCF(t0)
+ nop
+
+#if defined (_BCM96328_) || defined(_BCM96362_)
+// Enable PHY MIPS PI
+ li t1, 0x00130000
+ sw t1, DDR_CTL_PI_DSL_MIPS_CTL(t0)
+ nop
+#endif
+
+1:
+ lw t4, DDR_CTL_PI_UBUS_SMPL(t0) // Read a sample value.
+ srl t4, 16 // The sample is in the upper 16 bits.
+
+ andi t4, t4, 0x22 // Look at the 2 outermost bits; if the LSB is 0 and the MSB is 1,
+ beq t4, 0x20, 2f // then there is an edge somewhere in the sample.
+ nop
+ lw t5, DDR_CTL_PI_UBUS_CTL(t0)
+ and t5, 0xffff0000
+ or t5, t3
+ or t5, (1<<14) // move phase in positive direction
+ sw t5, DDR_CTL_PI_UBUS_CTL(t0)
+ nop
+ lw t5, DDR_CTL_PI_UBUS_CTL(t0) // Delay before reading another sample.
+ add t3, 1
+ bne t2, t3, 1b
+ nop
+
+ SETLEDS1('U','A','S','Y')
+ SETLEDS1('L','A','S','Y')
+ SETLEDS1('M','A','S','Y')
+ b run_async // failed to set sync mode
+ nop
+
+2:
+/*** check MIPS clk ratio *****/
+ li t4, 0xff410010
+ li t2, MISC_BASE
+ lw t1, MISC_STRAP_BUS(t2)
+
+ srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT
+ andi t1, 0x1f // Mask out strap bits
+
+ b _mips_align_2_ubus // none of the above means it is either 1/1 or 2/1
+ nop
+
+
+_mips_align_2_ubus:
+
+/***** MIPS align to UBUS *****/
+ li t1, 0xff410000
+
+ li t2, 0x00040000 // update PLL phase value every 5 MC cycles
+ sw t2, DDR_CTL_PI_MIPS_CTL(t0)
+
+ li t2, 0xc0001c03 // force update on mclk_period
+ sw t2, 0x40(t1)
+ li t2, 0x80001c83
+ sw t2, 0x40(t1)
+
+ lw t2, DDR_CTL_PI_MIPS_CTL(t0) // add delay
+ li t3, 1
+
+1: lw t4, 0x40(t1) // Read a sample value.
+ srl t4, 16 // The sample is in the upper 16 bits.
+
+ andi t4, t4, 0x22 // Look at the 2 outermost bits, if the LSB is 0 and the MSB is 1,
+ beq t4, 0x20, 2f // then there is an edge somewhere in the sample.
+ nop
+ lw t5, DDR_CTL_PI_MIPS_CTL(t0)
+ and t5, 0xffff0000
+ or t5, t3
+ or t5, (1<<14) // move phase in positive direction
+ sw t5, DDR_CTL_PI_MIPS_CTL(t0)
+ nop
+ lw t5, DDR_CTL_PI_MIPS_CTL(t0) // Delay before reading another sample.
+ add t3, 1
+ bne t2, t3, 1b
+ nop
+
+ SETLEDS1('U','A','S','Y')
+ SETLEDS1('L','A','S','Y')
+ SETLEDS1('M','A','S','Y')
+ b run_async // failed to set sync mode
+ nop
+2:
+ // Success
+ lw t2, DDR_CTL_PI_MIPS_CTL(t0) // Turn on auto-PI mode.
+ or t2, (1 << 20) // PI_UBUS_CTL_Hw_Cntr_En = 1
+ sw t2, DDR_CTL_PI_MIPS_CTL(t0)
+
+ /**----- Enable DDR/UBUS and DDR/LMB sync mode ------------------**/
+ /*** only MIPS in sync mode for these strap options */
+
+ li t2, MISC_BASE
+ lw t1, MISC_STRAP_BUS(t2)
+
+ srl t1, MISC_STRAP_BUS_MIPS_PLL_FVCO_SHIFT
+ andi t1, 0x1f // Mask out strap bits
+
+ li t3, 0 // Used to keep MC/MIPS and MC/UBUS sync/async mode
+
+ LOADREL(t2, dram_sync_table)
+
+ lw t4, 0x0(t2) // Ubus Sync vector
+ lw t5, 0x4(t2) // Lmb Sync vector
+
+#if defined (_96816_)
+ move t4, t6
+#endif
+ lw t6, 0x8(t2) // Mips Sync vector
+
+ srl t4, t1 // Get the ubus sync flag
+ srl t5, t1 // Get the lmb sync flag
+ srl t6, t1 // Get the mips sync flag
+ andi t4, 1 // Mask out other bits
+ andi t5, 1 // Mask out other bits
+ andi t6, 1 // Mask out other bits
+
+ li t2, 1
+ bne t4, t2, ubus_async // 1f below. If ubus is not sync, lmb can't be in sync
+ nop // Go to ubus_async (1f)
+
+ // Ubus Sync Mode. Turn on Ubus Clock tracking
+ lw t2, DDR_CTL_PI_UBUS_CTL(t0) // Turn on auto-PI mode.
+ or t2, (1 << 20) // PI_UBUS_CTL_Hw_Cntr_En = 1
+ sw t2, DDR_CTL_PI_UBUS_CTL(t0)
+
+ // Is LMB Sync as well?
+ li t2, 1
+ beq t5, t2, memc_all_sync // If both ubus and lmb are sync, go to memc_all_sync
+ nop
+
+memc_ubus_sync:
+#if UBUS_SYNC_ENABLE
+// set MC/UBUS to SYNC
+ li t3, 0x4
+ SETLEDS1('L','A','S','Y')
+ SETLEDS1('U','S','Y','N')
+#else
+// set MC/UBUS to ASYNC
+ li t3, 0xc
+ SETLEDS1('L','A','S','Y')
+ SETLEDS1('U','A','S','Y')
+#endif
+
+ b update_sync_mode
+ nop
+
+memc_all_sync:
+#if LMB_SYNC_ENABLE
+// set MC/MIPS to SYNC
+ nop
+ SETLEDS1('L','S','Y','N')
+#else
+// set MC/MIPS to ASYNC
+ li t1, 0x4
+ or t3, t1
+ SETLEDS1('L','A','S','Y')
+#endif
+#if UBUS_SYNC_ENABLE
+// set MC/UBUS to SYNC
+ nop
+ SETLEDS1('U','S','Y','N')
+#else
+// set MC/UBUS to ASYNC
+ li t1, 0x8
+ or t3, t1
+ SETLEDS1('U','A','S','Y')
+#endif
+
+update_sync_mode:
+ li t1, MISC_BASE
+ sw t3, MISC_MEMC_CONTROL(t1)
+ b 2f
+ nop
+1:
+ubus_async:
+ SETLEDS1('L','A','S','Y')
+ SETLEDS1('U','A','S','Y')
+
+2:
+ // Can Mips run in sync mode? If not, skip all below
+ beq t6, zero, run_async
+ nop
+
+#if MIPS_SYNC_ENABLE
+ /**----- Clear MIPS Async mode bit ------------------------------**/
+ mfc0 t1, C0_BCM_CONFIG, 5
+ and t1, ~(0x1 << 28)
+ mtc0 t1, C0_BCM_CONFIG, 5
+
+ SETLEDS1('M','S','Y','N')
+#else
+ SETLEDS1('M','A','S','Y')
+#endif
+
+3:
+ /**----- Enable RAC and LMB -------------------------------------**/
+ li t0, MIPS_BASE
+ lw t2, MIPS_LMB_CR(t0)
+#if LMB_ENABLE
+ or t2, LMB_EN // Enable LMB
+ SETLEDS1('L','M','B','E')
+#else
+ SETLEDS1('L','M','B','D')
+#endif
+ sw t2, MIPS_LMB_CR(t0)
+
+ li t2, 0xFFF << RAC_UPB_SHFT // Enable prefetch for RAM address range up to 256MB
+ sw t2, MIPS_RAC_ARR(t0)
+
+ lw t2, MIPS_RAC_CR0(t0)
+ or t2, (RAC_C_INV | RAC_I | RAC_PF_I)
+ sw t2, MIPS_RAC_CR0(t0)
+
+ lw t2, MIPS_RAC_CR1(t0)
+ or t2, (RAC_C_INV | RAC_I | RAC_PF_I)
+ sw t2, MIPS_RAC_CR1(t0)
+
+run_async:
+ /**----- Enable branch prediction and non-blocking data cache ---**/
+ mfc0 t1, C0_BCM_CONFIG
+ and t1, ~CP0_BCM_CFG_BTHD
+ or t1, CP0_BCM_CFG_NBK
+ or t1, CP0_BCM_CFG_CLF
+ mtc0 t1, C0_BCM_CONFIG
+
+#if DDR_TEST
+#######################################
+# Run test on DRAM using Test Engine #
+#######################################
+#define BACKGND_MODE_DATA 0x0
+#define BACKGND_MODE_LFSR 0x400
+#define BACKGND_MODE_PRBS 0x800
+#define BACKGND_MODE_NOT_PRBS 0xc00
+#define BACKGND_MODE_PAT 0x1000
+#define BACKGND_MODE_NOT_PAT 0x1400
+
+#define VICT_MODE_PRBS 0
+#define VICT_MODE_NOT_PRBS 0x100
+#define VICT_MODE_PAT 0x200
+#define VICT_MODE_NOT_PAT 0x300
+
+#define VICT_ENABLE 0x8000
+#define VICT_SWEEP_ENABLE 0x10000
+#define VICT_COUNT 0x0
+
+#define PRBS_ORDER(x) ((x & 0x3) << 13)
+
+#define TEST_COUNT 0x1000
+#define TEST_ADDR 0x0
+#define TEST_ADDR_UPDT 0x1
+#define TEST_PATTERN0 0x5555
+#define TEST_PATTERN1 0xaaaa
+#define TEST_PATTERN (TEST_PATTERN1 << 16 | TEST_PATTERN0)
+
+#define TEST_ENABLE 0x1
+#define TEST_DONE 0x2
+#define TEST_ERROR 0x4
+#define TEST_WRITE 0x10
+#define TEST_READ 0x0
+
+#define BACKGND_DATA0 0xa5a5a5a5
+#define BACKGND_DATA1 0x5a5a5a5a
+#define BACKGND_DATA2 0xa5a5a5a5
+#define BACKGND_DATA3 0x5a5a5a5a
+
+#define TEST_DATA0 0x02468ace
+#define TEST_DATA1 0x13579bdf
+#define TEST_DATA2 0x33cccc33
+#define TEST_DATA3 0x55aaaa55
+
+/***** Load DDR Base *************************************/
+ li t0, DDR_BASE
+ li t1, BACKGND_DATA0
+ sw t1, DDR_CTL_TEST_DATA0(t0)
+ li t1, BACKGND_DATA1
+ sw t1, DDR_CTL_TEST_DATA1(t0)
+ li t1, BACKGND_DATA2
+ sw t1, DDR_CTL_TEST_DATA2(t0)
+ li t1, BACKGND_DATA3
+ sw t1, DDR_CTL_TEST_DATA3(t0)
+ li t1, TEST_COUNT
+ li t2, VICT_COUNT
+ or t1, t2 # add victim count value
+ sw t1, DDR_CTL_TEST_COUNT(t0)
+ li t1, TEST_ADDR
+ sw t1, DDR_CTL_TEST_ADDR(t0)
+ li t1, TEST_ADDR_UPDT
+ sw t1, DDR_CTL_TEST_ADDR_UPDT(t0)
+ li t1, TEST_PATTERN
+ sw t1, DDR_CTL_TEST_PAT(t0)
+
+# Write a background pattern first
+ li t1, BACKGND_MODE_DATA
+ li t2, TEST_WRITE
+ or t1, t2
+ li t2, TEST_ENABLE
+ or t1, t2
+ sw t1, DDR_CTL_TEST_CFG1(t0)
+
+ li t2, 0x2
+ li t3, MISC_BASE
+
+ li t5, 0x10000
+2: li t1, 0x100
+1: addiu t1, -1
+ bnez t1, 1b
+ nop
+
+ lw t4, MISC_MEMC_CONTROL(t3)
+ and t4, 0x2
+ beq t4, t2, backgnd_write_done
+ nop
+ addiu t5, -1
+ bnez t5, 2b
+ nop
+
+# Background write operation is finished
+
+backgnd_write_done:
+ li t1, TEST_DATA0
+ sw t1, DDR_CTL_TEST_DATA0(t0)
+ li t1, TEST_DATA1
+ sw t1, DDR_CTL_TEST_DATA1(t0)
+ li t1, TEST_DATA2
+ sw t1, DDR_CTL_TEST_DATA2(t0)
+ li t1, TEST_DATA3
+ sw t1, DDR_CTL_TEST_DATA3(t0)
+ li t1, TEST_COUNT
+ li t2, VICT_COUNT
+ or t1, t2 # add victim count value
+ sw t1, DDR_CTL_TEST_COUNT(t0)
+ li t1, TEST_ADDR
+ sw t1, DDR_CTL_TEST_ADDR(t0)
+ li t1, TEST_ADDR_UPDT
+ sw t1, DDR_CTL_TEST_ADDR_UPDT(t0)
+ li t1, TEST_PATTERN
+ sw t1, DDR_CTL_TEST_PAT(t0)
+
+# li t1, BACKGND_MODE_DATA
+# li t1, BACKGND_MODE_PAT
+# li t2, VICT_MODE_NOT_PAT
+ li t1, BACKGND_MODE_PRBS
+ li t2, VICT_MODE_NOT_PRBS
+
+ or t1, t2
+ li t2, VICT_ENABLE
+ or t1, t2
+ li t2, VICT_SWEEP_ENABLE
+ or t1, t2
+ li t2, PRBS_ORDER(0)
+ or t1, t2
+ li t2, TEST_WRITE
+ or t1, t2
+ li t2, TEST_ENABLE
+ or t1, t2
+ sw t1, DDR_CTL_TEST_CFG1(t0)
+
+ li t2, 0x2
+ li t3, MISC_BASE
+
+ li t5, 0x10000
+2: li t1, 0x100
+1: addiu t1, -1
+ bnez t1, 1b
+ nop
+
+ lw t4, MISC_MEMC_CONTROL(t3)
+ and t4, 0x2
+ beq t4, t2, test_write_done
+ nop
+ addiu t5, -1
+ bnez t5, 2b
+ nop
+
+# Test write operation is finished
+
+test_write_done:
+ li t1, TEST_DATA0
+ sw t1, DDR_CTL_TEST_DATA0(t0)
+ li t1, TEST_DATA1
+ sw t1, DDR_CTL_TEST_DATA1(t0)
+ li t1, TEST_DATA2
+ sw t1, DDR_CTL_TEST_DATA2(t0)
+ li t1, TEST_DATA3
+ sw t1, DDR_CTL_TEST_DATA3(t0)
+ li t1, TEST_COUNT
+ li t2, VICT_COUNT
+ or t1, t2 # add victim count value
+ sw t1, DDR_CTL_TEST_COUNT(t0)
+ li t1, TEST_ADDR
+ sw t1, DDR_CTL_TEST_ADDR(t0)
+ li t1, TEST_ADDR_UPDT
+ sw t1, DDR_CTL_TEST_ADDR_UPDT(t0)
+ li t1, TEST_PATTERN
+ sw t1, DDR_CTL_TEST_PAT(t0)
+
+# li t1, BACKGND_MODE_DATA
+# li t1, BACKGND_MODE_PAT
+# li t2, VICT_MODE_NOT_PAT
+ li t1, BACKGND_MODE_PRBS
+ li t2, VICT_MODE_NOT_PRBS
+
+ or t1, t2
+ li t2, VICT_ENABLE
+ or t1, t2
+ li t2, VICT_SWEEP_ENABLE
+ or t1, t2
+ li t2, PRBS_ORDER(0)
+ or t1, t2
+ li t2, TEST_READ
+ or t1, t2
+ li t2, TEST_ENABLE
+ or t1, t2
+ sw t1, DDR_CTL_TEST_CFG1(t0)
+
+ li t3, MISC_BASE
+ li t2, 0x2
+
+ li t5, 0x10000
+2: li t1, 0x100
+1: addiu t1, -1
+ bnez t1, 1b
+ nop
+
+ lw t4, MISC_MEMC_CONTROL(t3)
+ and t4, 0x2
+ beq t4, t2, test_read_done
+ nop
+ addiu t5, -1
+ bnez t5, 2b
+ nop
+
+# Test read operation is finished
+
+test_read_done:
+ lw t1, DDR_CTL_TEST_CFG1(t0)
+ srl t1, 2
+ and t1, 1
+ beq t1, zero, test_passed
+ nop
+
+test_failed:
+ SETLEDS1('F','A','I','L')
+ b 1f
+ nop
+test_passed:
+ SETLEDS1('P','A','S','S')
+1:
+ SETLEDS1('-','-','-', '-')
+#endif
+
+ move ra,s0
+ j ra
+ nop
+
+ .set reorder
+
+END(board_draminit)
+
+/* *********************************************************************
+ * BOARD_SETLEDS(x)
+ *
+ * Set LEDs for boot-time progress indication. Not used if
+ * the board does not have progress LEDs. This routine
+ * must not call any other routines, since it may be invoked
+ * either from KSEG0 or KSEG1 and it may be invoked
+ * whether or not the icache is operational.
+ *
+ * Input parameters:
+ * a0 - LED value (8 bits per character, 4 characters)
+ *
+ * Return value:
+ * nothing
+ *
+ * Registers used:
+ * t7,t8,t9
+ ********************************************************************* */
+LEAF(board_setleds)
+#if 1
+ li t7, UART_BASE
+ li t8, TXFIFOEMT
+
+1: lh t9, UART0INTSTAT(t7)
+ and t9, t8
+ bne t9, t8, 1b
+
+ srl t8, a0, 24
+ sb t8, UART0DATA(t7)
+ srl t8, a0, 16
+ sb t8, UART0DATA(t7)
+ srl t8, a0, 8
+ sb t8, UART0DATA(t7)
+ sb a0, UART0DATA(t7)
+ li a0, '\r'
+ sb a0, UART0DATA(t7)
+ li a0, '\n'
+ sb a0, UART0DATA(t7)
+#endif
+ j ra
+END(board_setleds)
+
+/* *********************************************************************
+ * BCMCORE_TP1_SWITCH()
+ *
+ * Check if the thread switch is required. If we are already
+ * running on thread 1 this function will do nothing and just return
+ * If we are running on thread 0 this function will take thread 1
+ * out of reset and put thread 0 to sleep waiting for singnal from
+ * thread 1.
+ *
+ * Input parameters:
+ * nothing
+ *
+ * Return value:
+ * nothing
+ ********************************************************************* */
+LEAF(bcmcore_tp1_switch)
+
+#if defined(_BCM96328_)
+ li t1, OTP_BASE
+ addi t1, OTP_USER_BITS
+ addi t1, 0xc - ((OTP_TP1_DISABLE_BIT / 8) & ~3)
+ lw t0, 0(t1)
+ andi t0, 1 << (OTP_TP1_DISABLE_BIT % 32)
+ beqz t0, 1f
+ j ra
+1:
+#endif
+ mfc0 t1, C0_BCM_CONFIG, 3
+ li t2, CP0_CMT_TPID
+ and t1, t2
+ bnez t1, tp1 # Already running on thread 1
+
+# Start TP1
+# Set boot address for TP1
+ li t1, MIPS_BASE
+ li t2, 0x98000000 | ENABLE_ALT_BV
+ sw t2, MIPS_TP1_ALT_BV(t1)
+
+# Set a flag so we can wait for TP1 to catch up
+ li t1, 0x0
+ mtc0 t1, $31 # CO_DESAVE
+
+# Take TP1 out of reset
+ mfc0 t1, C0_BCM_CONFIG, 2
+ or t1, CP0_CMT_RSTSE
+ mtc0 t1, C0_BCM_CONFIG, 2
+
+ /* wait until second thread catches up with the first */
+waittp1:
+ mfc0 t0, $31 # CO_DESAVE
+ beqz t0, waittp1
+
+ li t0, THREAD_NUM_ADDRESS
+ FIXUP(t0)
+ lw t0, 0(t0)
+ li t1, 1
+ bne t0, t1, return # Linux will run on TP0, continue running bootloader
+
+# Voice will run on TP0. Set it up and put it to sleep
+
+ # enable interrupts and enable SW IRQ 0
+ li t0, M_SR_IE | M_SR_IBIT1
+ mtc0 t0, C0_SR
+
+ # Set up to use alternate exception vector 0x80000200
+ li t0, M_CAUSE_IV
+ mtc0 t0, C0_CAUSE
+
+ mfc0 t1, C0_BCM_CONFIG, 1
+ # set all ints except IRQ1 to TP1 and cross over SW IRQ 0
+ or t1, (CP0_CMT_XIR_4 | CP0_CMT_XIR_3 | CP0_CMT_XIR_2 | CP0_CMT_XIR_0 | CP0_CMT_SIR_0 | CP0_CMT_NMIR_TP1)
+ mtc0 t1, C0_BCM_CONFIG, 1
+
+ mfc0 t1, C0_BCM_CONFIG, 2
+ # Set debug on TP1, give priority to TP0, and
+ # set TLB exception serialization to ignore SCNT value in CP0 reg22 sel 4
+ and t1, ~CP0_CMT_TPS_MASK;
+ or t1, (CP0_CMT_DSU_TP1 | CP0_CMT_PRIO_TP0 | (1 << CP0_CMT_TPS_SHFT))
+ mtc0 t1, C0_BCM_CONFIG, 2
+
+ # Enable Data RAC on TP0
+ li t1, MIPS_BASE
+ lw t2, MIPS_RAC_CR0(t1)
+ or t2, (RAC_D | RAC_PF_D)
+ sw t2, MIPS_RAC_CR0(t1)
+
+2:
+ b wait_for_wake
+
+tp1:
+# Running on TP1....
+# First signal to TP0 that TP1 is up
+ li t1, 0x1
+ mtc0 t1, $31 # CO_DESAVE
+
+ li t0, THREAD_NUM_ADDRESS
+ FIXUP(t0)
+ lw t0, 0(t0)
+ li t1, 1
+ beq t0, t1, return # Linux will run on TP1, continue running bootloader
+
+# Voice will run on TP1. Set it up and put it to sleep
+
+ # enable interrupts and enable SW IRQ 0
+ li t0, M_SR_IE | M_SR_IBIT1
+ mtc0 t0, C0_SR
+
+ # Set up to use alternate exception vector 0x80000200
+ li t0, M_CAUSE_IV
+ mtc0 t0, C0_CAUSE
+
+ mfc0 t1, C0_BCM_CONFIG, 1
+ # set IRQ1 to TP1 and cross over SW IRQ 0
+ or t1, (CP0_CMT_XIR_1 | CP0_CMT_SIR_0 | CP0_CMT_NMIR_TP0)
+ mtc0 t1, C0_BCM_CONFIG, 1
+
+ mfc0 t1, C0_BCM_CONFIG, 2
+ # Set debug on TP0, give priority to TP1, and
+ # set TLB exception serialization to ignore SCNT value in CP0 reg22 sel 4
+ and t1, ~CP0_CMT_TPS_MASK;
+ or t1, (CP0_CMT_PRIO_TP1 | (1 << CP0_CMT_TPS_SHFT))
+ mtc0 t1, C0_BCM_CONFIG, 2
+
+ # Enable Data RAC on TP1
+ li t1, MIPS_BASE
+ lw t2, MIPS_RAC_CR1(t1)
+ or t2, (RAC_D | RAC_PF_D)
+ sw t2, MIPS_RAC_CR1(t1)
+ b 2b
+
+return:
+ j ra
+
+END(bcmcore_tp1_switch)
+
+# align this code to cache line. NAND flash is not memory mapped after system boots
+# so when we are signaling to the second TP to wake we need
+# jal instruction to be in cache
+ .align 4
+LEAF(wait_for_wake)
+ sync
+ wait # wait for interrupt
+ jal t8 # jump to entry point
+END(wait_for_wake)