2 * Jz5730 common routines
5 * Ingenic Semiconductor, <jlwei@ingenic.cn>
7 * This program is free software; you can redistribute it and/or
8 * modify it under the terms of the GNU General Public License as
9 * published by the Free Software Foundation; either version 2 of
10 * the License, or (at your option) any later version.
12 * This program is distributed in the hope that it will be useful,
13 * but WITHOUT ANY WARRANTY; without even the implied warranty of
14 * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
15 * GNU General Public License for more details.
17 * You should have received a copy of the GNU General Public License
18 * along with this program; if not, write to the Free Software
19 * Foundation, Inc., 59 Temple Place, Suite 330, Boston,
30 #include <asm/jz5730.h>
32 extern void board_early_init(void);
33 extern void board_led(char ch
);
35 static void sdram_init(void)
37 DECLARE_GLOBAL_DATA_PTR
;
39 register unsigned int dmcr
, sdmode
, tmp
, ns
;
40 volatile unsigned int *p
;
42 unsigned int cas_latency_sdmr
[2] = {
47 unsigned int cas_latency_dmcr
[2] = {
48 1 << EMC_DMCR_TCL_BIT
, /* CAS latency is 2 */
49 2 << EMC_DMCR_TCL_BIT
/* CAS latency is 3 */
52 REG_EMC_BCR
= EMC_BCR_BRE
; /* Enable SPLIT */
53 REG_EMC_RTCSR
= EMC_RTCSR_CKS_DISABLE
;
57 /* Basic DMCR register value. */
58 dmcr
= ((SDRAM_ROW
-11)<<EMC_DMCR_RA_BIT
) |
59 ((SDRAM_COL
-8)<<EMC_DMCR_CA_BIT
) |
60 (SDRAM_BANK4
<<EMC_DMCR_BA_BIT
) |
61 (SDRAM_BW16
<<EMC_DMCR_BW_BIT
) |
63 cas_latency_dmcr
[((SDRAM_CASL
== 3) ? 1 : 0)];
65 /* SDRAM timimg parameters */
66 ns
= 1000000000 / gd
->mem_clk
;
73 dmcr
|= ((tmp
-4) << EMC_DMCR_TRAS_BIT
);
77 dmcr
|= (tmp
<< EMC_DMCR_RCD_BIT
);
81 dmcr
|= (tmp
<< EMC_DMCR_TPC_BIT
);
85 dmcr
|= (tmp
<< EMC_DMCR_TRWL_BIT
);
86 tmp
= (SDRAM_TRAS
+ SDRAM_TPC
)/ns
;
89 dmcr
|= (((tmp
+ 1) >> 1) << EMC_DMCR_TRC_BIT
);
91 /* SDRAM mode values */
92 sdmode
= EMC_SDMR_BT_SEQ
|
95 cas_latency_sdmr
[((SDRAM_CASL
== 3) ? 1 : 0)];
102 /* First, precharge phase */
105 /* Set refresh registers */
112 REG_EMC_RTCSR
= EMC_RTCSR_CKS_64
; /* Divisor is 64, CKO/64 */
114 /* precharge all chip-selects */
115 REG8(EMC_SDMR0
|sdmode
) = 0;
116 REG8(EMC_SDMR1
|sdmode
) = 0;
118 /* wait for precharge, > 200us */
119 tmp
= (gd
->cpu_clk
/ 1000000) * 200;
122 /* enable refresh and set SDRAM mode */
123 REG_EMC_DMCR
= dmcr
| EMC_DMCR_RFSH
| EMC_DMCR_MRSET
;
125 /* write sdram mode register for each chip-select */
126 REG8(EMC_SDMR0
|sdmode
) = 0;
127 REG8(EMC_SDMR1
|sdmode
) = 0;
129 /* do simple memory check */
130 p
= (volatile unsigned int *)(0xa0100000);
136 if (*p
!= 0x12345678) {
137 /* memory initialization failed */
142 /* everything is ok now */
146 static void calc_clocks(void)
148 DECLARE_GLOBAL_DATA_PTR
;
152 unsigned int od
[4] = {1, 2, 2, 4};
153 unsigned int div
[10] = {1, 2, 3, 4, 6, 8, 12, 16, 24, 32};
154 unsigned int nf
, nr
, nd
;
156 nf
= __cpm_plcr1_fd() + 2;
157 nr
= __cpm_plcr1_rd() + 2;
158 nd
= od
[__cpm_plcr1_od()];
160 pllout
= (CFG_EXTAL
/ (nr
* nd
)) * nf
;
162 gd
->cpu_clk
= pllout
/ div
[__cpm_cfcr_ifr()];
163 gd
->sys_clk
= pllout
/ div
[__cpm_cfcr_sfr()];
164 gd
->per_clk
= pllout
/ div
[__cpm_cfcr_pfr()];
165 gd
->mem_clk
= pllout
/ div
[__cpm_cfcr_mfr()];
166 gd
->dev_clk
= CFG_EXTAL
;
168 gd
->cpu_clk
= gd
->sys_clk
= gd
->per_clk
=
169 gd
->mem_clk
= gd
->dev_clk
= CFG_EXTAL
;
173 static void check_reset(void)
175 if (REG_CPM_RSTR
& 0x4) {
176 /* CPU was reset by hibernate wakeup */
177 void (*resume
) (void);
180 REG_CPM_SCR
&= ~CPM_SCR_HGP
;
182 /* Jump to sleep address directly */
183 resume
= (void (*)(void))(REG_CPM_SPR
| 0x80000000);
188 /* PLL output clock = EXTAL * NF / (NR * NO)
190 * NF = FD + 2, NR = RD + 2
191 * NO = 1 (if OD = 0), NO = 2 (if OD = 1 or 2), NO = 4 (if OD = 3)
193 static void pll_init(void)
195 register unsigned int cfcr
, plcr1
;
197 0, 0, 1, 2, 3, 0, 4, 0, 5, 0, 0, 0, 6, 0, 0, 0,
198 7, 0, 0, 0, 0, 0, 0, 0, 8, 0, 0, 0, 0, 0, 0, 0,
201 int div
[5] = {1, 3, 3, 3, 10}; /* divisors of I:S:P:M:SSI */
204 cfcr
= CPM_CFCR_CKOEN
;
205 cfcr
|= ((CFG_CPU_SPEED
/48000000 - 1) << 25); /* USB clock divider */
207 cfcr
|= (n2FR
[div
[0]] << CPM_CFCR_IFR_BIT
) |
208 (n2FR
[div
[1]] << CPM_CFCR_SFR_BIT
) |
209 (n2FR
[div
[2]] << CPM_CFCR_PFR_BIT
) |
210 (n2FR
[div
[3]] << CPM_CFCR_MFR_BIT
) |
211 ((div
[4]-1) << CPM_CFCR_SSIFR_BIT
);
213 nf
= CFG_CPU_SPEED
* 2 / CFG_EXTAL
;
215 plcr1
= ((nf
- 2) << CPM_PLCR1_PLL1FD_BIT
) | /* FD=NF-2 */
216 (0 << CPM_PLCR1_PLL1RD_BIT
) | /* RD=0, NR=2, 1.8432 = 3.6864/2 */
217 (0 << CPM_PLCR1_PLL1OD_BIT
) | /* OD=0, NO=1 */
218 (0x20 << CPM_PLCR1_PLL1ST_BIT
) | /* PLL stable time */
219 CPM_PLCR1_PLL1EN
; /* enable PLL */
223 REG_CPM_PLCR1
= plcr1
;
226 //----------------------------------------------------------------------
227 // jz5730 board init routine
229 int jz_board_init(void)
231 board_early_init(); /* init gpio etc. */
232 pll_init(); /* init PLL */
233 calc_clocks(); /* calc the clocks */
234 sdram_init(); /* init sdram memory */
235 check_reset(); /* check the reset status */
239 //----------------------------------------------------------------------
240 // U-Boot common routines
242 long int initdram(int board_type
)
245 u32 rows
, cols
, dw
, banks
;
249 rows
= 11 + ((dmcr
& EMC_DMCR_RA_MASK
) >> EMC_DMCR_RA_BIT
);
250 cols
= 8 + ((dmcr
& EMC_DMCR_CA_MASK
) >> EMC_DMCR_CA_BIT
);
251 dw
= (dmcr
& EMC_DMCR_BW
) ? 2 : 4;
252 banks
= (dmcr
& EMC_DMCR_BA
) ? 4 : 2;
254 size
= (1 << (rows
+ cols
)) * dw
* banks
;
259 //----------------------------------------------------------------------
262 /* we always count down the max. */
263 #define TIMER_LOAD_VAL 0xffffffff
266 /* macro to read the 32 bit timer */
267 #define READ_TIMER __ost_get_count(CHANNEL_ID)
269 static ulong timestamp
;
270 static ulong lastdec
;
272 void reset_timer_masked (void);
273 ulong
get_timer_masked (void);
274 void udelay_masked (unsigned long usec
);
277 * timer without interrupts
282 __ost_set_clock(CHANNEL_ID
, OST_TCSR_CKS_PCLK_256
);
283 __ost_set_reload(CHANNEL_ID
, TIMER_LOAD_VAL
);
284 __ost_set_count(CHANNEL_ID
, TIMER_LOAD_VAL
);
285 __ost_enable_channel(CHANNEL_ID
);
287 lastdec
= TIMER_LOAD_VAL
;
293 void reset_timer(void)
295 reset_timer_masked ();
298 ulong
get_timer(ulong base
)
300 return get_timer_masked () - base
;
303 void set_timer(ulong t
)
308 void udelay (unsigned long usec
)
327 /* check for rollover during this delay */
329 if ((tmp
+ tmo
) < tmp
)
330 reset_timer_masked(); /* timer would roll over */
334 while (get_timer_masked () < tmo
);
337 void reset_timer_masked (void)
340 lastdec
= READ_TIMER
;
344 ulong
get_timer_masked (void)
346 ulong now
= READ_TIMER
;
348 if (lastdec
>= now
) {
350 timestamp
+= (lastdec
- now
);
352 /* we have an overflow ... */
353 timestamp
+= ((lastdec
+ TIMER_LOAD_VAL
) - now
);
360 void udelay_masked (unsigned long usec
)
380 endtime
= get_timer_masked () + tmo
;
383 ulong now
= get_timer_masked ();
384 diff
= endtime
- now
;
389 * This function is derived from PowerPC code (read timebase as long long).
390 * On MIPS it just returns the timer value.
392 unsigned long long get_ticks(void)
398 * This function is derived from PowerPC code (timebase clock frequency).
399 * On MIPS it returns the number of timer ticks per second.
401 ulong
get_tbclk (void)
406 //---------------------------------------------------------------------
407 // End of timer routine.
408 //---------------------------------------------------------------------
410 #endif /* CONFIG_JZ5730 */