summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2011-06-17 03:09:47 +0000
committerMichael Sevakis <jethead71@rockbox.org>2011-06-17 03:09:47 +0000
commitd4800fa3851d2d89c1be03ec99af81f277892579 (patch)
tree60c2beebe08192b2ba6a9c2db31e4409aa940b4e
parent7b605f04168400f3b1b2024600886045f0103c3a (diff)
downloadrockbox-d4800fa3851d2d89c1be03ec99af81f277892579.tar.gz
rockbox-d4800fa3851d2d89c1be03ec99af81f277892579.zip
Coldfire: Fix the modification of IMR. Interrupts must be masked at the core level at at least the level of the interrupt being masked. Not following the datasheet and relying strictly on and/or_l causes unhandled 'Levelx' exceptions (showing itself quite often in PCM mixer work which more greatly stresses PCM lockout).
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@30009 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/coldfire/iriver/h300/lcd-h300.c2
-rw-r--r--firmware/target/coldfire/kernel-coldfire.c2
-rw-r--r--firmware/target/coldfire/mpio/hd200/lcd-hd200.c2
-rw-r--r--firmware/target/coldfire/pcm-coldfire.c24
-rw-r--r--firmware/target/coldfire/system-coldfire.c12
-rw-r--r--firmware/target/coldfire/system-target.h5
-rw-r--r--firmware/target/coldfire/timer-coldfire.c4
7 files changed, 33 insertions, 18 deletions
diff --git a/firmware/target/coldfire/iriver/h300/lcd-h300.c b/firmware/target/coldfire/iriver/h300/lcd-h300.c
index ea0819aa3e..6c21a7e260 100644
--- a/firmware/target/coldfire/iriver/h300/lcd-h300.c
+++ b/firmware/target/coldfire/iriver/h300/lcd-h300.c
@@ -266,7 +266,7 @@ void lcd_init_device(void)
266 DSR3 = 1; 266 DSR3 = 1;
267 DIVR3 = 57; /* DMA3 is mapped into vector 57 in system.c */ 267 DIVR3 = 57; /* DMA3 is mapped into vector 57 in system.c */
268 ICR9 = (6 << 2); /* Enable DMA3 interrupt at level 6, priority 0 */ 268 ICR9 = (6 << 2); /* Enable DMA3 interrupt at level 6, priority 0 */
269 and_l(~(1<<17), &IMR); 269 coldfire_imr_mod(0, 1 << 17);
270 270
271 mutex_init(&lcd_mtx); 271 mutex_init(&lcd_mtx);
272 _display_on(); 272 _display_on();
diff --git a/firmware/target/coldfire/kernel-coldfire.c b/firmware/target/coldfire/kernel-coldfire.c
index 0b08ed13e3..a16f7ad05e 100644
--- a/firmware/target/coldfire/kernel-coldfire.c
+++ b/firmware/target/coldfire/kernel-coldfire.c
@@ -51,7 +51,7 @@ void tick_start(unsigned int interval_in_ms)
51 TER0 = 0xff; /* Clear all events */ 51 TER0 = 0xff; /* Clear all events */
52 52
53 ICR1 = 0x8c; /* Interrupt on level 3.0 */ 53 ICR1 = 0x8c; /* Interrupt on level 3.0 */
54 IMR &= ~0x200; 54 coldfire_imr_mod(0x000, 0x200);
55} 55}
56 56
57void TIMER0(void) __attribute__ ((interrupt_handler)); 57void TIMER0(void) __attribute__ ((interrupt_handler));
diff --git a/firmware/target/coldfire/mpio/hd200/lcd-hd200.c b/firmware/target/coldfire/mpio/hd200/lcd-hd200.c
index 682ed6a311..879352f7b4 100644
--- a/firmware/target/coldfire/mpio/hd200/lcd-hd200.c
+++ b/firmware/target/coldfire/mpio/hd200/lcd-hd200.c
@@ -167,7 +167,7 @@ void lcd_init_device(void)
167 DSR3 = 1; 167 DSR3 = 1;
168 DIVR3 = 57; /* DMA3 is mapped into vector 57 in system.c */ 168 DIVR3 = 57; /* DMA3 is mapped into vector 57 in system.c */
169 ICR9 = (6 << 2); /* Enable DMA3 interrupt at level 6, priority 0 */ 169 ICR9 = (6 << 2); /* Enable DMA3 interrupt at level 6, priority 0 */
170 and_l(~(1<<17), &IMR); 170 coldfire_imr_mod(0, 1 << 17);
171 171
172 mutex_init(&lcd_mtx); 172 mutex_init(&lcd_mtx);
173 173
diff --git a/firmware/target/coldfire/pcm-coldfire.c b/firmware/target/coldfire/pcm-coldfire.c
index fa320dff3f..a06542c31f 100644
--- a/firmware/target/coldfire/pcm-coldfire.c
+++ b/firmware/target/coldfire/pcm-coldfire.c
@@ -219,19 +219,19 @@ void pcm_postinit(void)
219static struct dma_lock dma_play_lock = 219static struct dma_lock dma_play_lock =
220{ 220{
221 .locked = 0, 221 .locked = 0,
222 .state = (0 << 14) /* bit 14 is DMA0 */ 222 .state = (1 << 14) /* bit 14 is DMA0 */
223}; 223};
224 224
225void pcm_play_lock(void) 225void pcm_play_lock(void)
226{ 226{
227 if (++dma_play_lock.locked == 1) 227 if (++dma_play_lock.locked == 1)
228 or_l((1 << 14), &IMR); 228 coldfire_imr_mod(1 << 14, 1 << 14);
229} 229}
230 230
231void pcm_play_unlock(void) 231void pcm_play_unlock(void)
232{ 232{
233 if (--dma_play_lock.locked == 0) 233 if (--dma_play_lock.locked == 0)
234 and_l(~dma_play_lock.state, &IMR); 234 coldfire_imr_mod(dma_play_lock.state, 1 << 14);
235} 235}
236 236
237/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */ 237/* Set up the DMA transfer that kicks in when the audio FIFO gets empty */
@@ -248,7 +248,7 @@ void pcm_play_dma_start(const void *addr, size_t size)
248 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_SINC | 248 DCR0 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_SINC |
249 DMA_SSIZE(DMA_SIZE_LINE) | DMA_START; 249 DMA_SSIZE(DMA_SIZE_LINE) | DMA_START;
250 250
251 dma_play_lock.state = (1 << 14); 251 dma_play_lock.state = (0 << 14);
252} /* pcm_play_dma_start */ 252} /* pcm_play_dma_start */
253 253
254/* Stops the DMA transfer and interrupt */ 254/* Stops the DMA transfer and interrupt */
@@ -260,7 +260,7 @@ void pcm_play_dma_stop(void)
260 260
261 iis_play_reset_if_playback(true); 261 iis_play_reset_if_playback(true);
262 262
263 dma_play_lock.state = (0 << 14); 263 dma_play_lock.state = (1 << 14);
264} /* pcm_play_dma_stop */ 264} /* pcm_play_dma_stop */
265 265
266void pcm_play_dma_pause(bool pause) 266void pcm_play_dma_pause(bool pause)
@@ -271,14 +271,14 @@ void pcm_play_dma_pause(bool pause)
271 and_l(~(DMA_EEXT | DMA_INT), &DCR0); /* per request and int OFF */ 271 and_l(~(DMA_EEXT | DMA_INT), &DCR0); /* per request and int OFF */
272 DSR0 = 1; /* stop channel */ 272 DSR0 = 1; /* stop channel */
273 iis_play_reset_if_playback(true); 273 iis_play_reset_if_playback(true);
274 dma_play_lock.state = (0 << 14); 274 dma_play_lock.state = (1 << 14);
275 } 275 }
276 else 276 else
277 { 277 {
278 /* restart playback on current buffer */ 278 /* restart playback on current buffer */
279 iis_play_reset_if_playback(true); 279 iis_play_reset_if_playback(true);
280 or_l(DMA_INT | DMA_EEXT | DMA_START, &DCR0); /* everything ON */ 280 or_l(DMA_INT | DMA_EEXT | DMA_START, &DCR0); /* everything ON */
281 dma_play_lock.state = (1 << 14); 281 dma_play_lock.state = (0 << 14);
282 } 282 }
283} /* pcm_play_dma_pause */ 283} /* pcm_play_dma_pause */
284 284
@@ -344,7 +344,7 @@ const void * pcm_play_dma_get_peak_buffer(int *count)
344static struct dma_lock dma_rec_lock = 344static struct dma_lock dma_rec_lock =
345{ 345{
346 .locked = 0, 346 .locked = 0,
347 .state = (0 << 15) /* bit 15 is DMA1 */ 347 .state = (1 << 15) /* bit 15 is DMA1 */
348}; 348};
349 349
350/* For the locks, DMA interrupt must be disabled when manipulating the lock 350/* For the locks, DMA interrupt must be disabled when manipulating the lock
@@ -353,13 +353,13 @@ static struct dma_lock dma_rec_lock =
353void pcm_rec_lock(void) 353void pcm_rec_lock(void)
354{ 354{
355 if (++dma_rec_lock.locked == 1) 355 if (++dma_rec_lock.locked == 1)
356 or_l((1 << 15), &IMR); 356 coldfire_imr_mod(1 << 15, 1 << 15);
357} 357}
358 358
359void pcm_rec_unlock(void) 359void pcm_rec_unlock(void)
360{ 360{
361 if (--dma_rec_lock.locked == 0) 361 if (--dma_rec_lock.locked == 0)
362 and_l(~dma_rec_lock.state, &IMR); 362 coldfire_imr_mod(dma_rec_lock.state, 1 << 15);
363} 363}
364 364
365void pcm_rec_dma_start(void *addr, size_t size) 365void pcm_rec_dma_start(void *addr, size_t size)
@@ -382,7 +382,7 @@ void pcm_rec_dma_start(void *addr, size_t size)
382 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_DINC | 382 DCR1 = DMA_INT | DMA_EEXT | DMA_CS | DMA_AA | DMA_DINC |
383 DMA_DSIZE(DMA_SIZE_LINE) | DMA_START; 383 DMA_DSIZE(DMA_SIZE_LINE) | DMA_START;
384 384
385 dma_rec_lock.state = (1 << 15); 385 dma_rec_lock.state = (0 << 15);
386} /* pcm_rec_dma_start */ 386} /* pcm_rec_dma_start */
387 387
388void pcm_rec_dma_stop(void) 388void pcm_rec_dma_stop(void)
@@ -395,7 +395,7 @@ void pcm_rec_dma_stop(void)
395 395
396 iis_play_reset_if_playback(false); 396 iis_play_reset_if_playback(false);
397 397
398 dma_rec_lock.state = (0 << 15); 398 dma_rec_lock.state = (1 << 15);
399} /* pcm_rec_dma_stop */ 399} /* pcm_rec_dma_stop */
400 400
401void pcm_rec_dma_init(void) 401void pcm_rec_dma_init(void)
diff --git a/firmware/target/coldfire/system-coldfire.c b/firmware/target/coldfire/system-coldfire.c
index 61a5da98cd..1fbd00825a 100644
--- a/firmware/target/coldfire/system-coldfire.c
+++ b/firmware/target/coldfire/system-coldfire.c
@@ -268,7 +268,7 @@ void system_init(void)
268 will do. */ 268 will do. */
269 coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE); 269 coldfire_set_macsr(EMAC_FRACTIONAL | EMAC_SATURATE);
270 270
271 IMR = 0x3ffff; 271 coldfire_imr_mod(0x3ffff, 0x3ffff);
272 INTPRI1 = 0; 272 INTPRI1 = 0;
273 INTPRI2 = 0; 273 INTPRI2 = 0;
274 INTPRI3 = 0; 274 INTPRI3 = 0;
@@ -365,6 +365,16 @@ void coldfire_set_pllcr_audio_bits(long bits)
365 PLLCR = (PLLCR & ~0x70400000) | (bits & 0x70400000); 365 PLLCR = (PLLCR & ~0x70400000) | (bits & 0x70400000);
366} 366}
367 367
368/* Safely modify the interrupt mask register as the core interrupt level is
369 required to be at least as high as the level interrupt being
370 masked/unmasked */
371void coldfire_imr_mod(unsigned long bits, unsigned long mask)
372{
373 unsigned long oldlevel = set_irq_level(DISABLE_INTERRUPTS);
374 IMR = (IMR & ~mask) | (bits & mask);
375 restore_irq(oldlevel);
376}
377
368/* Set DATAINCONTROL without disturbing FIFO reset state */ 378/* Set DATAINCONTROL without disturbing FIFO reset state */
369void coldfire_set_dataincontrol(unsigned long value) 379void coldfire_set_dataincontrol(unsigned long value)
370{ 380{
diff --git a/firmware/target/coldfire/system-target.h b/firmware/target/coldfire/system-target.h
index d1a2a1f115..3d7502a6dd 100644
--- a/firmware/target/coldfire/system-target.h
+++ b/firmware/target/coldfire/system-target.h
@@ -201,6 +201,11 @@ static inline uint32_t swap_odd_even32_hw(uint32_t value)
201#define DEFAULT_PLLCR_AUDIO_BITS 0x10400000 201#define DEFAULT_PLLCR_AUDIO_BITS 0x10400000
202void coldfire_set_pllcr_audio_bits(long bits); 202void coldfire_set_pllcr_audio_bits(long bits);
203 203
204/* Safely modify the interrupt mask register as the core interrupt level is
205 required to be at least as high as the level interrupt being
206 masked/unmasked */
207void coldfire_imr_mod(unsigned long bits, unsigned long mask);
208
204/* Set DATAINCONTROL without disturbing FIFO reset state */ 209/* Set DATAINCONTROL without disturbing FIFO reset state */
205void coldfire_set_dataincontrol(unsigned long value); 210void coldfire_set_dataincontrol(unsigned long value);
206 211
diff --git a/firmware/target/coldfire/timer-coldfire.c b/firmware/target/coldfire/timer-coldfire.c
index 49d22bb5fa..cc665cb9c6 100644
--- a/firmware/target/coldfire/timer-coldfire.c
+++ b/firmware/target/coldfire/timer-coldfire.c
@@ -89,7 +89,7 @@ bool timer_set(long cycles, bool start)
89bool timer_start(void) 89bool timer_start(void)
90{ 90{
91 ICR2 = 0x90; /* interrupt on level 4.0 */ 91 ICR2 = 0x90; /* interrupt on level 4.0 */
92 and_l(~(1<<10), &IMR); 92 coldfire_imr_mod(0, 1 << 10);
93 TMR1 |= 1; /* start timer */ 93 TMR1 |= 1; /* start timer */
94 return true; 94 return true;
95} 95}
@@ -97,7 +97,7 @@ bool timer_start(void)
97void timer_stop(void) 97void timer_stop(void)
98{ 98{
99 TMR1 = 0; /* disable timer 1 */ 99 TMR1 = 0; /* disable timer 1 */
100 or_l((1<<10), &IMR); /* disable interrupt */ 100 coldfire_imr_mod(1 << 10, 1 << 10); /* disable interrupt */
101} 101}
102 102
103void timers_adjust_prescale(int multiplier, bool enable_irq) 103void timers_adjust_prescale(int multiplier, bool enable_irq)