⭐ 欢迎来到虫虫下载站! | 📦 资源下载 📁 资源专辑 ℹ️ 关于我们
⭐ 虫虫下载站

📄 setupmpmc.cmm

📁 QUALCOMM JNAND DRIVER
💻 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 &reg_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 "   &reg_name:&time_ns ns = &intcycles clks + &leftover_ns ns margin"
    RETURN &intcycles                                 



⌨️ 快捷键说明

复制代码 Ctrl + C
搜索代码 Ctrl + F
全屏模式 F11
切换主题 Ctrl + Shift + D
显示快捷键 ?
增大字号 Ctrl + =
减小字号 Ctrl + -