📄 setupmpmc.cmm
字号:
;****************************************************************************
;** SetupMPMC.CMM **
;** This script sets up MSM6100/MSM6300's SDRAM, per ARM's PL172 TRM **
;** See ARM DDI 0215A, page 6-60 "Low-power SDRAM **
;** Initialization Example" **
;** **
;** Changes: **
;** 05-28-02 First version **
;****************************************************************************
;
; BEWARE that this script has different behavior based on the value in &HCLK_RATE
; -- timing values are calculated on the fly, based off &HCLK_RATE
;EBI1_MPMC_STDY_SEL, configures static or dynamic memory on RAMCS2 and RAMCS3
; beforehand, enable chip select two to be SDRAM
d.out &EBI1_MPMC_STDY_SEL %LONG 0x1
; setup EBI1_CFG for clock invert on SDRAM clk (bit 9), Power mgmt functions, and
; hclk debug enable
; this register will have to be reset when clock runs faster than TCXO
d.out &EBI1_CFG %LONG 0x280
; ***** ARM TRM Step 1.
wait 100.ms
; this next step just to protect the rest of the system from behavior during configuration
; Control: Enable MPMC, no mirroring, not low power mode, drain write buffers = 8
d.out &MPMCControl %LONG 0x00000009
wait 10.ms // wait until write buffers are drained -- should check status instead of wait
; control: set normal memory map, after drain buffers done, enable MPMC.
d.out &MPMCControl %LONG 0x00000001
; Config: 1:1 HCLK-MPMCCLK ratio, little endian formats = 0
d.out &MPMCConfig %LONG 0x00000000
; Clear the Static memory config for the MPMC
d.out &MPMCStaticConfig0 %LONG 0x81
; Clear the Static memory config for the MPMC
d.out &MPMCStaticConfig1 %LONG 0x81
; Clear the Static memory config for the MPMC
d.out &MPMCStaticConfig2 %LONG 0x81
; Clear the Static memory config for the MPMC
d.out &MPMCStaticConfig3 %LONG 0x81
;
;
;
; Switch the Memory controller if it is not set to MPMC
;
;
local &MemCtrlrSwitch
&MemCtrlrSwitch=data.word(RD:&EBI1_MEM_CTLR_SEL_STATUS)
IF &MemCtrlrSwitch!=&EBI1_MEM_CTLR_SEL_STATUS_MPMC
(
Print " SetupMPMC: memory controller was XMEMC--setting to MPMC"
d.out &EBI1_MEM_CTLR_SEL_CMD 0x0
wait 1.ms
)
; DynamicControl: set clocks always clocking and enabled
d.out &MPMCDynamicControl %LONG 0x00000003
IF &TARGET_MAX_HCLK_RATE<&HCLK_RATE
(
PRINT "SetupMPMC:ERROR:HCLK &HCLK_RATE > target max-&TARGET_MAX_HCLK_RATE"
END
)
;;
;; Set up all the time contants for SDRAM
;; in the MPMC. BEWARE THAT ALL TIME CONSTANTS
;; ARE SCALED BY THE CLOCK PERIOD SHOWN BELOW
;;
;; Caveat: Many of these values are limited to 4 or 5-bits. Lauterbach gives no
;; functions to limit width. It is exceptionally unlikely that
;; these values will ever exceed the field width (only for super-fast
;; microprocessors and exceptionally slow SDRAMs), but beware.
;;
local &HCLK_PERIOD
&HCLK_PERIOD=1.0/&HCLK_RATE*&SECS_TO_NANOSECS
local &clkcycles
; DynamicRefresh: set refresh interval, to be the clock rate in MHz, rounded down
; See the ARM reference to convince yourself that this is right.
local &REFRESH_CYCLES
;&REFRESH_CYCLES=CONV.signedword(CONV.FLOATTOINT(&HCLK_RATE/1000000.0))
;PRINT " MPMCDynamicRefresh: &REFRESH_CYCLES for &HCLK_RATE clock"
d.out &MPMCDynamicRefresh %LONG 0x2
; tRP: Precharge Command period
; is n+1 HCLK cycles. Enter value in nanosecs from data sheet here
GOSUB calcClkCyclesExceedTime 20.0 MPMCDynamictRP
ENTRY &clkcycles
d.out &MPMCDynamictRP %LONG CONV.signedword(&clkcycles-1)
; tRAS: Active to Precharge Command period
; is n+1 HCLK cycles. Enter value in nanosecs from data sheet here
GOSUB calcClkCyclesExceedTime 50.0 MPMCDynamictRAS
ENTRY &clkcycles
d.out &MPMCDynamictRAS %LONG CONV.signedword(&clkcycles-1)
; tSREX: Self-refresh exit time
; is n+1 HCLK cycles. Enter value in nanosecs from data sheet here
GOSUB calcClkCyclesExceedTime 100.0 MPMCDynamictSREX
ENTRY &clkcycles
d.out &MPMCDynamictSREX %LONG CONV.signedword(&clkcycles-1)
; tAPR: last-data-out to active command time
; is n+1 HCLK cycles. Enter value in nanosecs from data sheet here
GOSUB calcClkCyclesExceedTime 100.0 MPMCDynamictAPR
ENTRY &clkcycles
d.out &MPMCDynamictAPR %LONG CONV.signedword(&clkcycles-1)
; tDAL: Data-in to active command time (or tAPW)
; is n+1 HCLK cycles. Enter value in nanosecs from data sheet here
;GOSUB calcClkCyclesExceedTime .0 MPMCDynamictDAL
;ENTRY &clkcycles
;d.out &MPMCDynamictDAL %LONG CONV.signedword(&clkcycles-1)
; setting per Raghu, due to ARM's bug. 052902
d.out &MPMCDynamictDAL %LONG 0x6
; tWR: Write recovery time (or tDPL or tRWL or tRDL)
; is n+1 HCLK cycles. Enter value in nanosecs from data sheet here
GOSUB calcClkCyclesExceedTime 59.0 MPMCDynamictWR
ENTRY &clkcycles
d.out &MPMCDynamictWR %LONG CONV.signedword(&clkcycles-1)
; tRC: Active to active command period
; is n+1 HCLK cycles. Enter value in nanosecs from data sheet here
GOSUB calcClkCyclesExceedTime 100.0 MPMCDynamictRC
ENTRY &clkcycles
d.out &MPMCDynamictRC %LONG CONV.signedword(&clkcycles-1)
; tRFC: Auto refresh period and auto refresh to active command period (or sometimes tRC)
; is n+1 HCLK cycles. Enter value in nanosecs from data sheet here
GOSUB calcClkCyclesExceedTime 100.0 MPMCDynamictRFC
ENTRY &clkcycles
d.out &MPMCDynamictRFC %LONG CONV.signedword(&clkcycles-1)
; tXSR: exit self-refresh to active command time
; is n+1 HCLK cycles. Enter value in nanosecs from data sheet here
GOSUB calcClkCyclesExceedTime 100.0 MPMCDynamictXSR
ENTRY &clkcycles
d.out &MPMCDynamictXSR %LONG CONV.signedword(&clkcycles-1)
; tRRD: Active bank A to active bank B latency
; is n+1 HCLK cycles. Enter value in nanosecs from data sheet here
GOSUB calcClkCyclesExceedTime 20.0 MPMCDynamictRRD
ENTRY &clkcycles
d.out &MPMCDynamictRRD %LONG CONV.signedword(&clkcycles-1)
; tMRD: load mode register to active command time (or tRSA)
; is n+1 HCLK cycles. Enter value in nanosecs from data sheet here
GOSUB calcClkCyclesExceedTime 50.0 MPMCDynamictMRD
ENTRY &clkcycles
d.out &MPMCDynamictMRD %LONG CONV.signedword(&clkcycles-1)
;
; at this point, time constants are setup in MPMC.
;
;
; now, get the MPMC operating and configure the SDRAM devices...
;
;
; DynamicControl: issue a nop to the MPMC
d.out &MPMCDynamicControl %LONG 0x00000183
wait 1.ms
; ***** ARM TRM Step 2.
; DynamicControl: issue a Precharge All to the MPMC
d.out &MPMCDynamicControl %LONG 0x00000103
; ***** ARM TRM Step 3.
; DynamicRefresh: set up the refresh and wait for 8 refresh cycles have occurred
; The value 2 is magically chosen by ARM
d.out &MPMCDynamicRefresh %LONG 0x00000002
; ***** ARM TRM Step 4.
; a little overkill here: the value of 10.ms is enough to delay 256 cycles at the 32khz sleep clock
; For TCXO, it only needs to be 20.us. I doubt anyone will mind the extra 9+ milliseconds of delay
wait 10.ms // wait more than 8 refresh cycles (16*above_value = 32) = 256 clock cycles
; ***** ARM TRM Step 5.
; DynamicRefresh: set refresh interval, to be the clock rate in MHz, rounded down
; ARM subtracts a margin of about 3% -- can't argue with this.
; See the ARM reference to convince yourself that this is right.
&REFRESH_CYCLES=(&HCLK_RATE/1000000.)*0.97
&REFRESH_CYCLES=CONV.signedword(CONV.FLOATTOINT(&REFRESH_CYCLES))
PRINT " MPMCDynamicRefresh: &REFRESH_CYCLES for &HCLK_RATE clock"
d.out &MPMCDynamicRefresh %LONG &REFRESH_CYCLES
; ***** ARM TRM Steps 6,7.
;
; set the RAS and CAS latencies (two clocks each == 0x202)
; then set the DynamicConfig register
; set 01 into bits 29:28 to specify a 12-bit row width
; Set bit 26 to indicate 4 banks/device
; Set 011 into bits 24:22 to specify a 9-bit col width
; set 01 into bits 4:3 to indicate LP-SDRAM memory device type
; the bits above equal 0x14C00008
local &DynamicConfigBaseVal
;&DynamicConfigBaseVal=0x14C00008
;FEATURE_SAMSUNG
&DynamicConfigBaseVal=0x24800008
; set bits 14, 12:7 to reflect address mapping for memory part:
; -- see each specific section below for the value
; beware, when SDRAM parts or sizes change, these have to change!
local &DynamicConfigRegVal
IF STRING.SCAN("&SDRAM_WIDTH","16-bit",0)>-1
(
; 128-Mbit LP-SDRAM, 8Mx16 gets bits 12, 10, 7 set
; these bits = 0x1480
; &DynamicConfigRegVal=&DynamicConfigBaseVal|0x1480
;FEATURE_SAMSUNG
; &DynamicConfigRegVal=&DynamicConfigBaseVal|0x1680
&DynamicConfigRegVal=&DynamicConfigBaseVal|0x5700
; d.out &MPMCDynamicRasCas0 %LONG 0x00000202
;FEATURE_SAMSUNG
d.out &MPMCDynamicRasCas0 %LONG 0x00000303
d.out &MPMCDynamicConfig0 %LONG &DynamicConfigRegVal
)
ELSE IF STRING.SCAN("&SDRAM_WIDTH","2x16-bit",0)>-1
(
; 256-Mbit LP-SDRAM, 2ea 8Mx16 = 8Mx32 gets bits 14, 12, 10, 9, 8 set
; these bits = 0x5700
&DynamicConfigRegVal=&DynamicConfigBaseVal|0x5700
d.out &MPMCDynamicRasCas0 %LONG 0x00000202
d.out &MPMCDynamicConfig0 %LONG &DynamicConfigRegVal
;Only using one chip select for SDRAMs (two devices in parallel, not in series)
; In case we ever use two SDRAMs in series, then start configuring RASCAS1 and DynConfig1.
;d.out &MPMCDynamicRasCas1 %LONG 0x00000202
;d.out &MPMCDynamicConfig1 %LONG &DynamicConfigRegVal
)
ELSE IF STRING.SCAN("&SDRAM_WIDTH","32-bit",0)>-1
(
PRINT "FATAL ERROR:32-bit SDRAM is not setup in SetupMPMC.cmm"
wait 5.s
END
d.out &MPMCDynamicRasCas0 %LONG 0x00000202
d.out &MPMCDynamicConfig0 %LONG &DynamicConfigRegVal
)
ELSE
(
PRINT "SetupMPMC: SDRAM_WIDTH invalid value (&SDRAM_WIDTH)"
STOP
)
; ***** ARM TRM Step 8.
; DynamicControl: put the MPMC into Mode setting state
d.out &MPMCDynamicControl %LONG 0x00000080
; ***** ARM TRM Step 9.
; load the Memory Parts' mode register
; Per the ARM TRM, this is a little confusing:
; We read from an SDRAM address: The read action programs the device,
; and the address read indicates the configuration.
; Per the ARM PL172 TRM,
; A[2:0] = burst length (8 for 16-bit wide bus, 4 for 32-bit wide)
; A[3] = 0 (sequential burst type)
; A[6:4] = 010 (CAS latency = 2 for our timing)
; A[11:7] = 00000 (Operating mode= standard operation)
; this yields a value of 0x23 for 16-bit. Then there is a confusing
; lookup for (16-bit, 128Mb, 8Mx16 SDRAM) on page 6-49 (equiv to 10-bit left shift)
; to get the value of 0x00008C00 as the address to read from.
;
; for our 32-bit SDRAM, 8Mx32 (two 8Mx16s), the values yield 0x22 for 32-bit.
; After lookup (euqal to shift 10 bits left), the value is 0x00008800
local &mode_reg_val
IF STRING.SCAN("&SDRAM_WIDTH","16-bit",0)>-1
(
; &mode_reg_val=0x08C00
;FEATURE_SAMSUNG
; &mode_reg_val=0x0CC00
&mode_reg_val=0x0C800
)
ELSE IF STRING.SCAN("&SDRAM_WIDTH","2x16-bit",0)>-1
(
&mode_reg_val=0x08800
)
ELSE IF STRING.SCAN("&SDRAM_WIDTH","32-bit",0)>-1
(
PRINT "SetupMPMC: 32-bit SDRAM not configured in SetupMPMC.cmm"
STOP
)
ELSE
(
PRINT "SetupMPMC: SDRAM_WIDTH invalid value (&SDRAM_WIDTH)"
STOP
)
; write at this address offset from bottom of the device.
&mode_reg_val=&mode_reg_val+&EBI1_SDRAM_BASE_ADDR
d.in &mode_reg_val
; ***** ARM TRM Step 10.
; load the Memory Parts' extended mode register
; this register sets partial-array self refresh and also the temp compensated self refresh
; these values are fixed as far as we are concerned for now.
;&mode_reg_val=0x00800000
;&mode_reg_val=&mode_reg_val+&EBI1_SDRAM_BASE_ADDR
;d.in &mode_reg_val
; ***** ARM TRM Step 11.
; DynamicControl: put the MPMC Control into Normal mode
d.out &MPMCDynamicControl %LONG 0x00000003
; ***** ARM TRM Step 12.
; enable buffers for the first chip select
&DynamicConfigRegVal=&DynamicConfigRegVal|0x00080000
d.out &MPMCDynamicConfig0 %LONG &DynamicConfigRegVal
PRINT " MPMCDynamicConfig0 set to &DynamicConfigRegVal"
; set the clocks to run continuously, enabled during all times
d.out &MPMCDynamicControl %LONG 0x00000003
ENDDO
;
;
;
;
; The following (calcClkCyclesExceedTime) is a
; function to calculate number of clock cycles to exceed time target,
; including to exceed the time plus the margin parameter
;
; uses global parameter &HCLK_PERIOD, &MEM_CTL_MARGIN_NS
; assumes LOG_WIN is opened and setup already
calcClkCyclesExceedTime:
ENTRY &time_ns ®_name
IF WINDOW.NAME("LOG_WIN")
(
WinTOP LOG_WIN
)
LOCAL &fraccycles
LOCAL &intcycles
LOCAL &leftover_ns
;print "in &time_ns marg &MEM_CTL_MARGIN_NS hclk &HCLK_PERIOD"
&fraccycles=((&time_ns+&MEM_CTL_MARGIN_NS)/&HCLK_PERIOD)
&intcycles=CONV.FLOATTOINT(&fraccycles)
&leftover_ns=(&intcycles*&HCLK_PERIOD)-&time_ns-&MEM_CTL_MARGIN_NS
IF &leftover_ns<0
(
&intcycles=&intcycles+1.
)
&leftover_ns=(&intcycles*&HCLK_PERIOD)-&time_ns
IF &leftover_ns<&MEM_CTL_MARGIN_NS
(
print "ERROR:CLOCK SETTINGS UNDER MARGIN"
)
&leftover_ns=CONV.FLOATTOINT(&leftover_ns)
PRINT " ®_name:&time_ns ns = &intcycles clks + &leftover_ns ns margin"
RETURN &intcycles
⌨️ 快捷键说明
复制代码
Ctrl + C
搜索代码
Ctrl + F
全屏模式
F11
切换主题
Ctrl + Shift + D
显示快捷键
?
增大字号
Ctrl + =
减小字号
Ctrl + -