1 /******************************************************************************
\r
2 ** File Name: sdram_sc7710g2.c
\r
5 ** Copyright: 2013 Spreatrum, Incoporated. All Rights Reserved.
\r
7 ******************************************************************************/
\r
8 /******************************************************************************
\r
10 **-------------------------------------------------------------------------
\r
11 ** DATE NAME DESCRIPTION
\r
12 ** 11/03/2013 Create.
\r
13 ******************************************************************************/
\r
15 #include <asm/arch/sci_types.h>
\r
16 #include <asm/arch/arm_reg.h>
\r
17 #include <asm/arch/sc_reg.h>
\r
18 #include <asm/arch/sdram_sc7710g2.h>
\r
19 #include <asm/arch/emc_config.h>
\r
20 #include "asm/arch/chip_plf_export.h"
\r
21 #include <asm/arch/adi_hal_internal.h>
\r
22 #include <asm/arch/mfp.h>
\r
30 /*----------------------------------------------------------------------------*
\r
32 **----------------------------------------------------------------------------*/
\r
37 //uint32 SDRAM_BASE = 0x00000000;//(128*1024*1024/2)//0x30000000
\r
39 #define MEM_REF_DATA0 0x12345678
\r
40 #define SDRAM_BASE_ADDR 0x00000000UL
\r
42 #define DMC_SOFT_RST BIT_11
\r
44 LOCAL BOOLEAN s_emc_dll_open = FALSE;
\r
45 LOCAL EMC_PARAM_T s_emc_config = {0};
\r
47 LOCAL void DMC_Init(void);
\r
49 /**---------------------------------------------------------------------------*
\r
50 ** Static Function Prototypes *
\r
51 **---------------------------------------------------------------------------*/
\r
53 LOCAL void delay(uint32 k)
\r
55 volatile uint32 i, j;
\r
59 // for (j=0; j<1000; j++);
\r
65 LOCAL void EMC_AddrMode_Set(SDRAM_CFG_INFO_T_PTR mem_info)
\r
69 reg_val = REG32(EXT_MEM_DCFG0);
\r
70 reg_val &= ~((DATA_WIDTH_MASK<<8) | (COL_MODE_MASK<<4) | ROW_MODE_MASK);
\r
71 reg_val |= (((mem_info->data_width & DATA_WIDTH_MASK)<< 8)
\r
72 | ((mem_info->col_mode & COL_MODE_MASK) << 4)
\r
73 | (mem_info->row_mode & ROW_MODE_MASK));
\r
75 REG32(EXT_MEM_DCFG0) = reg_val;
\r
79 LOCAL void EMC_SoftReset(void)
\r
81 REG32(AHB_SOFT_RST) |= DMC_SOFT_RST;
\r
83 REG32(AHB_SOFT_RST) &= (~DMC_SOFT_RST);
\r
87 #ifndef SDRAM_AUTODETECT_SUPPORT
\r
89 PUBLIC uint32 SDRAM_GetCap(void) // capability in bytes
\r
93 SDRAM_CHIP_FEATURE_T_PTR mem_feature = SDRAM_GetFeature();
\r
95 SDRAM_Cap = mem_feature->cap;
\r
101 PUBLIC EMC_PHY_L1_TIMING_T_PTR EMC_GetPHYL1_Timing(DMEM_TYPE_E mem_type, uint32 cas_latency)
\r
103 #ifdef SDR_SDRAM_SUPPORT
\r
104 if (SDR_SDRAM == mem_type)
\r
106 if (CAS_LATENCY_2 == cas_latency)
\r
108 return (EMC_PHY_L1_TIMING_T_PTR)(&(EMC_PHY_TIMING_L1_INFO[EMC_PHYL1_TIMING_SDRAM_LATENCY2]));
\r
112 return (EMC_PHY_L1_TIMING_T_PTR)(&(EMC_PHY_TIMING_L1_INFO[EMC_PHYL1_TIMING_SDRAM_LATENCY3]));
\r
118 if (CAS_LATENCY_2 == cas_latency)
\r
120 return (EMC_PHY_L1_TIMING_T_PTR)(&(EMC_PHY_TIMING_L1_INFO[EMC_PHYL1_TIMING_DDRAM_LATENCY2]));
\r
124 return (EMC_PHY_L1_TIMING_T_PTR)(&(EMC_PHY_TIMING_L1_INFO[EMC_PHYL1_TIMING_DDRAM_LATENCY3]));
\r
129 PUBLIC EMC_PHY_L2_TIMING_T_PTR EMC_GetPHYL2_Timing(void)
\r
131 if (s_emc_dll_open)
\r
133 return (EMC_PHY_L2_TIMING_T_PTR)(&(EMC_PHY_TIMING_L2_INFO[EMC_PHYL2_TIMING_DLL_ON]));
\r
137 return (EMC_PHY_L2_TIMING_T_PTR)(&(EMC_PHY_TIMING_L2_INFO[EMC_PHYL2_TIMING_DLL_OFF]));
\r
142 /*****************************************************************************/
\r
143 // Description: EMC basic mode set function
\r
144 // set the base mode like:
\r
145 // EMC device endian
\r
146 // EMC auto gate en for power saving
\r
147 // EMC auto sleep en
\r
148 // EMC cmd queue mode
\r
149 // Global resource dependence: NONE
\r
150 // Related register: EMC_CFG0
\r
151 // Author: Johnny.Wang
\r
152 // Note: The default cs map space is 4g, if dram capability is larger than 4g,
\r
153 // emc_cs_map parameter must adjust.
\r
154 /*****************************************************************************/
\r
155 LOCAL void EMC_Base_Mode_Set(SDRAM_CFG_INFO_T_PTR mem_info)
\r
158 EMC_CS_MAP_E cs_position;
\r
160 cs_position = mem_info->cs_position;
\r
162 i = REG32(EXT_MEM_CFG0);
\r
164 i |=(EMC_DVC_ENDIAN_DEFAULT <<12) |
\r
165 (EMC_AUTO_GATE_EN <<11) |
\r
166 (EMC_AUTO_SLEEP_EN <<10) |
\r
167 (EMC_2DB_1CB <<6) |
\r
168 (EMC_CS_MODE_DEFAULT <<3) |
\r
169 (cs_position <<0) ;
\r
171 REG32(EXT_MEM_CFG0) = i;
\r
174 /*****************************************************************************/
\r
175 // Description: EMC each cs work mode set function
\r
176 // set each cs work mode parameter like:
\r
177 // memory write burst length
\r
178 // memory read burst length
\r
179 // memory write burst mode:wrap/increase
\r
180 // memory read burst mode:wrap/increase
\r
181 // AHB write busrt divided to single/busrt access
\r
182 // AHB read busrt divided to single/busrt access
\r
183 // Global resource dependence: memory burst length type
\r
184 // Related register: EMC_CFG0_CSx
\r
185 // Author: Johnny.Wang
\r
186 // Note: There are two cs pin in sc8810 emc, we usuall use cs0 to control external memory
\r
188 /*****************************************************************************/
\r
189 PUBLIC void EMC_CSx_Burst_Set(EMC_CS_NUM_E emc_cs_num, SDRAM_CFG_INFO_T_PTR mem_info)
\r
192 uint32 emc_cs_cfg = EXT_MEM_CFG0_CS0 + emc_cs_num*4;
\r
193 uint32 burst_len = 0;
\r
195 if (DDR_SDRAM == mem_info ->sdram_type)
\r
197 if (DATA_WIDTH_16 == mem_info ->data_width)
\r
199 burst_len = mem_info->burst_length -1;
\r
203 burst_len = mem_info->burst_length;
\r
206 #ifdef SDR_SDRAM_SUPPORT
\r
207 else if (SDR_SDRAM == mem_info ->sdram_type)
\r
213 i = REG32(emc_cs_cfg);
\r
214 i &= ~((0x7<<8)|(0x7<<4)|(1<<1)|1);
\r
215 i |=((burst_len <<8) | //write burst length
\r
216 (burst_len <<4) | //read burst length
\r
217 (HBURST_TO_BURST <<1) | //write hburst invert to mem burst
\r
218 (HBURST_TO_BURST <<0)); //rrite hburst invert to mem burst
\r
220 REG32(emc_cs_cfg) = i;
\r
223 /*****************************************************************************/
\r
224 // Description: EMC AXI channel set function
\r
225 // set each axi channel parameter like:
\r
227 // axi channel auto sleep en
\r
228 // channel endian switch
\r
229 // channel priority
\r
230 // Global resource dependence: NONE
\r
231 // Related register: EMC_CFG0_ACHx
\r
233 // Author: Johnny.Wang
\r
234 // Note: There are two axi channel in sc8810 emc, one for A5,the other for GPU
\r
236 /*****************************************************************************/
\r
237 LOCAL void EMC_AXI_CHL_Set(EMC_CHL_NUM_E emc_axi_num,
\r
238 EMC_CHL_PRI_E chl_wr_pri,
\r
239 EMC_CHL_PRI_E chl_rd_pri
\r
243 uint32 emc_axi_cfg0 = EXT_MEM_CFG0_CH0_BASE+ emc_axi_num*8;
\r
244 uint32 emc_axi_cfg1 = EXT_MEM_CFG1_CH0_BASE+ emc_axi_num*8;
\r
246 i = REG32(emc_axi_cfg0);
\r
247 i &= (~(ACH_RF_ENDIAN_SWT_CHX | ACH_CHL_PRI_WR_MASK));
\r
249 // i |= ACH_RF_AUTO_SLEEP_EN_CHX | ACH_RF_CH_EN_CHX | (EMC_ENDIAN_SWITCH_NONE<<4);
\r
250 i |= ACH_RF_CH_EN_CHX | (EMC_ENDIAN_SWITCH_NONE<<4);
\r
252 i |= (ACH_CHL_PRI_WR(chl_wr_pri));
\r
254 REG32(emc_axi_cfg0) = i;
\r
256 i = REG32(emc_axi_cfg1);
\r
257 i &= (~(ACH_RF_SYNC_SEL_CHX | ACH_CHL_PRI_RD_MASK)); // async
\r
258 i |= (EMC_CLK_ASYNC<<4); //emc clk async with axi clk
\r
259 i |= (ACH_RF_BRESP_MODE_CH); //axi channel response mode 0:at once 1:delay several clk
\r
260 i |= ACH_CHL_PRI_RD(chl_rd_pri);
\r
262 REG32(emc_axi_cfg1) = i;
\r
265 /*****************************************************************************/
\r
266 // Description: EMC AHB channel set function
\r
267 // Global resource dependence: NONE
\r
268 // Author: Johnny.Wang
\r
269 // Note: There are 7 ahb channel in sc8810 emc, but no one is relate with ARM,
\r
270 // so don't used temporarily
\r
272 /*****************************************************************************/
\r
273 LOCAL void EMC_AHB_CHL_Set(EMC_CHL_NUM_E emc_ahb_num,uint32 addr_offset, EMC_CHL_PRI_E chl_pri)
\r
275 uint32 emc_ahb_cfg0 = EXT_MEM_CFG0_CH0_BASE + emc_ahb_num*8;
\r
276 uint32 emc_ahb_cfg1 = EXT_MEM_CFG1_CH0_BASE + emc_ahb_num*8;
\r
278 REG32(emc_ahb_cfg1) &= (~HCH_CHL_PRI_MASK);
\r
280 // REG32(emc_ahb_cfg0) |= (HCH_RF_AUTO_SLEEP_EN_CHX | HCH_CHL_PRI(chl_pri));
\r
281 REG32(emc_ahb_cfg0) |= HCH_CHL_PRI(chl_pri);
\r
283 REG32(emc_ahb_cfg1) &= ~0x03ff0000; //clear bit16~25
\r
284 REG32(emc_ahb_cfg1) |= (addr_offset & 0x03ff) << 16;
\r
287 /*****************************************************************************/
\r
288 // Description: EMC Memroy all timing parameter set function
\r
289 // set all timing parameter of EMC when operate external memory like:
\r
301 // Global resource dependence: NONE
\r
302 // Author: Johnny.Wang
\r
303 // Related register: EMC_DCFG1
\r
307 /*****************************************************************************/
\r
308 LOCAL void EMC_MEM_Timing_Set(uint32 emc_freq,
\r
309 SDRAM_CFG_INFO_T_PTR mem_info,
\r
310 SDRAM_TIMING_PARA_T_PTR mem_timing)
\r
312 #if 1 // low code size
\r
315 case EMC_CLK_26MHZ:
\r
316 REG32(EXT_MEM_DCFG1) = 0x13311211;
\r
317 REG32(EXT_MEM_DCFG2) = 0x02020322;
\r
319 case EMC_CLK_67MHZ:
\r
320 REG32(EXT_MEM_DCFG1) = 0x13321211;
\r
321 REG32(EXT_MEM_DCFG2) = 0x04050322;
\r
323 case EMC_CLK_133MHZ:
\r
324 REG32(EXT_MEM_DCFG1) = 0x13341322;
\r
325 REG32(EXT_MEM_DCFG2) = 0x080A0322;
\r
327 case EMC_CLK_200MHZ:
\r
328 REG32(EXT_MEM_DCFG1) = 0x13352333;
\r
329 REG32(EXT_MEM_DCFG2) = 0x0B0E0322;
\r
331 case EMC_CLK_266MHZ:
\r
332 REG32(EXT_MEM_DCFG1) = 0x13383455;
\r
333 REG32(EXT_MEM_DCFG2) = 0x10140322;
\r
335 case EMC_CLK_333MHZ:
\r
336 REG32(EXT_MEM_DCFG1) = 0x13393455;
\r
337 REG32(EXT_MEM_DCFG2) = 0x13180322;
\r
339 case EMC_CLK_370MHZ:
\r
340 case EMC_CLK_400MHZ:
\r
342 REG32(EXT_MEM_DCFG1) = 0x133A3566;
\r
343 REG32(EXT_MEM_DCFG2) = 0x161C0322;
\r
347 uint32 cycle_ns = (uint32)(2000000000/emc_freq);//2000/(clk); //device clock is half of emc clock.
\r
348 uint32 cycle_t_ref = 1000000/EMC_T_REF_CLK;
\r
350 // uint32 row_mode = mem_info->row_mode + ROW_LINE_MIN;
\r
352 uint32 t_wtr = mem_timing->wtr_min+1;
\r
353 uint32 t_rtw = mem_info->cas_latency;
\r
362 uint32 tREFI = mem_timing->trefi_max;
\r
364 uint32 t_mrd = mem_timing->mrd_min;
\r
366 //round all timing parameter
\r
367 t_ras = ((mem_timing->ras_min % cycle_ns) == 0) ? (mem_timing->ras_min/cycle_ns) : (mem_timing->ras_min/cycle_ns + 1);
\r
368 t_rrd = ((mem_timing->rrd_min % cycle_ns) == 0) ? (mem_timing->rrd_min/cycle_ns) : (mem_timing->rrd_min/cycle_ns + 1);
\r
369 t_rcd = ((mem_timing->rcd_min % cycle_ns) == 0) ? (mem_timing->rcd_min/cycle_ns) : (mem_timing->rcd_min/cycle_ns + 1);
\r
370 t_rp = ((mem_timing->row_pre_min % cycle_ns) == 0) ? (mem_timing->row_pre_min/cycle_ns) : (mem_timing->row_pre_min/cycle_ns + 1);
\r
371 t_rfc = ((mem_timing->rfc_min % cycle_ns) == 0) ? (mem_timing->rfc_min/cycle_ns) : (mem_timing->rfc_min/cycle_ns + 1);
\r
372 t_xsr = ((mem_timing->xsr_min % cycle_ns) == 0) ? (mem_timing->xsr_min/cycle_ns) : (mem_timing->xsr_min/cycle_ns + 1);
\r
375 #ifdef SDR_SDRAM_SUPPORT
\r
376 if (SDR_SDRAM == mem_info->sdram_type)
\r
378 t_wr = mem_timing->wr_min/cycle_ns;
\r
383 t_wr = mem_timing->wr_min/cycle_ns+2;//note: twr should add 2 for ddr
\r
386 t_ref = tREFI / cycle_t_ref;
\r
388 //prevent the maximun overflow of all timing parameter
\r
389 t_ras = (t_ras >= 0xf) ? 0xa : t_ras;
\r
390 t_xsr = (t_xsr >= 0xff) ? 0x26 : t_xsr;
\r
391 t_rfc = (t_rfc >= 0x3f) ? 0x1a : t_rfc;
\r
392 t_wr = (t_wr >= 0xf) ? 0x4 : t_wr;
\r
393 t_rcd = (t_rcd >= 0xf) ? 0x7 : t_rcd;
\r
394 t_rp = (t_rp >= 0xf) ? 0x7 : t_rp;
\r
395 t_rrd = (t_rrd >= 0xf) ? 0x4 : t_rrd;
\r
396 t_mrd = (t_mrd >= 0xf) ? 0x3 : t_mrd;
\r
397 t_wtr = (t_wtr >= 0xf) ? 0x3 : t_wtr;
\r
398 t_ref = (t_ref >=0xfff) ? 0x32: t_ref ;
\r
400 //prevent the minmun value of all timing
\r
401 t_ras = (t_ras == 0) ? 0xa : t_ras;
\r
402 t_xsr = (t_xsr == 0) ? 0x26 : t_xsr;
\r
403 t_rfc = (t_rfc == 0) ? 0x1a : t_rfc;
\r
404 t_wr = (t_wr == 0) ? 0x4 : t_wr;
\r
405 t_rcd = (t_rcd == 0) ? 0x7 : t_rcd;
\r
406 t_rp = (t_rp == 0) ? 0x7 : t_rp;
\r
407 t_rrd = (t_rrd == 0) ? 0x4 : t_rrd;
\r
408 t_mrd = (t_mrd == 0) ? 0x3 : t_mrd;
\r
409 t_wtr = (t_wtr == 0) ? 0x3 : t_wtr;
\r
410 t_ref = (t_ref == 0) ? 0x32: t_ref ;
\r
412 REG32(EXT_MEM_DCFG1) =
\r
413 ((t_rtr << 28) |//read to read turn around time between different cs,default:0 2 cs or above:1
\r
422 REG32(EXT_MEM_DCFG2) =
\r
431 /*****************************************************************************/
\r
432 // Description: EMC software command send function
\r
433 // this function will send software initialization command to external memory
\r
434 // Global resource dependence: memory type
\r
435 // Author: Johnny.Wang
\r
436 // Related register:
\r
439 /*****************************************************************************/
\r
440 LOCAL void EMC_SCMD_Issue(SDRAM_CFG_INFO_T_PTR mem_info)
\r
444 //shut down auto-refresh
\r
445 REG32(EXT_MEM_DCFG0) &= ~(DCFG0_AUTOREF_EN);
\r
447 //precharge all bank
\r
448 REG32(EXT_MEM_DCFG4) = 0x40010000;
\r
449 while (REG32(EXT_MEM_DCFG4) & BIT_16);
\r
450 for (i=0; i<=50; i++);
\r
452 //software auto refresh
\r
453 REG32(EXT_MEM_DCFG4) = 0x40020000;
\r
454 while (REG32(EXT_MEM_DCFG4) & BIT_17);
\r
455 for (i=0; i<=50; i++);
\r
457 //software auto refresh
\r
458 REG32(EXT_MEM_DCFG4) = 0x40020000;
\r
459 while (REG32(EXT_MEM_DCFG4) & BIT_17);
\r
460 for (i=0; i<=50; i++);
\r
462 //load nornal mode register
\r
463 REG32(EXT_MEM_DCFG4) = 0x40040000 | (mem_info->cas_latency<<4) | (mem_info->burst_length);
\r
464 while (REG32(EXT_MEM_DCFG4) & BIT_18);
\r
465 for (i=0; i<=50; i++);
\r
467 if (SDRAM_EXT_MODE_INVALID != mem_info->ext_mode_val)
\r
469 mem_info->ext_mode_val &= (~(0x7 << 5));
\r
470 mem_info->ext_mode_val |= (s_emc_config.ddr_drv << 5);
\r
472 //load external mode register
\r
473 REG32(EXT_MEM_DCFG4) = 0x40040000 | mem_info->ext_mode_val;
\r
474 while (REG32(EXT_MEM_DCFG4) & BIT_18);
\r
475 for (i=0; i<=50; i++);
\r
478 //open auto-refresh
\r
479 REG32(EXT_MEM_DCFG0) |= (DCFG0_AUTOREF_EN);
\r
484 /*****************************************************************************/
\r
485 // Description: EMC phy latency set function
\r
486 // set parameter relate with cas latency like:
\r
487 // timing adjustment sample clock latency
\r
488 // DQS output latency
\r
489 // write dm latency
\r
491 // write data latency
\r
492 // read data latency
\r
493 // Global resource dependence: dram type , cas_latency
\r
494 // Author: Johnny.Wang
\r
495 // Related register: EMC_DCFG5
\r
499 /*****************************************************************************/
\r
500 PUBLIC void EMC_PHY_Latency_Set(SDRAM_CFG_INFO_T_PTR mem_info)
\r
502 #ifdef SDR_SDRAM_SUPPORT
\r
503 if (SDR_SDRAM == mem_info->sdram_type)
\r
505 if (CAS_LATENCY_2 == mem_info->cas_latency)
\r
507 REG32(EXT_MEM_DCFG5) = 0x00400007;
\r
509 else if (CAS_LATENCY_3 == mem_info->cas_latency)
\r
511 REG32(EXT_MEM_DCFG5) = 0x00600209;
\r
518 if (CAS_LATENCY_2 == mem_info->cas_latency)
\r
520 REG32(EXT_MEM_DCFG5) = 0x00622728;
\r
522 else if (CAS_LATENCY_3 == mem_info->cas_latency)
\r
524 REG32(EXT_MEM_DCFG5) = 0x0062272A;
\r
528 /*****************************************************************************/
\r
529 // Description: EMC phy mode set function
\r
530 // set parameter relate with emc phy work mode like:
\r
531 // cke map to cs0 or cs1
\r
532 // dqs gate delay,delay line or loopback
\r
533 // dqs gate mode,mode0 or mode1
\r
534 // DMEM data output mode,dff or dl
\r
535 // DMEM DDR DQS[3:0] output mode,dff or dl
\r
536 // DMEM DDR DQS PAD IE mode,dff or dl
\r
537 // DMEM sample clock mode,internal or from dqs
\r
538 // DMEM CK/CK# output mode,dff or dl
\r
539 // DMEM READ strobe clock loopback dis/en
\r
540 // Global resource dependence: dll on or off, external memory type
\r
541 // Author: Johnny.Wang
\r
542 // Related register: EMC_CFG1
\r
546 /*****************************************************************************/
\r
547 LOCAL void EMC_PHY_Mode_Set(SDRAM_CFG_INFO_T_PTR mem_info)
\r
551 // SCI_ASSERT(mem_info != NULL);
\r
553 i = REG32(EXT_MEM_CFG1);
\r
554 i &= ~((3<<14)|0x3ff);
\r
555 i |=(EMC_CKE_SEL_DEFAULT << 14) |
\r
556 (EMC_DQS_GATE_DEFAULT<< 8) |
\r
557 (EMC_DQS_GATE_MODE_DEFAULT<< 7) |
\r
558 (mem_info->sdram_type<< 6) |//DMEM data output mode,0:dff 1:dl
\r
559 (0<<5) |//DMEM DDR DQS[3:0] output mode,0:dff 1:dl
\r
560 (0<<4) |//DMEM DDR DQS PAD IE mode,0:dff 1:dl
\r
561 (mem_info->sdram_type<<3) |//DMEM sample clock mode,0:internal 1:out-of-chip
\r
562 (0<<2) |//DMEM CK/CK# output mode,0:dff 1:dl
\r
563 ((~mem_info->sdram_type & 0x1) <<1) |//DMEM READ strobe clock loopback 0:dis 1:en
\r
564 mem_info->sdram_type;
\r
566 REG32(EXT_MEM_CFG1) = i;
\r
572 /*****************************************************************************/
\r
573 // Description: EMC phy timing set function
\r
574 // set parameter relate with emc phy work mode like:
\r
575 // data pad ie delay
\r
576 // data pad oe delay
\r
577 // dqs pad ie delay
\r
578 // dqs pad oe delay
\r
579 // all delay line timing parameter
\r
580 // Global resource dependence: dll on or off, external memory type
\r
581 // Author: Johnny.Wang
\r
582 // Related register: EMC_DCFG6,7,8 and EMC_DMEM_DL0~DL19
\r
585 /*****************************************************************************/
\r
586 PUBLIC void EMC_PHY_Timing_Set(SDRAM_CFG_INFO_T_PTR mem_info,
\r
587 EMC_PHY_L1_TIMING_T_PTR emc_phy_l1_timing,
\r
588 EMC_PHY_L2_TIMING_T_PTR emc_phy_l2_timing)
\r
592 uint8 emc_dll_rd_val;
\r
593 // uint32 clkwr_dll = (64*s_emc_config.clk_wr)/(s_emc_config.read_value/2);
\r
596 // SCI_ASSERT((mem_info != NULL) && (emc_phy_l1_timing != NULL) && (emc_phy_l2_timing != NULL));
\r
598 REG32(EXT_MEM_DCFG8) = ((emc_phy_l1_timing->data_pad_ie_delay & 0xffff) <<16) |
\r
599 (emc_phy_l1_timing->data_pad_oe_delay & 0xff);
\r
602 if (DDR_SDRAM == mem_info->sdram_type)
\r
604 REG32(EXT_MEM_DCFG6) = ((emc_phy_l1_timing->dqs_gate_pst_delay& 0xffff) <<16) |
\r
605 (emc_phy_l1_timing->dqs_gate_pre_delay& 0xffff);
\r
607 REG32(EXT_MEM_DCFG7) = ((emc_phy_l1_timing->dqs_ie_delay& 0xffff) <<16) |
\r
608 (emc_phy_l1_timing->dqs_oe_delay& 0xff);
\r
610 if (s_emc_dll_open)
\r
612 REG32(EXT_MEM_CFG0_DLL) = 0x11080; //DLL and compensation en
\r
618 REG32(EXT_MEM_CFG0_DLL) &= ~BIT_10; //DLL disable
\r
620 REG32(EXT_MEM_CFG0_DLL) &= ~BIT_7; //DLL disable
\r
622 REG32(EXT_MEM_CFG0_DLL) = 0; //DLL disable
\r
625 for (i = 0; i < 20; i++)
\r
627 REG32(EXT_MEM_DL0 + i*4) = REG32((unsigned int)emc_phy_l2_timing + i * 4);
\r
630 if (s_emc_dll_open)
\r
632 emc_dll_rd_val = (REG32(EXT_MEM_CFG0_DLL_STS) & 0xFF);
\r
634 clkwr_dll = (s_emc_config.clk_wr << 6) / ((emc_dll_rd_val & 0xff) >> 1);
\r
636 for (i = 0; i < 4; i++)
\r
638 REG32(EXT_MEM_DL0 + i*4) = (0x8000 | (clkwr_dll & 0x7F));
\r
641 REG32(EXT_MEM_CFG0_DLL) |= DCFG0_DLL_COMPENSATION_EN;
\r
647 REG32(EXT_MEM_DCFG6) = 0X400020;
\r
648 REG32(EXT_MEM_DCFG7) = 0XF0000E;
\r
649 REG32(EXT_MEM_DCFG8) = 0X400001;
\r
654 LOCAL void EMC_CHL_Init(EMC_CHL_INFO_PTR emc_chl_info)
\r
657 EMC_CHL_NUM_E emc_channel_num;
\r
659 while (emc_chl_info[i].emc_chl_num != EMC_CHL_MAX)
\r
661 emc_channel_num = emc_chl_info[i].emc_chl_num;
\r
663 if ((emc_channel_num >= EMC_AXI_MIN) && (emc_channel_num <= EMC_AXI_MAX))
\r
665 EMC_AXI_CHL_Set(emc_channel_num,
\r
666 emc_chl_info[i].axi_chl_wr_pri,
\r
667 emc_chl_info[i].axi_chl_rd_pri
\r
670 else if ((emc_channel_num >= EMC_AHB_MIN) && (emc_channel_num <= EMC_AHB_MAX))
\r
672 EMC_AHB_CHL_Set(emc_channel_num, 0, emc_chl_info[i].ahb_chl_pri);
\r
684 LOCAL void set_emc_pad(uint32 dqs_drv,uint32 data_drv,uint32 ctl_drv, uint32 clk_drv)
\r
686 unsigned int i = 0;
\r
688 // SCI_ASSERT(dqs_drv < 4);
\r
689 // SCI_ASSERT(data_drv < 4);
\r
690 // SCI_ASSERT(ctl_drv < 4);
\r
691 // SCI_ASSERT(clk_drv < 4);
\r
698 for(i = 0; i < 2; i++)
\r
700 REG32((CHIPPIN_CTL_BEGIN + PIN_CLKDMMEM_REG_OFFS) + i*4) &= (~0x30F);
\r
701 REG32((CHIPPIN_CTL_BEGIN + PIN_CLKDMMEM_REG_OFFS) + i*4) |= ((clk_drv<<8) | 0x4);
\r
705 for(i = 0; i < 14; i++)
\r
707 REG32((CHIPPIN_CTL_BEGIN + PIN_EMA0_REG_OFFS) + i*4) &= (~0x30F);
\r
708 REG32((CHIPPIN_CTL_BEGIN + PIN_EMA0_REG_OFFS) + i*4) |= ((ctl_drv<<8) | 0x4);
\r
711 for(i = 0; i < 7; i++)
\r
712 {//bank0 bank1 casn cke0 cke1 csn0 csn1
\r
713 REG32((CHIPPIN_CTL_BEGIN + PIN_EMBA0_REG_OFFS) + i*4) &= (~0x30F);
\r
714 REG32((CHIPPIN_CTL_BEGIN + PIN_EMBA0_REG_OFFS) + i*4) |= ((ctl_drv<<8) | 0x4);
\r
717 for(i = 0; i < 2; i++)
\r
719 REG32((CHIPPIN_CTL_BEGIN + PIN_EMCKE0_REG_OFFS) + i*4) |= 0x5;
\r
722 for(i = 0; i < 4; i++)
\r
724 REG32((CHIPPIN_CTL_BEGIN + PIN_EMDQM0_REG_OFFS) + i*4) &= (~0x30F);
\r
725 REG32((CHIPPIN_CTL_BEGIN + PIN_EMDQM0_REG_OFFS) + i*4) |= ((data_drv<<8) | 0x4);
\r
728 for(i = 0; i < 4; i++)
\r
730 REG32((CHIPPIN_CTL_BEGIN + PIN_EMDQS0_REG_OFFS) + i*4) &= (~0x30F);
\r
731 REG32((CHIPPIN_CTL_BEGIN + PIN_EMDQS0_REG_OFFS) + i*4) |= ((dqs_drv<<8) | 0x4);
\r
735 for(i = 0; i < 32; i++)
\r
737 REG32((CHIPPIN_CTL_BEGIN + PIN_EMD0_REG_OFFS) + i*4) &= (~0x30F);
\r
738 REG32((CHIPPIN_CTL_BEGIN + PIN_EMD0_REG_OFFS) + i*4) |= ((data_drv<<8) | 0x4);
\r
741 for(i = 0; i < 2; i++)
\r
742 {//gpre_loop gpst_loop
\r
743 REG32((CHIPPIN_CTL_BEGIN + PIN_EMGPRE_LOOP_REG_OFFS) + i*4) &= (~0x300F);
\r
744 REG32((CHIPPIN_CTL_BEGIN + PIN_EMGPRE_LOOP_REG_OFFS) + i*4) |= ((ctl_drv<<8) | 0x4);
\r
747 for(i = 0; i < 2; i++)
\r
749 REG32((CHIPPIN_CTL_BEGIN + PIN_EMRAS_N_REG_OFFS) + i*4) &= (~0x30F);
\r
750 REG32((CHIPPIN_CTL_BEGIN + PIN_EMRAS_N_REG_OFFS) + i*4) |= ((ctl_drv<<8) | 0x4);
\r
754 #ifdef SDRAM_AUTODETECT_SUPPORT
\r
755 LOCAL BOOLEAN __is_rw_ok(uint32 addr,uint32 val)
\r
758 BOOLEAN ret = SCI_TRUE;
\r
763 REG32(addr + 4) = 0;
\r
764 REG32(addr + 4) = (~val);
\r
768 if ((REG32(addr) == val) && (REG32(addr + 4) == (~val)))
\r
781 LOCAL void dram_detect_write_addr(uint32 start_addr, uint32 detect_size)
\r
784 uint32 detect_unit = 0x200;
\r
785 uint32 detect_region = (start_addr + detect_size);
\r
787 for(addr = start_addr; addr < detect_region; addr = start_addr + detect_unit)
\r
789 *(volatile uint32 *)addr = addr;
\r
794 LOCAL uint32 dram_detect_check_addr(uint32 start_addr, uint32 detect_size)
\r
797 uint32 detect_unit = 0x200;
\r
798 uint32 detect_region = (start_addr + detect_size);
\r
800 for(addr = start_addr; addr < detect_region; addr = start_addr + detect_unit)
\r
802 if(*(volatile uint32 *)addr != addr)
\r
810 if (addr < detect_region)
\r
815 return detect_region;
\r
819 LOCAL BOOLEAN dram_mode_check(uint32 dram_cap)
\r
821 BOOLEAN ret = TRUE;
\r
823 uint32 detect_block_size = CAP_2G_BIT;
\r
824 uint32 start_detect_addr_len = 0;
\r
825 uint32 start_detect_addr[] = {
\r
832 // SCI_ASSERT(dram_cap >= CAP_1G_BIT);
\r
839 start_detect_addr[2] = INVALIDE_VAL;
\r
843 start_detect_addr[1] = INVALIDE_VAL;
\r
844 start_detect_addr[2] = INVALIDE_VAL;
\r
848 start_detect_addr_len = sizeof(start_detect_addr) / sizeof(start_detect_addr[0]);
\r
850 for(i = 0; i < start_detect_addr_len; i++)
\r
852 if (start_detect_addr[i] != INVALIDE_VAL)
\r
854 dram_detect_write_addr(start_detect_addr[i], detect_block_size);
\r
858 for(i = 0; i < start_detect_addr_len; i++)
\r
860 if (start_detect_addr[i] != INVALIDE_VAL)
\r
862 if (dram_detect_check_addr(start_detect_addr[i], detect_block_size) != (start_detect_addr[i] + detect_block_size))
\r
873 LOCAL BOOLEAN DRAM_Para_SelfAdapt(void)
\r
876 // BOOLEAN ret = FALSE;
\r
877 SDRAM_CFG_INFO_T_PTR pCfg = SDRAM_GetCfg();
\r
878 SDRAM_MODE_PTR modetable_ptr = SDRAM_GetModeTable();
\r
884 if (__is_rw_ok(SDRAM_BASE_ADDR, MEM_REF_DATA0))
\r
889 if((pCfg->data_width == DATA_WIDTH_32)
\r
890 && (pCfg->sdram_type == DDR_SDRAM)
\r
893 pCfg->data_width = DATA_WIDTH_16;
\r
895 else if((pCfg->data_width == DATA_WIDTH_16)
\r
896 && (pCfg->sdram_type == DDR_SDRAM)
\r
899 pCfg->data_width = DATA_WIDTH_32;
\r
900 pCfg->sdram_type = SDR_SDRAM;
\r
902 else if((pCfg->data_width == DATA_WIDTH_32)
\r
903 && (pCfg->sdram_type == SDR_SDRAM)
\r
906 pCfg->data_width = DATA_WIDTH_16;
\r
914 for(i=0; modetable_ptr[i].capacity != CAP_ZERO; i++)
\r
916 if(modetable_ptr[i].data_width != pCfg->data_width)
\r
921 pCfg->cs_position = modetable_ptr[i].cs_position;
\r
922 pCfg->col_mode = modetable_ptr[i].col_mode;
\r
923 pCfg->row_mode = modetable_ptr[i].row_mode;
\r
927 if(dram_mode_check(modetable_ptr[i].capacity))
\r
929 DRAM_CAP = modetable_ptr[i].capacity;
\r
934 if (modetable_ptr[i].capacity == CAP_ZERO)
\r
946 LOCAL void DMC_Init(void)
\r
948 uint32 emc_freq = s_emc_config.emc_clk;
\r
949 SDRAM_CFG_INFO_T_PTR mem_info = SDRAM_GetCfg();
\r
950 SDRAM_TIMING_PARA_T_PTR mem_timing = SDRAM_GetTimingPara();
\r
951 EMC_PHY_L1_TIMING_T_PTR emc_phy_l1_timing = NULL;
\r
952 EMC_PHY_L2_TIMING_T_PTR emc_phy_l2_timing = EMC_GetPHYL2_Timing();
\r
953 EMC_CHL_INFO_PTR emc_chl_info = EMC_GetChlInfo();
\r
956 EMC_CHL_Init(emc_chl_info);
\r
958 EMC_Base_Mode_Set(mem_info);
\r
959 EMC_AddrMode_Set(mem_info);
\r
960 EMC_CSx_Burst_Set(EMC_CS0, mem_info);
\r
961 EMC_CSx_Burst_Set(EMC_CS1, mem_info);
\r
962 EMC_PHY_Mode_Set(mem_info);
\r
963 EMC_PHY_Latency_Set(mem_info);
\r
965 emc_phy_l1_timing = EMC_GetPHYL1_Timing(mem_info->sdram_type, mem_info->cas_latency);
\r
966 EMC_PHY_Timing_Set(mem_info, emc_phy_l1_timing, emc_phy_l2_timing);
\r
967 EMC_MEM_Timing_Set(emc_freq, mem_info, mem_timing);
\r
968 EMC_SCMD_Issue(mem_info);
\r
973 LOCAL void emc_clock_select(EMC_CLK_SOURCE_E emc_clk_sel)
\r
977 // SCI_ASSERT(emc_clk_sel < EMC_CLK_NONE);
\r
979 i = REG32(AHB_ARM_CLK);
\r
980 i &= ~(1 << 3); // clk_emc_async
\r
982 i |= ((emc_clk_sel & 0x3) << 12);
\r
984 REG32(AHB_ARM_CLK) = i;
\r
987 LOCAL void set_emc_clock_div(uint32 emc_div)
\r
991 i = REG32(AHB_ARM_CLK);
\r
993 i |= ((emc_div & 0xF) << 8); // emc div = n + 1
\r
995 REG32(AHB_ARM_CLK) = i;
\r
998 LOCAL void set_dpll_clock_freq(uint32 clk_freq_hz)
\r
1004 dpll_clk = (clk_freq_hz / 1000000 / 4);
\r
1006 //APB_GEN1_PCLK M_PLL_CTRL_WE
\r
1007 REG32(GR_GEN1) |= (1 << 9);
\r
1009 i = REG32(GR_DPLL_CTL); //0x8b000040
\r
1011 i |= (dpll_clk & 0x7FF);
\r
1013 REG32(GR_DPLL_CTL) = i;
\r
1014 REG32(GR_GEN1) &= ~(1 << 9);
\r
1018 LOCAL void set_emc_clock_freq(void)
\r
1020 uint32 emc_div = 0;
\r
1021 uint32 emc_clk_freq = s_emc_config.emc_clk;
\r
1022 EMC_CLK_SOURCE_E emc_clk_sel;
\r
1024 switch (emc_clk_freq)
\r
1026 case EMC_CLK_26MHZ:
\r
1027 emc_clk_sel = EMC_CLK_XTL_SOURCE;
\r
1029 case EMC_CLK_67MHZ:
\r
1030 emc_clk_sel = EMC_CLK_DPLL_SOURCE;
\r
1032 case EMC_CLK_133MHZ:
\r
1033 emc_clk_sel = EMC_CLK_DPLL_SOURCE;
\r
1035 case EMC_CLK_266MHZ:
\r
1036 emc_clk_sel = EMC_CLK_DPLL_SOURCE;
\r
1038 case EMC_CLK_333MHZ:
\r
1039 emc_clk_sel = EMC_CLK_DPLL_SOURCE;
\r
1041 case EMC_CLK_370MHZ:
\r
1042 emc_clk_sel = EMC_CLK_DPLL_SOURCE;
\r
1044 case EMC_CLK_200MHZ:
\r
1045 emc_clk_sel = EMC_CLK_DPLL_SOURCE;
\r
1047 case EMC_CLK_400MHZ:
\r
1049 emc_clk_sel = EMC_CLK_DPLL_SOURCE;
\r
1050 emc_clk_freq = EMC_CLK_400MHZ;
\r
1054 if (emc_clk_sel == EMC_CLK_DPLL_SOURCE)
\r
1056 set_dpll_clock_freq(emc_clk_freq);
\r
1057 set_emc_clock_div(emc_div);
\r
1060 emc_clock_select(emc_clk_sel);
\r
1062 if (emc_clk_freq <= EMC_CLK_67MHZ)
\r
1064 s_emc_dll_open = FALSE;
\r
1068 s_emc_dll_open = TRUE;
\r
1073 void sdram_init(void)
\r
1077 EMC_PARAM_PTR emc_ptr = EMC_GetPara();
\r
1079 // s_emc_config.arm_clk = emc_ptr->arm_clk;
\r
1080 s_emc_config.emc_clk = emc_ptr->emc_clk;
\r
1081 s_emc_config.dqs_drv = emc_ptr->dqs_drv;
\r
1082 s_emc_config.dat_drv = emc_ptr->dat_drv;
\r
1083 s_emc_config.ctl_drv = emc_ptr->ctl_drv;
\r
1084 s_emc_config.clk_drv = emc_ptr->clk_drv;
\r
1085 s_emc_config.clk_wr = emc_ptr->clk_wr;
\r
1086 s_emc_config.ddr_drv = emc_ptr->ddr_drv;
\r
1088 set_emc_pad(s_emc_config.dqs_drv, s_emc_config.dat_drv, s_emc_config.ctl_drv, s_emc_config.clk_drv);
\r
1090 set_emc_clock_freq();
\r
1094 #ifdef SDRAM_AUTODETECT_SUPPORT
\r
1095 for (i=0; i<3; i++)
\r
1097 if (DRAM_Para_SelfAdapt())
\r
1103 SCI_ASSERT(i < 3);
\r
1106 DRAM_CAP = SDRAM_GetCap(); // get size
\r
1113 #ifdef __cplusplus
\r