1 /***************************************************************************
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
10 * Copyright (C) 2011 by Marcin Bukat
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 ****************************************************************************/
25 #include "system-target.h"
27 #define default_interrupt(name) \
28 extern __attribute__((weak,alias("UIRQ"))) void name (void)
30 void irq_handler(void) __attribute__((interrupt ("IRQ"), naked
));
31 void fiq_handler(void) __attribute__((interrupt ("FIQ"), naked
, \
32 weak
, alias("fiq_dummy")));
34 default_interrupt(INT_UART0
);
35 default_interrupt(INT_UART1
);
36 default_interrupt(INT_TIMER0
);
37 default_interrupt(INT_TIMER1
);
38 default_interrupt(INT_TIMER2
);
39 default_interrupt(INT_GPIO0
);
40 default_interrupt(INT_SW_INT0
);
41 default_interrupt(INT_AHB0_MAILBOX
);
42 default_interrupt(INT_RTC
);
43 default_interrupt(INT_SCU
);
44 default_interrupt(INT_SD
);
45 default_interrupt(INT_SPI
);
46 default_interrupt(INT_HDMA
);
47 default_interrupt(INT_A2A_BRIDGE
);
48 default_interrupt(INT_I2C
);
49 default_interrupt(INT_I2S
);
50 default_interrupt(INT_UDC
);
51 default_interrupt(INT_UHC
);
52 default_interrupt(INT_PWM0
);
53 default_interrupt(INT_PWM1
);
54 default_interrupt(INT_PWM2
);
55 default_interrupt(INT_PWM3
);
56 default_interrupt(INT_ADC
);
57 default_interrupt(INT_GPIO1
);
58 default_interrupt(INT_VIP
);
59 default_interrupt(INT_DWDMA
);
60 default_interrupt(INT_NANDC
);
61 default_interrupt(INT_LCDC
);
62 default_interrupt(INT_DSP
);
63 default_interrupt(INT_SW_INT1
);
64 default_interrupt(INT_SW_INT2
);
65 default_interrupt(INT_SW_INT3
);
67 static void (* const irqvector
[])(void) =
69 INT_UART0
,INT_UART1
,INT_TIMER0
,INT_TIMER1
,INT_TIMER2
,INT_GPIO0
,INT_SW_INT0
,INT_AHB0_MAILBOX
,
70 INT_RTC
,INT_SCU
,INT_SD
,INT_SPI
,INT_HDMA
,INT_A2A_BRIDGE
,INT_I2C
,INT_I2S
,
71 INT_UDC
,INT_UHC
,INT_PWM0
,INT_PWM1
,INT_PWM2
,INT_PWM3
,INT_ADC
,INT_GPIO1
,
72 INT_VIP
,INT_DWDMA
,INT_NANDC
,INT_LCDC
,INT_DSP
,INT_SW_INT1
,INT_SW_INT2
,INT_SW_INT3
75 static const char * const irqname
[] =
77 "INT_UART0","INT_UART1","INT_TIMER0","INT_TIMER1","INT_TIMER2","INT_GPIO0","INT_SW_INT0","INT_AHB0_MAILBOX",
78 "INT_RTC","INT_SCU","INT_SD","INT_SPI","INT_HDMA","INT_A2A_BRIDGE","INT_I2C","INT_I2S",
79 "INT_UDC","INT_UHC","INT_PWM0","INT_PWM1","INT_PWM2","INT_PWM3","INT_ADC","INT_GPIO1",
80 "INT_VIP","INT_DWDMA","INT_NANDC","INT_LCDC","INT_DSP","INT_SW_INT1","INT_SW_INT2","INT_SW_INT3"
83 static void UIRQ(void)
85 unsigned int offset
= INTC_ISR
& 0x1f;
86 panicf("Unhandled IRQ %02X: %s", offset
, irqname
[offset
]);
89 void irq_handler(void)
92 * Based on: linux/arch/arm/kernel/entry-armv.S and system-meg-fx.c
95 asm volatile( "stmfd sp!, {r0-r7, ip, lr} \n" /* Store context */
96 "sub sp, sp, #8 \n"); /* Reserve stack */
98 int irq_no
= INTC_ISR
& 0x1f;
102 /* clear interrupt */
103 INTC_ICCR
= (1 << irq_no
);
105 asm volatile( "add sp, sp, #8 \n" /* Cleanup stack */
106 "ldmfd sp!, {r0-r7, ip, lr} \n" /* Restore context */
107 "subs pc, lr, #4 \n"); /* Return from IRQ */
113 "subs pc, lr, #4 \r\n"
118 void system_init(void)
121 MCSDR_MODE
= (2<<4)|3; /* CAS=2, burst=8 */
122 MCSDR_T_REF
= (125*100) >> 3; /* 125/8 = 15.625 autorefresh interval */
123 MCSDR_T_RFC
= (64*100) / 1000; /* autorefresh period */
124 MCSDR_T_RP
= 1; /* precharge period */
125 MCSDR_T_RCD
= 1; /* active to RD/WR delay */
127 /* turn off clock for unused modules */
128 SCU_CLKCFG
|= (1<<31) | /* WDT pclk */
129 (1<<30) | /* RTC pclk */
130 (1<<26) | /* HS_ADC clock */
131 (1<<25) | /* HS_ADC HCLK */
132 (1<<21) | /* SPI clock */
133 (1<<19) | /* UART1 clock */
134 (1<<18) | /* UART0 clock */
135 (1<<15) | /* VIP clock */
136 (1<<14) | /* VIP HCLK */
137 (1<<13) | /* LCDC clock */
138 (1<<9) | /* NAND HCLK */
139 (1<<5) | /* USB host HCLK */
140 (1<<1) | /* DSP clock */
141 (1<<0); /* OTP clock (dunno what it is */
143 /* turn off DSP pll */
144 SCU_PLLCON2
|= (1<<22);
146 /* turn off codec pll */
147 SCU_PLLCON3
|= (1<<22);
152 void system_reboot(void)
154 /* use Watchdog to reset */
155 SCU_CLKCFG
&= ~(1<<31);
157 WDTCON
= (1<<4) | (1<<3);
159 /* Wait for reboot to kick in */
163 void system_exception_wait(void)
168 int system_memory_guard(int newmode
)
174 /* usecs may be at most 2^32/200 (~21 seconds) for 200MHz max cpu freq */
175 void udelay(unsigned usecs
)
177 unsigned cycles_per_usec
;
180 if (cpu_frequency
== CPUFREQ_MAX
) {
181 cycles_per_usec
= (CPUFREQ_MAX
+ 999999) / 1000000;
183 cycles_per_usec
= (CPUFREQ_NORMAL
+ 999999) / 1000000;
186 delay
= (usecs
* cycles_per_usec
+ 3) / 4;
189 "1: subs %0, %0, #1 \n" /* 1 cycle */
190 " bne 1b \n" /* 3 cycles */
195 void commit_discard_idcache(void)
197 /* invalidate cache way 0 */
200 /* wait for invalidate process to complete */
201 while (CACHEOP
& 0x03);
203 /* invalidate cache way 1 */
204 CACHEOP
= 0x80000002;
206 /* wait for invalidate process to complete */
207 while (CACHEOP
& 0x03);
209 void commit_discard_dcache (void) __attribute__((alias("commit_discard_idcache")));
211 void commit_discard_dcache_range (const void *base
, unsigned int size
)
213 int cnt
= size
+ ((unsigned long)base
& 0x1f);
214 unsigned long opcode
= ((unsigned long)base
& 0xffffffe0) | 0x01;
220 while (CACHEOP
& 0x03);