blob: 8b20360b469389633275c05fdfa2f4245abba0f7 [file] [log] [blame]
Michael Sevakisf29cae02006-10-30 14:17:14 +00001/***************************************************************************
2 * __________ __ ___.
3 * Open \______ \ ____ ____ | | _\_ |__ _______ ___
4 * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
5 * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
6 * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
7 * \/ \/ \/ \/ \/
8 * $Id$
9 *
10 * Copyright (C) 2002 by Alan Korr
11 *
12 * All files in this archive are subject to the GNU General Public License.
13 * See the file COPYING in the source tree root for full license agreement.
14 *
15 * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
16 * KIND, either express or implied.
17 *
18 ****************************************************************************/
19#include <stdio.h>
20#include "config.h"
21#include "system.h"
22#include "lcd.h"
23#include "font.h"
24
25#define default_interrupt(name) \
26 extern __attribute__((weak,alias("UIE"))) void name (void)
27
28static const char* const irqname[] = {
Michael Sevakis59f9deb2006-11-02 15:39:08 +000029 "", "", "AccessErr","AddrErr","IllInstr", "DivX0", "","",
Michael Sevakisf29cae02006-10-30 14:17:14 +000030 "PrivVio","Trace","Line-A", "Line-F","Debug","","FormErr","Uninit",
31 "","","","","","","","",
32 "Spurious","Level1","Level2","Level3","Level4","Level5","Level6","Level7",
33 "Trap0","Trap1","Trap2","Trap3","Trap4","Trap5","Trap6","Trap7",
34 "Trap8","Trap9","Trap10","Trap11","Trap12","Trap13","Trap14","Trap15",
35 "SWT","Timer0","Timer1","I2C","UART1","UART2","DMA0","DMA1",
36 "DMA2","DMA3","QSPI","","","","","",
37 "PDIR1FULL","PDIR2FULL","EBUTXEMPTY","IIS2TXEMPTY",
38 "IIS1TXEMPTY","PDIR3FULL","PDIR3RESYN","UQ2CHANERR",
39 "AUDIOTICK","PDIR2RESYN","PDIR2UNOV","PDIR1RESYN",
40 "PDIR1UNOV","UQ1CHANERR","IEC2BUFATTEN","IEC2PARERR",
41 "IEC2VALNOGOOD","IEC2CNEW","IEC1BUFATTEN","UCHANTXNF",
42 "UCHANTXUNDER","UCHANTXEMPTY","PDIR3UNOV","IEC1PARERR",
43 "IEC1VALNOGOOD","IEC1CNEW","EBUTXRESYN","EBUTXUNOV",
44 "IIS2TXRESYN","IIS2TXUNOV","IIS1TXRESYN","IIS1TXUNOV",
45 "GPI0","GPI1","GPI2","GPI3","GPI4","GPI5","GPI6","GPI7",
46 "","","","","","","","SOFTINT0",
47 "SOFTINT1","SOFTINT2","SOFTINT3","",
48 "","CDROMCRCERR","CDROMNOSYNC","CDROMILSYNC",
49 "CDROMNEWBLK","","","","","","","",
50 "","","","","","","","",
51 "","","","","","","","",
52 "","","","","","","","",
53 "","","","","","","","",
54 "","","","","","","","",
55 "","","","","","","","",
56 "","","","","","","","",
57 "","","","","","","",""
58};
59
60default_interrupt (TRAP0); /* Trap #0 */
61default_interrupt (TRAP1); /* Trap #1 */
62default_interrupt (TRAP2); /* Trap #2 */
63default_interrupt (TRAP3); /* Trap #3 */
64default_interrupt (TRAP4); /* Trap #4 */
65default_interrupt (TRAP5); /* Trap #5 */
66default_interrupt (TRAP6); /* Trap #6 */
67default_interrupt (TRAP7); /* Trap #7 */
68default_interrupt (TRAP8); /* Trap #8 */
69default_interrupt (TRAP9); /* Trap #9 */
70default_interrupt (TRAP10); /* Trap #10 */
71default_interrupt (TRAP11); /* Trap #11 */
72default_interrupt (TRAP12); /* Trap #12 */
73default_interrupt (TRAP13); /* Trap #13 */
74default_interrupt (TRAP14); /* Trap #14 */
75default_interrupt (TRAP15); /* Trap #15 */
76default_interrupt (SWT); /* Software Watchdog Timer */
77default_interrupt (TIMER0); /* Timer 0 */
78default_interrupt (TIMER1); /* Timer 1 */
79default_interrupt (I2C); /* I2C */
80default_interrupt (UART1); /* UART 1 */
81default_interrupt (UART2); /* UART 2 */
82default_interrupt (DMA0); /* DMA 0 */
83default_interrupt (DMA1); /* DMA 1 */
84default_interrupt (DMA2); /* DMA 2 */
85default_interrupt (DMA3); /* DMA 3 */
86default_interrupt (QSPI); /* QSPI */
87
88default_interrupt (PDIR1FULL); /* Processor data in 1 full */
89default_interrupt (PDIR2FULL); /* Processor data in 2 full */
90default_interrupt (EBUTXEMPTY); /* EBU transmit FIFO empty */
91default_interrupt (IIS2TXEMPTY); /* IIS2 transmit FIFO empty */
92default_interrupt (IIS1TXEMPTY); /* IIS1 transmit FIFO empty */
93default_interrupt (PDIR3FULL); /* Processor data in 3 full */
94default_interrupt (PDIR3RESYN); /* Processor data in 3 resync */
95default_interrupt (UQ2CHANERR); /* IEC958-2 Rx U/Q channel error */
96default_interrupt (AUDIOTICK); /* "tick" interrupt */
97default_interrupt (PDIR2RESYN); /* Processor data in 2 resync */
98default_interrupt (PDIR2UNOV); /* Processor data in 2 under/overrun */
99default_interrupt (PDIR1RESYN); /* Processor data in 1 resync */
100default_interrupt (PDIR1UNOV); /* Processor data in 1 under/overrun */
101default_interrupt (UQ1CHANERR); /* IEC958-1 Rx U/Q channel error */
102default_interrupt (IEC2BUFATTEN);/* IEC958-2 channel buffer full */
103default_interrupt (IEC2PARERR); /* IEC958-2 Rx parity or symbol error */
104default_interrupt (IEC2VALNOGOOD);/* IEC958-2 flag not good */
105default_interrupt (IEC2CNEW); /* IEC958-2 New C-channel received */
106default_interrupt (IEC1BUFATTEN);/* IEC958-1 channel buffer full */
107default_interrupt (UCHANTXNF); /* U channel Tx reg next byte is first */
108default_interrupt (UCHANTXUNDER);/* U channel Tx reg underrun */
109default_interrupt (UCHANTXEMPTY);/* U channel Tx reg is empty */
110default_interrupt (PDIR3UNOV); /* Processor data in 3 under/overrun */
111default_interrupt (IEC1PARERR); /* IEC958-1 Rx parity or symbol error */
112default_interrupt (IEC1VALNOGOOD);/* IEC958-1 flag not good */
113default_interrupt (IEC1CNEW); /* IEC958-1 New C-channel received */
114default_interrupt (EBUTXRESYN); /* EBU Tx FIFO resync */
115default_interrupt (EBUTXUNOV); /* EBU Tx FIFO under/overrun */
116default_interrupt (IIS2TXRESYN); /* IIS2 Tx FIFO resync */
117default_interrupt (IIS2TXUNOV); /* IIS2 Tx FIFO under/overrun */
118default_interrupt (IIS1TXRESYN); /* IIS1 Tx FIFO resync */
119default_interrupt (IIS1TXUNOV); /* IIS1 Tx FIFO under/overrun */
120default_interrupt (GPI0); /* GPIO interrupt 0 */
121default_interrupt (GPI1); /* GPIO interrupt 1 */
122default_interrupt (GPI2); /* GPIO interrupt 2 */
123default_interrupt (GPI3); /* GPIO interrupt 3 */
124default_interrupt (GPI4); /* GPIO interrupt 4 */
125default_interrupt (GPI5); /* GPIO interrupt 5 */
126default_interrupt (GPI6); /* GPIO interrupt 6 */
127default_interrupt (GPI7); /* GPIO interrupt 7 */
128
129default_interrupt (SOFTINT0); /* Software interrupt 0 */
130default_interrupt (SOFTINT1); /* Software interrupt 1 */
131default_interrupt (SOFTINT2); /* Software interrupt 2 */
132default_interrupt (SOFTINT3); /* Software interrupt 3 */
133
134default_interrupt (CDROMCRCERR); /* CD-ROM CRC error */
135default_interrupt (CDROMNOSYNC); /* CD-ROM No sync */
136default_interrupt (CDROMILSYNC); /* CD-ROM Illegal sync */
137default_interrupt (CDROMNEWBLK); /* CD-ROM New block */
138
Jens Arnold88760182007-03-05 00:04:00 +0000139#if defined(IAUDIO_X5) || defined(IAUDIO_M5)
Michael Sevakis0fb67cd2006-11-03 10:19:04 +0000140#define EXCP_BUTTON_GPIO_READ GPIO_READ
141#define EXCP_BUTTON_MASK 0x0c000000
142#define EXCP_BUTTON_VALUE 0x08000000 /* On button and !hold */
143#define EXCP_PLLCR 0x10400000
144#else
145#define EXCP_BUTTON_GPIO_READ GPIO1_READ
146#define EXCP_BUTTON_MASK 0x00000022
147#define EXCP_BUTTON_VALUE 0x00000000
148#define EXCP_PLLCR 0x10800000
149#endif
Michael Sevakis59f9deb2006-11-02 15:39:08 +0000150
Michael Sevakis0fb67cd2006-11-03 10:19:04 +0000151static void system_display_exception_info(unsigned long format,
Magnus Holmgren7b3abf22007-05-23 18:11:55 +0000152 unsigned long pc) __attribute__ ((noreturn, used));
Michael Sevakis0fb67cd2006-11-03 10:19:04 +0000153static void system_display_exception_info(unsigned long format,
154 unsigned long pc)
Michael Sevakis59f9deb2006-11-02 15:39:08 +0000155{
Michael Sevakis0fb67cd2006-11-03 10:19:04 +0000156 int vector = (format >> 18) & 0xff;
Michael Sevakisf29cae02006-10-30 14:17:14 +0000157 char str[32];
158
Michael Sevakisf29cae02006-10-30 14:17:14 +0000159 /* clear screen */
160 lcd_clear_display ();
161 lcd_setfont(FONT_SYSFIXED);
162
Michael Sevakis59f9deb2006-11-02 15:39:08 +0000163 snprintf(str, sizeof(str), "I%02x:%s", vector, irqname[vector]);
164 lcd_puts(0, 0, str);
165 snprintf(str, sizeof(str), "at %08x", pc);
166 lcd_puts(0, 1, str);
Michael Sevakisf29cae02006-10-30 14:17:14 +0000167 lcd_update();
168
169 /* set cpu frequency to 11mhz (to prevent overheating) */
Michael Sevakis0fb67cd2006-11-03 10:19:04 +0000170 DCR = (DCR & ~0x01ff) | 1;
171 PLLCR = EXCP_PLLCR;
Michael Sevakisf29cae02006-10-30 14:17:14 +0000172
173 while (1)
174 {
Michael Sevakis0fb67cd2006-11-03 10:19:04 +0000175 if ((EXCP_BUTTON_GPIO_READ & EXCP_BUTTON_MASK) == EXCP_BUTTON_VALUE)
Michael Sevakisf29cae02006-10-30 14:17:14 +0000176 SYPCR = 0xc0;
177 /* Start watchdog timer with 512 cycles timeout. Don't service it. */
Michael Sevakis59f9deb2006-11-02 15:39:08 +0000178 }
Michael Sevakisf29cae02006-10-30 14:17:14 +0000179
180 /* We need a reset method that works in all cases. Calling system_reboot()
181 doesn't work when we're called from the debug interrupt, because then
182 the CPU is in emulator mode and the only ways leaving it are exexcuting
183 an rte instruction or performing a reset. Even disabling the breakpoint
184 logic and performing special rte magic doesn't make system_reboot()
185 reliable. The system restarts, but boot often fails with ata error -42. */
Michael Sevakis59f9deb2006-11-02 15:39:08 +0000186}
187
188static void UIE(void) __attribute__ ((noreturn));
189static void UIE(void)
190{
Michael Sevakis0fb67cd2006-11-03 10:19:04 +0000191 asm volatile("subq.l #4,%sp"); /* phony return address - never used */
192 asm volatile("jmp system_display_exception_info");
193 while (1); /* loop to silence 'noreturn' function does return */
Michael Sevakisf29cae02006-10-30 14:17:14 +0000194}
195
196/* reset vectors are handled in crt0.S */
197void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) =
198{
199 UIE,UIE,UIE,UIE,UIE,UIE,
200 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
201 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
202 UIE,UIE,UIE,TIMER0,TIMER1,UIE,UIE,UIE,
203 /* lvl 3 lvl 4 */
204
205 TRAP0,TRAP1,TRAP2,TRAP3,TRAP4,TRAP5,TRAP6,TRAP7,
206 TRAP8,TRAP9,TRAP10,TRAP11,TRAP12,TRAP13,TRAP14,TRAP15,
207
208 SWT,UIE,UIE,I2C,UART1,UART2,DMA0,DMA1,
209 DMA2,DMA3,QSPI,UIE,UIE,UIE,UIE,UIE,
210 PDIR1FULL,PDIR2FULL,EBUTXEMPTY,IIS2TXEMPTY,
211 IIS1TXEMPTY,PDIR3FULL,PDIR3RESYN,UQ2CHANERR,
212 AUDIOTICK,PDIR2RESYN,PDIR2UNOV,PDIR1RESYN,
213 PDIR1UNOV,UQ1CHANERR,IEC2BUFATTEN,IEC2PARERR,
214 IEC2VALNOGOOD,IEC2CNEW,IEC1BUFATTEN,UCHANTXNF,
215 UCHANTXUNDER,UCHANTXEMPTY,PDIR3UNOV,IEC1PARERR,
216 IEC1VALNOGOOD,IEC1CNEW,EBUTXRESYN,EBUTXUNOV,
217 IIS2TXRESYN,IIS2TXUNOV,IIS1TXRESYN,IIS1TXUNOV,
218 GPI0,GPI1,GPI2,GPI3,GPI4,GPI5,GPI6,GPI7,
219 UIE,UIE,UIE,UIE,UIE,UIE,UIE,SOFTINT0,
220 SOFTINT1,SOFTINT2,SOFTINT3,UIE,
221 UIE,CDROMCRCERR,CDROMNOSYNC,CDROMILSYNC,
222 CDROMNEWBLK,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
223
224 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
225 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
226 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
227 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
228 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
229 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
230 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
231 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE
232};
233
234void system_init(void)
235{
236 /* Clear the accumulators. From here on it's the responsibility of
Michael Sevakis2c9cbc12007-02-25 21:43:10 +0000237 whoever uses them to clear them after use and before giving control
238 to "foreign" code (use movclr instruction). */
Michael Sevakisf29cae02006-10-30 14:17:14 +0000239 asm volatile ("movclr.l %%acc0, %%d0\n\t"
240 "movclr.l %%acc1, %%d0\n\t"
241 "movclr.l %%acc2, %%d0\n\t"
242 "movclr.l %%acc3, %%d0\n\t"
243 : : : "d0");
Michael Sevakisf29cae02006-10-30 14:17:14 +0000244
Michael Sevakis306aa752007-02-25 22:59:39 +0000245 /* Set EMAC unit to fractional mode with saturation, since that's
246 what'll be the most useful for most things which the main thread
247 will do. */
248 coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
249
Michael Sevakisf29cae02006-10-30 14:17:14 +0000250 /* Set INTBASE and SPURVEC */
251 INTBASE = 64;
252 SPURVEC = 24;
Linus Nielsen Feltzing97444332007-02-22 14:54:13 +0000253
254 MPARK = 0x81; /* PARK[1,0]=10 + BCR24BIT */
Steve Bavinc90c18e2007-10-02 07:54:50 +0000255
256#ifndef HAVE_ADJUSTABLE_CPU_FREQ
257 cf_set_cpu_frequency(CPUFREQ_DEFAULT);
258#endif
Michael Sevakisf29cae02006-10-30 14:17:14 +0000259}
260
261void system_reboot (void)
262{
263 set_cpu_frequency(0);
264
265 asm(" move.w #0x2700,%sr");
266 /* Reset the cookie for the crt0 crash check */
267 asm(" move.l #0,%d0");
268 asm(" move.l %d0,0x10017ffc");
269 asm(" movec.l %d0,%vbr");
270 asm(" move.l 0,%sp");
271 asm(" move.l 4,%a0");
272 asm(" jmp (%a0)");
273}
274
275/* Utilise the breakpoint hardware to catch invalid memory accesses. */
276int system_memory_guard(int newmode)
277{
278 static const unsigned long modes[MAXMEMGUARD][8] = {
279 { /* catch nothing */
280 0x2C870000, 0x00000000, /* TDR = 0x00000000 */
281 0x2C8D0000, 0x00000000, /* ABLR = 0x00000000 */
282 0x2C8C0000, 0x00000000, /* ABHR = 0x00000000 */
283 0x2C860000, 0x00050000, /* AATR = 0x0005 */
284 },
285 { /* catch flash ROM writes */
286 0x2C8D0000, 0x00000000, /* ABLR = 0x00000000 */
287 0x2C8C0FFF, 0xFFFF0000, /* ABHR = 0x0FFFFFFF */
288 0x2C860000, 0x6F050000, /* AATR = 0x6F05 */
289 0x2C878000, 0x20080000, /* TDR = 0x80002008 */
290 },
291 { /* catch all accesses to zero area */
292 0x2C8D0000, 0x00000000, /* ABLR = 0x00000000 */
293 0x2C8C0FFF, 0xFFFF0000, /* ABHR = 0x0FFFFFFF */
294 0x2C860000, 0xEF050000, /* AATR = 0xEF05 */
295 0x2C878000, 0x20080000, /* TDR = 0x80002008 */
296 }
297 /* Note: CPU space accesses (movec instruction), interrupt acknowledges
298 and emulator mode accesses are never caught. */
299 };
300 static int cur_mode = MEMGUARD_NONE;
301
302 int oldmode = cur_mode;
303 const unsigned long *ptr;
304 int i;
305
306 if (newmode == MEMGUARD_KEEP)
307 newmode = oldmode;
308
309 /* Always set the new mode, we don't know the old settings
310 as we cannot read back */
311 ptr = modes[newmode];
312 for (i = 0; i < 4; i++)
313 {
314 asm ( "wdebug (%0) \n" : : "a"(ptr));
315 ptr += 2;
316 }
317 cur_mode = newmode;
318
319 return oldmode;
320}
Michael Sevakis0f5cb942006-11-06 18:07:30 +0000321
322/* allow setting of audio clock related bits */
323void coldfire_set_pllcr_audio_bits(long bits)
324{
Miika Pekkarinen46a608b2006-12-06 10:02:06 +0000325 PLLCR = (PLLCR & ~0x70400000) | (bits & 0x70400000);
Michael Sevakis0f5cb942006-11-06 18:07:30 +0000326}
327
Michael Sevakis8867d002007-03-05 08:14:27 +0000328/* Set DATAINCONTROL without disturbing FIFO reset state */
329void coldfire_set_dataincontrol(unsigned long value)
330{
Michael Sevakis633f3882007-03-07 06:23:02 +0000331 /* Have to be atomic against recording stop initiated by DMA1 */
332 int level = set_irq_level(DMA_IRQ_LEVEL);
Michael Sevakis8867d002007-03-05 08:14:27 +0000333 DATAINCONTROL = (DATAINCONTROL & (1 << 9)) | value;
Michael Sevakis633f3882007-03-07 06:23:02 +0000334 set_irq_level(level);
Michael Sevakis8867d002007-03-05 08:14:27 +0000335}