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