1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2007 by Karl Kurbjun
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.
17 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
18 * KIND, either express or implied.
20 ****************************************************************************/
26 #include "uart-target.h"
27 #include "system-arm.h"
30 #include "dma-target.h"
33 #define default_interrupt(name) \
34 extern __attribute__((weak,alias("UIRQ"))) void name (void)
36 void irq_handler(void) __attribute__((interrupt ("IRQ"), naked
));
37 void fiq_handler(void) __attribute__((interrupt ("FIQ"), naked
));
39 default_interrupt(TIMER0
);
40 default_interrupt(TIMER1
);
41 default_interrupt(TIMER2
);
42 default_interrupt(TIMER3
);
43 default_interrupt(CCD_VD0
);
44 default_interrupt(CCD_VD1
);
45 default_interrupt(CCD_WEN
);
46 default_interrupt(VENC
);
47 default_interrupt(SERIAL0
);
48 default_interrupt(SERIAL1
);
49 default_interrupt(EXT_HOST
);
50 default_interrupt(DSPHINT
);
51 default_interrupt(UART0
);
52 default_interrupt(UART1
);
53 default_interrupt(USB_DMA
);
54 default_interrupt(USB_CORE
);
55 default_interrupt(VLYNQ
);
56 default_interrupt(MTC0
);
57 default_interrupt(MTC1
);
58 default_interrupt(SD_MMC
);
59 default_interrupt(SDIO_MS
);
60 default_interrupt(GIO0
);
61 default_interrupt(GIO1
);
62 default_interrupt(GIO2
);
63 default_interrupt(GIO3
);
64 default_interrupt(GIO4
);
65 default_interrupt(GIO5
);
66 default_interrupt(GIO6
);
67 default_interrupt(GIO7
);
68 default_interrupt(GIO8
);
69 default_interrupt(GIO9
);
70 default_interrupt(GIO10
);
71 default_interrupt(GIO11
);
72 default_interrupt(GIO12
);
73 default_interrupt(GIO13
);
74 default_interrupt(GIO14
);
75 default_interrupt(GIO15
);
76 default_interrupt(PREVIEW0
);
77 default_interrupt(PREVIEW1
);
78 default_interrupt(WATCHDOG
);
79 default_interrupt(I2C
);
80 default_interrupt(CLKC
);
81 default_interrupt(ICE
);
82 default_interrupt(ARMCOM_RX
);
83 default_interrupt(ARMCOM_TX
);
84 default_interrupt(RESERVED
);
86 /* The entry address is equal to base address plus an offset.
87 * The offset is based on the priority of the interrupt. So if
88 * the priority of an interrupt is changed, the user should also
89 * change the offset for the interrupt in the entry table.
92 static const unsigned short const irqpriority
[] =
94 IRQ_TIMER0
,IRQ_TIMER1
,IRQ_TIMER2
,IRQ_TIMER3
,IRQ_CCD_VD0
,IRQ_CCD_VD1
,
95 IRQ_CCD_WEN
,IRQ_VENC
,IRQ_SERIAL0
,IRQ_SERIAL1
,IRQ_EXT_HOST
,IRQ_DSPHINT
,
96 IRQ_UART0
,IRQ_UART1
,IRQ_USB_DMA
,IRQ_USB_CORE
,IRQ_VLYNQ
,IRQ_MTC0
,IRQ_MTC1
,
97 IRQ_SD_MMC
,IRQ_SDIO_MS
,IRQ_GIO0
,IRQ_GIO1
,IRQ_GIO2
,IRQ_GIO3
,IRQ_GIO4
,IRQ_GIO5
,
98 IRQ_GIO6
,IRQ_GIO7
,IRQ_GIO8
,IRQ_GIO9
,IRQ_GIO10
,IRQ_GIO11
,IRQ_GIO12
,IRQ_GIO13
,
99 IRQ_GIO14
,IRQ_GIO15
,IRQ_PREVIEW0
,IRQ_PREVIEW1
,IRQ_WATCHDOG
,IRQ_I2C
,IRQ_CLKC
,
100 IRQ_ICE
,IRQ_ARMCOM_RX
,IRQ_ARMCOM_TX
,IRQ_RESERVED
101 }; /* IRQ priorities, ranging from highest to lowest */
103 static void (* const irqvector
[])(void) =
105 TIMER0
,TIMER1
,TIMER2
,TIMER3
,CCD_VD0
,CCD_VD1
,
106 CCD_WEN
,VENC
,SERIAL0
,SERIAL1
,EXT_HOST
,DSPHINT
,
107 UART0
,UART1
,USB_DMA
,USB_CORE
,VLYNQ
,MTC0
,MTC1
,
108 SD_MMC
,SDIO_MS
,GIO0
,GIO1
,GIO2
,GIO3
,GIO4
,GIO5
,
109 GIO6
,GIO7
,GIO8
,GIO9
,GIO10
,GIO11
,GIO12
,GIO13
,
110 GIO14
,GIO15
,PREVIEW0
,PREVIEW1
,WATCHDOG
,I2C
,CLKC
,
111 ICE
,ARMCOM_RX
,ARMCOM_TX
,RESERVED
114 static const char * const irqname
[] =
116 "TIMER0","TIMER1","TIMER2","TIMER3","CCD_VD0","CCD_VD1",
117 "CCD_WEN","VENC","SERIAL0","SERIAL1","EXT_HOST","DSPHINT",
118 "UART0","UART1","USB_DMA","USB_CORE","VLYNQ","MTC0","MTC1",
119 "SD_MMC","SDIO_MS","GIO0","GIO1","GIO2","GIO3","GIO4","GIO5",
120 "GIO6","GIO7","GIO8","GIO9","GIO10","GIO11","GIO12","GIO13",
121 "GIO14","GIO15","PREVIEW0","PREVIEW1","WATCHDOG","I2C","CLKC",
122 "ICE","ARMCOM_RX","ARMCOM_TX","RESERVED"
125 static void UIRQ(void)
127 unsigned int offset
= (IO_INTC_IRQENTRY0
>>2)-1;
128 panicf("Unhandled IRQ %02X: %s", offset
, irqname
[offset
]);
131 void irq_handler(void)
134 * Based on: linux/arch/arm/kernel/entry-armv.S and system-meg-fx.c
137 asm volatile( "stmfd sp!, {r0-r7, ip, lr} \n" /* Store context */
138 "sub sp, sp, #8 \n"); /* Reserve stack */
139 unsigned short addr
= IO_INTC_IRQENTRY0
>>2;
145 asm volatile( "add sp, sp, #8 \n" /* Cleanup stack */
146 "ldmfd sp!, {r0-r7, ip, lr} \n" /* Restore context */
147 "subs pc, lr, #4 \n"); /* Return from IRQ */
150 void fiq_handler(void)
153 * Based on: linux/arch/arm/kernel/entry-armv.S and system-meg-fx.c
157 "sub lr, lr, #4 \r\n"
158 "stmfd sp!, {r0-r3, ip, lr} \r\n"
159 "mov r0, #0x00030000 \r\n"
160 "ldr r0, [r0, #0x510] \r\n" /* Fetch value from IO_INTC_FIQENTRY0 */
161 "sub r0, r0, #1 \r\n"
162 "ldr r1, =irqvector \r\n"
163 "ldr r1, [r1, r0, lsl #2] \r\n" /* Divide value by 4 (TBA0/TBA1 is set to 0) and load appropriate pointer from the vector list */
164 "blx r1 \r\n" /* Jump to handler */
165 "ldmfd sp!, {r0-r3, ip, pc}^ \r\n" /* Return from FIQ */
169 void system_reboot(void)
171 /* Code taken from linux/include/asm-arm/arch-itdm320-20/system.h at NeuroSVN */
172 __asm__
__volatile__(
174 "mcr p15, 0, ip, c7, c7, 0 @ invalidate cache \n"
175 "mcr p15, 0, ip, c7, c10,4 @ drain WB \n"
176 "mcr p15, 0, ip, c8, c7, 0 @ flush TLB (v4) \n"
177 "mrc p15, 0, ip, c1, c0, 0 @ get ctrl register\n"
178 "bic ip, ip, #0x000f @ ............wcam \n"
179 "bic ip, ip, #0x2100 @ ..v....s........ \n"
180 "mcr p15, 0, ip, c1, c0, 0 @ ctrl register \n"
181 "mov ip, #0xFF000000 \n"
182 "orr pc, ip, #0xFF0000 @ ip = 0xFFFF0000 \n"
189 void system_exception_wait(void)
194 void system_init(void)
196 /* taken from linux/arch/arm/mach-itdm320-20/irq.c */
198 /* Clearing all FIQs and IRQs. */
199 IO_INTC_IRQ0
= 0xFFFF;
200 IO_INTC_IRQ1
= 0xFFFF;
201 IO_INTC_IRQ2
= 0xFFFF;
203 IO_INTC_FIQ0
= 0xFFFF;
204 IO_INTC_FIQ1
= 0xFFFF;
205 IO_INTC_FIQ2
= 0xFFFF;
207 /* Masking all Interrupts. */
212 /* Setting INTC to all IRQs. */
217 /* IRQENTRY only reflects enabled interrupts */
220 IO_INTC_ENTRY_TBA0
= 0;
221 IO_INTC_ENTRY_TBA1
= 0;
224 /* Set interrupt priorities to predefined values */
225 for(i
= 0; i
< 23; i
++)
226 DM320_REG(0x0540+i
*2) = ((irqpriority
[i
*2+1] & 0x3F) << 8) | (irqpriority
[i
*2] & 0x3F); /* IO_INTC_PRIORITYx */
228 /* Turn off all timers */
229 IO_TIMER0_TMMD
= CONFIG_TIMER0_TMMD_STOP
;
230 IO_TIMER1_TMMD
= CONFIG_TIMER1_TMMD_STOP
;
231 IO_TIMER2_TMMD
= CONFIG_TIMER2_TMMD_STOP
;
232 IO_TIMER3_TMMD
= CONFIG_TIMER3_TMMD_STOP
;
235 /* set GIO26 (reset pin) to output and low */
236 IO_GIO_BITCLR1
=(1<<10);
237 IO_GIO_DIR1
&=~(1<<10);
247 /* MMU initialization (Starts data and instruction cache) */
249 /* Make sure everything is mapped on itself */
250 map_section(0, 0, 0x1000, CACHE_NONE
);
251 /* Enable caching for RAM */
252 map_section(CONFIG_SDRAM_START
, CONFIG_SDRAM_START
, MEM
, CACHE_ALL
);
253 /* enable buffered writing for the framebuffer */
254 map_section((int)FRAME
, (int)FRAME
, 1, BUFFERED
);
257 map_section(0x00100000, 0x00100000, 4, CACHE_NONE
);
258 map_section(0x04700000, 0x04700000, 2, BUFFERED
);
259 map_section(0x40000000, 0x40000000, 16, CACHE_NONE
);
260 map_section(0x50000000, 0x50000000, 16, CACHE_NONE
);
261 map_section(0x60000000, 0x60000000, 16, CACHE_NONE
);
262 map_section(0x80000000, 0x80000000, 1, CACHE_NONE
);
267 int system_memory_guard(int newmode
)
273 #ifdef HAVE_ADJUSTABLE_CPU_FREQ
275 void set_cpu_frequency(long frequency
)
277 if (frequency
== CPUFREQ_MAX
)
279 asm volatile("mov r0, #0\n"
280 "mrc p15, 0, r0, c1, c0, 0\n"
281 "orr r0, r0, #3<<30\n" /* set to Asynchronous mode*/
282 "mcr p15, 0, r0, c1, c0, 0" : : : "r0");
288 asm volatile("mov r0, #0\n"
289 "mrc p15, 0, r0, c1, c0, 0\n"
290 "bic r0, r0, #3<<30\n" /* set to FastBus mode*/
291 "mcr p15, 0, r0, c1, c0, 0" : : : "r0");
293 FREQ
= CPUFREQ_NORMAL
;