as3514: mute headphones at the lowest volume
[kugel-rb.git] / firmware / target / coldfire / system-coldfire.c
blobba67daa3a635c0167bfcbdb46233beba80fd6053
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 #elif defined(MPIO_HD200)
156 #define EXCP_BUTTON_GPIO_READ GPIO1_READ
157 #define EXCP_BUTTON_MASK 0x01000010
158 #define EXCP_BUTTON_VALUE 0x01000000 /* Play button and !hold */
159 #define EXCP_PLLCR 0x10800000
160 #else
161 #define EXCP_BUTTON_GPIO_READ GPIO1_READ
162 #define EXCP_BUTTON_MASK 0x00000022
163 #define EXCP_BUTTON_VALUE 0x00000000
164 #define EXCP_PLLCR 0x10800000
165 #endif
167 static void system_display_exception_info(unsigned long format,
168 unsigned long pc) __attribute__ ((noreturn, used));
169 static void system_display_exception_info(unsigned long format,
170 unsigned long pc)
172 int vector = (format >> 18) & 0xff;
174 /* clear screen */
175 #if LCD_DEPTH > 1
176 lcd_set_backdrop(NULL);
177 lcd_set_drawmode(DRMODE_SOLID);
178 lcd_set_foreground(LCD_BLACK);
179 lcd_set_background(LCD_WHITE);
180 #endif
181 lcd_setfont(FONT_SYSFIXED);
182 lcd_set_viewport(NULL);
183 lcd_clear_display();
185 lcd_putsf(0, 0, "I%02x:%s", vector, irqname[vector]);
186 lcd_putsf(0, 1, "at %08x", pc);
187 lcd_update();
189 system_exception_wait();
191 /* Start watchdog timer with 512 cycles timeout. Don't service it. */
192 SYPCR = 0xc0;
193 while (1);
195 /* We need a reset method that works in all cases. Calling system_reboot()
196 doesn't work when we're called from the debug interrupt, because then
197 the CPU is in emulator mode and the only ways leaving it are exexcuting
198 an rte instruction or performing a reset. Even disabling the breakpoint
199 logic and performing special rte magic doesn't make system_reboot()
200 reliable. The system restarts, but boot often fails with ata error -42. */
203 static void UIE(void) __attribute__ ((noreturn));
204 static void UIE(void)
206 asm volatile("subq.l #4,%sp"); /* phony return address - never used */
207 asm volatile("jmp system_display_exception_info");
208 while (1); /* loop to silence 'noreturn' function does return */
211 /* reset vectors are handled in crt0.S */
212 void (* const vbr[]) (void) __attribute__ ((section (".vectors"))) =
214 UIE,UIE,UIE,UIE,UIE,UIE,
215 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
216 UIE,UIE,UIE,UIE,UIE,UIE,UIE,UIE,
217 UIE,UIE,UIE,TIMER0,TIMER1,UIE,UIE,UIE,
218 /* lvl 3 lvl 4 */
220 TRAP0,TRAP1,TRAP2,TRAP3,TRAP4,TRAP5,TRAP6,TRAP7,
221 TRAP8,TRAP9,TRAP10,TRAP11,TRAP12,TRAP13,TRAP14,TRAP15,
223 SWT,UIE,UIE,I2C,UART1,UART2,DMA0,DMA1,
224 DMA2,DMA3,QSPI,UIE,UIE,UIE,UIE,UIE,
225 PDIR1FULL,PDIR2FULL,EBUTXEMPTY,IIS2TXEMPTY,
226 IIS1TXEMPTY,PDIR3FULL,PDIR3RESYN,UQ2CHANERR,
227 AUDIOTICK,PDIR2RESYN,PDIR2UNOV,PDIR1RESYN,
228 PDIR1UNOV,UQ1CHANERR,IEC2BUFATTEN,IEC2PARERR,
229 IEC2VALNOGOOD,IEC2CNEW,IEC1BUFATTEN,UCHANTXNF,
230 UCHANTXUNDER,UCHANTXEMPTY,PDIR3UNOV,IEC1PARERR,
231 IEC1VALNOGOOD,IEC1CNEW,EBUTXRESYN,EBUTXUNOV,
232 IIS2TXRESYN,IIS2TXUNOV,IIS1TXRESYN,IIS1TXUNOV,
233 GPI0,GPI1,GPI2,GPI3,GPI4,GPI5,GPI6,GPI7,
234 UIE,UIE,UIE,UIE,UIE,UIE,UIE,SOFTINT0,
235 SOFTINT1,SOFTINT2,SOFTINT3,UIE,
236 UIE,CDROMCRCERR,CDROMNOSYNC,CDROMILSYNC,
237 CDROMNEWBLK,UIE,UIE,UIE,UIE,UIE,IIC2,ADC,
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,
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
249 void system_init(void)
251 /* Clear the accumulators. From here on it's the responsibility of
252 whoever uses them to clear them after use and before giving control
253 to "foreign" code (use movclr instruction). */
254 asm volatile ("movclr.l %%acc0, %%d0\n\t"
255 "movclr.l %%acc1, %%d0\n\t"
256 "movclr.l %%acc2, %%d0\n\t"
257 "movclr.l %%acc3, %%d0\n\t"
258 : : : "d0");
260 /* Set EMAC unit to fractional mode with saturation, since that's
261 what'll be the most useful for most things which the main thread
262 will do. */
263 coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
265 IMR = 0x3ffff;
266 INTPRI1 = 0;
267 INTPRI2 = 0;
268 INTPRI3 = 0;
269 INTPRI4 = 0;
270 INTPRI5 = 0;
271 INTPRI6 = 0;
272 INTPRI7 = 0;
273 INTPRI8 = 0;
275 /* Set INTBASE and SPURVEC */
276 INTBASE = 64;
277 SPURVEC = 24;
279 MPARK = 0x81; /* PARK[1,0]=10 + BCR24BIT */
281 #ifndef HAVE_ADJUSTABLE_CPU_FREQ
282 cf_set_cpu_frequency(CPUFREQ_DEFAULT);
283 #endif
286 void system_reboot (void)
288 adc_close();
289 set_cpu_frequency(0);
291 asm(" move.w #0x2700,%sr");
292 /* Reset the cookie for the crt0 crash check */
293 asm(" move.l #0,%d0");
294 asm(" move.l %d0,0x10017ffc");
295 asm(" movec.l %d0,%vbr");
296 asm(" move.l 0,%sp");
297 asm(" move.l 4,%a0");
298 asm(" jmp (%a0)");
301 void system_exception_wait(void)
303 /* set cpu frequency to 11mhz (to prevent overheating) */
304 DCR = (DCR & ~0x01ff) | 1;
305 PLLCR = EXCP_PLLCR;
306 while ((EXCP_BUTTON_GPIO_READ & EXCP_BUTTON_MASK) != EXCP_BUTTON_VALUE);
309 /* Utilise the breakpoint hardware to catch invalid memory accesses. */
310 int system_memory_guard(int newmode)
312 static const unsigned long modes[MAXMEMGUARD][8] = {
313 { /* catch nothing */
314 0x2C870000, 0x00000000, /* TDR = 0x00000000 */
315 0x2C8D0000, 0x00000000, /* ABLR = 0x00000000 */
316 0x2C8C0000, 0x00000000, /* ABHR = 0x00000000 */
317 0x2C860000, 0x00050000, /* AATR = 0x0005 */
319 { /* catch flash ROM writes */
320 0x2C8D0000, 0x00000000, /* ABLR = 0x00000000 */
321 0x2C8C0FFF, 0xFFFF0000, /* ABHR = 0x0FFFFFFF */
322 0x2C860000, 0x6F050000, /* AATR = 0x6F05 */
323 0x2C878000, 0x20080000, /* TDR = 0x80002008 */
325 { /* catch all accesses to zero area */
326 0x2C8D0000, 0x00000000, /* ABLR = 0x00000000 */
327 0x2C8C0FFF, 0xFFFF0000, /* ABHR = 0x0FFFFFFF */
328 0x2C860000, 0xEF050000, /* AATR = 0xEF05 */
329 0x2C878000, 0x20080000, /* TDR = 0x80002008 */
331 /* Note: CPU space accesses (movec instruction), interrupt acknowledges
332 and emulator mode accesses are never caught. */
334 static int cur_mode = MEMGUARD_NONE;
336 int oldmode = cur_mode;
337 const unsigned long *ptr;
338 int i;
340 if (newmode == MEMGUARD_KEEP)
341 newmode = oldmode;
343 /* Always set the new mode, we don't know the old settings
344 as we cannot read back */
345 ptr = modes[newmode];
346 for (i = 0; i < 4; i++)
348 asm ( "wdebug (%0) \n" : : "a"(ptr));
349 ptr += 2;
351 cur_mode = newmode;
353 return oldmode;
356 /* allow setting of audio clock related bits */
357 void coldfire_set_pllcr_audio_bits(long bits)
359 PLLCR = (PLLCR & ~0x70400000) | (bits & 0x70400000);
362 /* Set DATAINCONTROL without disturbing FIFO reset state */
363 void coldfire_set_dataincontrol(unsigned long value)
365 /* Have to be atomic against recording stop initiated by DMA1 */
366 int level = set_irq_level(DMA_IRQ_LEVEL);
367 DATAINCONTROL = (DATAINCONTROL & (1 << 9)) | value;
368 restore_irq(level);
371 void cpucache_invalidate(void)
373 asm volatile ("move.l #0x01000000,%d0\n"
374 "movec.l %d0,%cacr\n"
375 "move.l #0x80000000,%d0\n"
376 "movec.l %d0,%cacr");