Rename cache coherency functions.
[maemo-rb.git] / firmware / target / coldfire / system-coldfire.c
blob57d729f7e8c73206a7b0df8f812bc176857819e8
1 /***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
10 * Copyright (C) 2002 by Alan Korr
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 ****************************************************************************/
21 #include <stdio.h>
22 #include "config.h"
23 #include "gcc_extensions.h"
24 #include "adc.h"
25 #include "system.h"
26 #include "lcd.h"
27 #include "font.h"
29 #define default_interrupt(name) \
30 extern __attribute__((weak,alias("UIE"))) void name (void)
32 static const char* const irqname[] = {
33 "", "", "AccessErr","AddrErr","IllInstr", "DivX0", "","",
34 "PrivVio","Trace","Line-A", "Line-F","Debug","","FormErr","Uninit",
35 "","","","","","","","",
36 "Spurious","Level1","Level2","Level3","Level4","Level5","Level6","Level7",
37 "Trap0","Trap1","Trap2","Trap3","Trap4","Trap5","Trap6","Trap7",
38 "Trap8","Trap9","Trap10","Trap11","Trap12","Trap13","Trap14","Trap15",
39 "SWT","Timer0","Timer1","I2C","UART1","UART2","DMA0","DMA1",
40 "DMA2","DMA3","QSPI","","","","","",
41 "PDIR1FULL","PDIR2FULL","EBUTXEMPTY","IIS2TXEMPTY",
42 "IIS1TXEMPTY","PDIR3FULL","PDIR3RESYN","UQ2CHANERR",
43 "AUDIOTICK","PDIR2RESYN","PDIR2UNOV","PDIR1RESYN",
44 "PDIR1UNOV","UQ1CHANERR","IEC2BUFATTEN","IEC2PARERR",
45 "IEC2VALNOGOOD","IEC2CNEW","IEC1BUFATTEN","UCHANTXNF",
46 "UCHANTXUNDER","UCHANTXEMPTY","PDIR3UNOV","IEC1PARERR",
47 "IEC1VALNOGOOD","IEC1CNEW","EBUTXRESYN","EBUTXUNOV",
48 "IIS2TXRESYN","IIS2TXUNOV","IIS1TXRESYN","IIS1TXUNOV",
49 "GPI0","GPI1","GPI2","GPI3","GPI4","GPI5","GPI6","GPI7",
50 "","","","","","","","SOFTINT0",
51 "SOFTINT1","SOFTINT2","SOFTINT3","",
52 "","CDROMCRCERR","CDROMNOSYNC","CDROMILSYNC",
53 "CDROMNEWBLK","","","","","","IIC2","ADC",
54 "","","","","","","","",
55 "","","","","","","","",
56 "","","","","","","","",
57 "","","","","","","","",
58 "","","","","","","","",
59 "","","","","","","","",
60 "","","","","","","","",
61 "","","","","","","",""
64 default_interrupt (TRAP0); /* Trap #0 */
65 default_interrupt (TRAP1); /* Trap #1 */
66 default_interrupt (TRAP2); /* Trap #2 */
67 default_interrupt (TRAP3); /* Trap #3 */
68 default_interrupt (TRAP4); /* Trap #4 */
69 default_interrupt (TRAP5); /* Trap #5 */
70 default_interrupt (TRAP6); /* Trap #6 */
71 default_interrupt (TRAP7); /* Trap #7 */
72 default_interrupt (TRAP8); /* Trap #8 */
73 default_interrupt (TRAP9); /* Trap #9 */
74 default_interrupt (TRAP10); /* Trap #10 */
75 default_interrupt (TRAP11); /* Trap #11 */
76 default_interrupt (TRAP12); /* Trap #12 */
77 default_interrupt (TRAP13); /* Trap #13 */
78 default_interrupt (TRAP14); /* Trap #14 */
79 default_interrupt (TRAP15); /* Trap #15 */
80 default_interrupt (SWT); /* Software Watchdog Timer */
81 default_interrupt (TIMER0); /* Timer 0 */
82 default_interrupt (TIMER1); /* Timer 1 */
83 default_interrupt (I2C); /* I2C */
84 default_interrupt (UART1); /* UART 1 */
85 default_interrupt (UART2); /* UART 2 */
86 default_interrupt (DMA0); /* DMA 0 */
87 default_interrupt (DMA1); /* DMA 1 */
88 default_interrupt (DMA2); /* DMA 2 */
89 default_interrupt (DMA3); /* DMA 3 */
90 default_interrupt (QSPI); /* QSPI */
92 default_interrupt (PDIR1FULL); /* Processor data in 1 full */
93 default_interrupt (PDIR2FULL); /* Processor data in 2 full */
94 default_interrupt (EBUTXEMPTY); /* EBU transmit FIFO empty */
95 default_interrupt (IIS2TXEMPTY); /* IIS2 transmit FIFO empty */
96 default_interrupt (IIS1TXEMPTY); /* IIS1 transmit FIFO empty */
97 default_interrupt (PDIR3FULL); /* Processor data in 3 full */
98 default_interrupt (PDIR3RESYN); /* Processor data in 3 resync */
99 default_interrupt (UQ2CHANERR); /* IEC958-2 Rx U/Q channel error */
100 default_interrupt (AUDIOTICK); /* "tick" interrupt */
101 default_interrupt (PDIR2RESYN); /* Processor data in 2 resync */
102 default_interrupt (PDIR2UNOV); /* Processor data in 2 under/overrun */
103 default_interrupt (PDIR1RESYN); /* Processor data in 1 resync */
104 default_interrupt (PDIR1UNOV); /* Processor data in 1 under/overrun */
105 default_interrupt (UQ1CHANERR); /* IEC958-1 Rx U/Q channel error */
106 default_interrupt (IEC2BUFATTEN);/* IEC958-2 channel buffer full */
107 default_interrupt (IEC2PARERR); /* IEC958-2 Rx parity or symbol error */
108 default_interrupt (IEC2VALNOGOOD);/* IEC958-2 flag not good */
109 default_interrupt (IEC2CNEW); /* IEC958-2 New C-channel received */
110 default_interrupt (IEC1BUFATTEN);/* IEC958-1 channel buffer full */
111 default_interrupt (UCHANTXNF); /* U channel Tx reg next byte is first */
112 default_interrupt (UCHANTXUNDER);/* U channel Tx reg underrun */
113 default_interrupt (UCHANTXEMPTY);/* U channel Tx reg is empty */
114 default_interrupt (PDIR3UNOV); /* Processor data in 3 under/overrun */
115 default_interrupt (IEC1PARERR); /* IEC958-1 Rx parity or symbol error */
116 default_interrupt (IEC1VALNOGOOD);/* IEC958-1 flag not good */
117 default_interrupt (IEC1CNEW); /* IEC958-1 New C-channel received */
118 default_interrupt (EBUTXRESYN); /* EBU Tx FIFO resync */
119 default_interrupt (EBUTXUNOV); /* EBU Tx FIFO under/overrun */
120 default_interrupt (IIS2TXRESYN); /* IIS2 Tx FIFO resync */
121 default_interrupt (IIS2TXUNOV); /* IIS2 Tx FIFO under/overrun */
122 default_interrupt (IIS1TXRESYN); /* IIS1 Tx FIFO resync */
123 default_interrupt (IIS1TXUNOV); /* IIS1 Tx FIFO under/overrun */
124 default_interrupt (GPI0); /* GPIO interrupt 0 */
125 default_interrupt (GPI1); /* GPIO interrupt 1 */
126 default_interrupt (GPI2); /* GPIO interrupt 2 */
127 default_interrupt (GPI3); /* GPIO interrupt 3 */
128 default_interrupt (GPI4); /* GPIO interrupt 4 */
129 default_interrupt (GPI5); /* GPIO interrupt 5 */
130 default_interrupt (GPI6); /* GPIO interrupt 6 */
131 default_interrupt (GPI7); /* GPIO interrupt 7 */
133 default_interrupt (SOFTINT0); /* Software interrupt 0 */
134 default_interrupt (SOFTINT1); /* Software interrupt 1 */
135 default_interrupt (SOFTINT2); /* Software interrupt 2 */
136 default_interrupt (SOFTINT3); /* Software interrupt 3 */
138 default_interrupt (CDROMCRCERR); /* CD-ROM CRC error */
139 default_interrupt (CDROMNOSYNC); /* CD-ROM No sync */
140 default_interrupt (CDROMILSYNC); /* CD-ROM Illegal sync */
141 default_interrupt (CDROMNEWBLK); /* CD-ROM New block */
143 default_interrupt (IIC2); /* I2C 2 */
144 default_interrupt (ADC); /* A/D converter */
146 #if defined(IAUDIO_X5) || defined(IAUDIO_M5)
147 #define EXCP_BUTTON_GPIO_READ GPIO_READ
148 #define EXCP_BUTTON_MASK 0x0c000000
149 #define EXCP_BUTTON_VALUE 0x08000000 /* On button and !hold */
150 #define EXCP_PLLCR 0x10400000
151 #elif defined(IAUDIO_M3)
152 #define EXCP_BUTTON_GPIO_READ GPIO1_READ
153 #define EXCP_BUTTON_MASK 0x00000202
154 #define EXCP_BUTTON_VALUE 0x00000200 /* On button and !hold */
155 #define EXCP_PLLCR 0x10800000
156 #elif defined(MPIO_HD200)
157 #define EXCP_BUTTON_GPIO_READ GPIO1_READ
158 #define EXCP_BUTTON_MASK 0x01000010
159 #define EXCP_BUTTON_VALUE 0x01000000 /* Play button and !hold */
160 #define EXCP_PLLCR 0x10800000
161 #else
162 #define EXCP_BUTTON_GPIO_READ GPIO1_READ
163 #define EXCP_BUTTON_MASK 0x00000022
164 #define EXCP_BUTTON_VALUE 0x00000000
165 #define EXCP_PLLCR 0x10800000
166 #endif
168 static void system_display_exception_info(unsigned long format,
169 unsigned long pc) __attribute__ ((noreturn, used));
170 static void system_display_exception_info(unsigned long format,
171 unsigned long pc)
173 int vector = (format >> 18) & 0xff;
175 /* clear screen */
176 #if LCD_DEPTH > 1
177 lcd_set_backdrop(NULL);
178 lcd_set_drawmode(DRMODE_SOLID);
179 lcd_set_foreground(LCD_BLACK);
180 lcd_set_background(LCD_WHITE);
181 #endif
182 lcd_setfont(FONT_SYSFIXED);
183 lcd_set_viewport(NULL);
184 lcd_clear_display();
186 lcd_putsf(0, 0, "I%02x:%s", vector, irqname[vector]);
187 lcd_putsf(0, 1, "at %08x", pc);
188 lcd_update();
190 system_exception_wait();
192 /* Start watchdog timer with 512 cycles timeout. Don't service it. */
193 SYPCR = 0xc0;
194 while (1);
196 /* We need a reset method that works in all cases. Calling system_reboot()
197 doesn't work when we're called from the debug interrupt, because then
198 the CPU is in emulator mode and the only ways leaving it are exexcuting
199 an rte instruction or performing a reset. Even disabling the breakpoint
200 logic and performing special rte magic doesn't make system_reboot()
201 reliable. The system restarts, but boot often fails with ata error -42. */
204 static void UIE(void) NORETURN_ATTR;
205 static void UIE(void)
207 asm volatile("subq.l #4,%sp"); /* phony return address - never used */
208 asm volatile("jmp system_display_exception_info");
209 while (1); /* loop to silence 'noreturn' function does return */
212 /* reset vectors are handled in crt0.S */
213 void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) =
215 UIE,UIE,UIE,UIE,UIE,UIE,
216 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
217 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
218 UIE,UIE,UIE,TIMER0,TIMER1,UIE,UIE,UIE,
219 /* lvl 3 lvl 4 */
221 TRAP0,TRAP1,TRAP2,TRAP3,TRAP4,TRAP5,TRAP6,TRAP7,
222 TRAP8,TRAP9,TRAP10,TRAP11,TRAP12,TRAP13,TRAP14,TRAP15,
224 SWT,UIE,UIE,I2C,UART1,UART2,DMA0,DMA1,
225 DMA2,DMA3,QSPI,UIE,UIE,UIE,UIE,UIE,
226 PDIR1FULL,PDIR2FULL,EBUTXEMPTY,IIS2TXEMPTY,
227 IIS1TXEMPTY,PDIR3FULL,PDIR3RESYN,UQ2CHANERR,
228 AUDIOTICK,PDIR2RESYN,PDIR2UNOV,PDIR1RESYN,
229 PDIR1UNOV,UQ1CHANERR,IEC2BUFATTEN,IEC2PARERR,
230 IEC2VALNOGOOD,IEC2CNEW,IEC1BUFATTEN,UCHANTXNF,
231 UCHANTXUNDER,UCHANTXEMPTY,PDIR3UNOV,IEC1PARERR,
232 IEC1VALNOGOOD,IEC1CNEW,EBUTXRESYN,EBUTXUNOV,
233 IIS2TXRESYN,IIS2TXUNOV,IIS1TXRESYN,IIS1TXUNOV,
234 GPI0,GPI1,GPI2,GPI3,GPI4,GPI5,GPI6,GPI7,
235 UIE,UIE,UIE,UIE,UIE,UIE,UIE,SOFTINT0,
236 SOFTINT1,SOFTINT2,SOFTINT3,UIE,
237 UIE,CDROMCRCERR,CDROMNOSYNC,CDROMILSYNC,
238 CDROMNEWBLK,UIE,UIE,UIE,UIE,UIE,IIC2,ADC,
240 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
241 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
242 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
243 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
244 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
245 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
246 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
247 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE
250 void system_init(void)
252 /* Clear the accumulators. From here on it's the responsibility of
253 whoever uses them to clear them after use and before giving control
254 to "foreign" code (use movclr instruction). */
255 asm volatile ("movclr.l %%acc0, %%d0\n\t"
256 "movclr.l %%acc1, %%d0\n\t"
257 "movclr.l %%acc2, %%d0\n\t"
258 "movclr.l %%acc3, %%d0\n\t"
259 : : : "d0");
261 /* Set EMAC unit to fractional mode with saturation, since that's
262 what'll be the most useful for most things which the main thread
263 will do. */
264 coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
266 IMR = 0x3ffff;
267 INTPRI1 = 0;
268 INTPRI2 = 0;
269 INTPRI3 = 0;
270 INTPRI4 = 0;
271 INTPRI5 = 0;
272 INTPRI6 = 0;
273 INTPRI7 = 0;
274 INTPRI8 = 0;
276 /* Set INTBASE and SPURVEC */
277 INTBASE = 64;
278 SPURVEC = 24;
280 MPARK = 0x81; /* PARK[1,0]=10 + BCR24BIT */
282 #ifndef HAVE_ADJUSTABLE_CPU_FREQ
283 cf_set_cpu_frequency(CPUFREQ_DEFAULT);
284 #endif
287 void system_reboot (void)
289 adc_close();
290 set_cpu_frequency(0);
292 asm(" move.w #0x2700,%sr");
293 /* Reset the cookie for the crt0 crash check */
294 asm(" move.l #0,%d0");
295 asm(" move.l %d0,0x10017ffc");
296 asm(" movec.l %d0,%vbr");
297 asm(" move.l 0,%sp");
298 asm(" move.l 4,%a0");
299 asm(" jmp (%a0)");
302 void system_exception_wait(void)
304 /* set cpu frequency to 11mhz (to prevent overheating) */
305 DCR = (DCR & ~0x01ff) | 1;
306 PLLCR = EXCP_PLLCR;
307 while ((EXCP_BUTTON_GPIO_READ & EXCP_BUTTON_MASK) != EXCP_BUTTON_VALUE);
310 /* Utilise the breakpoint hardware to catch invalid memory accesses. */
311 int system_memory_guard(int newmode)
313 static const unsigned long modes[MAXMEMGUARD][8] = {
314 { /* catch nothing */
315 0x2C870000, 0x00000000, /* TDR = 0x00000000 */
316 0x2C8D0000, 0x00000000, /* ABLR = 0x00000000 */
317 0x2C8C0000, 0x00000000, /* ABHR = 0x00000000 */
318 0x2C860000, 0x00050000, /* AATR = 0x0005 */
320 { /* catch flash ROM writes */
321 0x2C8D0000, 0x00000000, /* ABLR = 0x00000000 */
322 0x2C8C0FFF, 0xFFFF0000, /* ABHR = 0x0FFFFFFF */
323 0x2C860000, 0x6F050000, /* AATR = 0x6F05 */
324 0x2C878000, 0x20080000, /* TDR = 0x80002008 */
326 { /* catch all accesses to zero area */
327 0x2C8D0000, 0x00000000, /* ABLR = 0x00000000 */
328 0x2C8C0FFF, 0xFFFF0000, /* ABHR = 0x0FFFFFFF */
329 0x2C860000, 0xEF050000, /* AATR = 0xEF05 */
330 0x2C878000, 0x20080000, /* TDR = 0x80002008 */
332 /* Note: CPU space accesses (movec instruction), interrupt acknowledges
333 and emulator mode accesses are never caught. */
335 static int cur_mode = MEMGUARD_NONE;
337 int oldmode = cur_mode;
338 const unsigned long *ptr;
339 int i;
341 if (newmode == MEMGUARD_KEEP)
342 newmode = oldmode;
344 /* Always set the new mode, we don't know the old settings
345 as we cannot read back */
346 ptr = modes[newmode];
347 for (i = 0; i < 4; i++)
349 asm ( "wdebug (%0) \n" : : "a"(ptr));
350 ptr += 2;
352 cur_mode = newmode;
354 return oldmode;
357 /* allow setting of audio clock related bits */
358 void coldfire_set_pllcr_audio_bits(long bits)
360 PLLCR = (PLLCR & ~0x70400000) | (bits & 0x70400000);
363 /* Set DATAINCONTROL without disturbing FIFO reset state */
364 void coldfire_set_dataincontrol(unsigned long value)
366 /* Have to be atomic against recording stop initiated by DMA1 */
367 int level = set_irq_level(DMA_IRQ_LEVEL);
368 DATAINCONTROL = (DATAINCONTROL & (1 << 9)) | value;
369 restore_irq(level);
372 void cpucache_commit_discard(void)
374 asm volatile ("move.l #0x01000000,%d0\n"
375 "movec.l %d0,%cacr\n"
376 "move.l #0x80000000,%d0\n"
377 "movec.l %d0,%cacr");
380 void cpucache_invalidate(void) __attribute__((alias("cpucache_commit_discard")));