📄 sbmemc.s
字号:
li a1,MEMC_CONTROL_INIT7 sw a1,MEMC_CONTROL(a0) /* Wait for SDRAM controller to refresh. * We want 8uS delay. (Assumes >= 160ns per iteration) */ li t8,501: lw a1,R_SBIDLOW(a0) lw a1,R_SBIDHIGH(a0) bnez t8,1b subu t8,1 jr t7 nop/* * Routines for initializing SDR SDRAM */ memc_sdr_init: beqz t3,sdr_find_ncdl # Do we have ncdl values? nop li t4,-1 bne t3,t4,break_sdr_ncdl nopsdr_find_ncdl:/* Register usage */#define pass_count s0#define clkdsum s1#define pass_countmax s2#define strmmax s3#define strdmax s4#define clkdmax s5#define clkdlim s6#define strm t2#define strd t3#define clkd t4#define STRMLIM 4#define STRDLIM 16#define CLKDLIM 128#define CLKDLIM_IC 256 /* Initialize counter & saved values */ move pass_countmax,zero move strmmax,zero move strdmax,zero li clkdlim,CLKDLIM and strm,t0,0x2000 # Test for internal clock (Using strm as a temp) beqz strm,strmloop nop li clkdlim,CLKDLIM_IC move strm,zero # strm loopstrmloop: move strd,zerostrdloop: move pass_count,zero move clkdsum,zero move clkd,zero /* Inner loop: call sdr_do_init to re-initialize and the test mem */clkdloop: bal sdr_do_init nop bal test_mem nop beqz v0,failclkd nop /* Memory is ok */ addi pass_count,1 add clkdsum,clkdsum,clkd b nextclkd nopfailclkd: bnez pass_count,clkdout # End of passing range, leave clkd loop nopnextclkd: addi clkd,clkd,1 blt clkd,clkdlim,clkdloop nopclkdout: /* If no passing values, skip to next strm */ beqz pass_count,nextstrm nop /* If this is a new max, Save the values */ ble pass_count,pass_countmax,nextstrd nop move pass_countmax,pass_count div zero,clkdsum,pass_count mflo clkdmax move strdmax,strd move strmmax,strmnextstrd: addi strd,strd,1 blt strd,STRDLIM,strdloop nopnextstrm: addi strm,strm,1 blt strm,STRMLIM,strmloop nop /* All done, program the new ncdl values */ beqz pass_countmax,1f nop move clkd,clkdmax move strd,strdmax move strm,strmmax b sdr_got_ncdl nop /* No passing values, panic! (use defaults) */1:#ifdef MEMSDR li t3,MEMC_SDR_NCDL # If rev0, 2: bne v1,1,2f nop li t3,MEMC_SDR1_NCDL # rev1:#else li t3,MEMC_DDR_NCDL # If rev0, 2: bne v1,1,2f nop li t3,MEMC_DDR1_NCDL # rev1:#endif2:break_sdr_ncdl: andi t4,t3,0xff # t4: cd srl t2,t3,16 # t2: sm andi t2,t2,3 # sm is 2 bits only srl t3,t3,8 # t3: sd andi t3,t3,0xf # sd is 4 bitssdr_got_ncdl: bal sdr_do_init nop b szmem nop /* Do an init of the memc core for sdr * a0: memc core pointer * t0: memc config value * t1: memc mode value * t2: memc strobe mode ncdl value * t3: memc strobe delay ncdl value * t4: memc clock delay ncdl value * * Uses a1, t7, t8, t9 (here and by calling sb_core_reset) */sdr_do_init: /* Save return address */ move t7,ra bal sb_core_reset li a1,0x40 /* Initialize SDRAM */ li a1,MEMC_SD_CONFIG_INIT or a1,a1,t0 sw a1,MEMC_CONFIG(a0) li a1,MEMC_SD_DRAMTIM3_INIT # Assume CAS latency of 3 andi t8,t1,0xf0 # Find out the CAS latency bne t8,0x20,1f nop li a1,MEMC_SD_DRAMTIM2_INIT # CAS latency is 21: sw a1,MEMC_DRAMTIM(a0) andi t8,t4,0xff ble t8,MEMC_CD_THRESHOLD,1f # if (cd <= 128) rd = cd nop li t8,MEMC_CD_THRESHOLD # else rd = 1281: # t8 is now rd sll a1,t8,8 # .. replicate it 4 times or a1,a1,t8 sll t8,a1,16 or t8,t8,a1 li a1,MEMC_SD_RDNCDLCOR_INIT or a1,a1,t8 sw a1,MEMC_RDNCDLCOR(a0) li a1,MEMC_SD1_WRNCDLCOR_INIT # rev1 beq v1,1,1f nop li a1,MEMC_SD_WRNCDLCOR_INIT # rev0, 21: li t8,0 ble t4,MEMC_CD_THRESHOLD,2f # if (cd <= 128) wr = 0 nop andi t8,t4,0xff # else wr = cd - 128 sub t8,t8,MEMC_CD_THRESHOLD andi t8,t8,0xff2: # t8 is now wr, a0 is extra bits or a1,a1,t8 sw a1,MEMC_WRNCDLCOR(a0) andi t8,t2,3 sll a1,t8,28 andi t8,t3,0xf sll t8,t8,24 or t8,t8,a1 li a1,MEMC_SD_MISCDLYCTL_INIT bne v1,1,3f # If rev0, 2: nop li a1,MEMC_SD1_MISCDLYCTL_INIT # rev1:3: or a1,a1,t8 sw a1,MEMC_MISCDLYCTL(a0) li a1,MEMC_SD_CONTROL_INIT0 sw a1,MEMC_CONTROL(a0) li a1,MEMC_SD_CONTROL_INIT1 sw a1,MEMC_CONTROL(a0) li a1,MEMC_SD_CONTROL_INIT2 sw a1,MEMC_CONTROL(a0) lw a1,MEMC_CONTROL(a0) lw a1,MEMC_CONTROL(a0) lw a1,MEMC_CONTROL(a0) li a1,MEMC_SD_CONTROL_INIT2 sw a1,MEMC_CONTROL(a0) lw a1,MEMC_CONTROL(a0) lw a1,MEMC_CONTROL(a0) lw a1,MEMC_CONTROL(a0) li a1,MEMC_SD_CONTROL_INIT2 sw a1,MEMC_CONTROL(a0) lw a1,MEMC_CONTROL(a0) lw a1,MEMC_CONTROL(a0) lw a1,MEMC_CONTROL(a0) li a1,MEMC_SD_REFRESH_INIT sw a1,MEMC_REFRESH(a0) li a1,MEMC_SD_MODEBUF_INIT or a1,a1,t1 sw a1,MEMC_MODEBUF(a0) li a1,MEMC_SD_CONTROL_INIT3 sw a1,MEMC_CONTROL(a0) li a1,MEMC_SD_CONTROL_INIT4 sw a1,MEMC_CONTROL(a0) li t8,501: lw a1,R_SBIDLOW(a0) lw a1,R_SBIDHIGH(a0) bnez t8,1b subu t8,1 jr t7 nop/* * Common exit code and subroutines shared by SDR and DDR initialization. */ /* Determine memory size and return * * Somewhat simplistic, assumes size is a power of 2 and looks * for aliases of location 0. */szmem: li t0,PHYS_TO_K1(0) li t2,0xaa55beef sw t2,0(t0) li v0,4 /* Assume minimum of 4MB */1: sll t0,v0,20 or t0,PHYS_TO_K1(0) lw t1,0(t0) beq t1,t2,done nop sll v0,v0,1 bne v0,128,1b /* Fully populated at 128MB, no alias */ nopdone: jr t6 nop /* * Test memory * * Uses arg in t2(wr/sd), t3(rd/sm) and t4(g/clkd) * Returns success (1) or failure (0) in v0 * Uses a1, a2, a3 & t5 */test_mem: /* Use t4 to generate a semi-random address in the second KB */ li a1,0xa0000000 addi a2,t4,255 sll a2,a2,2 add a1,a1,a2 /* First set: 0 & its negation */ li a2,0 sw a2,0(a1) not a3,a2 sw a3,4(a1) nop lw t5,0(a1) bne a2,t5,bad_mem nop lw t5,4(a1) bne a3,t5,bad_mem nop /* Second set: 0xaaaaaaaa & its negation */ li a2,0xaaaaaaaa sw a2,0(a1) not a3,a2 sw a3,4(a1) nop lw t5,0(a1) bne a2,t5,bad_mem nop lw t5,4(a1) bne a3,t5,bad_mem nop /* Third set: 0x12345678 & its negation */ li a2,0x12345678 sw a2,0(a1) not a3,a2 sw a3,4(a1) nop lw t5,0(a1) bne a2,t5,bad_mem nop lw t5,4(a1) bne a3,t5,bad_mem nop /* Fourth set: the ncdl & its negation */ sll a2,t2,8 or a2,t3 sll a2,a2,8 or a2,t4 sw a2,0(a1) not a3,a2 sw a3,4(a1) nop lw t5,0(a1) bne a2,t5,bad_mem nop lw t5,4(a1) bne a3,t5,bad_mem nop /* Fifth set: the CPU count register & its negation */ mfc0 a2,$9 sw a2,0(a1) not a3,a2 sw a3,4(a1) nop lw t5,0(a1) bne a2,t5,bad_mem nop lw t5,4(a1) bne a3,t5,bad_mem nop jr ra li v0,1bad_mem: jr ra li v0,0 /* Special sb_core_reset that makes sure the first time * clock is enabled, address line 6 is in the state specified * by a1. * * a0: Core pointer * a1: 0x40 if a6 needs to be 1, 0 otherwise * uses t8, t9 */ .align 6sb_core_reset: /* Save return address */ move t9,ra /* run uncached */ bal kseg1_switch nop /* Figure out our address */ bal h0 noph0: add t8,ra,24 # This is (h1 - h0) andi t8,t8,0x40 bne t8,a1,alt_core_reset nop /* Set reset while enabling the clock */ li t8,(M_SBTS_FC | M_SBTS_CE | M_SBTS_RS) # 2 instructionsh1: sw t8,R_SBTMSTATELOW(a0) b cont nop /* Now pad to 0x40: We want (h2 - h1) == 0x40 and there * are 5 instructions in between them. */ .space (0x40 - 20)alt_core_reset: /* Set reset while enabling the clock */ li t8,(M_SBTS_FC | M_SBTS_CE | M_SBTS_RS) # 2 instructionsh2: sw t8,R_SBTMSTATELOW(a0)cont: /* Read back and delay */ lw t8, R_SBTMSTATELOW(a0) lw t8, R_SBTMSTATELOW(a0) lw t8, R_SBTMSTATELOW(a0) /* Clear reset */ li t8, (M_SBTS_FC | M_SBTS_CE) sw t8, R_SBTMSTATELOW(a0) /* Read back and delay */ lw t8, R_SBTMSTATELOW(a0) lw t8, R_SBTMSTATELOW(a0) lw t8, R_SBTMSTATELOW(a0) /* Leave clock enabled */ li t8, M_SBTS_CE sw t8, R_SBTMSTATELOW(a0) /* Read back and delay */ lw t8, R_SBTMSTATELOW(a0) lw t8, R_SBTMSTATELOW(a0) lw t8, R_SBTMSTATELOW(a0) jr t9 nop kseg1_switch: and ra, ra, 0x1fffffff or ra, ra, PHYS_TO_K1(0) jr ra nop .set reorder END(board_draminit)
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -