diff options
Diffstat (limited to 'cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S')
-rwxr-xr-x | cfe/cfe/arch/mips/board/bcm63xx_rom/src/bcm63xx_impl1_rom_boot.S | 1818 |
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) |