summaryrefslogtreecommitdiff
path: root/firmware/target/mips/ingenic_jz47xx/system-jz4760.c
diff options
context:
space:
mode:
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/system-jz4760.c')
-rw-r--r--firmware/target/mips/ingenic_jz47xx/system-jz4760.c710
1 files changed, 710 insertions, 0 deletions
diff --git a/firmware/target/mips/ingenic_jz47xx/system-jz4760.c b/firmware/target/mips/ingenic_jz47xx/system-jz4760.c
new file mode 100644
index 0000000000..8472a7378f
--- /dev/null
+++ b/firmware/target/mips/ingenic_jz47xx/system-jz4760.c
@@ -0,0 +1,710 @@
1/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2016 by Roman Stolyarov
11 *
12 * This program is free software; you can redistribute it and/or
13 * modify it under the terms of the GNU General Public License
14 * as published by the Free Software Foundation; either version 2
15 * of the License, or (at your option) any later version.
16 *
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
19 *
20 ****************************************************************************/
21
22#include "config.h"
23#include "cpu.h"
24#include "mips.h"
25#include "mmu-mips.h"
26#include "panic.h"
27#include "system.h"
28#include "kernel.h"
29#include "power.h"
30
31static int irq;
32static void UIRQ(void)
33{
34 panicf("Unhandled interrupt occurred: %d", irq);
35}
36
37#define intr(name) extern __attribute__((weak,alias("UIRQ"))) void name (void)
38
39intr(I2C1);intr(I2C0);intr(UART3);intr(UART2);intr(UART1);intr(UART0);intr(GPU);
40intr(SSI1);intr(SSI0);intr(TSSI);intr(KBC);intr(SADC);intr(ETH);intr(UHC);
41intr(OTG);intr(TCU2);intr(TCU1);intr(TCU0);intr(GPS);intr(IPU);intr(CIM);
42intr(LCD);intr(RTC);intr(OWI);intr(AIC);intr(MSC2);intr(MSC1);intr(MSC0);
43intr(SCC);intr(BCH);intr(PCM);intr(HARB0);intr(HARB2);intr(AOSD);intr(CPM);
44
45intr(DMA0);intr(DMA1);intr(DMA2);intr(DMA3);intr(DMA4);intr(DMA5);
46intr(DMA6);intr(DMA7);intr(DMA8);intr(DMA9);intr(DMA10);intr(DMA11);
47intr(MDMA0);intr(MDMA1);intr(MDMA2);
48intr(BDMA0);intr(BDMA1);intr(BDMA2);
49
50intr(GPIO0);intr(GPIO1);intr(GPIO2);intr(GPIO3);intr(GPIO4);intr(GPIO5);
51intr(GPIO6);intr(GPIO7);intr(GPIO8);intr(GPIO9);intr(GPIO10);intr(GPIO11);
52intr(GPIO12);intr(GPIO13);intr(GPIO14);intr(GPIO15);intr(GPIO16);intr(GPIO17);
53intr(GPIO18);intr(GPIO19);intr(GPIO20);intr(GPIO21);intr(GPIO22);intr(GPIO23);
54intr(GPIO24);intr(GPIO25);intr(GPIO26);intr(GPIO27);intr(GPIO28);intr(GPIO29);
55intr(GPIO30);intr(GPIO31);intr(GPIO32);intr(GPIO33);intr(GPIO34);intr(GPIO35);
56intr(GPIO36);intr(GPIO37);intr(GPIO38);intr(GPIO39);intr(GPIO40);intr(GPIO41);
57intr(GPIO42);intr(GPIO43);intr(GPIO44);intr(GPIO45);intr(GPIO46);intr(GPIO47);
58intr(GPIO48);intr(GPIO49);intr(GPIO50);intr(GPIO51);intr(GPIO52);intr(GPIO53);
59intr(GPIO54);intr(GPIO55);intr(GPIO56);intr(GPIO57);intr(GPIO58);intr(GPIO59);
60intr(GPIO60);intr(GPIO61);intr(GPIO62);intr(GPIO63);intr(GPIO64);intr(GPIO65);
61intr(GPIO66);intr(GPIO67);intr(GPIO68);intr(GPIO69);intr(GPIO70);intr(GPIO71);
62intr(GPIO72);intr(GPIO73);intr(GPIO74);intr(GPIO75);intr(GPIO76);intr(GPIO77);
63intr(GPIO78);intr(GPIO79);intr(GPIO80);intr(GPIO81);intr(GPIO82);intr(GPIO83);
64intr(GPIO84);intr(GPIO85);intr(GPIO86);intr(GPIO87);intr(GPIO88);intr(GPIO89);
65intr(GPIO90);intr(GPIO91);intr(GPIO92);intr(GPIO93);intr(GPIO94);intr(GPIO95);
66intr(GPIO96);intr(GPIO97);intr(GPIO98);intr(GPIO99);intr(GPIO100);intr(GPIO101);
67intr(GPIO102);intr(GPIO103);intr(GPIO104);intr(GPIO105);intr(GPIO106);
68intr(GPIO107);intr(GPIO108);intr(GPIO109);intr(GPIO110);intr(GPIO111);
69intr(GPIO112);intr(GPIO113);intr(GPIO114);intr(GPIO115);intr(GPIO116);
70intr(GPIO117);intr(GPIO118);intr(GPIO119);intr(GPIO120);intr(GPIO121);
71intr(GPIO122);intr(GPIO123);intr(GPIO124);intr(GPIO125);intr(GPIO126);
72intr(GPIO127);intr(GPIO128);intr(GPIO129);intr(GPIO130);intr(GPIO131);
73intr(GPIO132);intr(GPIO133);intr(GPIO134);intr(GPIO135);intr(GPIO136);
74intr(GPIO137);intr(GPIO138);intr(GPIO139);intr(GPIO140);intr(GPIO141);
75intr(GPIO142);intr(GPIO143);intr(GPIO144);intr(GPIO145);intr(GPIO146);
76intr(GPIO147);intr(GPIO148);intr(GPIO149);intr(GPIO150);intr(GPIO151);
77intr(GPIO152);intr(GPIO153);intr(GPIO154);intr(GPIO155);intr(GPIO156);
78intr(GPIO157);intr(GPIO158);intr(GPIO159);intr(GPIO160);intr(GPIO161);
79intr(GPIO162);intr(GPIO163);intr(GPIO164);intr(GPIO165);intr(GPIO166);
80intr(GPIO167);intr(GPIO168);intr(GPIO169);intr(GPIO170);intr(GPIO171);
81intr(GPIO172);intr(GPIO173);intr(GPIO174);intr(GPIO175);intr(GPIO176);
82intr(GPIO177);intr(GPIO178);intr(GPIO179);intr(GPIO180);intr(GPIO181);
83intr(GPIO182);intr(GPIO183);intr(GPIO184);intr(GPIO185);intr(GPIO186);
84intr(GPIO187);intr(GPIO188);intr(GPIO189);intr(GPIO190);intr(GPIO191);
85
86static void (* const irqvector[])(void) =
87{
88 I2C1,I2C0,UART3,UART2,UART1,UART0,GPU,SSI1,
89 SSI0,TSSI,UIRQ,KBC,UIRQ,UIRQ,UIRQ,UIRQ,
90 UIRQ,UIRQ,SADC,ETH,UHC,OTG,UIRQ,UIRQ,
91 UIRQ,TCU2,TCU1,TCU0,GPS,IPU,CIM,LCD,
92
93 RTC,OWI,AIC,MSC2,MSC1,MSC0,SCC,BCH, // 32
94 PCM,HARB0,HARB2,AOSD,CPM,UIRQ,
95
96 DMA0,DMA1,DMA2,DMA3,DMA4,DMA5,DMA6,DMA7, // 46
97 DMA8,DMA9,DMA10,DMA11,MDMA0,MDMA1,MDMA2,BDMA0,
98 BDMA1,BDMA2,
99
100 GPIO0,GPIO1,GPIO2,GPIO3,GPIO4,GPIO5,GPIO6,GPIO7, // 64
101 GPIO8,GPIO9,GPIO10,GPIO11,GPIO12,GPIO13,GPIO14,GPIO15,
102 GPIO16,GPIO17,GPIO18,GPIO19,GPIO20,GPIO21,GPIO22,GPIO23,
103 GPIO24,GPIO25,GPIO26,GPIO27,GPIO28,GPIO29,GPIO30,GPIO31,
104 GPIO32,GPIO33,GPIO34,GPIO35,GPIO36,GPIO37,GPIO38,GPIO39,
105 GPIO40,GPIO41,GPIO42,GPIO43,GPIO44,GPIO45,GPIO46,GPIO47,
106 GPIO48,GPIO49,GPIO50,GPIO51,GPIO52,GPIO53,GPIO54,GPIO55,
107 GPIO56,GPIO57,GPIO58,GPIO59,GPIO60,GPIO61,GPIO62,GPIO63,
108 GPIO64,GPIO65,GPIO66,GPIO67,GPIO68,GPIO69,GPIO70,GPIO71,
109 GPIO72,GPIO73,GPIO74,GPIO75,GPIO76,GPIO77,GPIO78,GPIO79,
110 GPIO80,GPIO81,GPIO82,GPIO83,GPIO84,GPIO85,GPIO86,GPIO87,
111 GPIO88,GPIO89,GPIO90,GPIO91,GPIO92,GPIO93,GPIO94,GPIO95,
112 GPIO96,GPIO97,GPIO98,GPIO99,GPIO100,GPIO101,GPIO102,GPIO103,
113 GPIO104,GPIO105,GPIO106,GPIO107,GPIO108,GPIO109,GPIO110,GPIO111,
114 GPIO112,GPIO113,GPIO114,GPIO115,GPIO116,GPIO117,GPIO118,GPIO119,
115 GPIO120,GPIO121,GPIO122,GPIO123,GPIO124,GPIO125,GPIO126,GPIO127,
116 GPIO128,GPIO129,GPIO130,GPIO131,GPIO132,GPIO133,GPIO134,GPIO135,
117 GPIO136,GPIO137,GPIO138,GPIO139,GPIO140,GPIO141,GPIO142,GPIO143,
118 GPIO144,GPIO145,GPIO146,GPIO147,GPIO148,GPIO149,GPIO150,GPIO151,
119 GPIO152,GPIO153,GPIO154,GPIO155,GPIO156,GPIO157,GPIO158,GPIO159,
120 GPIO160,GPIO161,GPIO162,GPIO163,GPIO164,GPIO165,GPIO166,GPIO167,
121 GPIO168,GPIO169,GPIO170,GPIO171,GPIO172,GPIO173,GPIO174,GPIO175,
122 GPIO176,GPIO177,GPIO178,GPIO179,GPIO180,GPIO181,GPIO182,GPIO183,
123 GPIO184,GPIO185,GPIO186,GPIO187,GPIO188,GPIO189,GPIO190,GPIO191
124};
125
126static unsigned int dma_irq_mask = 0;
127static unsigned char mdma_irq_mask = 0;
128static unsigned char bdma_irq_mask = 0;
129static unsigned int gpio_irq_mask[6] = {0};
130
131void system_enable_irq(unsigned int irq)
132{
133 register unsigned int t;
134 if ((irq >= IRQ_GPIO_0) && (irq <= IRQ_GPIO_0 + NUM_GPIO))
135 {
136 __gpio_unmask_irq(irq - IRQ_GPIO_0);
137 t = (irq - IRQ_GPIO_0) >> 5;
138 gpio_irq_mask[t] |= (1 << ((irq - IRQ_GPIO_0) & 0x1f));
139 __intc_unmask_irq(IRQ_GPIO0 - t);
140 }
141 else if ((irq >= IRQ_DMA_0) && (irq <= IRQ_DMA_0 + NUM_DMA))
142 {
143 __dmac_channel_enable_irq(irq - IRQ_DMA_0);
144 t = (irq - IRQ_DMA_0) / HALF_DMA_NUM;
145 dma_irq_mask |= (1 << (irq - IRQ_DMA_0));
146 __intc_unmask_irq(IRQ_DMAC0 - t);
147 }
148 else if ((irq >= IRQ_MDMA_0) && (irq <= IRQ_MDMA_0 + NUM_MDMA))
149 {
150 __mdmac_channel_enable_irq(irq - IRQ_MDMA_0);
151 mdma_irq_mask |= (1 << (irq - IRQ_MDMA_0));
152 __intc_unmask_irq(IRQ_MDMA);
153 }
154 else if ((irq >= IRQ_BDMA_0) && (irq <= IRQ_BDMA_0 + NUM_BDMA))
155 {
156 __bdmac_channel_enable_irq(irq - IRQ_BDMA_0);
157 bdma_irq_mask |= (1 << (irq - IRQ_BDMA_0));
158 __intc_unmask_irq(IRQ_BDMA);
159 }
160 else if (irq < IRQ_INTC_MAX)
161 __intc_unmask_irq(irq);
162}
163
164static void dis_irq(unsigned int irq)
165{
166 register unsigned int t;
167 if ((irq >= IRQ_GPIO_0) && (irq <= IRQ_GPIO_0 + NUM_GPIO))
168 {
169 __gpio_mask_irq(irq - IRQ_GPIO_0);
170 t = (irq - IRQ_GPIO_0) >> 5;
171 gpio_irq_mask[t] &= ~(1 << ((irq - IRQ_GPIO_0) & 0x1f));
172 if (!gpio_irq_mask[t])
173 __intc_mask_irq(IRQ_GPIO0 - t);
174 }
175 else if ((irq >= IRQ_DMA_0) && (irq < IRQ_DMA_0 + NUM_DMA))
176 {
177 __dmac_channel_disable_irq(irq - IRQ_DMA_0);
178 dma_irq_mask &= ~(1 << (irq - IRQ_DMA_0));
179 if (!(dma_irq_mask & 0x003F))
180 __intc_mask_irq(IRQ_DMAC0);
181 if (!(dma_irq_mask & 0x0FC0))
182 __intc_mask_irq(IRQ_DMAC1);
183 }
184 else if ((irq >= IRQ_MDMA_0) && (irq < IRQ_MDMA_0 + NUM_MDMA))
185 {
186 __mdmac_channel_disable_irq(irq - IRQ_MDMA_0);
187 mdma_irq_mask &= ~(1 << (irq - IRQ_MDMA_0));
188 if (!mdma_irq_mask)
189 __intc_mask_irq(IRQ_MDMA);
190 }
191 else if ((irq >= IRQ_BDMA_0) && (irq < IRQ_BDMA_0 + NUM_BDMA))
192 {
193 __bdmac_channel_disable_irq(irq - IRQ_BDMA_0);
194 bdma_irq_mask &= ~(1 << (irq - IRQ_BDMA_0));
195 if (!bdma_irq_mask)
196 __intc_mask_irq(IRQ_BDMA);
197 }
198 else if (irq < IRQ_INTC_MAX)
199 __intc_mask_irq(irq);
200}
201
202static void ack_irq(unsigned int irq)
203{
204 if ((irq >= IRQ_GPIO_0) && (irq <= IRQ_GPIO_0 + NUM_GPIO))
205 {
206 __gpio_ack_irq(irq - IRQ_GPIO_0);
207 }
208}
209
210static int get_irq_number(void)
211{
212 static unsigned long ipl0, ipl1;
213 register int irq0, irq1;
214
215 ipl0 |= REG_INTC_ICPR(0);
216 ipl1 |= REG_INTC_ICPR(1);
217
218 if (!(ipl0 || ipl1))
219 return -1;
220
221 __asm__ __volatile__("negu $8, %0 \n"
222 "and $8, %0, $8 \n"
223 "clz %0, %1 \n"
224 "li $8, 31 \n"
225 "subu %0, $8, %0 \n"
226 : "=r" (irq0)
227 : "r" (ipl0)
228 : "t0"
229 );
230
231 __asm__ __volatile__("negu $8, %0 \n"
232 "and $8, %0, $8 \n"
233 "clz %0, %1 \n"
234 "li $8, 31 \n"
235 "subu %0, $8, %0 \n"
236 : "=r" (irq1)
237 : "r" (ipl1)
238 : "t0"
239 );
240
241 if (UNLIKELY(irq0 < 0) && UNLIKELY(irq1 < 0))
242 return -1;
243
244 if (!(ipl0 & 3)) {
245 if (ipl0) {
246 irq = irq0;
247 ipl0 &= ~(1<<irq0);
248 } else {
249 irq = irq1 + 32;
250 ipl1 &= ~(1<<irq1);
251 }
252 } else {
253 if (ipl0 & 2) {
254 irq = 1;
255 ipl0 &= ~(1<<irq);
256 } else {
257 irq = 0;
258 ipl0 &= ~(1<<irq);
259 }
260 }
261
262 switch (irq)
263 {
264 case IRQ_GPIO0:
265 case IRQ_GPIO1:
266 case IRQ_GPIO2:
267 case IRQ_GPIO3:
268 case IRQ_GPIO4:
269 case IRQ_GPIO5:
270 irq = __gpio_get_irq() + IRQ_GPIO_0;
271 break;
272 case IRQ_DMAC0:
273 case IRQ_DMAC1:
274 irq = __dmac_get_irq() + IRQ_DMA_0;
275 break;
276 case IRQ_MDMA:
277 irq = __mdmac_get_irq() + IRQ_MDMA_0;
278 break;
279 case IRQ_BDMA:
280 irq = __bdmac_get_irq() + IRQ_BDMA_0;
281 break;
282 }
283
284 return irq;
285}
286
287void intr_handler(void)
288{
289 register int irq = get_irq_number();
290 if(UNLIKELY(irq < 0))
291 return;
292
293 ack_irq(irq);
294 if(LIKELY(irq >= 0))
295 irqvector[irq]();
296}
297
298#define EXC(x,y) case (x): return (y);
299static char* parse_exception(unsigned int cause)
300{
301 switch(cause & M_CauseExcCode)
302 {
303 EXC(EXC_INT, "Interrupt");
304 EXC(EXC_MOD, "TLB Modified");
305 EXC(EXC_TLBL, "TLB Exception (Load or Ifetch)");
306 EXC(EXC_ADEL, "Address Error (Load or Ifetch)");
307 EXC(EXC_ADES, "Address Error (Store)");
308 EXC(EXC_TLBS, "TLB Exception (Store)");
309 EXC(EXC_IBE, "Instruction Bus Error");
310 EXC(EXC_DBE, "Data Bus Error");
311 EXC(EXC_SYS, "Syscall");
312 EXC(EXC_BP, "Breakpoint");
313 EXC(EXC_RI, "Reserved Instruction");
314 EXC(EXC_CPU, "Coprocessor Unusable");
315 EXC(EXC_OV, "Overflow");
316 EXC(EXC_TR, "Trap Instruction");
317 EXC(EXC_FPE, "Floating Point Exception");
318 EXC(EXC_C2E, "COP2 Exception");
319 EXC(EXC_MDMX, "MDMX Exception");
320 EXC(EXC_WATCH, "Watch Exception");
321 EXC(EXC_MCHECK, "Machine Check Exception");
322 EXC(EXC_CacheErr, "Cache error caused re-entry to Debug Mode");
323 default:
324 return NULL;
325 }
326}
327
328void exception_handler(void* stack_ptr, unsigned int cause, unsigned int epc)
329{
330 panicf("Exception occurred: %s [0x%08x] at 0x%08x (stack at 0x%08x)", parse_exception(cause), read_c0_badvaddr(), epc, (unsigned int)stack_ptr);
331}
332
333void tlb_refill_handler(void)
334{
335 panicf("TLB refill handler at 0x%08lx! [0x%x]", read_c0_epc(), read_c0_badvaddr());
336}
337
338void udelay(unsigned int usec)
339{
340 unsigned int i = usec * (__cpm_get_cclk() / 2000000);
341 __asm__ __volatile__ (
342 ".set noreorder \n"
343 "1: \n"
344 "bne %0, $0, 1b \n"
345 "addi %0, %0, -1 \n"
346 ".set reorder \n"
347 : "=r" (i)
348 : "0" (i)
349 );
350}
351
352void mdelay(unsigned int msec)
353{
354 unsigned int i;
355 for(i=0; i<msec; i++)
356 udelay(1000);
357}
358
359#define MHZ (1000 * 1000)
360static inline unsigned int pll_calc_m_n_od(unsigned int speed, unsigned int xtal)
361{
362 const int pll_m_max = 0x7f, pll_m_min = 4;
363 const int pll_n_max = 0x0f, pll_n_min = 2;
364
365 int od[] = {1, 2, 4, 8};
366
367 unsigned int plcr_m_n_od = 0;
368 unsigned int distance;
369 unsigned int tmp, raw;
370
371 int i, j, k;
372 int m, n;
373
374 distance = 0xFFFFFFFF;
375
376 for (i = 0; i < (int)sizeof (od) / (int)sizeof(int); i++) {
377 /* Limit: 500MHZ <= CLK_OUT * OD <= 1500MHZ */
378 if ((speed * od[i]) < 500 * MHZ || (speed * od[i]) > 1500 * MHZ)
379 continue;
380 for (k = pll_n_min; k <= pll_n_max; k++) {
381 n = k;
382
383 /* Limit: 1MHZ <= XIN/N <= 50MHZ */
384 if ((xtal / n) < (1 * MHZ))
385 break;
386 if ((xtal / n) > (15 * MHZ))
387 continue;
388
389 for (j = pll_m_min; j <= pll_m_max; j++) {
390 m = j*2;
391
392 raw = xtal * m / n;
393 tmp = raw / od[i];
394
395 tmp = (tmp > speed) ? (tmp - speed) : (speed - tmp);
396
397 if (tmp < distance) {
398 distance = tmp;
399
400 plcr_m_n_od = (j << CPPCR0_PLLM_LSB)
401 | (k << CPPCR0_PLLN_LSB)
402 | (i << CPPCR0_PLLOD_LSB);
403
404 if (!distance) { /* Match. */
405 return plcr_m_n_od;
406 }
407 }
408 }
409 }
410 }
411 return plcr_m_n_od;
412}
413
414/* PLL output clock = EXTAL * NF / (NR * NO)
415 *
416 * NF = FD + 2, NR = RD + 2
417 * NO = 1 (if OD = 0), NO = 2 (if OD = 1 or 2), NO = 4 (if OD = 3)
418 */
419static void pll0_init(unsigned int freq)
420{
421 register unsigned int cfcr, plcr1;
422 int n2FR[9] = {
423 0, 0, 1, 2, 3, 0, 4, 0, 5
424 };
425
426 /** divisors,
427 * for jz4760b,I:H:H2:P:M:S.
428 * DIV should be one of [1, 2, 3, 4, 6, 8]
429 */
430 int div[6] = {1, 4, 4, 4, 4, 4};
431 int usbdiv;
432
433 /* set ahb **/
434 REG32(HARB0_BASE) = 0x00300000;
435 REG32(0xb3070048) = 0x00000000;
436 REG32(HARB2_BASE) = 0x00FFFFFF;
437
438 cfcr = CPCCR_PCS |
439 (n2FR[div[0]] << CPCCR_CDIV_LSB) |
440 (n2FR[div[1]] << CPCCR_HDIV_LSB) |
441 (n2FR[div[2]] << CPCCR_H2DIV_LSB) |
442 (n2FR[div[3]] << CPCCR_PDIV_LSB) |
443 (n2FR[div[4]] << CPCCR_MDIV_LSB) |
444 (n2FR[div[5]] << CPCCR_SDIV_LSB);
445
446 // write REG_DDRC_CTRL 8 times to clear ddr fifo
447 REG_DDRC_CTRL = 0;
448 REG_DDRC_CTRL = 0;
449 REG_DDRC_CTRL = 0;
450 REG_DDRC_CTRL = 0;
451 REG_DDRC_CTRL = 0;
452 REG_DDRC_CTRL = 0;
453 REG_DDRC_CTRL = 0;
454 REG_DDRC_CTRL = 0;
455
456 if (CFG_EXTAL > 16000000)
457 cfcr |= CPCCR_ECS;
458 else
459 cfcr &= ~CPCCR_ECS;
460
461 cfcr &= ~CPCCR_MEM; /* mddr */
462 cfcr |= CPCCR_CE;
463
464 plcr1 = pll_calc_m_n_od(freq, CFG_EXTAL);
465 plcr1 |= (0x20 << CPPCR0_PLLST_LSB) /* PLL stable time */
466 | CPPCR0_PLLEN; /* enable PLL */
467
468 /*
469 * Init USB Host clock, pllout2 must be n*48MHz
470 * For JZ4760b UHC - River.
471 */
472 usbdiv = (cfcr & CPCCR_PCS) ? CPU_FREQ : (CPU_FREQ / 2);
473 REG_CPM_UHCCDR = usbdiv / 48000000 - 1;
474
475 /* init PLL */
476 REG_CPM_CPCCR = cfcr;
477 REG_CPM_CPPCR0 = plcr1;
478
479 __cpm_enable_pll_change();
480
481 /*wait for pll output stable ...*/
482 while (!(REG_CPM_CPPCR0 & CPPCR0_PLLS));
483
484 REG_CPM_CPPCR0 &= ~CPPCR0_LOCK;
485}
486
487void pll1_init(unsigned int freq)
488{
489 register unsigned int plcr2;
490
491 /* set CPM_CPCCR_MEM only for ddr1 or ddr2 */
492 plcr2 = pll_calc_m_n_od(freq, CFG_EXTAL)
493 | CPPCR1_PLL1EN; /* enable PLL1 */
494
495 /* init PLL_1 , source clock is extal clock */
496 REG_CPM_CPPCR1 = plcr2;
497
498 __cpm_enable_pll_change();
499
500 /*wait for pll_1 output stable ...*/
501 while (!(REG_CPM_CPPCR1 & CPPCR1_PLL1S));
502
503 REG_CPM_CPPCR1 &= ~CPPCR1_LOCK;
504}
505
506static void serial_setbrg(void)
507{
508 volatile u8 *uart_lcr = (volatile u8 *)(CFG_UART_BASE + OFF_LCR);
509 volatile u8 *uart_dlhr = (volatile u8 *)(CFG_UART_BASE + OFF_DLHR);
510 volatile u8 *uart_dllr = (volatile u8 *)(CFG_UART_BASE + OFF_DLLR);
511 volatile u8 *uart_umr = (volatile u8 *)(CFG_UART_BASE + OFF_UMR);
512 volatile u8 *uart_uacr = (volatile u8 *)(CFG_UART_BASE + OFF_UACR);
513 u16 baud_div, tmp;
514
515 *uart_umr = 16;
516 *uart_uacr = 0;
517 baud_div = 13; /* 57600 */
518
519 tmp = *uart_lcr;
520 tmp |= UARTLCR_DLAB;
521 *uart_lcr = tmp;
522
523 *uart_dlhr = (baud_div >> 8) & 0xff;
524 *uart_dllr = baud_div & 0xff;
525
526 tmp &= ~UARTLCR_DLAB;
527 *uart_lcr = tmp;
528}
529
530int serial_preinit(void)
531{
532 volatile u8 *uart_fcr = (volatile u8 *)(CFG_UART_BASE + OFF_FCR);
533 volatile u8 *uart_lcr = (volatile u8 *)(CFG_UART_BASE + OFF_LCR);
534 volatile u8 *uart_ier = (volatile u8 *)(CFG_UART_BASE + OFF_IER);
535 volatile u8 *uart_sircr = (volatile u8 *)(CFG_UART_BASE + OFF_SIRCR);
536
537 __gpio_as_uart1();
538 __cpm_start_uart1();
539
540 /* Disable port interrupts while changing hardware */
541 *uart_ier = 0;
542
543 /* Disable UART unit function */
544 *uart_fcr = ~UARTFCR_UUE;
545
546 /* Set both receiver and transmitter in UART mode (not SIR) */
547 *uart_sircr = ~(SIRCR_RSIRE | SIRCR_TSIRE);
548
549 /* Set databits, stopbits and parity. (8-bit data, 1 stopbit, no parity) */
550 *uart_lcr = UARTLCR_WLEN_8 | UARTLCR_STOP1;
551
552 /* Set baud rate */
553 serial_setbrg();
554
555 /* Enable UART unit, enable and clear FIFO */
556 *uart_fcr = UARTFCR_UUE | UARTFCR_FE | UARTFCR_TFLS | UARTFCR_RFLS;
557
558 return 0;
559}
560
561void usb_preinit(void)
562{
563 /* Clear ECS bit of CPCCR, 0:clock source is EXCLK, 1:clock source is EXCLK/2 */
564 REG_CPM_CPCCR &= ~CPCCR_ECS;
565
566 /* Clear all bits of USBCDR, 0:OTG clock source is pin EXCLK, PLL0 output, divider = 1:12MHZ */
567 REG_CPM_USBCDR = 0;
568
569 /* Set CE bit of CPCCR, it means frequence is changed immediately */
570 REG_CPM_CPCCR |= CPCCR_CE;
571
572 udelay(3);
573
574 /* Clear OTG bit of CLKGR0, 0:device can be accessed */
575 REG_CPM_CLKGR0 &= ~CLKGR0_OTG;
576
577 /* fil */
578 REG_CPM_USBVBFIL = 0x80;
579
580 /* rdt */
581 REG_CPM_USBRDT = (600 * (CPU_FREQ / 1000000)) / 1000;
582
583 /* rdt - filload_en */
584 REG_CPM_USBRDT |= (1 << 25);
585
586 /* TXRISETUNE & TXVREFTUNE. */
587 REG_CPM_USBPCR &= ~0x3f;
588 REG_CPM_USBPCR |= 0x35;
589
590 /* enable tx pre-emphasis */
591 REG_CPM_USBPCR |= 0x40;
592
593 /* most DC leave of tx */
594 REG_CPM_USBPCR |= 0xf;
595
596 /* Device Mode. */
597 REG_CPM_USBPCR &= ~(1 << 31);
598 REG_CPM_USBPCR |= USBPCR_VBUSVLDEXT;
599
600 /* phy reset */
601 REG_CPM_USBPCR |= USBPCR_POR;
602 udelay(30);
603 REG_CPM_USBPCR &= ~USBPCR_POR;
604 udelay(300);
605
606 /* Enable the USB PHY */
607 REG_CPM_OPCR |= OPCR_OTGPHY_ENABLE;
608
609 /* Wait PHY Clock Stable. */
610 udelay(300);
611}
612
613void dma_preinit(void)
614{
615 __cpm_start_mdma();
616 __cpm_start_dmac();
617
618 REG_MDMAC_DMACKES = 0x1;
619
620 REG_DMAC_DMACR(DMA_AIC_TX_CHANNEL) = DMAC_DMACR_DMAE | DMAC_DMACR_FAIC;
621 REG_DMAC_DMACR(DMA_SD_RX_CHANNEL) = DMAC_DMACR_DMAE | DMAC_DMACR_FMSC;
622 REG_DMAC_DMACR(DMA_SD_TX_CHANNEL) = DMAC_DMACR_DMAE | DMAC_DMACR_FMSC;
623}
624
625/* Gets called *before* main */
626void ICODE_ATTR system_main(void)
627{
628 int i;
629
630 __dcache_writeback_all();
631 __icache_invalidate_all();
632
633 write_c0_status(1 << 28 | 1 << 10 ); /* Enable CP | Mask interrupt 2 */
634
635 /* Disable all interrupts */
636 for(i=0; i<IRQ_INTC_MAX; i++)
637 dis_irq(i);
638
639 mmu_init();
640
641 pll0_init(CPU_FREQ);
642 pll1_init(CPU_FREQ);
643
644 serial_preinit();
645 usb_preinit();
646 dma_preinit();
647
648 /* Enable interrupts at core level */
649 enable_interrupt();
650}
651
652void system_reboot(void)
653{
654 REG_WDT_WCSR = WCSR_PRESCALE4 | WCSR_CLKIN_EXT;
655 REG_WDT_WCNT = 0;
656 REG_WDT_WDR = JZ_EXTAL/1000; /* reset after 4ms */
657 REG_TCU_TSCR = TSCR_WDT; /* enable wdt clock */
658 REG_WDT_WCER = WCER_TCEN; /* wdt start */
659 while (1);
660}
661
662void system_exception_wait(void)
663{
664 /* check for power button without including any .h file */
665 while(1)
666 {
667 if( (~REG_GPIO_PXPIN(0)) & (1 << 30) )
668 return;
669 asm volatile("nop");
670 }
671}
672
673void power_off(void)
674{
675 REG_CPM_RSR = 0x0;
676
677 /* Set minimum wakeup_n pin low-level assertion time for wakeup: 100ms */
678 rtc_write_reg(RTC_HWFCR, HWFCR_WAIT_TIME(1000));
679
680 /* Set reset pin low-level assertion time after wakeup: must > 60ms */
681 rtc_write_reg(RTC_HRCR, HRCR_WAIT_TIME(60));
682
683 /* clear wakeup status register */
684 rtc_write_reg(RTC_HWRSR, 0x0);
685
686 /* set wake up valid level as low */
687 rtc_write_reg(RTC_HWCR,0x8);
688
689 /* Put CPU to hibernate mode */
690 rtc_write_reg(RTC_HCR, HCR_PD);
691
692 while (1);
693}
694
695void system_init(void)
696{
697}
698
699int system_memory_guard(int newmode)
700{
701 (void)newmode;
702 return 0;
703}
704
705#ifdef HAVE_ADJUSTABLE_CPU_FREQ
706void set_cpu_frequency(long frequency)
707{
708 serial_putsf("set_cpu_frequency: %d\n", frequency);
709}
710#endif