diff options
author | Solomon Peachy <pizza@shaftnet.org> | 2018-06-28 06:24:26 -0400 |
---|---|---|
committer | Michael Giacomelli <giac2000@hotmail.com> | 2018-07-28 10:56:31 -0400 |
commit | 0662793ca0050e823cd1207cc4689a1cba5068bd (patch) | |
tree | 08cd2ec59c9044c96b697b5bf8d0640841d044e0 /firmware/target/mips/ingenic_jz47xx/system-jz4760.c | |
parent | b3e2bd619b1b7ea94ef29d32db48e80b347a1990 (diff) | |
download | rockbox-0662793ca0050e823cd1207cc4689a1cba5068bd.tar.gz rockbox-0662793ca0050e823cd1207cc4689a1cba5068bd.zip |
Add cleaned-up xDuoo X3 support
Cleaned up, rebased, and forward-ported from the xvortex fork.
(original credit to vsoftster@gmail.com)
Change-Id: Ibcc023a0271ea81e901450a88317708c2683236d
Signed-off-by: Solomon Peachy <pizza@shaftnet.org>
Diffstat (limited to 'firmware/target/mips/ingenic_jz47xx/system-jz4760.c')
-rw-r--r-- | firmware/target/mips/ingenic_jz47xx/system-jz4760.c | 710 |
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 | |||
31 | static int irq; | ||
32 | static 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 | |||
39 | intr(I2C1);intr(I2C0);intr(UART3);intr(UART2);intr(UART1);intr(UART0);intr(GPU); | ||
40 | intr(SSI1);intr(SSI0);intr(TSSI);intr(KBC);intr(SADC);intr(ETH);intr(UHC); | ||
41 | intr(OTG);intr(TCU2);intr(TCU1);intr(TCU0);intr(GPS);intr(IPU);intr(CIM); | ||
42 | intr(LCD);intr(RTC);intr(OWI);intr(AIC);intr(MSC2);intr(MSC1);intr(MSC0); | ||
43 | intr(SCC);intr(BCH);intr(PCM);intr(HARB0);intr(HARB2);intr(AOSD);intr(CPM); | ||
44 | |||
45 | intr(DMA0);intr(DMA1);intr(DMA2);intr(DMA3);intr(DMA4);intr(DMA5); | ||
46 | intr(DMA6);intr(DMA7);intr(DMA8);intr(DMA9);intr(DMA10);intr(DMA11); | ||
47 | intr(MDMA0);intr(MDMA1);intr(MDMA2); | ||
48 | intr(BDMA0);intr(BDMA1);intr(BDMA2); | ||
49 | |||
50 | intr(GPIO0);intr(GPIO1);intr(GPIO2);intr(GPIO3);intr(GPIO4);intr(GPIO5); | ||
51 | intr(GPIO6);intr(GPIO7);intr(GPIO8);intr(GPIO9);intr(GPIO10);intr(GPIO11); | ||
52 | intr(GPIO12);intr(GPIO13);intr(GPIO14);intr(GPIO15);intr(GPIO16);intr(GPIO17); | ||
53 | intr(GPIO18);intr(GPIO19);intr(GPIO20);intr(GPIO21);intr(GPIO22);intr(GPIO23); | ||
54 | intr(GPIO24);intr(GPIO25);intr(GPIO26);intr(GPIO27);intr(GPIO28);intr(GPIO29); | ||
55 | intr(GPIO30);intr(GPIO31);intr(GPIO32);intr(GPIO33);intr(GPIO34);intr(GPIO35); | ||
56 | intr(GPIO36);intr(GPIO37);intr(GPIO38);intr(GPIO39);intr(GPIO40);intr(GPIO41); | ||
57 | intr(GPIO42);intr(GPIO43);intr(GPIO44);intr(GPIO45);intr(GPIO46);intr(GPIO47); | ||
58 | intr(GPIO48);intr(GPIO49);intr(GPIO50);intr(GPIO51);intr(GPIO52);intr(GPIO53); | ||
59 | intr(GPIO54);intr(GPIO55);intr(GPIO56);intr(GPIO57);intr(GPIO58);intr(GPIO59); | ||
60 | intr(GPIO60);intr(GPIO61);intr(GPIO62);intr(GPIO63);intr(GPIO64);intr(GPIO65); | ||
61 | intr(GPIO66);intr(GPIO67);intr(GPIO68);intr(GPIO69);intr(GPIO70);intr(GPIO71); | ||
62 | intr(GPIO72);intr(GPIO73);intr(GPIO74);intr(GPIO75);intr(GPIO76);intr(GPIO77); | ||
63 | intr(GPIO78);intr(GPIO79);intr(GPIO80);intr(GPIO81);intr(GPIO82);intr(GPIO83); | ||
64 | intr(GPIO84);intr(GPIO85);intr(GPIO86);intr(GPIO87);intr(GPIO88);intr(GPIO89); | ||
65 | intr(GPIO90);intr(GPIO91);intr(GPIO92);intr(GPIO93);intr(GPIO94);intr(GPIO95); | ||
66 | intr(GPIO96);intr(GPIO97);intr(GPIO98);intr(GPIO99);intr(GPIO100);intr(GPIO101); | ||
67 | intr(GPIO102);intr(GPIO103);intr(GPIO104);intr(GPIO105);intr(GPIO106); | ||
68 | intr(GPIO107);intr(GPIO108);intr(GPIO109);intr(GPIO110);intr(GPIO111); | ||
69 | intr(GPIO112);intr(GPIO113);intr(GPIO114);intr(GPIO115);intr(GPIO116); | ||
70 | intr(GPIO117);intr(GPIO118);intr(GPIO119);intr(GPIO120);intr(GPIO121); | ||
71 | intr(GPIO122);intr(GPIO123);intr(GPIO124);intr(GPIO125);intr(GPIO126); | ||
72 | intr(GPIO127);intr(GPIO128);intr(GPIO129);intr(GPIO130);intr(GPIO131); | ||
73 | intr(GPIO132);intr(GPIO133);intr(GPIO134);intr(GPIO135);intr(GPIO136); | ||
74 | intr(GPIO137);intr(GPIO138);intr(GPIO139);intr(GPIO140);intr(GPIO141); | ||
75 | intr(GPIO142);intr(GPIO143);intr(GPIO144);intr(GPIO145);intr(GPIO146); | ||
76 | intr(GPIO147);intr(GPIO148);intr(GPIO149);intr(GPIO150);intr(GPIO151); | ||
77 | intr(GPIO152);intr(GPIO153);intr(GPIO154);intr(GPIO155);intr(GPIO156); | ||
78 | intr(GPIO157);intr(GPIO158);intr(GPIO159);intr(GPIO160);intr(GPIO161); | ||
79 | intr(GPIO162);intr(GPIO163);intr(GPIO164);intr(GPIO165);intr(GPIO166); | ||
80 | intr(GPIO167);intr(GPIO168);intr(GPIO169);intr(GPIO170);intr(GPIO171); | ||
81 | intr(GPIO172);intr(GPIO173);intr(GPIO174);intr(GPIO175);intr(GPIO176); | ||
82 | intr(GPIO177);intr(GPIO178);intr(GPIO179);intr(GPIO180);intr(GPIO181); | ||
83 | intr(GPIO182);intr(GPIO183);intr(GPIO184);intr(GPIO185);intr(GPIO186); | ||
84 | intr(GPIO187);intr(GPIO188);intr(GPIO189);intr(GPIO190);intr(GPIO191); | ||
85 | |||
86 | static 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 | |||
126 | static unsigned int dma_irq_mask = 0; | ||
127 | static unsigned char mdma_irq_mask = 0; | ||
128 | static unsigned char bdma_irq_mask = 0; | ||
129 | static unsigned int gpio_irq_mask[6] = {0}; | ||
130 | |||
131 | void 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 | |||
164 | static 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 | |||
202 | static 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 | |||
210 | static 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 | |||
287 | void 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); | ||
299 | static 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 | |||
328 | void 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 | |||
333 | void tlb_refill_handler(void) | ||
334 | { | ||
335 | panicf("TLB refill handler at 0x%08lx! [0x%x]", read_c0_epc(), read_c0_badvaddr()); | ||
336 | } | ||
337 | |||
338 | void 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 | |||
352 | void 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) | ||
360 | static 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 | */ | ||
419 | static 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 | |||
487 | void 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 | |||
506 | static 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 | |||
530 | int 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 | |||
561 | void 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 | |||
613 | void 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 */ | ||
626 | void 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 | |||
652 | void 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 | |||
662 | void 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 | |||
673 | void 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 | |||
695 | void system_init(void) | ||
696 | { | ||
697 | } | ||
698 | |||
699 | int system_memory_guard(int newmode) | ||
700 | { | ||
701 | (void)newmode; | ||
702 | return 0; | ||
703 | } | ||
704 | |||
705 | #ifdef HAVE_ADJUSTABLE_CPU_FREQ | ||
706 | void set_cpu_frequency(long frequency) | ||
707 | { | ||
708 | serial_putsf("set_cpu_frequency: %d\n", frequency); | ||
709 | } | ||
710 | #endif | ||