change console=tty0 to enable linux framebuffer console
[jz_uboot.git] / cpu / mips / jz5730.c
blob79ea797b9522926c1675ab16544cff11ad3e2219
1 /*
2 * Jz5730 common routines
4 * Copyright (c) 2005
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,
20 * MA 02111-1307 USA
23 #include <config.h>
25 #ifdef CONFIG_JZ5730
27 #include <common.h>
28 #include <command.h>
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] = {
43 EMC_SDMR_CAS_2,
44 EMC_SDMR_CAS_3,
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;
54 REG_EMC_RTCOR = 0;
55 REG_EMC_RTCNT = 0;
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) |
62 EMC_DMCR_EPIN |
63 cas_latency_dmcr[((SDRAM_CASL == 3) ? 1 : 0)];
65 /* SDRAM timimg parameters */
66 ns = 1000000000 / gd->mem_clk;
68 tmp = SDRAM_TRAS/ns;
69 if (tmp < 4)
70 tmp = 4;
71 if (tmp > 11)
72 tmp = 11;
73 dmcr |= ((tmp-4) << EMC_DMCR_TRAS_BIT);
74 tmp = SDRAM_RCD/ns;
75 if (tmp > 3)
76 tmp = 3;
77 dmcr |= (tmp << EMC_DMCR_RCD_BIT);
78 tmp = SDRAM_TPC/ns;
79 if (tmp > 7)
80 tmp = 7;
81 dmcr |= (tmp << EMC_DMCR_TPC_BIT);
82 tmp = SDRAM_TRWL/ns;
83 if (tmp > 3)
84 tmp = 3;
85 dmcr |= (tmp << EMC_DMCR_TRWL_BIT);
86 tmp = (SDRAM_TRAS + SDRAM_TPC)/ns;
87 if (tmp > 14)
88 tmp = 14;
89 dmcr |= (((tmp + 1) >> 1) << EMC_DMCR_TRC_BIT);
91 /* SDRAM mode values */
92 sdmode = EMC_SDMR_BT_SEQ |
93 EMC_SDMR_OM_NORMAL |
94 EMC_SDMR_BL_4 |
95 cas_latency_sdmr[((SDRAM_CASL == 3) ? 1 : 0)];
97 if (SDRAM_BW16)
98 sdmode <<= 1;
99 else
100 sdmode <<= 2;
102 /* First, precharge phase */
103 REG_EMC_DMCR = dmcr;
105 /* Set refresh registers */
106 tmp = SDRAM_TREF/ns;
107 tmp = tmp/64 + 1;
108 if (tmp > 0xff)
109 tmp = 0xff;
111 REG_EMC_RTCOR = tmp;
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;
120 while (tmp--);
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);
131 *p = 0x12345678;
132 p += 1;
133 *p = 0x87654321;
134 p -= 1;
136 if (*p != 0x12345678) {
137 /* memory initialization failed */
138 board_led(0xe);
139 while (1);
142 /* everything is ok now */
143 board_led(0x1);
146 static void calc_clocks(void)
148 DECLARE_GLOBAL_DATA_PTR;
150 #ifndef CONFIG_FPGA
151 unsigned int pllout;
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;
167 #else
168 gd->cpu_clk = gd->sys_clk = gd->per_clk =
169 gd->mem_clk = gd->dev_clk = CFG_EXTAL;
170 #endif
173 static void check_reset(void)
175 if (REG_CPM_RSTR & 0x4) {
176 /* CPU was reset by hibernate wakeup */
177 void (*resume) (void);
179 /* Clear HGP */
180 REG_CPM_SCR &= ~CPM_SCR_HGP;
182 /* Jump to sleep address directly */
183 resume = (void (*)(void))(REG_CPM_SPR | 0x80000000);
184 resume();
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;
196 int n2FR[33] = {
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 */
202 int nf;
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 */
221 /* init PLL */
222 REG_CPM_CFCR = cfcr;
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 */
236 return 0;
239 //----------------------------------------------------------------------
240 // U-Boot common routines
242 long int initdram(int board_type)
244 u32 dmcr;
245 u32 rows, cols, dw, banks;
246 ulong size;
248 dmcr = REG_EMC_DMCR;
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;
256 return size;
259 //----------------------------------------------------------------------
260 // Timer routines
262 /* we always count down the max. */
263 #define TIMER_LOAD_VAL 0xffffffff
265 #define CHANNEL_ID 0
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
280 int timer_init(void)
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;
288 timestamp = 0;
290 return 0;
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)
305 timestamp = t;
308 void udelay (unsigned long usec)
310 ulong tmo,tmp;
312 /* normalize */
313 if (usec >= 1000) {
314 tmo = usec / 1000;
315 tmo *= CFG_HZ;
316 tmo /= 1000;
318 else {
319 if (usec >= 1) {
320 tmo = usec * CFG_HZ;
321 tmo /= (1000*1000);
323 else
324 tmo = 1;
327 /* check for rollover during this delay */
328 tmp = get_timer (0);
329 if ((tmp + tmo) < tmp )
330 reset_timer_masked(); /* timer would roll over */
331 else
332 tmo += tmp;
334 while (get_timer_masked () < tmo);
337 void reset_timer_masked (void)
339 /* reset time */
340 lastdec = READ_TIMER;
341 timestamp = 0;
344 ulong get_timer_masked (void)
346 ulong now = READ_TIMER;
348 if (lastdec >= now) {
349 /* normal mode */
350 timestamp += (lastdec - now);
351 } else {
352 /* we have an overflow ... */
353 timestamp += ((lastdec + TIMER_LOAD_VAL) - now);
355 lastdec = now;
357 return timestamp;
360 void udelay_masked (unsigned long usec)
362 ulong tmo;
363 ulong endtime;
364 signed long diff;
366 /* normalize */
367 if (usec >= 1000) {
368 tmo = usec / 1000;
369 tmo *= CFG_HZ;
370 tmo /= 1000;
371 } else {
372 if (usec > 1) {
373 tmo = usec * CFG_HZ;
374 tmo /= (1000*1000);
375 } else {
376 tmo = 1;
380 endtime = get_timer_masked () + tmo;
382 do {
383 ulong now = get_timer_masked ();
384 diff = endtime - now;
385 } while (diff >= 0);
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)
394 return get_timer(0);
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)
403 return CFG_HZ;
406 //---------------------------------------------------------------------
407 // End of timer routine.
408 //---------------------------------------------------------------------
410 #endif /* CONFIG_JZ5730 */