3 * Texas Instruments, <www.ti.com>
4 * Richard Woodruff <r-woodruff2@ti.com>
6 * This program is free software; you can redistribute it and/or
7 * modify it under the terms of the GNU General Public License as
8 * published by the Free Software Foundation; either version 2 of
9 * the License, or (at your option) any later version.
11 * This program is distributed in the hope that it will be useful,
12 * but WITHOUT ANY WARRANTY; without even the implied warranty of
13 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
14 * GNU General Public License for more details.
16 * You should have received a copy of the GNU General Public License
17 * along with this program; if not, write to the Free Software
18 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
23 #include <asm/arch/omap2420.h>
25 #include <asm/arch/bits.h>
26 #include <asm/arch/mux.h>
27 #include <asm/arch/mem.h>
28 #include <asm/arch/clocks.h>
29 #include <asm/arch/sys_proto.h>
30 #include <asm/arch/sys_info.h>
32 /************************************************************
33 * sdelay() - simple spin loop. Will be constant time as
34 * its generally used in 12MHz bypass conditions only. This
35 * is necessary until timers are accessible.
37 * not inline to increase chances its in cache when called
38 *************************************************************/
39 void sdelay (unsigned long loops
)
41 __asm__
volatile ("1:\n" "subs %0, %1, #1\n"
42 "bne 1b":"=r" (loops
):"0" (loops
));
45 /*********************************************************************************
46 * prcm_init() - inits clocks for PRCM as defined in clocks.h (config II default).
47 * -- called from SRAM, or Flash (using temp SRAM stack).
48 *********************************************************************************/
52 void (*f_lock_pll
) (u32
, u32
, u32
, u32
);
53 extern void *_end_vect
, *_start
;
55 f_lock_pll
= (void *)((u32
)&_end_vect
- (u32
)&_start
+ SRAM_VECT_CODE
);
57 __raw_writel(0, CM_FCLKEN1_CORE
); /* stop all clocks to reduce ringing */
58 __raw_writel(0, CM_FCLKEN2_CORE
); /* may not be necessary */
59 __raw_writel(0, CM_ICLKEN1_CORE
);
60 __raw_writel(0, CM_ICLKEN2_CORE
);
62 __raw_writel(DPLL_OUT
, CM_CLKSEL2_PLL
); /* set DPLL out */
63 __raw_writel(MPU_DIV
, CM_CLKSEL_MPU
); /* set MPU divider */
64 __raw_writel(DSP_DIV
, CM_CLKSEL_DSP
); /* set dsp and iva dividers */
65 __raw_writel(GFX_DIV
, CM_CLKSEL_GFX
); /* set gfx dividers */
68 __raw_writel(div
, CM_CLKSEL1_CORE
);/* set L3/L4/USB/Display/Vlnc/SSi dividers */
71 if(running_in_sram()){
72 /* If running fully from SRAM this is OK. The Flash bus drops out for just a little.
73 * but then comes back. If running from Flash this sequence kills you, thus you need
74 * to run it using CONFIG_PARTIAL_SRAM.
76 __raw_writel(MODE_BYPASS_FAST
, CM_CLKEN_PLL
); /* go to bypass, fast relock */
77 wait_on_value(BIT0
|BIT1
, BIT0
, CM_IDLEST_CKGEN
, LDELAY
); /* wait till in bypass */
79 /* set clock selection and dpll dividers. */
80 __raw_writel(DPLL_VAL
, CM_CLKSEL1_PLL
); /* set pll for target rate */
81 __raw_writel(COMMIT_DIVIDERS
, PRCM_CLKCFG_CTRL
); /* commit dividers */
83 __raw_writel(DPLL_LOCK
, CM_CLKEN_PLL
); /* enable dpll */
85 wait_on_value(BIT0
|BIT1
, BIT1
, CM_IDLEST_CKGEN
, LDELAY
); /*wait for dpll lock */
86 }else if(running_in_flash()){
87 /* if running from flash, need to jump to small relocated code area in SRAM.
88 * This is the only safe spot to do configurations from.
90 (*f_lock_pll
)(PRCM_CLKCFG_CTRL
, CM_CLKEN_PLL
, DPLL_LOCK
, CM_IDLEST_CKGEN
);
93 __raw_writel(DPLL_LOCK
|APLL_LOCK
, CM_CLKEN_PLL
); /* enable apll */
94 wait_on_value(BIT8
, BIT8
, CM_IDLEST_CKGEN
, LDELAY
); /* wait for apll lock */
98 /**************************************************************************
99 * make_cs1_contiguous() - for es2 and above remap cs1 behind cs0 to allow
100 * command line mem=xyz use all memory with out discontigious support
101 * compiled in. Could do it at the ATAG, but there really is two banks...
102 * Called as part of 2nd phase DDR init.
103 **************************************************************************/
104 void make_cs1_contiguous(void)
106 u32 size
, a_add_low
, a_add_high
;
108 size
= get_sdr_cs_size(SDRC_CS0_OSET
);
109 size
/= SZ_32M
; /* find size to offset CS1 */
110 a_add_high
= (size
& 3) << 8; /* set up low field */
111 a_add_low
= (size
& 0x3C) >> 2; /* set up high field */
112 __raw_writel((a_add_high
|a_add_low
),SDRC_CS_CFG
);
116 /********************************************************
117 * mem_ok() - test used to see if timings are correct
118 * for a part. Helps in gussing which part
119 * we are currently using.
120 *******************************************************/
124 u32 pattern
= 0x12345678;
126 __raw_writel(0x0,OMAP2420_SDRC_CS0
+0x400); /* clear pos A */
127 __raw_writel(pattern
, OMAP2420_SDRC_CS0
); /* pattern to pos B */
128 __raw_writel(0x0,OMAP2420_SDRC_CS0
+4); /* remove pattern off the bus */
129 val1
= __raw_readl(OMAP2420_SDRC_CS0
+0x400); /* get pos A value */
130 val2
= __raw_readl(OMAP2420_SDRC_CS0
); /* get val2 */
132 if ((val1
!= 0) || (val2
!= pattern
)) /* see if pos A value changed*/
139 /********************************************************
140 * sdrc_init() - init the sdrc chip selects CS0 and CS1
141 * - early init routines, called from flash or
143 *******************************************************/
147 do_sdrc_init(SDRC_CS0_OSET
, EARLY_INIT
); /* only init up first bank here */
150 /*************************************************************************
151 * do_sdrc_init(): initialize the SDRAM for use.
152 * -called from low level code with stack only.
153 * -code sets up SDRAM timing and muxing for 2422 or 2420.
154 * -optimal settings can be placed here, or redone after i2c
155 * inspection of board info
157 * This is a bit ugly, but should handle all memory moduels
158 * used with the H4. The first time though this code from s_init()
159 * we configure the first chip select. Later on we come back and
160 * will configure the 2nd chip select if it exists.
162 **************************************************************************/
163 void do_sdrc_init(u32 offset
, u32 early
)
165 u32 cpu
, dllen
=0, rev
, common
=0, cs0
=0, pmask
=0, pass_type
, mtype
;
166 sdrc_data_t
*sdata
; /* do not change type */
169 static const sdrc_data_t sdrc_2422
=
171 H4_2422_SDRC_SHARING
, H4_2422_SDRC_MDCFG_0_DDR
, 0 , H4_2422_SDRC_ACTIM_CTRLA_0
,
172 H4_2422_SDRC_ACTIM_CTRLB_0
, H4_2422_SDRC_RFR_CTRL
, H4_2422_SDRC_MR_0_DDR
,
173 0, H4_2422_SDRC_DLLAB_CTRL
175 static const sdrc_data_t sdrc_2420
=
177 H4_2420_SDRC_SHARING
, H4_2420_SDRC_MDCFG_0_DDR
, H4_2420_SDRC_MDCFG_0_SDR
,
178 H4_2420_SDRC_ACTIM_CTRLA_0
, H4_2420_SDRC_ACTIM_CTRLB_0
,
179 H4_2420_SDRC_RFR_CTRL
, H4_2420_SDRC_MR_0_DDR
, H4_2420_SDRC_MR_0_SDR
,
180 H4_2420_SDRC_DLLAB_CTRL
183 if (offset
== SDRC_CS0_OSET
)
184 cs0
= common
= 1; /* int regs shared between both chip select */
186 cpu
= get_cpu_type();
189 /* warning generated, though code generation is correct. this may bite later,
190 * but is ok for now. there is only so much C code you can do on stack only
193 if (cpu
== CPU_2422
){
194 sdata
= (sdrc_data_t
*)&sdrc_2422
;
197 sdata
= (sdrc_data_t
*)&sdrc_2420
;
201 __asm__
__volatile__("": : :"memory"); /* limit compiler scope */
203 /* u-boot is compiled to run in DDR or SRAM at 8xxxxxxx or 4xxxxxxx.
204 * If we are running in flash prior to relocation and we use data
205 * here which is not pc relative we need to get the address correct.
206 * We need to find the current flash mapping to dress up the initial
207 * pointer load. As long as this is const data we should be ok.
209 if((early
) && running_in_flash()){
210 sdata
= (sdrc_data_t
*)(((u32
)sdata
& 0x0003FFFF) | get_gpmc0_base());
211 /* NOR internal boot offset is 0x4000 from xloader signature */
212 if(running_from_internal_boot())
213 sdata
= (sdrc_data_t
*)((u32
)sdata
+ 0x4000);
216 if (!early
&& (((mtype
= get_mem_type()) == DDR_COMBO
)||(mtype
== DDR_STACKED
))) {
217 if(mtype
== DDR_COMBO
){
218 pmask
= BIT2
;/* combo part has a shared CKE signal, can't use feature */
219 pass_type
= COMBO_DDR
; /* CS1 config */
220 __raw_writel((__raw_readl(SDRC_POWER
)) & ~pmask
, SDRC_POWER
);
222 if(rev
!= CPU_2420_2422_ES1
) /* for es2 and above smooth things out */
223 make_cs1_contiguous();
227 if (common
) { /* do a SDRC reset between types to clear regs*/
228 __raw_writel(SOFTRESET
, SDRC_SYSCONFIG
); /* reset sdrc */
229 wait_on_value(BIT0
, BIT0
, SDRC_STATUS
, 12000000);/* wait till reset done set */
230 __raw_writel(0, SDRC_SYSCONFIG
); /* clear soft reset */
231 __raw_writel(sdata
->sdrc_sharing
, SDRC_SHARING
);
233 __raw_writel(__raw_readl(SMS_SYSCONFIG
)|SMART_IDLE
, SMS_SYSCONFIG
);
234 __raw_writel(sdata
->sdrc_sharing
|SMART_IDLE
, SDRC_SHARING
);
235 __raw_writel((__raw_readl(SDRC_POWER
)|BIT6
), SDRC_POWER
);
239 if ((pass_type
== IP_DDR
) || (pass_type
== STACKED
)) /* (IP ddr-CS0),(2422-CS0/CS1) */
240 __raw_writel(sdata
->sdrc_mdcfg_0_ddr
, SDRC_MCFG_0
+offset
);
241 else if (pass_type
== COMBO_DDR
){ /* (combo-CS0/CS1) */
242 __raw_writel(H4_2420_COMBO_MDCFG_0_DDR
,SDRC_MCFG_0
+offset
);
243 } else if (pass_type
== IP_SDR
){ /* ip sdr-CS0 */
244 __raw_writel(sdata
->sdrc_mdcfg_0_sdr
, SDRC_MCFG_0
+offset
);
247 a
= sdata
->sdrc_actim_ctrla_0
;
248 b
= sdata
->sdrc_actim_ctrlb_0
;
249 r
= sdata
->sdrc_dllab_ctrl
;
251 /* work around ES1 DDR issues */
252 if((pass_type
!= IP_SDR
) && (rev
== CPU_2420_2422_ES1
)){
253 a
= H4_242x_SDRC_ACTIM_CTRLA_0_ES1
;
254 b
= H4_242x_SDRC_ACTIM_CTRLB_0_ES1
;
255 r
= H4_242x_SDRC_RFR_CTRL_ES1
;
259 __raw_writel(a
, SDRC_ACTIM_CTRLA_0
);
260 __raw_writel(b
, SDRC_ACTIM_CTRLB_0
);
262 __raw_writel(a
, SDRC_ACTIM_CTRLA_1
);
263 __raw_writel(b
, SDRC_ACTIM_CTRLB_1
);
265 __raw_writel(r
, SDRC_RFR_CTRL
+offset
);
267 /* init sequence for mDDR/mSDR using manual commands (DDR is a bit different) */
268 __raw_writel(CMD_NOP
, SDRC_MANUAL_0
+offset
);
269 sdelay(5000); /* susposed to be 100us per design spec for mddr/msdr */
270 __raw_writel(CMD_PRECHARGE
, SDRC_MANUAL_0
+offset
);
271 __raw_writel(CMD_AUTOREFRESH
, SDRC_MANUAL_0
+offset
);
272 __raw_writel(CMD_AUTOREFRESH
, SDRC_MANUAL_0
+offset
);
275 * CSx SDRC Mode Register
276 * Burst length = (4 - DDR) (2-SDR)
280 if(pass_type
== IP_SDR
)
281 __raw_writel(sdata
->sdrc_mr_0_sdr
, SDRC_MR_0
+offset
);
283 __raw_writel(sdata
->sdrc_mr_0_ddr
, SDRC_MR_0
+offset
);
285 /* NOTE: ES1 242x _BUG_ DLL + External Bandwidth fix*/
286 if (rev
== CPU_2420_2422_ES1
){
287 dllen
= (BIT0
|BIT3
); /* es1 clear both bit0 and bit3 */
288 __raw_writel((__raw_readl(SMS_CLASS_ARB0
)|BURSTCOMPLETE_GROUP7
)
289 ,SMS_CLASS_ARB0
);/* enable bust complete for lcd */
292 dllen
= BIT0
|BIT1
; /* es2, clear bit0, and 1 (set phase to 72) */
294 /* enable & load up DLL with good value for 75MHz, and set phase to 90
295 * ES1 recommends 90 phase, ES2 recommends 72 phase.
297 if (common
&& (pass_type
!= IP_SDR
)) {
298 __raw_writel(sdata
->sdrc_dllab_ctrl
, SDRC_DLLA_CTRL
);
299 __raw_writel(sdata
->sdrc_dllab_ctrl
& ~(BIT2
|dllen
), SDRC_DLLA_CTRL
);
300 __raw_writel(sdata
->sdrc_dllab_ctrl
, SDRC_DLLB_CTRL
);
301 __raw_writel(sdata
->sdrc_dllab_ctrl
& ~(BIT2
|dllen
) , SDRC_DLLB_CTRL
);
306 return; /* STACKED, other configued type */
307 ++pass_type
; /* IPDDR->COMBODDR->IPSDR for CS0 */
311 /*****************************************************
312 * gpmc_init(): init gpmc bus
313 * Init GPMC for x16, MuxMode (SDRAM in x32).
314 * This code can only be executed from SRAM or SDRAM.
315 *****************************************************/
318 u32 mux
=0, mtype
, mwidth
, rev
, tval
;
321 if (rev
== CPU_2420_2422_ES1
)
324 tval
= 0; /* disable bit switched meaning */
326 /* global settings */
327 __raw_writel(0x10, GPMC_SYSCONFIG
); /* smart idle */
328 __raw_writel(0x0, GPMC_IRQENABLE
); /* isr's sources masked */
329 __raw_writel(tval
, GPMC_TIMEOUT_CONTROL
);/* timeout disable */
331 __raw_writel(0x001, GPMC_CONFIG
); /* set nWP, disable limited addr */
333 __raw_writel(0x111, GPMC_CONFIG
); /* set nWP, disable limited addr */
336 /* discover bus connection from sysboot */
337 if (is_gpmc_muxed() == GPMC_MUXED
)
339 mtype
= get_gpmc0_type();
340 mwidth
= get_gpmc0_width();
343 __raw_writel(0x0, GPMC_CONFIG7_0
); /* disable current map */
347 __raw_writel(H4_24XX_GPMC_CONFIG1_0
|mtype
|mwidth
, GPMC_CONFIG1_0
);
349 __raw_writel(H4_24XX_GPMC_CONFIG1_0
|mux
|mtype
|mwidth
, GPMC_CONFIG1_0
);
352 #ifdef PRCM_CONFIG_III
353 __raw_writel(H4_24XX_GPMC_CONFIG2_0
, GPMC_CONFIG2_0
);
355 __raw_writel(H4_24XX_GPMC_CONFIG3_0
, GPMC_CONFIG3_0
);
356 __raw_writel(H4_24XX_GPMC_CONFIG4_0
, GPMC_CONFIG4_0
);
357 #ifdef PRCM_CONFIG_III
358 __raw_writel(H4_24XX_GPMC_CONFIG5_0
, GPMC_CONFIG5_0
);
359 __raw_writel(H4_24XX_GPMC_CONFIG6_0
, GPMC_CONFIG6_0
);
361 __raw_writel(H4_24XX_GPMC_CONFIG7_0
, GPMC_CONFIG7_0
);/* enable new mapping */
365 __raw_writel(0, GPMC_CONFIG7_1
); /* disable any mapping */
367 __raw_writel(H4_24XX_GPMC_CONFIG1_1
|mux
, GPMC_CONFIG1_1
);
368 __raw_writel(H4_24XX_GPMC_CONFIG2_1
, GPMC_CONFIG2_1
);
369 __raw_writel(H4_24XX_GPMC_CONFIG3_1
, GPMC_CONFIG3_1
);
370 __raw_writel(H4_24XX_GPMC_CONFIG4_1
, GPMC_CONFIG4_1
);
371 __raw_writel(H4_24XX_GPMC_CONFIG5_1
, GPMC_CONFIG5_1
);
372 __raw_writel(H4_24XX_GPMC_CONFIG6_1
, GPMC_CONFIG6_1
);
373 __raw_writel(H4_24XX_GPMC_CONFIG7_1
, GPMC_CONFIG7_1
); /* enable mapping */