diff options
Diffstat (limited to 'board/aspeed/ast2400/platform.S')
-rw-r--r-- | board/aspeed/ast2400/platform.S | 3089 |
1 files changed, 3089 insertions, 0 deletions
diff --git a/board/aspeed/ast2400/platform.S b/board/aspeed/ast2400/platform.S new file mode 100644 index 0000000000..27e8f26311 --- /dev/null +++ b/board/aspeed/ast2400/platform.S @@ -0,0 +1,3089 @@ +/* + * 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 + */ +/* + * Board specific setup info + * + ****************************************************************************** + * ASPEED Technology Inc. + * AST2300/AST2400 DDR2/DDR3 SDRAM controller initialization and calibration sequence + * + * Gary Hsu, <gary_hsu@aspeedtech.com> + * + * Release date: 2014.12.29 formal release for SDK0.60 + * + * Modified list from v0.23 + * EC1. Modify DQIDLY and DQSI-MCLK2X calibration algorithm + * EC2. Remove pass 2 DQIDLY finetune process + * EC3. Modify ECC code + * EC4. Add AST2400 supporting + * EC5. Add SPI timing calibration for AST2400 + * EC6. Remove AST2300-A0 PCI-e workaround + * EC7. Add CK duty calibration for AST2400 + * EC8. Remove #define CONFIG_DRAM_UART_OUT, default has message output to UART5 + * EC9. Add DRAM size auto-detection + * EC10. Add GPIO register clear when watchdog reboot (only for AST2400) + * EC11. Move the "Solve ASPM" code position of AST2300 to avoid watchdog reset + * + * Modified list from v0.53 + * EC1. Add solution of LPC lock issue due to watchdog reset. (AP note A2300-11) + * + * Modified list from v0.56 + * EC1. Fix read DQS input mask window too late issue if DRAM's t_DQSCK is earlier too much + * (ex. Nanya NT5CB64M16FP) + * 1. Change init value of MCR18[4] from '1' to '0' + * 2. Add CBR4 code to finetune MCR18[4] + * + * Modified list from v0.59 + * EC1. Add DQS input gating window delay tuning (1/2 T) when CBR retry + * EC2. Modify DLL1 MAdj = 0x4C + * + * Optional define variable + * 1. DRAM Speed // + * CONFIG_DRAM_336 // 336MHz (DDR-667) + * CONFIG_DRAM_408 // 408MHz (DDR-800) (default) + * 2. ECC Function enable + * CONFIG_DRAM_ECC // define to enable ECC function + * // when enabled, must define the ECC protected memory size at 0x1e6e0054 + * 3. UART5 message output // + * CONFIG_DRAM_UART_38400 // set the UART baud rate to 38400, default is 115200 + ****************************************************************************** + */ + +#include <config.h> +#include <version.h> +/****************************************************************************** + Calibration Macro Start + Usable registers: + r0, r1, r2, r3, r5, r6, r7, r8, r9, r10, r11 + ******************************************************************************/ +/* PATTERN_TABLE, + init_delay_timer, + check_delay_timer, + clear_delay_timer, + record_dll2_pass_range, + record_dll2_pass_range_h, + are for DRAM calibration */ + +PATTERN_TABLE: + .word 0xff00ff00 + .word 0xcc33cc33 + .word 0xaa55aa55 + .word 0x88778877 + .word 0x92cc4d6e @ 5 + .word 0x543d3cde + .word 0xf1e843c7 + .word 0x7c61d253 + .word 0x00000000 @ 8 + + .macro init_delay_timer + ldr r0, =0x1e782024 @ Set Timer3 Reload + str r2, [r0] + + ldr r0, =0x1e6c0038 @ Clear Timer3 ISR + ldr r1, =0x00040000 + str r1, [r0] + + ldr r0, =0x1e782030 @ Enable Timer3 + ldr r1, [r0] + mov r2, #7 + orr r1, r1, r2, lsl #8 + str r1, [r0] + + ldr r0, =0x1e6c0090 @ Check ISR for Timer3 timeout + .endm + + .macro check_delay_timer + ldr r1, [r0] + bic r1, r1, #0xFFFBFFFF + mov r2, r1, lsr #18 + cmp r2, #0x01 + .endm + + .macro clear_delay_timer + ldr r0, =0x1e782030 @ Disable Timer3 + ldr r1, [r0] + bic r1, r1, #0x00000F00 + str r1, [r0] + + ldr r0, =0x1e6c0038 @ Clear Timer3 ISR + ldr r1, =0x00040000 + str r1, [r0] + .endm + + .macro record_dll2_pass_range + ldr r1, [r0] + bic r2, r1, #0xFFFFFF00 + cmp r2, r3 @ record min + bicgt r1, r1, #0x000000FF + orrgt r1, r1, r3 + bic r2, r1, #0xFFFF00FF + cmp r3, r2, lsr #8 @ record max + bicgt r1, r1, #0x0000FF00 + orrgt r1, r1, r3, lsl #8 + str r1, [r0] + .endm + + .macro record_dll2_pass_range_h + ldr r1, [r0] + bic r2, r1, #0xFF00FFFF + mov r2, r2, lsr #16 + cmp r2, r3 @ record min + bicgt r1, r1, #0x00FF0000 + orrgt r1, r1, r3, lsl #16 + bic r2, r1, #0x00FFFFFF + cmp r3, r2, lsr #24 @ record max + bicgt r1, r1, #0xFF000000 + orrgt r1, r1, r3, lsl #24 + str r1, [r0] + .endm + + .macro init_spi_checksum + ldr r0, =0x1e620084 + ldr r1, =0x20010000 + str r1, [r0] + ldr r0, =0x1e62008C + ldr r1, =0x20000200 + str r1, [r0] + ldr r0, =0x1e620080 + ldr r1, =0x0000000D + orr r2, r2, r7 + orr r1, r1, r2, lsl #8 + and r2, r6, #0xF + orr r1, r1, r2, lsl #4 + str r1, [r0] + ldr r0, =0x1e620008 + ldr r2, =0x00000800 + .endm + +/****************************************************************************** + Calibration Macro End + ******************************************************************************/ +LPC_Patch: @ load to SRAM base 0x1e720400 + str r1, [r0] + str r3, [r2] + bic r1, r1, #0xFF +LPC_Patch_S1: + subs r5, r5, #0x01 + moveq pc, r8 + ldr r3, [r2] + tst r3, #0x01 + movne pc, r8 + mov pc, r7 +LPC_Patch_S2: @ load to SRAM base 0x1e720480 + str r1, [r0] + mov pc, r9 +LPC_Patch_E: + +.globl lowlevel_init +lowlevel_init: + +init_dram: + /* save lr */ + mov r4, lr +/* Test - DRAM initial time */ + ldr r0, =0x1e782044 + ldr r1, =0xFFFFFFFF + str r1, [r0] + + ldr r0, =0x1e782030 + ldr r1, [r0] + bic r1, r1, #0x0000F000 + str r1, [r0] + mov r2, #3 + orr r1, r1, r2, lsl #12 + str r1, [r0] +/* Test - DRAM initial time */ + + /*Set Scratch register Bit 7 before initialize*/ + ldr r0, =0x1e6e2000 + ldr r1, =0x1688a8a8 + str r1, [r0] + + ldr r0, =0x1e6e2040 + ldr r1, [r0] + orr r1, r1, #0x80 + str r1, [r0] + + /* Fix LPC lock issue for AST2300 */ + ldr r0, =0x1e6e207c @ Check AST2300 + ldr r1, [r0] + mov r1, r1, lsr #24 + cmp r1, #0x01 + bne lpc_recover_end @ not match AST2300 + + mov r3, #0x0 +lpc_recover_check: + ldr r0, =0x1e78900c @ check HICR3[4]=0x1 + ldr r1, [r0] + tst r1, #0x10 + beq lpc_recover_end + ldr r0, =0x1e789004 @ check HICR1[7]=0x1 + ldr r1, [r0] + tst r1, #0x80 + beq lpc_recover_end + ldr r0, =0x1e7890a0 @ check LHCR0[27:24]=0x6 + ldr r1, [r0] + mov r1, r1, lsr #24 + and r1, r1, #0xF + cmp r1, #0x06 + bne lpc_recover_end + add r3, r3, #0x01 + cmp r3, #0x5 @ repeat 5 times + ble lpc_recover_check + + mov r3, #0x0 +lpc_recover_init: + ldr r0, =0x1e7890a4 @ set LHCR1[1:0]=0x0 + ldr r1, =0x00000000 + str r1, [r0] + add r3, r3, #0x01 + cmp r3, #0x20 + bge lpc_recover_end + ldr r1, [r0] + tst r1, #0x01 + bne lpc_recover_init + + ldr r0, =0x1e7890b0 @ set LHCR4[7:0]=0xFF + ldr r1, =0x000000FF + str r1, [r0] + ldr r0, =0x1e7890b4 @ set LHCR5[31:0]=0xFFFFFFFF + ldr r1, =0xFFFFFFFF + str r1, [r0] + ldr r0, =0x1e7890b8 @ set LHCR6[31:0]=0xFFFFFFFF + str r1, [r0] + + adr r6, LPC_Patch + adr r7, LPC_Patch_S2 + ldr r0, =0x1e720400 +copy_lpc_patch_1: + ldr r1, [r6] + str r1, [r0] + add r6, r6, #0x4 + add r0, r0, #0x4 + cmp r6, r7 + bne copy_lpc_patch_1 + + adr r6, LPC_Patch_S2 + adr r7, LPC_Patch_E + ldr r0, =0x1e720480 +copy_lpc_patch_2: + ldr r1, [r6] + str r1, [r0] + add r6, r6, #0x4 + add r0, r0, #0x4 + cmp r6, r7 + bne copy_lpc_patch_2 + + ldr r0, =0x1e7890a0 @ set LHCR0[31:0]=0xFFFFFF01 + ldr r1, =0xFFFFFF01 + add r2, r0, #0x4 + mov r3, #0x01 + mov r5, #0x10 + adr r9, lpc_recover_end + adr r6, LPC_Patch + adr r7, LPC_Patch_S1 + sub r6, r7, r6 + ldr r7, =0x1e720400 + add r7, r7, r6 + ldr r8, =0x1e720480 + ldr pc, =0x1e720400 + +lpc_recover_end: + ldr r0, =0x1e7890a0 @ set LHCR0[31:0]=0xFFFFFF00 + ldr r1, =0xFFFFFF00 + str r1, [r0] + /* <END> Fix LPC lock issue for AST2300 */ + + /* Check Scratch Register Bit 6 */ + ldr r0, =0x1e6e2040 + ldr r1, [r0] + bic r1, r1, #0xFFFFFFBF + mov r2, r1, lsr #6 + cmp r2, #0x01 + beq platform_exit + + ldr r2, =0x033103F1 @ load PLL parameter for 24Mhz CLKIN (396:324) +/* ldr r2, =0x019001F0 @ load PLL parameter for 24Mhz CLKIN (408:336) */ + ldr r0, =0x1e6e207c @ Check Revision ID + ldr r1, [r0] + mov r1, r1, lsr #24 + cmp r1, #0x02 + bne set_MPLL @ not match AST2400 + + ldr r0, =0x1e6e2070 @ Check CLKIN freq + ldr r1, [r0] + mov r1, r1, lsr #23 + tst r1, #0x01 + ldrne r2, =0x017001D0 @ load PLL parameter for 25Mhz CLKIN (400:325) + +set_MPLL: + ldr r0, =0x1e6e2020 @ M-PLL (DDR SDRAM) Frequency + ldr r1, =0xFFFF +#if defined(CONFIG_DRAM_336) + mov r2, r2, lsr #16 +#endif + and r1, r2, r1 + str r1, [r0] + +/* Debug - UART console message */ + ldr r0, =0x1e78400c + mov r1, #0x83 + str r1, [r0] + + ldr r0, =0x1e6e202c + ldr r2, [r0] + mov r2, r2, lsr #12 + tst r2, #0x01 + ldr r0, =0x1e784000 + moveq r1, #0x0D @ Baudrate 115200 + movne r1, #0x01 @ Baudrate 115200, div13 +#if defined(CONFIG_DRAM_UART_38400) + moveq r1, #0x27 @ Baudrate 38400 + movne r1, #0x03 @ Baudrate 38400 , div13 +#endif + str r1, [r0] + + ldr r0, =0x1e784004 + mov r1, #0x00 + str r1, [r0] + + ldr r0, =0x1e78400c + mov r1, #0x03 + str r1, [r0] + + ldr r0, =0x1e784008 + mov r1, #0x07 + str r1, [r0] + + ldr r0, =0x1e784000 + mov r1, #0x0D @ '\r' + str r1, [r0] + mov r1, #0x0A @ '\n' + str r1, [r0] + mov r1, #0x44 @ 'D' + str r1, [r0] + mov r1, #0x52 @ 'R' + str r1, [r0] + mov r1, #0x41 @ 'A' + str r1, [r0] + mov r1, #0x4D @ 'M' + str r1, [r0] + mov r1, #0x20 @ ' ' + str r1, [r0] + mov r1, #0x49 @ 'I' + str r1, [r0] + mov r1, #0x6E @ 'n' + str r1, [r0] + mov r1, #0x69 @ 'i' + str r1, [r0] + mov r1, #0x74 @ 't' + str r1, [r0] + mov r1, #0x2D @ '-' + str r1, [r0] + mov r1, #0x44 @ 'D' + str r1, [r0] + mov r1, #0x44 @ 'D' + str r1, [r0] + mov r1, #0x52 @ 'R' + str r1, [r0] +/* Debug - UART console message */ + + /* Delay about 100us */ + ldr r0, =0x1e782030 @ Init Timer3 Control + ldr r1, [r0] + bic r1, r1, #0x00000F00 + str r1, [r0] + + ldr r2, =0x00000064 @ Set Timer3 Reload = 100 us + init_delay_timer +delay_0: + check_delay_timer + bne delay_0 + clear_delay_timer + /* end delay 100us */ + +/****************************************************************************** + Init DRAM common registers + ******************************************************************************/ + ldr r0, =0x1e6e0000 + ldr r1, =0xfc600309 + str r1, [r0] + + /* Reset MMC */ + ldr r1, =0x00000000 + ldr r0, =0x1e6e0034 + str r1, [r0] + ldr r0, =0x1e6e0018 + str r1, [r0] + ldr r0, =0x1e6e0024 + str r1, [r0] + ldr r0, =0x1e6e0064 @ REG_MADJ, power down DLL + str r1, [r0] + + ldr r1, =0x00034C4C @ REG_MADJ, reset DLL + str r1, [r0] + + ldr r0, =0x1e6e0068 @ REG_SADJ + ldr r1, =0x00001800 + str r1, [r0] + + /* Delay about 10us */ + ldr r2, =0x0000000B @ Set Timer3 Reload = 10 us + init_delay_timer +delay_1: + check_delay_timer + bne delay_1 + clear_delay_timer + /* end delay 10us */ + + ldr r0, =0x1e6e0064 @ REG_MADJ | 0xC0000, enable DLL + ldr r1, [r0] + ldr r2, =0xC0000 + orr r1, r1, r2 + str r1, [r0] + + ldr r0, =0x1e6e0008 + ldr r1, =0x0090040f /* VGA */ + str r1, [r0] + + ldr r0, =0x1e6e0018 + ldr r1, =0x4000A120 + str r1, [r0] + + ldr r0, =0x1e6e0018 + ldr r1, =0x00000120 + str r1, [r0] + + ldr r0, =0x1e6e0038 + ldr r1, =0x00000000 + str r1, [r0] + + ldr r0, =0x1e6e0040 + ldr r1, =0xFF444444 + str r1, [r0] + + ldr r0, =0x1e6e0044 + ldr r1, =0x22222222 + str r1, [r0] + + ldr r0, =0x1e6e0048 + ldr r1, =0x22222222 + str r1, [r0] + + ldr r0, =0x1e6e004c + ldr r1, =0x22222222 + str r1, [r0] + + ldr r0, =0x1e6e0050 + ldr r1, =0x80000000 + str r1, [r0] + + ldr r0, =0x1e6e0050 + ldr r1, =0x00000000 + str r1, [r0] + + ldr r0, =0x1e6e0054 + ldr r1, =0x00000000 + str r1, [r0] + + ldr r0, =0x1e6e0060 @ REG_DRV + ldr r1, =0x000000FA @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x000000FA +#endif + str r1, [r0] + + ldr r0, =0x1e6e0070 + ldr r1, =0x00000000 + str r1, [r0] + + ldr r0, =0x1e6e0074 + ldr r1, =0x00000000 + str r1, [r0] + + ldr r0, =0x1e6e0078 + ldr r1, =0x00000000 + str r1, [r0] + + ldr r0, =0x1e6e007c + ldr r1, =0x00000000 + str r1, [r0] + + ldr r0, =0x1e6e0080 + ldr r1, =0x00000000 + str r1, [r0] + + ldr r0, =0x1e6e0084 + ldr r1, =0x00FFFFFF + str r1, [r0] + + ldr r0, =0x1e6e0088 @ REG_DQIDLY + ldr r1, =0x00000089 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x00000074 +#endif + str r1, [r0] + + ldr r0, =0x1e6e0020 @ REG_DQSIC + ldr r1, =0x000000E2 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x000000BA +#endif + str r1, [r0] + + /* Delay about 10us */ + ldr r2, =0x0000000B @ Set Timer3 Reload = 10 us + init_delay_timer +delay_2: + check_delay_timer + bne delay_2 + clear_delay_timer + /* end delay 10us */ + + /* Check DRAM Type by H/W Trapping */ + ldr r0, =0x1e6e2070 + ldr r1, [r0] + bic r1, r1, #0xFEFFFFFF @ bit[24]=1 => DDR2 + mov r2, r1, lsr #24 + cmp r2, #0x01 + beq ddr2_init + b ddr3_init +.LTORG + +/****************************************************************************** + DDR3 Init + + tRCD = 15 ns + tRAS = 37.5 ns + tRRD = max(4 CK,10 ns) + tRP = 15 ns + tRFC = 110ns/1Gbit, 160ns/2Gbit, 300ns/4Gbit + tRTP = max(4 CK,7.5 ns) + tWR = 15 ns + tXSNR = max(10 CK,200 ns) + tWTR = max(4 CK,7.5 ns) + tFAW = 50 ns + tMRD = max(15 CK,20 ns) + ******************************************************************************/ +ddr3_init: +/* Debug - UART console message */ + ldr r0, =0x1e784000 + mov r1, #0x33 @ '3' + str r1, [r0] + mov r1, #0x0D @ '\r' + str r1, [r0] + mov r1, #0x0A @ '\n' + str r1, [r0] +/* Debug - UART console message */ + + ldr r0, =0x1e6e0004 + ldr r1, =0x00000531 @ Default set to 1Gbit + str r1, [r0] + + ldr r0, =0x1e6e0010 @ REG_AC1 + ldr r1, =0x33302825 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x22202725 +#endif + str r1, [r0] + + /* Check DRAM CL Timing by H/W Trapping */ + ldr r0, =0x1e6e2070 + ldr r1, [r0] + bic r1, r1, #0xF9FFFFFF + mov r2, r1, lsr #9 @ Set CL + ldr r1, =0x00020000 + add r2, r2, r1 + ldr r1, [r0] + bic r1, r1, #0xFBFFFFFF + mov r1, r1, lsr #6 @ Set CWL + orr r2, r2, r1 + ldr r1, =0x00300000 + add r2, r2, r1 + + ldr r0, =0x1e6e0014 @ REG_AC2 + ldr r1, =0xCC00963F @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0xAA007636 +#endif + orr r1, r1, r2 + str r1, [r0] + + ldr r0, =0x1e6e0004 @ check 2400 mode + ldr r2, [r0] + mov r2, r2, lsr #10 + + ldr r0, =0x1e6e006c @ REG_IOZ + ldr r1, =0x00002312 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x00002312 +#endif + tst r2, #0x01 + moveq r1, r1, lsr #8 + str r1, [r0] + + ldr r0, =0x1e6e0120 + mov r1, #0 + str r1, [r0] + tst r2, #0x01 @ check AST2300 + beq CBRDLL1_2300_Start + ldr r0, =0x1e6e207c @ check AST2400 revision A0 + ldr r1, [r0] + mov r1, r1, lsr #16 + and r1, r1, #0xFF + cmp r1, #0x0 + beq CBRDLL1_2300_Start + b CBRDLL1_2400_Start +MCLK2X_Phase_CBR_Done_DDR3: + ldr r0, =0x1e6e0018 + ldr r1, [r0] + orr r1, r1, #0x40 + str r1, [r0] + + ldr r0, =0x1e6e0034 + ldr r1, =0x00000001 + str r1, [r0] + + ldr r0, =0x1e6e000c + ldr r1, =0x00000040 + str r1, [r0] + + /* Delay about 400us */ + ldr r2, =0x00000190 @ Set Timer3 Reload = 400 us + init_delay_timer +delay3_4: + check_delay_timer + bne delay3_4 + clear_delay_timer + /* end delay 400us */ + + /* Check DRAM CL Timing by H/W Trapping */ + ldr r0, =0x1e6e2070 + ldr r1, [r0] + bic r1, r1, #0xF9FFFFFF + mov r2, r1, lsr #21 @ Set CL + ldr r1, =0x00000010 + add r2, r2, r1 + ldr r1, [r0] + bic r1, r1, #0xFBFFFFFF + mov r1, r1, lsr #7 @ Set CWL + orr r2, r2, r1 + + ldr r0, =0x1e6e002c @ REG_MRS + ldr r1, =0x04001700 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x04001500 +#endif + orr r1, r1, r2 + str r1, [r0] + + ldr r0, =0x1e6e0030 @ REG_EMRS + ldr r1, =0x00000000 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x00000000 +#endif + str r1, [r0] + + ldr r0, =0x1e6e0028 @ Set EMRS2 + ldr r1, =0x00000005 + str r1, [r0] + + ldr r0, =0x1e6e0028 @ Set EMRS3 + ldr r1, =0x00000007 + str r1, [r0] + + ldr r0, =0x1e6e0028 @ Set EMRS + ldr r1, =0x00000003 + str r1, [r0] + + ldr r0, =0x1e6e0028 @ Set MRS + ldr r1, =0x00000001 + str r1, [r0] + + ldr r0, =0x1e6e002c @ REG_MRS + ldr r1, =0x04001600 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x04001400 +#endif + orr r1, r1, r2 + str r1, [r0] + + ldr r0, =0x1e6e000c @ Refresh 8 times + ldr r1, =0x00005C48 + str r1, [r0] + + ldr r0, =0x1e6e0028 @ Set MRS + ldr r1, =0x00000001 + str r1, [r0] + + ldr r0, =0x1e6e000c @ Set refresh cycle + ldr r1, =0x00002001 + str r1, [r0] + + ldr r0, =0x1e6e0014 + ldr r1, [r0] + bic r1, r1, #0xFFF9FFFF + mov r2, r1, lsr #3 @ get CL + + ldr r0, =0x1e6e0034 @ REG_PWC + ldr r1, =0x00000303 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x00000303 +#endif + orr r1, r1, r2 + str r1, [r0] + + b Calibration_Start +.LTORG +/****************************************************************************** + End DDR3 Init + ******************************************************************************/ + +/****************************************************************************** + DDR2 Init + + tRCD = 15 ns + tRAS = 45 ns + tRRD = 10 ns + tRP = 15 ns + tRFC = 105ns/512Mbit, 127.5ns/1Gbit, 197.5ns/2Gbit, 327.5ns/4Gbit + tRTP = 7.5 ns + tWR = 15 ns + tXSNR = 200 ns + tWTR = 7.5 ns + tFAW = 50 ns + tMRD = 4 CK + ******************************************************************************/ +ddr2_init: +/* Debug - UART console message */ + ldr r0, =0x1e784000 + mov r1, #0x32 @ '2' + str r1, [r0] + mov r1, #0x0D @ '\r' + str r1, [r0] + mov r1, #0x0A @ '\n' + str r1, [r0] +/* Debug - UART console message */ + + ldr r0, =0x1e6e0004 + ldr r1, =0x00000510 @ Default set to 512Mbit + str r1, [r0] + + ldr r0, =0x1e6e0010 @ REG_AC1 + ldr r1, =0x33302714 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x22201613 +#endif + str r1, [r0] + + /* Check DRAM CL Timing by H/W Trapping */ + ldr r0, =0x1e6e2070 + ldr r1, [r0] + bic r1, r1, #0xF9FFFFFF + mov r2, r1, lsr #5 @ Set CL + mov r1, r2, lsr #4 @ Set CWL + orr r2, r2, r1 + ldr r1, =0x00110000 + add r2, r2, r1 + + ldr r0, =0x1e6e0014 @ REG_AC2 + ldr r1, =0xCC00B03F @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0xAA00903B +#endif + orr r1, r1, r2 + str r1, [r0] + + ldr r0, =0x1e6e0004 @ check 2400 mode + ldr r2, [r0] + mov r2, r2, lsr #10 + + ldr r0, =0x1e6e006c @ REG_IOZ + ldr r1, =0x00002312 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x00002312 +#endif + tst r2, #0x01 + moveq r1, r1, lsr #8 + str r1, [r0] + + ldr r0, =0x1e6e0120 + mov r1, #1 + str r1, [r0] + tst r2, #0x01 @ check AST2300 + beq CBRDLL1_2300_Start + ldr r0, =0x1e6e207c @ check AST2400 revision A0 + ldr r1, [r0] + mov r1, r1, lsr #16 + and r1, r1, #0xFF + cmp r1, #0x0 + beq CBRDLL1_2300_Start + b CBRDLL1_2400_Start +MCLK2X_Phase_CBR_Done_DDR2: + + ldr r0, =0x1e6e0034 + ldr r1, =0x00000001 + str r1, [r0] + + ldr r0, =0x1e6e000c + ldr r1, =0x00000000 + str r1, [r0] + + /* Delay about 400us */ + ldr r2, =0x00000190 @ Set Timer3 Reload = 400 us + init_delay_timer +delay2_4: + check_delay_timer + bne delay2_4 + clear_delay_timer + /* end delay 400us */ + + /* Check DRAM CL Timing by H/W Trapping */ + ldr r0, =0x1e6e2070 + ldr r1, [r0] + bic r1, r1, #0xF9FFFFFF + mov r2, r1, lsr #21 @ Set CL + ldr r1, =0x00000040 + orr r2, r2, r1 + + ldr r0, =0x1e6e002c @ REG_MRS + ldr r1, =0x00000D03 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x00000B03 +#endif + orr r1, r1, r2 + str r1, [r0] + + ldr r0, =0x1e6e0030 @ REG_EMRS + ldr r1, =0x00000040 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x00000040 +#endif + str r1, [r0] + + ldr r0, =0x1e6e0028 @ Set EMRS2 + ldr r1, =0x00000005 + str r1, [r0] + + ldr r0, =0x1e6e0028 @ Set EMRS3 + ldr r1, =0x00000007 + str r1, [r0] + + ldr r0, =0x1e6e0028 @ Set EMRS + ldr r1, =0x00000003 + str r1, [r0] + + ldr r0, =0x1e6e0028 @ Set MRS + ldr r1, =0x00000001 + str r1, [r0] + + ldr r0, =0x1e6e000c @ Refresh 8 times + ldr r1, =0x00005C08 + str r1, [r0] + + ldr r0, =0x1e6e002c @ REG_MRS + ldr r1, =0x00000C03 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x00000A03 +#endif + orr r1, r1, r2 + str r1, [r0] + + ldr r0, =0x1e6e0028 @ Set MRS + ldr r1, =0x00000001 + str r1, [r0] + + ldr r0, =0x1e6e0030 @ REG_EMRS + ldr r1, =0x000003C0 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x000003C0 +#endif + str r1, [r0] + + ldr r0, =0x1e6e0028 @ Set EMRS + ldr r1, =0x00000003 + str r1, [r0] + + ldr r0, =0x1e6e0030 @ REG_EMRS + ldr r1, =0x00000040 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x00000040 +#endif + str r1, [r0] + + ldr r0, =0x1e6e0028 @ Set EMRS + ldr r1, =0x00000003 + str r1, [r0] + + ldr r0, =0x1e6e000c @ Set refresh cycle + ldr r1, =0x00002001 + str r1, [r0] + + ldr r0, =0x1e6e0014 + ldr r1, [r0] + bic r1, r1, #0xFFF9FFFF + mov r2, r1, lsr #3 @ get CL + + ldr r0, =0x1e6e0034 @ REG_PWC + ldr r1, =0x00000503 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x00000503 +#endif + orr r1, r1, r2 + str r1, [r0] + + b Calibration_Start +.LTORG +/****************************************************************************** + End DDR2 Init + ******************************************************************************/ +/****************************************************************************** + DDR CK duty finetune program + SRAM buffer definition + 0x1E720204 : gdll golden DLL1 record + 0x1E720208 : gduty golden duty setting record + 0x1E72020C : gdutysum golden duty data record + 0x1E720210 : duty record of delay 0 invert + 0x1E720214 : duty record of delay 1 invert + .... + 0x1E72024C : duty record of delay 15 invert + 0x1E720250 : duty record of delay 0 + 0x1E720254 : duty record of delay 1 + .... + 0x1E72028C : duty record of delay 15 + + Register usage + r0 - r3 = free + r4 = record the return pc value, do not use + r5 = free + r6 = free + r7 = duty count + r8 = gdll + r9 = gduty + r10 = gdutysum + ******************************************************************************/ +CBRDLL1_2400_Start: + ldr r0, =0x1e6e0120 + ldr r1, [r0] + orr r1, r1, #0x02 + str r1, [r0] + + ldr r1, =0x00000000 + ldr r0, =0x1e720204 + ldr r2, =0x1e7202a0 +init_sram_start0: + str r1, [r0] + add r0, r0, #4 + cmp r0, r2 + blt init_sram_start0 + + ldr r0, =0x1e6e0034 + mov r1, #0x20 + str r1, [r0] + + ldr r0, =0x1e6e0060 + ldr r1, [r0] + mov r2, #0x01 + orr r1, r1, r2, lsl #13 + str r1, [r0] + + mov r7, #0x0 @ init duty count + mov r8, #0x0 @ init gdll + mov r9, #0x0 @ init gduty + mov r10, #0x0 @ init gdutysum +cbrdll1_duty_start: + cmp r7, #32 + bge cbrdll1_duty_end + + ldr r0, =0x1e6e0018 + ldr r1, =0x00008120 + str r1, [r0] + + ldr r0, =0x1e6e0060 + ldr r1, [r0] + bic r1, r1, #0x00001F00 + orr r1, r1, r7, lsl #8 + mov r2, #0x10 + eor r1, r1, r2, lsl #8 + str r1, [r0] + + ldr r0, =0x1e6e0000 @ dummy read + ldr r1, [r0] + + b CBRDLL1_2300_Start +CBRDLL1_2400_Call: + + mov r5, #0x01 @ init dqidly count + mov r6, #0x00 @ init duty sum +cbrdll1_duty_cal_start: + cmp r5, #0x05 + bge cbrdll1_duty_cal_end + + ldr r0, =0x1e6e0018 + ldr r1, =0x00200120 + orr r1, r1, r5, lsl #16 + str r1, [r0] + + ldr r0, =0x1e6e0000 + ldr r1, [r0] + + ldr r0, =0x1e6e0018 + ldr r1, [r0] + mov r2, #0x10 + orr r1, r1, r2, lsl #24 + str r1, [r0] + + ldr r0, =0x1e6e0080 + ldr r1, =0x80000000 @ init duty cal waiting +cbrdll1_duty_cal_wait: + ldr r2, [r0] + tst r2, r1 + beq cbrdll1_duty_cal_wait + + ldr r0, =0x1e6e008c + ldr r2, [r0] + + ldr r0, =0x1e720210 + add r0, r0, r7, lsl #2 + str r2, [r0] + + ldr r1, =0xFFFF + and r3, r1, r2 + cmp r3, r1 + moveq r2, r2, lsr #16 + and r3, r1, r2 + add r6, r6, r3 + ldr r1, =0xF000 + cmp r3, r1 + blt cbrdll1_duty_cal_end + add r5, r5, #0x01 + b cbrdll1_duty_cal_start + +cbrdll1_duty_cal_end: + mov r6, r6, lsr #2 @ get dutysum + cmp r6, r10 @ check dutysum > gdutysum + ble cbrdll1_duty_next + ldr r0, =0x1e6e0068 + ldr r8, [r0] + eor r9, r7, #0x10 + mov r10, r6 + +cbrdll1_duty_next: + add r7, r7, #0x01 + cmp r7, #16 @ check duty >= 15 + blt cbrdll1_duty_start + ldr r0, =0xFA00 @ check gdutysum > 0xFA00 + cmp r10, r0 + blt cbrdll1_duty_start + +cbrdll1_duty_end: + ldr r0, =0x1e6e0060 + ldr r1, [r0] + bic r1, r1, #0x00001F00 + orr r1, r1, r9, lsl #8 + str r1, [r0] + + ldr r0, =0x1e6e0068 + bic r8, r8, #0xFF000000 + bic r8, r8, #0x00FF0000 + str r8, [r0] + + ldr r0, =0x1e720204 @ record result + str r8, [r0] + add r0, r0, #0x04 + str r9, [r0] + add r0, r0, #0x04 + str r10, [r0] + + ldr r0, =0x1e6e0018 + ldr r1, =0x00008120 + str r1, [r0] + ldr r0, =0x1e6e0000 @ dummy read + ldr r1, [r0] + ldr r0, =0x1e6e0018 + ldr r1, =0x00000120 + str r1, [r0] + + ldr r0, =0x1e6e0120 + ldr r1, [r0] + cmp r1, #0x3 + beq MCLK2X_Phase_CBR_Done_DDR2 + b MCLK2X_Phase_CBR_Done_DDR3 + +/****************************************************************************** + MCLK2X lock to MCLK program + r0 - r3 = free + r5 = madjmax + r6 = dllend + 0x1E720200 = 0x96cnt:failcnt:dllmax:dllmin + ******************************************************************************/ +CBRDLL1_2300_Start: + ldr r0, =0x1e6e0064 + ldr r5, [r0] + and r5, r5, #0xFF @ init madjmax + mov r6, r5 @ init dllend + + ldr r1, =0x000000ff + ldr r0, =0x1e720200 + str r1, [r0] @ init dllcnt2:dllmax:dllmin + + mov r3, #0x0 @ init loop count +cbrdll1_scan_start: + cmp r3, r6 + bge cbrdll1_scan_end + + ldr r0, =0x1e6e0018 + ldr r1, =0x00008120 + str r1, [r0] + + ldr r0, =0x1e6e0068 + mov r1, r3 + cmp r1, r5 + subge r1, r1, r5 + str r1, [r0] + + ldr r0, =0x1e6e0000 @ dummy read + ldr r1, [r0] + + ldr r0, =0x1e6e0018 + ldr r1, =0x00000120 + str r1, [r0] + + ldr r0, =0x1e6e0000 @ dummy read + ldr r1, [r0] + ldr r0, =0x1e6e0000 @ dummy read + ldr r1, [r0] + + ldr r0, =0x1e6e001c + ldr r1, [r0] + mov r1, r1, lsr #16 + and r1, r1, #0xFF + + and r2, r1, #0x96 + cmp r2, #0x96 + beq cbrdll1_scan_pass @ if (mclk2x_phase & 0x96) == 0x96 + ldr r0, =0x1e720200 + ldr r1, [r0] + mov r2, r1, lsr #8 + ands r2, r2, #0xFF @ get dllmax + beq cbrdll1_scan_next @ if dllmax == 0 + mov r2, r1, lsr #16 + and r2, r2, #0xFF + add r2, r2, #0x01 + cmp r2, #0x02 + movge r6, r3 + bic r1, r1, #0x00FF0000 + orr r1, r1, r2, lsl #16 + str r1, [r0] + b cbrdll1_scan_next + +cbrdll1_scan_pass: + cmp r3, #0x0 @ if dll = 0 + moveq r3, #0x0F + addeq r6, r6, #0x10 + beq cbrdll1_scan_next + ldr r0, =0x1e720200 + ldr r2, [r0] + cmp r1, #0x96 + bne cbrdll1_scan_pass2 + mov r1, r2, lsr #24 + add r1, r1, #0x01 + bic r2, r2, #0xFF000000 + orr r2, r2, r1, lsl #24 + cmp r1, #0x03 @ check (phase == 0x96) count == 3 + bicge r2, r2, #0x0000FF00 + bicge r2, r2, #0x000000FF + orrge r2, r2, r3, lsl #8 + orrge r2, r2, r3 + str r2, [r0] + bge cbrdll1_scan_end + +cbrdll1_scan_pass2: + and r1, r2, #0xFF @ if(dllmin > dll) + cmp r1, r3 + bicgt r2, r2, #0x000000FF + orrgt r2, r2, r3 + + mov r1, r2, lsr #8 @ if(dllmax < dll) + and r1, r1, #0xFF + cmp r1, r3 + biclt r2, r2, #0x0000FF00 + orrlt r2, r2, r3, lsl #8 + + bic r2, r2, #0x00FF0000 + str r2, [r0] + +cbrdll1_scan_next: + add r3, r3, #0x01 + b cbrdll1_scan_start + +cbrdll1_scan_end: + ldr r0, =0x1e720200 + ldr r1, [r0] + mov r2, r1, lsr #8 @ get dllmax + ands r2, r2, #0xFF + bne cbrdll1_scan_done @ if(dllmax != 0) + ldr r0, =0x1e6e0064 + ldr r3, [r0] + bic r1, r3, #0x000C0000 + str r1, [r0] + add r0, r0, #0x04 + mov r1, #0x0 + str r1, [r0] + + /* Delay about 10us */ + ldr r2, =0x0000000A @ Set Timer3 Reload = 10 us + init_delay_timer +delay0_1: + check_delay_timer + bne delay0_1 + clear_delay_timer + /* end delay 10us */ + + ldr r0, =0x1e6e0064 + str r3, [r0] + + /* Delay about 10us */ + ldr r2, =0x0000000A @ Set Timer3 Reload = 10 us + init_delay_timer +delay0_2: + check_delay_timer + bne delay0_2 + clear_delay_timer + /* end delay 10us */ + + b CBRDLL1_2300_Start + +cbrdll1_scan_done: + and r1, r1, #0xFF + add r1, r1, r2 + mov r6, r1, lsr #1 @ dll1.0 = (dllmin + dllmax) >> 1 + cmp r6, r5 + subge r6, r6, r5 + add r3, r6, r5, lsr #2 @ dll1.1 = dll1.0 + (MADJ >> 2) + + ldr r0, =0x1e6e0004 + ldr r1, [r0] + mov r1, r1, lsr #10 + tst r1, #0x1 + bne cbrdll1_scan_set_2400 + cmp r3, r5 + subge r3, r3, r5 + mov r2, #0x0 + tst r3, #0x08 + beq cbrdll1_scan_set_2300_2 @ if !(dll & 8) +cbrdll1_scan_set_2300_1: @ if (dll & 8) + mov r1, #0x0 + tst r3, #0x08 + addeq r1, r1, #0x01 + cmp r2, #0x05 + addge r1, r1, #0x01 + cmp r1, #0x02 + beq cbrdll1_scan_set + add r2, r2, #0x01 + add r3, r3, #0x01 + cmp r3, r5 + subge r3, r3, r5 + b cbrdll1_scan_set_2300_1 + +cbrdll1_scan_set_2300_2: + and r1, r3, #0x07 + cmp r1, #0x07 + beq cbrdll1_scan_set + cmp r2, #0x05 + bge cbrdll1_scan_set + add r2, r2, #0x01 + add r3, r3, #0x01 + cmp r3, r5 + subge r3, r3, r5 + b cbrdll1_scan_set_2300_2 + +cbrdll1_scan_set_2400: + add r3, r3, #0x05 @ dll1.1 = dll1.0 + (MADJ >> 2) + 5 + cmp r3, r5 + subge r3, r3, r5 + +cbrdll1_scan_set: + orr r1, r6, r3, lsl #8 + ldr r0, =0x1e6e0068 + str r1, [r0] + + ldr r0, =0x1e6e0120 + ldr r1, [r0] + cmp r1, #0x0 + beq MCLK2X_Phase_CBR_Done_DDR3 + cmp r1, #0x1 + beq MCLK2X_Phase_CBR_Done_DDR2 + b CBRDLL1_2400_Call + +.LTORG + +/****************************************************************************** + Calibration Code Start + SRAM buffer definition + 0x1E720000 : Pass 1, DLLI MIN value range + 0x1E720008 : DQS0 DLL valid range, 2nd time CBR + 0x1E72000C : DQS1 DLL valid range, 2nd time CBR + 0x1E720010 : DQ0 DLL valid range, Pass 1 + 0x1E720014 : DQ1 DLL valid range, Pass 1 + .... + 0x1E720048 : DQ14 DLL valid range, Pass 1 + 0x1E72004C : DQ15 DLL valid range, Pass 1 + 0x1E720090 : DLL1 SAdj record + 0x1E720094 : DQL Pass1 finetune result + 0x1E720098 : DQH Pass1 finetune result + 0x1E72009C : DRAM initial time, (us) + 0x1E7200A0 : CBR3 retry counter + 0x1E7200A4 : DRAM initial time, (us) + 0x1E7200A8 : Released date + 0x1E7200AC : Released SDK version + 0x1E7200B0 : DQS input mask window for MCR18[4] = 0 + 0x1E7200B4 : DQS input mask window for MCR18[4] = 1 + 0x1E720100 : DQIDLY=00, DLL valid range + 0x1E720104 : DQIDLY=01, DLL valid range + .... + 0x1E720178 : DQIDLY=30, DLL valid range + 0x1E72017C : DQIDLY=31, DLL valid range + 0x1E720180 : DQSI-MCLK2X P-phase pass record DLL2= 0-31 + 0x1E720184 : DQSI-MCLK2X P-phase pass record DLL2=32-63 + 0x1E720188 : DQSI-MCLK2X N-phase pass record DLL2= 0-31 + 0x1E72018C : DQSI-MCLK2X N-phase pass record DLL2=32-63 + ******************************************************************************/ +Calibration_Start_pre: @ Toggle DQSI mask delay + ldr r0, =0x1e6e0018 + ldr r1, [r0] + eor r1, r1, #0x10 + str r1, [r0] + +Calibration_Start: +/* Init SRAM buffer */ + ldr r1, =0x000000ff + ldr r0, =0x1e720000 + ldr r2, =0x1e720100 +init_sram_start: + str r1, [r0] + add r0, r0, #4 + cmp r0, r2 + blt init_sram_start + + ldr r1, =0x00ff00ff + ldr r0, =0x1e720100 + ldr r2, =0x1e720180 +init_sram_start2: + str r1, [r0] + add r0, r0, #4 + cmp r0, r2 + blt init_sram_start2 + + ldr r1, =0x00000000 + ldr r0, =0x1e720180 + ldr r2, =0x1e720200 +init_sram_start3: + str r1, [r0] + add r0, r0, #4 + cmp r0, r2 + blt init_sram_start3 + + ldr r0, =0x1e6e0068 @ save the DLL1 SAdj initial value + ldr r1, [r0] + ldr r0, =0x1e720090 + str r1, [r0] + +/* Start + r0 = free + r1 = free + r2 = free + r3 = free + r4 = record the return pc value, do not use + r5 = pattern table index + r6 = pass count + r7 = dram DLL2 parameter index (0x1e6e0068), max is 0x4C +*/ +/****************************************************************************** + Fine DQI delay and DQSI-MCLK phase + r8 = DQIDLY count + r9 = DQSI-MCLK2X phase count + r10 = pattern fail retry counter, initialize to 2 (fail 2 times) + r11 = passcnt accumulator for each DQIDLY + *****************************************************************************/ +CBR0_START: +/* Debug - UART console message */ + ldr r0, =0x1e784000 + mov r1, #0x43 @ 'C' + str r1, [r0] + mov r1, #0x42 @ 'B' + str r1, [r0] + mov r1, #0x52 @ 'R' + str r1, [r0] + mov r1, #0x30 @ '0' + str r1, [r0] + mov r1, #0x2D @ '-' + str r1, [r0] +/* Debug - UART console message */ + + ldr r0, =0x1e6e0018 + ldr r1, [r0] + bic r1, r1, #0xFF000000 + bic r1, r1, #0x00FF0000 + str r1, [r0] + + ldr r0, =0x1e6e0074 @ set the testing DRAM size = 1KB + ldr r1, =0x000003FF + str r1, [r0] + + mov r8, #0x00 @ init DQIDLY + mov r9, #0x00 @ init DQSI-MCLK2X phase + mov r11, #0x01 @ init passcnt accumulator + +cbr0_next_dqidly: + cmp r9, #0x00 + bne cbr0_next_dqsiphase + cmp r11, #0x00 + addeq r8, r8, #0x01 @ jump 1 stage if no pass at previous stage + mov r11, #0x00 + add r8, r8, #0x01 + cmp r8, #0x1F @ max DQIDLY = 31 + bgt CBR0_END + +/* Debug - UART console message */ + ldr r0, =0x1e784000 + and r1, r8, #0x07 + add r1, r1, #0x30 @ '0-7' + str r1, [r0] +/* Debug - UART console message */ + + ldr r0, =0x1e6e0018 + ldr r1, [r0] + bic r1, r1, #0x00FF0000 + orr r1, r1, r8, lsl #16 + str r1, [r0] + mov r9, #0x01 @ '1':p_phase, '0':n_phase + + /* Delay about 3us */ @ wait DQIDLY load + ldr r2, =0x00000003 @ Set Timer4 Reload = 3 us + init_delay_timer +delay_4: + check_delay_timer + bne delay_4 + clear_delay_timer + /* end delay 3us */ + + b cbr0_dll2_scan_start + +cbr0_next_dqsiphase: + ldr r0, =0x1e6e0018 + ldr r1, [r0] + orr r1, r1, r9, lsl #23 @ set DQSI-MCLK2X phase + str r1, [r0] + mov r9, #0x00 + +cbr0_dll2_scan_start: + mov r6, #0x00 @ init pass count + mov r7, #0x00 @ init DLL2 parameter index + +/**************************** + DLL2 delay margin test loop + ***************************/ +cbr0_next_dll2_parameter: + ldr r0, =0x1e6e0068 @ load DLL2 parameter + ldr r1, [r0] + bic r1, r1, #0x00FF0000 + bic r1, r1, #0xFF000000 + orr r1, r1, r7, lsl #16 + str r1, [r0] + ldr r2, =0x40404040 @ DLL2 max is 0x40404040 + cmp r7, r2 + bge cbr0_next_dqidly + ldr r2, =0x01010101 + add r7, r7, r2 + +/* CBRScan3() start */ + adrl r5, PATTERN_TABLE @ init pattern table index +/**************************** + Test pattern iteration loop + ***************************/ +cbr0_next_test_pattern: + mov r10, #2 @ set the retry loop = 2 of each pattern + ldr r1, [r5] @ load test pattern + ldr r0, =0x1e6e007c + str r1, [r0] + cmp r1, #0x00 @ the last data in pattern is 0x00 + bne cbr0_test_burst + + and r3, r7, #0xFF + sub r3, r3, #0x01 @ we add 1 after loop check so we need to decrease 1 + cmp r3, #0x00 + beq cbr0_next_dqidly @ pass at dlli = 0, invalid + add r6, r6, #0x01 @ increment pass count + add r11, r11, #0x01 @ increment pass count + + ldr r0, =0x1e720180 @ record DLL2 pass window + cmp r9, #0x00 @ DQSI-MCLK2X phase check + addeq r0, r0, #0x08 + cmp r3, #32 + addge r0, r0, #0x4 + and r1, r3, #0x1F + mov r2, #0x1 + mov r2, r2, lsl r1 + ldr r1, [r0] + orr r1, r1, r2 + str r1, [r0] + + ldr r0, =0x1e720100 @ record DLL2 min:max value for each DQIDLY + add r0, r0, r8, lsl #2 + cmp r9, #0x00 @ DQSI-MCLK2X phase check + beq cbr0_test_pass_dqsin + record_dll2_pass_range + b cbr0_next_dll2_parameter + +cbr0_test_pass_dqsin: + record_dll2_pass_range_h + b cbr0_next_dll2_parameter + +cbr0_test_pattern_fail: + cmp r6, #5 @ passcnt >= 5 + bge cbr0_next_dqidly + ldr r0, =0x1e720100 @ reset DLL2 min:max value + add r0, r0, r8, lsl #2 + ldr r1, [r0] + ldr r2, =0xFFFF0000 + ldr r3, =0x000000FF + cmp r9, #0x00 + moveq r2, r2, lsr #16 + moveq r3, r3, lsl #16 + and r1, r1, r2 + orr r1, r1, r3 + str r1, [r0] + b cbr0_next_dll2_parameter @ CBRScan3() end and test result fail, go to next step + +/**************************** + Test fail retry loop + ***************************/ +cbr0_pattern_fail_retry: + +/* CBRTest3() start */ +cbr0_test_burst: + ldr r0, =0x1e6e0070 + ldr r1, =0x00000000 + str r1, [r0] + ldr r1, =0x000000C1 + str r1, [r0] + ldr r3, =0x3000 +cbr0_wait_engine_idle_0: + ldr r2, [r0] + tst r2, r3 @ D[12] = idle bit + beq cbr0_wait_engine_idle_0 + + ldr r2, [r0] @ read fail bit status + mov r1, #0x0 + str r1, [r0] + mov r2, r2, lsr #13 @ D[13] = fail bit + cmp r2, #0x00 + bne cbr0_test_fail + +cbr0_test_single: + ldr r0, =0x1e6e0070 + ldr r1, =0x00000000 + str r1, [r0] + ldr r1, =0x00000085 + str r1, [r0] + ldr r3, =0x3000 +cbr0_wait_engine_idle_1: + ldr r2, [r0] + tst r2, r3 @ D[12] = idle bit + beq cbr0_wait_engine_idle_1 + + ldr r2, [r0] @ read fail bit status + mov r1, #0x0 + str r1, [r0] + mov r2, r2, lsr #13 @ D[13] = fail bit + cmp r2, #0x00 + beq cbr0_test_pass + +/* CBRTest3() end */ + +cbr0_test_fail: + subs r10, r10, #1 + bne cbr0_pattern_fail_retry + b cbr0_test_pattern_fail @ CBRScan3() return(0) + +cbr0_test_pass: + add r5, r5, #0x04 @ increase the test pattern index + b cbr0_next_test_pattern + +CBR0_END: + mov r5, #0x0 @ init DQIDLY search count + mov r6, #0x0 @ init max_margin:g_margin + mov r8, #0x0 @ init g_side + mov r7, #0x0 @ init maximum margin DQIDLY,DQSI-MCLK2X phase +cbr0_search_dll_margin_s: + ldr r0, =0x1e720100 + add r0, r0, r5, lsl #2 + ldr r1, [r0] + and r2, r1, #0xFF @ get dllmin_p + mov r1, r1, lsr #8 + and r3, r1, #0xFF @ get dllmax_p + subs r2, r3, r2 @ get margin-P + movmi r2, #0x0 + mov r1, r1, lsr #8 + and r3, r1, #0xFF @ get dllmin_n + mov r1, r1, lsr #8 + and r1, r1, #0xFF @ get dllmax_n + subs r3, r1, r3 @ get margin-N + movmi r3, #0x0 + add r1, r2, r3 + cmp r1, #0x0 + beq cbr0_search_dll_margin_e @ if margin-P = 0 && margin-N = 0 + + ldr r9, [r0] + ldr r0, =0x1e720180 + cmp r2, r3 + orrlt r5, r5, #0x80 @ margin-N > margin-P + addlt r0, r0, #0x08 + movlt r9, r9, lsr #16 + movge r3, r2 @ max(margin-P/N) + add r2, r3, #0x2 @ define +/- 2 steps of variation + mov r1, r6, lsr #16 + cmp r2, r1 + blt cbr0_search_dll_margin_e @ if max(margin-P/N) + 2 < max_margin + + and r1, r9, #0xFF @ r1 = dlli counter + cmp r1, #32 + ldrge r2, [r0, #0x4] @ load pass window + ldrlt r2, [r0] + and r1, r1, #0x1F + mov r10, #0x1 @ init test bit mask + mov r10, r10, lsl r1 + and r1, r9, #0xFF +cbr0_search_dllmin_margin_s: + tst r2, r10 + beq cbr0_search_dllmin_margin_e + mov r10, r10, lsr #1 + cmp r1, #32 + ldreq r2, [r0] + ldreq r10, =0x80000000 + subs r1, r1, #0x1 + bne cbr0_search_dllmin_margin_s + +cbr0_search_dllmin_margin_e: + and r2, r9, #0xFF + sub r11, r2, r1 @ get dllmin side margin + + mov r9, r9, lsr #8 + and r1, r9, #0xFF @ r1 = dlli counter + cmp r1, #32 + ldrge r2, [r0, #0x4] @ load pass window + ldrlt r2, [r0] + and r1, r1, #0x1F + mov r10, #0x1 @ init test bit mask + mov r10, r10, lsl r1 + and r1, r9, #0xFF +cbr0_search_dllmax_margin_s: + tst r2, r10 + beq cbr0_search_dllmax_margin_e + mov r10, r10, lsl #1 + cmp r1, #31 + ldreq r2, [r0, #0x4] + ldreq r10, =0x00000001 + add r1, r1, #0x1 + cmp r1, #64 + bne cbr0_search_dllmax_margin_s + +cbr0_search_dllmax_margin_e: + and r2, r9, #0xFF + sub r1, r1, r2 @ get dllmax side margin + cmp r1, r11 + movlt r11, r1 @ get side_margin + +cbr0_check_dll_margin: @ if max(margin-P/N) > g_margin && side_margin >= g_side && dqidly <= 20 + cmp r5, #20 + bgt cbr0_check_dll_margin2 + and r1, r6, #0xFF + cmp r3, r1 + ble cbr0_check_dll_margin3 + cmp r11, r8 + bge cbr0_set_dll_margin + +cbr0_check_dll_margin2: @ if max(margin-P/N) > g_margin+1 && side_margin >= g_side) + and r1, r6, #0xFF + add r2, r1, #0x1 + cmp r3, r2 + ble cbr0_check_dll_margin3 + cmp r11, r8 + bge cbr0_set_dll_margin + +cbr0_check_dll_margin3: @ if side_margin > g_side && g_side < 8 + cmp r8, #8 + bge cbr0_search_dll_margin_e + cmp r11, r8 + ble cbr0_search_dll_margin_e + +cbr0_set_dll_margin: + mov r1, r6, lsr #16 + cmp r3, r1 + bicgt r6, r6, #0x00FF0000 + orrgt r6, r6, r3, lsl #16 + bic r6, r6, #0x000000FF + orr r6, r6, r3 + mov r7, r5 + mov r8, r11 + +cbr0_search_dll_margin_e: + and r5, r5, #0x7F + add r5, r5, #0x01 + cmp r5, #0x20 @ last DQIDLY + blt cbr0_search_dll_margin_s + + ldr r0, =0x1e6e0018 + ldr r1, [r0] + bic r1, r1, #0x00FF0000 + orr r1, r1, r7, lsl #16 + str r1, [r0] + + ldr r0, =0x1e6e0068 + ldr r1, [r0] + bic r1, r1, #0x00FF0000 + bic r1, r1, #0xFF000000 + str r1, [r0] + + /* Delay about 5us */ + ldr r2, =0x00000005 @ Set Timer5 Reload = 5 us + init_delay_timer +delay_5: + check_delay_timer + bne delay_5 + clear_delay_timer + /* end delay 5us */ + + ldr r0, =0x1e6e000c @ Set refresh cycle + ldr r1, =0x00005C01 + str r1, [r0] + +/****************************************************************************** + Fine tune per bit DQ input delay -- Pass 1, left edge align + r8 = free + r9 = DQ fail bit accumulator + r10 = pattern fail counter, initialize to 5 (fail 5 times) + r11 = free + *****************************************************************************/ +CBR1_START: +/* Debug - UART console message */ + ldr r0, =0x1e784000 + mov r1, #0x0D @ '\r' + str r1, [r0] + mov r1, #0x0A @ '\n' + str r1, [r0] + mov r1, #0x43 @ 'C' + str r1, [r0] + mov r1, #0x42 @ 'B' + str r1, [r0] + mov r1, #0x52 @ 'R' + str r1, [r0] + mov r1, #0x31 @ '1' + str r1, [r0] +/* Debug - UART console message */ + + mov r6, #0x00 @ init pass count + mov r7, #0x00 @ init DLL2 parameter index + +/**************************** + DLL2 delay margin test loop + ***************************/ +cbr1_next_dll2_parameter: + ldr r0, =0x1e6e0068 @ load DLL2 parameter + ldr r1, [r0] + bic r1, r1, #0x00FF0000 + bic r1, r1, #0xFF000000 + orr r1, r1, r7, lsl #16 + str r1, [r0] + ldr r2, =0x40404040 @ parameter's max is to 0x40404040 + cmp r7, r2 + bge CBR1_END + ldr r2, =0x01010101 + add r7, r7, r2 + + ldr r0, =0x1e6e0074 @ set the testing DRAM size = 4KB + ldr r1, =0x00000FFF + str r1, [r0] + +/* CBRScan2() start */ + ldr r9, =0xFFFF @ init test status + adrl r5, PATTERN_TABLE @ init pattern table index +/**************************** + Test pattern iteration loop + ***************************/ +cbr1_next_test_pattern: + mov r10, #5 @ set the retry loop of each pattern + ldr r1, [r5] @ load test pattern + ldr r0, =0x1e6e007c + str r1, [r0] + cmp r1, #0x00 @ the last data in pattern is 0x00 + bne cbr1_test_single + +cbr1_test_pattern_end: + cmp r9, #0x00 + bne cbr1_test_pass_dqi + cmp r6, #10 + bge CBR1_END + b cbr1_next_dll2_parameter @ CBRScan2() end and test result fail, go to next step + +cbr1_test_pass_dqi: + and r3, r7, #0xFF + sub r3, r3, #0x01 @ we add 1 after loop check so we need to decrease 1 + add r6, r6, #0x01 @ increment pass count + ldr r0, =0x1e720010 + mov r8, #0x01 +cbr1_test_pass_dqi_loop_s: + tst r9, r8 + beq cbr1_test_pass_dqi_loop_e + record_dll2_pass_range + +cbr1_test_pass_dqi_loop_e: + add r0, r0, #0x04 + mov r8, r8, lsl #1 + ldr r1, =0xFFFF + tst r8, r1 + bne cbr1_test_pass_dqi_loop_s + b cbr1_next_dll2_parameter + +/**************************** + Test fail retry loop + ***************************/ +cbr1_pattern_fail_retry: + +/* CBRTest2() start */ +cbr1_test_single: + ldr r0, =0x1e6e0070 + ldr r1, =0x00000000 + str r1, [r0] + ldr r1, =0x00000005 + str r1, [r0] + ldr r3, =0x1000 + ldr r1, =0x1000 +cbr1_wait_engine_idle_0: + subs r1, r1, #1 + beq cbr1_test_single_end + ldr r2, [r0] + tst r2, r3 @ D[12] = idle bit + beq cbr1_wait_engine_idle_0 + +cbr1_test_single_end: + ldr r0, =0x1e6e0078 @ read fail bit status + ldr r11, [r0] + orr r11, r11, r11, lsr #16 + bic r11, r11, #0xFF000000 + bic r11, r11, #0x00FF0000 + + ldr r1, =0xFFFF + cmp r11, r1 + beq cbr1_test_fail + +cbr1_test_burst: + ldr r0, =0x1e6e0070 + ldr r2, =0x00000000 + str r2, [r0] + ldr r2, =0x00000041 + str r2, [r0] + ldr r3, =0x1000 + ldr r1, =0x1000 +cbr1_wait_engine_idle_1: + subs r1, r1, #1 + beq cbr1_test_burst_end + ldr r2, [r0] + tst r2, r3 @ D[12] = idle bit + beq cbr1_wait_engine_idle_1 + +cbr1_test_burst_end: + ldr r0, =0x1e6e0078 @ read fail bit status + ldr r2, [r0] + orr r2, r2, r2, lsr #16 + bic r2, r2, #0xFF000000 + bic r2, r2, #0x00FF0000 + orr r11, r11, r2 + + ldr r2, =0xFFFF + cmp r11, r2 + bne cbr1_test_pass +/* CBRTest2() end */ + +cbr1_test_fail: + subs r10, r10, #1 + bne cbr1_pattern_fail_retry + mov r9, #0x00 + b cbr1_test_pattern_end @ CBRScan2() return(0) + +cbr1_test_pass: + ldr r1, =0xFFFF @ record the pass bit + eor r11, r11, r1 + and r9, r9, r11 @ DQ pass bit + cmp r9, #0x00 + beq cbr1_test_pattern_end @ CBRScan2() return(0) + + add r5, r5, #0x04 @ increase the test pattern index + b cbr1_next_test_pattern + +CBR1_END: + mov r5, #0x0 @ init DQ DLL_min sum + mov r6, #0x0 @ init DQ DLL_min valid count + ldr r0, =0x1e72000c + ldr r3, =0x1e720050 +cbr1_search_dllmin_s: + add r0, r0, #0x04 + cmp r0, r3 + beq cbr1_search_dllmin_e + ldr r1, [r0] + mov r2, r1, lsr #8 + and r2, r2, #0xFF @ get dllmax + and r1, r1, #0xFF @ get dllmin + subs r2, r2, r1 @ dllmax - dllmin + bmi cbr1_search_dllmin_s @ no valid margin found, bypass fine tune + cmp r2, #10 @ (dllmax - dllmin) < 10 + blt cbr1_search_dllmin_s @ no enough margin found, bypass fine tune + add r5, r5, r1 + add r6, r6, #1 + b cbr1_search_dllmin_s + +cbr1_search_dllmin_e: + cmp r6, #16 + bne Calibration_Start_pre @ not all bits valid, retry again + + mov r5, r5, lsr #4 + ldr r0, =0x1e720000 + str r5, [r0] + + mov r6, #0x00 @ init DQL CBR value + ldr r0, =0x1e720030 + ldr r7, =0x1e72000c +cbr1_set_result_dql: + sub r0, r0, #4 + cmp r0, r7 + beq cbr1_set_result_next + mov r6, r6, lsl #3 + ldr r1, [r0] + mov r2, r1, lsr #8 + and r2, r2, #0xFF @ get dllmax + and r1, r1, #0xFF @ get dllmin + mov r3, r1 @ dll = dllmin + cmp r5, r3 + blt cbr1_set_result_dql_neg + sub r1, r5, r3 + mov r2, #19 + mul r1, r2, r1 + mov r1, r1, lsr #5 @ dqi_tune = ((gold_dll - dll) * 19) >> 5 + cmp r1, #2 @ dqi_tune max = 2 + movgt r1, #2 + orr r6, r6, r1 + b cbr1_set_result_dql + +cbr1_set_result_dql_neg: + sub r1, r3, r5 + mov r2, #19 + mul r1, r2, r1 + mov r1, r1, lsr #5 @ dqi_tune = ((gold_dll - dll) * 19) >> 5 + cmp r1, #2 @ dqi_tune max = -2 + movgt r1, #2 + mov r2, #8 + sub r1, r2, r1 + and r1, r1, #7 + orr r6, r6, r1 + b cbr1_set_result_dql + +cbr1_set_result_next: + ldr r0, =0x1e6e0080 @ save DQL fine tune result + str r6, [r0] + ldr r0, =0x1e720094 + str r6, [r0] + + mov r6, #0x00 @ init DQH CBR value + ldr r0, =0x1e720050 + ldr r7, =0x1e72002c +cbr1_set_result_dqh: + sub r0, r0, #4 + cmp r0, r7 + beq cbr1_set_result_end + mov r6, r6, lsl #3 + ldr r1, [r0] + mov r2, r1, lsr #8 + and r2, r2, #0xFF @ get dllmax + and r1, r1, #0xFF @ get dllmin + mov r3, r1 @ dll = dllmin + cmp r5, r3 + blt cbr1_set_result_dqh_neg + sub r1, r5, r3 + mov r2, #19 + mul r1, r2, r1 + mov r1, r1, lsr #5 @ dqi_tune = ((gold_dll - dll) * 19) >> 5 + cmp r1, #3 @ dqi_tune max = 2 + movgt r1, #3 + subs r1, r1, #1 + movmi r1, #7 + orr r6, r6, r1 + b cbr1_set_result_dqh + +cbr1_set_result_dqh_neg: + sub r1, r3, r5 + mov r2, #19 + mul r1, r2, r1 + mov r1, r1, lsr #5 @ dqi_tune = ((gold_dll - dll) * 19) >> 5 + add r1, r1, #1 + cmp r1, #2 @ dqi_tune max = -2 + movgt r1, #2 + mov r2, #8 + sub r1, r2, r1 + and r1, r1, #7 + orr r6, r6, r1 + b cbr1_set_result_dqh + +cbr1_set_result_end: + ldr r0, =0x1e6e0084 @ save DQH fine tune result + str r6, [r0] + ldr r0, =0x1e720098 + str r6, [r0] + +/****************************************************************************** + Search the DLL2 detail margin + *****************************************************************************/ + ldr r0, =0x1e7200a0 + mov r1, #0 + str r1, [r0] + +CBR3_START: +/* Debug - UART console message */ + ldr r0, =0x1e784000 + mov r1, #0x33 @ '3' + str r1, [r0] +/* Debug - UART console message */ + + mov r6, #0x00 @ init pass count + mov r7, #0x00 @ init DLL2 parameter index + ldr r1, =0x000000ff + ldr r0, =0x1e720008 @ init DQL dllmax,dllmin + str r1, [r0] + ldr r0, =0x1e72000c @ init DQH dllmax,dllmin + str r1, [r0] + + ldr r0, =0x1e7200a0 @ CBR3 iteration counter + ldr r1, [r0] + add r1, r1, #1 + str r1, [r0] + +/**************************** + DLL2 delay margin test loop + ***************************/ +cbr3_next_dll2_parameter: + ldr r0, =0x1e6e0068 @ load DLL2 parameter + ldr r1, [r0] + bic r1, r1, #0x00FF0000 + bic r1, r1, #0xFF000000 + orr r1, r1, r7, lsl #16 + str r1, [r0] + ldr r2, =0x40404040 @ parameter's max is to 0x40404040 + cmp r7, r2 + bge CBR3_END + ldr r2, =0x01010101 + add r7, r7, r2 + + ldr r0, =0x1e6e0074 @ set the testing DRAM size = 64KB + ldr r1, =0x0000FFFF + str r1, [r0] + +/* CBRScan() start */ + mov r9, #0x03 @ init test status + adrl r5, PATTERN_TABLE @ init pattern table index +/**************************** + Test pattern iteration loop + ***************************/ +cbr3_next_test_pattern: + mov r10, #5 @ set the retry loop of each pattern + ldr r1, [r5] @ load test pattern + ldr r0, =0x1e6e007c + str r1, [r0] + cmp r1, #0x00 @ the last data in pattern is 0x00 + bne cbr3_test_single + +cbr3_test_pattern_end: + cmp r9, #0x00 + bne cbr3_test_pass_dql + cmp r6, #10 + bge CBR3_END + b cbr3_next_dll2_parameter @ CBRScan() end and test result fail, go to next step + +cbr3_test_pass_dql: + and r3, r7, #0xFF + sub r3, r3, #0x01 @ we add one after loop check so we need to decrease 1 + add r6, r6, #0x01 @ increment pass count + tst r9, #0x01 + beq cbr3_test_pass_dqh + + ldr r0, =0x1E720008 + record_dll2_pass_range + +cbr3_test_pass_dqh: + tst r9, #0x02 + beq cbr3_next_dll2_parameter + ldr r0, =0x1E72000c + record_dll2_pass_range + b cbr3_next_dll2_parameter + +/**************************** + Test fail retry loop + ***************************/ +cbr3_pattern_fail_retry: + +/* CBRTest() start */ +cbr3_test_single: + ldr r0, =0x1e6e0070 + ldr r1, =0x00000000 + str r1, [r0] + ldr r1, =0x00000005 + str r1, [r0] + ldr r3, =0x1000 + ldr r8, =0x10000 +cbr3_wait_engine_idle_0: + subs r8, r8, #1 + beq cbr3_test_single_end + ldr r2, [r0] + tst r2, r3 @ D[12] = idle bit + beq cbr3_wait_engine_idle_0 + +cbr3_test_single_end: + ldr r0, =0x1e6e0078 @ read fail bit status + ldr r11, [r0] + orr r11, r11, r11, lsr #16 + bic r11, r11, #0xFF000000 + bic r11, r11, #0x00FF0000 + + ldr r1, =0xFF + tst r11, r1 + beq cbr3_test_burst + tst r11, r1, lsl #8 + bne cbr3_test_fail + +cbr3_test_burst: + mov r1, #0x00 @ initialize loop index, r1 is loop's index +cbr3_test_burst_loop: + ldr r0, =0x1e6e0070 + ldr r2, =0x00000000 + str r2, [r0] + mov r2, r1, lsl #3 + orr r2, r2, #0x41 @ test command = 0x41 | (datagen << 3) + str r2, [r0] + ldr r3, =0x1000 + ldr r8, =0x10000 +cbr3_wait_engine_idle_1: + subs r8, r8, #1 + beq cbr3_test_burst_end + ldr r2, [r0] + tst r2, r3 @ D[12] = idle bit + beq cbr3_wait_engine_idle_1 + +cbr3_test_burst_end: + ldr r0, =0x1e6e0078 @ read fail bit status + ldr r2, [r0] + orr r2, r2, r2, lsr #16 + bic r2, r2, #0xFF000000 + bic r2, r2, #0x00FF0000 + orr r11, r11, r2 + + ldr r2, =0xFF + tst r11, r2 + beq cbr3_next_test_burst_mode + tst r11, r2, lsl #8 + beq cbr3_next_test_burst_mode +/* CBRTest() end */ + +cbr3_test_fail: + subs r10, r10, #1 + bne cbr3_pattern_fail_retry + mov r9, #0x00 + b cbr3_test_pattern_end @ CBRScan() return(0) + +cbr3_next_test_burst_mode: + add r1, r1, #1 @ increase the test mode index + cmp r1, #0x08 @ there are 8 modes + bne cbr3_test_burst_loop + + ldr r1, =0xFF @ record the pass byte + tst r11, r1 + andne r9, r9, #0x02 @ DQL fail + tst r11, r1, lsl #8 + andne r9, r9, #0x01 @ DQH fail + cmp r9, #0x00 + beq cbr3_test_pattern_end @ CBRScan() return(0) + + add r5, r5, #0x04 @ increase the test pattern index + b cbr3_next_test_pattern + +CBR3_END: + ldr r0, =0x1e72000c @ check DQH margin + ldr r1, [r0] + mov r2, r1, lsr #8 + and r2, r2, #0xFF @ get dllmax + and r1, r1, #0xFF @ get dllmin + subs r5, r2, r1 @ dllmax - dllmin + bmi CBR3_START @ no valid margin found, retry again + cmp r5, #10 @ (dllmax - dllmin) < 10 + blt CBR3_START @ no enough margin found, retry again + add r2, r1, r2 @ (dllmin[1] + dllmax[1] + 1) >> 1 + add r2, r2, #0x01 + mov r1, r2, lsr #1 + mov r3, r1, lsl #8 + ldr r1, [r0] @ store the dll search result + bic r1, r1, #0xFF000000 + bic r1, r1, #0x00FF0000 + orr r1, r1, r3, lsl #8 + str r1, [r0] + + ldr r0, =0x1e720008 @ check DQL margin + ldr r1, [r0] + mov r2, r1, lsr #8 + and r2, r2, #0xFF @ get dllmax + and r1, r1, #0xFF @ get dllmin + subs r5, r2, r1 @ dllmax - dllmin + bmi CBR3_START @ no valid margin found, retry again + cmp r5, #10 @ (dllmax - dllmin) < 10 + blt CBR3_START @ no enough margin found, retry again + add r2, r1, r2 @ (dllmin[0] + dllmax[0] + 1) >> 1 + add r2, r2, #0x01 + mov r1, r2, lsr #1 + ldr r2, [r0] @ store the dll search result + bic r2, r2, #0xFF000000 + bic r2, r2, #0x00FF0000 + orr r2, r2, r1, lsl #16 + str r2, [r0] + orr r3, r3, r1 + + ldr r0, =0x1e6e0068 @ save the result dll value + ldr r1, [r0] + bic r1, r1, #0xFF000000 + bic r1, r1, #0x00FF0000 + orr r1, r1, r3, lsl #16 + str r1, [r0] + b CBR4_START + +.LTORG + +/****************************************************************************** + Search the DQS input mask margin + *****************************************************************************/ +CBR4_START: +/* Debug - UART console message */ + ldr r0, =0x1e784000 + mov r1, #0x34 @ '4' + str r1, [r0] +/* Debug - UART console message */ + + ldr r0, =0x1e6e0074 @ set the testing DRAM size = 4KB + ldr r1, =0x00000FFF + str r1, [r0] + + mov r8, #0x00 @ init MCR18[4] + ldr r1, =0x000000ff + ldr r0, =0x1e7200b0 @ init MCR18[4]=0 max,min + str r1, [r0] + ldr r0, =0x1e7200b4 @ init MCR18[4]=1 max,min + str r1, [r0] + + ldr r0, =0x1e6e0018 + ldr r1, [r0] + bic r1, r1, #0x0000001F + str r1, [r0] + + b cbr4_scan_start + +cbr4_next_maskdly: + add r8, r8, #0x01 + and r2, r8, #0x01 + ldr r0, =0x1e6e0018 + ldr r1, [r0] + bic r1, r1, #0x0000001F + orr r1, r1, r2, lsl #4 + str r1, [r0] + cmp r8, #0x02 + bge CBR4_END + +cbr4_scan_start: + mov r6, #0x00 @ init pass count + mov r7, #0x00 @ init mask delay + +/**************************** + DQS Mask delay margin test loop + ***************************/ +cbr4_next_parameter: + cmp r7, #0x10 @ max delay = 0xF + bge cbr4_next_maskdly + ldr r0, =0x1e6e0018 @ load MCR18 parameter + ldr r1, [r0] + bic r1, r1, #0x0000000F + orr r1, r1, r7 + str r1, [r0] + add r7, r7, #0x01 + +/* CBRScan3() start */ + adrl r5, PATTERN_TABLE @ init pattern table index +/**************************** + Test pattern iteration loop + ***************************/ +cbr4_next_test_pattern: + mov r10, #2 @ set the retry loop = 2 of each pattern + ldr r1, [r5] @ load test pattern + ldr r0, =0x1e6e007c + str r1, [r0] + cmp r1, #0x00 @ the last data in pattern is 0x00 + bne cbr4_test_burst + + and r3, r7, #0xFF + sub r3, r3, #0x01 @ we add 1 after loop check so we need to decrease 1 + add r6, r6, #0x01 @ increment pass count + + ldr r0, =0x1e7200b0 @ record pass window + add r0, r0, r8, lsl #2 + record_dll2_pass_range + mov r2, #0x01 + add r1, r1, r2, lsl #16 + str r1, [r0] + b cbr4_next_parameter + +cbr4_test_pattern_fail: + cmp r6, #5 @ passcnt >= 5 + bge cbr4_next_maskdly + b cbr4_next_parameter + +/**************************** + Test fail retry loop + ***************************/ +cbr4_pattern_fail_retry: + +/* CBRTest3() start */ +cbr4_test_burst: + ldr r0, =0x1e6e0070 + ldr r1, =0x00000000 + str r1, [r0] + ldr r1, =0x000000C1 + str r1, [r0] + ldr r3, =0x3000 +cbr4_wait_engine_idle_0: + ldr r2, [r0] + tst r2, r3 @ D[12] = idle bit + beq cbr4_wait_engine_idle_0 + + ldr r2, [r0] @ read fail bit status + mov r1, #0x0 + str r1, [r0] + mov r2, r2, lsr #13 @ D[13] = fail bit + cmp r2, #0x00 + bne cbr4_test_fail + +cbr4_test_single: + ldr r0, =0x1e6e0070 + ldr r1, =0x00000000 + str r1, [r0] + ldr r1, =0x00000085 + str r1, [r0] + ldr r3, =0x3000 +cbr4_wait_engine_idle_1: + ldr r2, [r0] + tst r2, r3 @ D[12] = idle bit + beq cbr4_wait_engine_idle_1 + + ldr r2, [r0] @ read fail bit status + mov r1, #0x0 + str r1, [r0] + mov r2, r2, lsr #13 @ D[13] = fail bit + cmp r2, #0x00 + beq cbr4_test_pass + +/* CBRTest3() end */ + +cbr4_test_fail: + subs r10, r10, #1 + bne cbr4_pattern_fail_retry + b cbr4_test_pattern_fail @ CBRScan3() return(0) + +cbr4_test_pass: + add r5, r5, #0x04 @ increase the test pattern index + b cbr4_next_test_pattern + +CBR4_END: + ldr r0, =0x1e7200b0 @ check mask margin + ldr r1, [r0] + add r0, r0, #0x04 + ldr r2, [r0] + ands r6, r2, #0xFF @ get min of MCR18[4] = 1 + bne cbr4_noset_delay + ands r5, r1, #0xFF @ get min of MCR18[4] = 0 + bne cbr4_set_delay + mov r1, r1, lsr #8 @ get max of MCR18[4] = 0 + and r1, r1, #0xFF + mov r2, r2, lsr #8 @ get max of MCR18[4] = 1 + and r2, r2, #0xFF + sub r1, r1, r5 + sub r2, r2, r6 + cmp r1, r2 + bge cbr4_noset_delay + +cbr4_set_delay: + ldr r0, =0x1e6e0018 + ldr r1, [r0] + orr r1, r1, #0x10 + str r1, [r0] + +cbr4_noset_delay: + ldr r0, =0x1e6e0070 + ldr r1, =0x00000000 + str r1, [r0] + +/****************************************************************************** + CBR Finish + *****************************************************************************/ +/****************************************************************************** + Check DRAM Size + *****************************************************************************/ + ldr r0, =0x1e6e2070 + ldr r1, [r0] + bic r1, r1, #0xFEFFFFFF @ bit[24]=1 => DDR2 + mov r2, r1, lsr #24 + cmp r2, #0x01 + beq check_ddr2_size + + ldr r0, =0x1e6e0004 + ldr r5, [r0] + bic r5, r5, #0x00000003 @ record MCR04 + orr r1, r5, #0x3 + str r1, [r0] @ set to 4Gbit + ldr r6, =0x003F2217 +#if defined(CONFIG_DRAM_336) + ldr r6, =0x00361C13 +#endif + b check_dram_size + +check_ddr2_size: + ldr r0, =0x1e6e0004 + ldr r5, [r0] + bic r5, r5, #0x00000023 @ record MCR04 + orr r1, r5, #0x23 + str r1, [r0] @ set to 4Gbit + ldr r6, =0x3F2B1B16 +#if defined(CONFIG_DRAM_336) + ldr r6, =0x3B231612 +#endif + + ldr r0, =0x40000000 + ldr r1, =0x1817191A + str r1, [r0] + ldr r0, =0x40002000 + ldr r1, =0x73616532 + str r1, [r0] + ldr r0, =0x40000000 + ldr r1, =0x1817191A + ldr r2, [r0] + cmp r1, r2 + bne check_dram_size_end @ == 512Mbit + orr r5, r5, #0x20 @ >= 1Gbit + mov r6, r6, lsr #8 + +check_dram_size: + ldr r0, =0x50100000 + ldr r1, =0x41424344 + str r1, [r0] + ldr r0, =0x48100000 + ldr r1, =0x25262728 + str r1, [r0] + ldr r0, =0x40100000 + ldr r1, =0x191A1B1C + str r1, [r0] + ldr r0, =0x50100000 + ldr r1, =0x41424344 + ldr r2, [r0] + cmp r2, r1 @ == 4Gbit + orreq r5, r5, #0x03 + moveq r6, r6, lsr #16 + beq check_dram_size_end + ldr r0, =0x48100000 + ldr r1, =0x25262728 + ldr r2, [r0] + cmp r2, r1 @ == 2Gbit + orreq r5, r5, #0x02 + moveq r6, r6, lsr #8 + beq check_dram_size_end + orr r5, r5, #0x01 @ == 1Gbit + +check_dram_size_end: + ldr r0, =0x1e6e0004 + str r5, [r0] + ldr r0, =0x1e6e0014 + ldr r1, [r0] + bic r1, r1, #0x000000FF + and r6, r6, #0xFF + orr r1, r1, r6 + str r1, [r0] + + ldr r0, =0x1e6e0120 @ VGA Compatible Mode + ldr r1, =0x000050C0 @ 408 MHz +#if defined(CONFIG_DRAM_336) + ldr r1, =0x00004DC0 +#endif + str r1, [r0] + +/****************************************************************************** + Version Number + *****************************************************************************/ + ldr r0, =0x1e7200a8 + ldr r1, =0x20141229 @ released date + str r1, [r0] + + add r0, r0, #4 + ldr r1, =0x00000060 @ released SDK version + str r1, [r0] + +/****************************************************************************** + Calibration Code End + ******************************************************************************/ + +set_scratch: + /*Set Scratch register Bit 6 after ddr initial finished */ + ldr r0, =0x1e6e2040 + ldr r1, [r0] + orr r1, r1, #0x40 + str r1, [r0] + +/* Debug - UART console message */ + ldr r0, =0x1e784000 + mov r1, #0x44 @ 'D' + str r1, [r0] + mov r1, #0x6F @ 'o' + str r1, [r0] + mov r1, #0x6E @ 'n' + str r1, [r0] + mov r1, #0x65 @ 'e' + str r1, [r0] + mov r1, #0x0D @ '\r' + str r1, [r0] + mov r1, #0x0A @ '\n' + str r1, [r0] +/* Debug - UART console message */ + +/****************************************************************************** + Solve PCIe ASPM issue, only applied to AST2300 series + ******************************************************************************/ + ldr r0, =0x1e6e207c @ Check bounding for AST1150 existence + ldr r1, [r0] + mov r2, r1, lsr #24 + cmp r2, #0x01 + bne platform_exit @ not match AST2300 + bic r1, r1, #0xFFFFFCFF + mov r1, r1, lsr #8 + cmp r1, #0x02 + beq platform_exit @ match AST1050 + + ldr r0, =0x1e6e2004 @ Disable I2C controller reset + ldr r1, [r0] + orr r1, r1, #0x04 + str r1, [r0] + bic r1, r1, #0x04 + str r1, [r0] + + ldr r0, =0x1e78a054 @ Check I2C bus state, if busy then quit + ldr r1, [r0] + mov r1, r1, lsr #17 + and r1, r1, #0x03 + cmp r1, #0x03 + bne platform_exit + + ldr r0, =0x1e78a040 @ Init I2C1 controller + mov r1, #0x01 + orr r1, r1, r1, lsl #16 + str r1, [r0] + + ldr r0, =0x1e78a044 + ldr r1, =0x77776704 + str r1, [r0] + + mov r1, #0x0 + ldr r0, =0x1e78a048 + str r1, [r0] + ldr r0, =0x1e78a04c + str r1, [r0] + + ldr r0, =0x1e78a050 + ldr r1, =0xFFFFFFFF + str r1, [r0] + + ldr r0, =0x1e78a200 @ Set AST1150 I2C password + ldr r1, =0x00A88FA8 + str r1, [r0] + + ldr r0, =0x1e78a05c + ldr r1, =0x00000200 @ Enable buffer mode transfering 3 bytes + str r1, [r0] + + ldr r0, =0x1e78a054 + ldr r1, =0x00000063 @ Fire commmand + str r1, [r0] + + ldr r0, =0x1e78a050 +i2c_wait_cmddone_1: + ldr r1, [r0] + tst r1, #0x38 + beq i2c_wait_cmddone_1 + tst r1, #0x2A @ transmit error + bne platform_exit2 + ldr r1, =0xFFFFFFFF + str r1, [r0] + + ldr r0, =0x1e78a200 @ Disable ASPM capability + ldr r1, =0x04005DA8 + str r1, [r0] + + ldr r0, =0x1e78a204 + ldr r1, =0x00000024 + str r1, [r0] + + ldr r0, =0x1e78a05c + ldr r1, =0x00000200 @ Enable buffer mode transfering 3 bytes + str r1, [r0] + + ldr r0, =0x1e78a054 + ldr r1, =0x00000063 @ Fire commmand + str r1, [r0] + + ldr r0, =0x1e78a050 +i2c_wait_cmddone_2: + ldr r1, [r0] + tst r1, #0x38 + beq i2c_wait_cmddone_2 + tst r1, #0x2A @ transmit error + bne platform_exit2 + ldr r1, =0xFFFFFFFF + str r1, [r0] + +platform_exit2: + ldr r0, =0x1e78a040 @ Disable I2C1 controller + mov r1, #0x00 + str r1, [r0] + + b platform_exit +.LTORG + +platform_exit: +#ifdef CONFIG_DRAM_ECC + ldr r0, =0x1e6e0004 + ldr r1, [r0] + orr r1, r1, #0x80 + str r1, [r0] + + ldr r0, =0x1e6e0054 + ldr r1, =0x05000000 /* ECC protected memory size, default set at 80M */ + str r1, [r0] + + ldr r0, =0x1e6e007C + ldr r1, =0x00000000 + str r1, [r0] + ldr r0, =0x1e6e0074 + str r1, [r0] + + ldr r0, =0x1e6e0070 + ldr r1, =0x00000221 + str r1, [r0] + + ldr r0, =0x1e6e0070 + ldr r2, =0x00001000 +ECC_Init_Flag: + ldr r1, [r0] + tst r1, r2 @ D[12] = 1, Done + beq ECC_Init_Flag + + ldr r0, =0x1e6e0070 + ldr r1, =0x00000000 + str r1, [r0] + + ldr r0, =0x1e6e0050 + ldr r1, =0x80000000 + str r1, [r0] + + ldr r0, =0x1e6e0050 + ldr r1, =0x00000000 + str r1, [r0] + + ldr r0, =0x1e6e0070 + ldr r1, =0x00000400 + str r1, [r0] +#endif + ldr r0, =0x1e6e2008 @ Set Video ECLK phase + ldr r1, [r0] + ldr r2, =0xfffffff3 + and r1, r1, r2 + orr r1, r1, #0x08 + str r1, [r0] + + ldr r0, =0x1e6e2004 + ldr r1, [r0] + ldr r2, =0xFFBFFFFF @ Enable JTAG Master, solve ARM stucked by JTAG issue + and r1, r1, r2 + str r1, [r0] + + ldr r0, =0x1e6e2048 @ Set MAC interface delay timing + ldr r1, =0x2255 + str r1, [r0] + + ldr r0, =0x1e6e2070 @ Set MAC AHB bus clock + ldr r1, [r0] + mov r2, #0x04 @ Default RMII, set MHCLK = HPLL/10 + tst r1, #0xC0 + movne r2, #0x02 @ if RGMII, set MHCLK = HPLL/6 + ldr r0, =0x1e6e2008 + ldr r1, [r0] + bic r1, r1, #0x00070000 + orr r1, r1, r2, lsl #16 + str r1, [r0] + +/* Test - DRAM initial time */ + ldr r0, =0x1e782040 + ldr r1, [r0] + ldr r0, =0xFFFFFFFF + sub r1, r0, r1 + ldr r0, =0x1e72009c + str r1, [r0] + ldr r0, =0x1e7200a4 + str r1, [r0] + ldr r0, =0x1e782030 + ldr r1, [r0] + bic r1, r1, #0x0000F000 + str r1, [r0] +/* Test - DRAM initial time */ + +/****************************************************************************** + Reset GPIO registers when watchdog reset + ******************************************************************************/ + ldr r0, =0x1e6e207c @ Check Revision ID + ldr r1, [r0] + mov r1, r1, lsr #24 + cmp r1, #0x02 + bne platform_exit3 @ not match AST2400 + + ldr r0, =0x1e6e203c @ Check watchdog reset event + ldr r1, [r0] + and r1, r1, #0x06 + cmp r1, #0x0 + beq platform_exit3 @ no watchdog reset event + + ldr r0, =0x1e6e209c @ Check watchdog GPIO selection + ldr r1, [r0] + mov r1, r1, lsr #21 + tst r1, #0x01 + beq platform_exit3 @ no watchdog reset selection + + ldr r1, =0x00000000 @ clear GPIO register reset by PRST_N + ldr r2, =0xFFFFFFFF + ldr r0, =0x1e780008 + str r1, [r0] + ldr r0, =0x1e78000c + str r1, [r0] + ldr r0, =0x1e780010 + str r1, [r0] + ldr r0, =0x1e780014 + str r1, [r0] + ldr r0, =0x1e780018 + str r2, [r0] + ldr r0, =0x1e780028 + str r1, [r0] + ldr r0, =0x1e78002c + str r1, [r0] + ldr r0, =0x1e780030 + str r1, [r0] + ldr r0, =0x1e780034 + str r1, [r0] + ldr r0, =0x1e780038 + str r2, [r0] + ldr r0, =0x1e780040 + str r1, [r0] + ldr r0, =0x1e780044 + str r1, [r0] + ldr r0, =0x1e780048 + str r1, [r0] + ldr r0, =0x1e78004c + str r1, [r0] + ldr r0, =0x1e780050 + str r1, [r0] + ldr r0, =0x1e780054 + str r1, [r0] + ldr r0, =0x1e780058 + str r1, [r0] + ldr r0, =0x1e780060 + str r1, [r0] + ldr r0, =0x1e780064 + str r1, [r0] + ldr r0, =0x1e780068 + str r1, [r0] + ldr r0, =0x1e78006c + str r1, [r0] + ldr r0, =0x1e780090 + str r1, [r0] + ldr r0, =0x1e780094 + str r1, [r0] + ldr r0, =0x1e780098 + str r1, [r0] + ldr r0, =0x1e78009c + str r1, [r0] + ldr r0, =0x1e7800a0 + str r1, [r0] + ldr r0, =0x1e7800a4 + str r1, [r0] + ldr r0, =0x1e7800a8 + str r2, [r0] + ldr r0, =0x1e7800b0 + str r1, [r0] + ldr r0, =0x1e7800b4 + str r1, [r0] + ldr r0, =0x1e7800b8 + str r1, [r0] + ldr r0, =0x1e7800e0 + str r1, [r0] + ldr r0, =0x1e7800e4 + str r1, [r0] + ldr r0, =0x1e7800e8 + str r1, [r0] + ldr r0, =0x1e7800ec + str r1, [r0] + ldr r0, =0x1e7800f0 + str r1, [r0] + ldr r0, =0x1e7800f4 + str r1, [r0] + ldr r0, =0x1e7800f8 + str r2, [r0] + ldr r0, =0x1e780100 + str r1, [r0] + ldr r0, =0x1e780104 + str r1, [r0] + ldr r0, =0x1e780108 + str r1, [r0] + ldr r0, =0x1e780110 + str r1, [r0] + ldr r0, =0x1e780114 + str r1, [r0] + ldr r0, =0x1e780118 + str r1, [r0] + ldr r0, =0x1e78011c + str r1, [r0] + ldr r0, =0x1e780120 + str r1, [r0] + ldr r0, =0x1e780124 + str r1, [r0] + ldr r0, =0x1e780128 + str r2, [r0] + ldr r0, =0x1e780130 + str r1, [r0] + ldr r0, =0x1e780134 + str r1, [r0] + ldr r0, =0x1e780138 + str r1, [r0] + ldr r0, =0x1e780140 + str r1, [r0] + ldr r0, =0x1e780144 + str r1, [r0] + ldr r0, =0x1e780148 + str r1, [r0] + ldr r0, =0x1e78014c + str r1, [r0] + ldr r0, =0x1e780150 + str r1, [r0] + ldr r0, =0x1e780154 + str r1, [r0] + ldr r0, =0x1e780158 + str r2, [r0] + ldr r0, =0x1e780160 + str r1, [r0] + ldr r0, =0x1e780164 + str r1, [r0] + ldr r0, =0x1e780168 + str r1, [r0] + ldr r0, =0x1e780170 + str r1, [r0] + ldr r0, =0x1e780174 + str r1, [r0] + ldr r0, =0x1e780178 + str r1, [r0] + ldr r0, =0x1e78017c + str r1, [r0] + ldr r0, =0x1e780180 + str r1, [r0] + ldr r0, =0x1e780184 + str r1, [r0] + ldr r0, =0x1e780188 + str r2, [r0] + ldr r0, =0x1e780190 + str r1, [r0] + ldr r0, =0x1e780194 + str r1, [r0] + ldr r0, =0x1e780198 + str r1, [r0] + ldr r0, =0x1e7801d0 + str r1, [r0] + ldr r0, =0x1e7801d4 + str r1, [r0] + + ldr r0, =0x1e780204 @ clear SGPIOM register reset by PRST_N + str r1, [r0] + ldr r0, =0x1e780208 + str r1, [r0] + ldr r0, =0x1e78020c + str r1, [r0] + ldr r0, =0x1e780210 + str r1, [r0] + ldr r0, =0x1e780214 + str r2, [r0] + ldr r0, =0x1e780220 + str r1, [r0] + ldr r0, =0x1e780224 + str r1, [r0] + ldr r0, =0x1e780228 + str r1, [r0] + ldr r0, =0x1e78022c + str r1, [r0] + ldr r0, =0x1e780230 + str r2, [r0] + ldr r0, =0x1e78023c + str r1, [r0] + ldr r0, =0x1e780240 + str r1, [r0] + ldr r0, =0x1e780244 + str r1, [r0] + ldr r0, =0x1e780248 + str r1, [r0] + ldr r0, =0x1e78024c + str r2, [r0] + ldr r0, =0x1e780254 + ldr r3, =0x01000040 + str r3, [r0] + ldr r0, =0x1e780258 + str r1, [r0] + ldr r0, =0x1e78025c + str r1, [r0] + ldr r0, =0x1e780260 + str r1, [r0] + + ldr r0, =0x1e780300 @ clear SGPIOS register reset by PRST_N + str r1, [r0] + ldr r0, =0x1e780304 + str r1, [r0] + ldr r0, =0x1e780308 + str r1, [r0] + ldr r0, =0x1e78030c + str r1, [r0] + ldr r0, =0x1e780310 + str r1, [r0] + ldr r0, =0x1e780314 + str r1, [r0] + ldr r0, =0x1e780318 + str r2, [r0] + ldr r0, =0x1e78031c + str r2, [r0] + ldr r0, =0x1e780320 + str r2, [r0] + +platform_exit3: + +/****************************************************************************** + SPI Timing Calibration, not applicable to AST2300 series + ******************************************************************************/ + ldr r0, =0x1e6e207c @ Check Revision ID + ldr r1, [r0] + mov r1, r1, lsr #24 + cmp r1, #0x02 + blt platform_exit4 @ not match AST2400 or later + + ldr r0, =0x1e6e2070 @ Check SPI flash + ldr r1, [r0] + and r1, r1, #0x03 + cmp r1, #0x02 + bne platform_exit4 + + mov r2, #0x0 + mov r6, #0x0 + mov r7, #0x0 + init_spi_checksum +spi_checksum_wait_0: + ldr r1, [r0] + tst r1, r2 + beq spi_checksum_wait_0 + ldr r0, =0x1e620090 + ldr r5, [r0] @ record golden checksum + ldr r0, =0x1e620080 + mov r1, #0x0 + str r1, [r0] + + ldr r0, =0x1e620010 @ set to fast read mode + ldr r1, =0x000B0041 + str r1, [r0] + + ldr r6, =0x00F7E6D0 @ Init spiclk loop + mov r8, #0x0 @ Init delay record + +spi_cbr_next_clkrate: + mov r6, r6, lsr #0x4 + cmp r6, #0x0 + beq spi_cbr_end + + mov r7, #0x0 @ Init delay loop + mov r8, r8, lsl #4 + +spi_cbr_next_delay_s: + mov r2, #0x8 + init_spi_checksum +spi_checksum_wait_1: + ldr r1, [r0] + tst r1, r2 + beq spi_checksum_wait_1 + ldr r0, =0x1e620090 + ldr r2, [r0] @ read checksum + ldr r0, =0x1e620080 + mov r1, #0x0 + str r1, [r0] + cmp r2, r5 + bne spi_cbr_next_delay_e + + mov r2, #0x0 + init_spi_checksum +spi_checksum_wait_2: + ldr r1, [r0] + tst r1, r2 + beq spi_checksum_wait_2 + ldr r0, =0x1e620090 + ldr r2, [r0] @ read checksum + ldr r0, =0x1e620080 + mov r1, #0x0 + str r1, [r0] + cmp r2, r5 + bne spi_cbr_next_delay_e + + orr r8, r8, r7 @ record passed delay + b spi_cbr_next_clkrate + +spi_cbr_next_delay_e: + add r7, r7, #0x1 + cmp r7, #0x6 + blt spi_cbr_next_delay_s + b spi_cbr_next_clkrate + +spi_cbr_end: + ldr r0, =0x1e620094 + str r8, [r0] + ldr r0, =0x1e620010 + mov r1, #0x0 + str r1, [r0] + +platform_exit4: + + /* restore lr */ + mov lr, r4 + + /* back to arch calling code */ + mov pc, lr |