summaryrefslogtreecommitdiff
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2008-03-31 01:29:50 +0000
committerMichael Sevakis <jethead71@rockbox.org>2008-03-31 01:29:50 +0000
commita65406e3f48daed80f4d1b8627fae38a683fecb6 (patch)
tree0ba581f99dfcf18727fa05152b5a8b25fae86410
parent241fd0fbdb218518cabbc6430dc0159b348549bc (diff)
downloadrockbox-a65406e3f48daed80f4d1b8627fae38a683fecb6.tar.gz
rockbox-a65406e3f48daed80f4d1b8627fae38a683fecb6.zip
meg-fx: It's important to make sure certain interrupt-related registers have bits changed atomically.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@16894 a1c6a512-1295-4272-9138-f99709370657
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c3
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c12
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c9
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c32
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c20
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/system-target.h9
-rw-r--r--firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c8
7 files changed, 59 insertions, 34 deletions
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c
index 4c448c2e41..9a934c2487 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/adc-meg-fx.c
@@ -17,6 +17,7 @@
17 * 17 *
18 ****************************************************************************/ 18 ****************************************************************************/
19#include "cpu.h" 19#include "cpu.h"
20#include "system.h"
20#include "adc-target.h" 21#include "adc-target.h"
21#include "kernel.h" 22#include "kernel.h"
22 23
@@ -35,7 +36,7 @@ void adc_init(void)
35 int i; 36 int i;
36 37
37 /* Turn on the ADC PCLK */ 38 /* Turn on the ADC PCLK */
38 CLKCON |= (1<<15); 39 s3c_regset(&CLKCON, 1<<15);
39 40
40 /* Set channel 0, normal mode, disable "start by read" */ 41 /* Set channel 0, normal mode, disable "start by read" */
41 ADCCON &= ~(0x3F); 42 ADCCON &= ~(0x3F);
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c
index 7e4e608e15..c5d23a3673 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/i2c-meg-fx.c
@@ -41,7 +41,7 @@ void i2c_write(int addr, const unsigned char *buf, int count)
41 mutex_lock(&i2c_mtx); 41 mutex_lock(&i2c_mtx);
42 42
43 /* Turn on I2C clock */ 43 /* Turn on I2C clock */
44 CLKCON |= (1 << 16); 44 s3c_regset(&CLKCON, 1 << 16);
45 45
46 /* Set mode to master transmitter and enable lines */ 46 /* Set mode to master transmitter and enable lines */
47 IICSTAT = I2C_MODE_MASTER | I2C_MODE_TX | I2C_RXTX_ENB; 47 IICSTAT = I2C_MODE_MASTER | I2C_MODE_TX | I2C_RXTX_ENB;
@@ -74,7 +74,7 @@ void i2c_write(int addr, const unsigned char *buf, int count)
74 IICSTAT = 0; 74 IICSTAT = 0;
75 75
76 /* Turn off I2C clock */ 76 /* Turn off I2C clock */
77 CLKCON &= ~(1 << 16); 77 s3c_regclr(&CLKCON, 1 << 16);
78 78
79 mutex_unlock(&i2c_mtx); 79 mutex_unlock(&i2c_mtx);
80} 80}
@@ -90,11 +90,11 @@ void i2c_init(void)
90 INTPND = IIC_MASK; 90 INTPND = IIC_MASK;
91 91
92 /* Enable i2c interrupt in controller */ 92 /* Enable i2c interrupt in controller */
93 INTMOD &= ~IIC_MASK; 93 s3c_regclr(&INTMOD, IIC_MASK);
94 INTMSK &= ~IIC_MASK; 94 s3c_regclr(&INTMSK, IIC_MASK);
95 95
96 /* Turn on I2C clock */ 96 /* Turn on I2C clock */
97 CLKCON |= (1 << 16); 97 s3c_regset(&CLKCON, 1 << 16);
98 98
99 /* Set GPE15 (IICSDA) and GPE14 (IICSCL) to IIC */ 99 /* Set GPE15 (IICSDA) and GPE14 (IICSCL) to IIC */
100 GPECON = (GPECON & ~((3 << 30) | (3 << 28))) | 100 GPECON = (GPECON & ~((3 << 30) | (3 << 28))) |
@@ -108,7 +108,7 @@ void i2c_init(void)
108 IICLC = (0 << 0); 108 IICLC = (0 << 0);
109 109
110 /* Turn off I2C clock */ 110 /* Turn off I2C clock */
111 CLKCON &= ~(1 << 16); 111 s3c_regclr(&CLKCON, 1 << 16);
112} 112}
113 113
114void IIC(void) 114void IIC(void)
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
index 0d532f62c9..e6a70c9f23 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/lcd-meg-fx.c
@@ -1,4 +1,5 @@
1#include "config.h" 1#include "config.h"
2#include "system.h"
2#include "cpu.h" 3#include "cpu.h"
3#include "string.h" 4#include "string.h"
4#include "lcd.h" 5#include "lcd.h"
@@ -81,7 +82,7 @@ void SPI_Send_Bytes(const unsigned char *array, int count)
81 82
82void Setup_LCD_SPI(void) 83void Setup_LCD_SPI(void)
83{ 84{
84 CLKCON|=0x40000; 85 s3c_regset(&CLKCON, 0x40000);
85 SPI_LCD_CS(false); 86 SPI_LCD_CS(false);
86 SPCON0=0x3E; 87 SPCON0=0x3E;
87 SPPRE0=24; 88 SPPRE0=24;
@@ -146,8 +147,8 @@ void lcd_init_device(void)
146#if !defined(BOOTLOADER) 147#if !defined(BOOTLOADER)
147 lcd_poweroff = false; 148 lcd_poweroff = false;
148#endif 149#endif
149 150
150 CLKCON |= 0x20; /* enable LCD clock */ 151 s3c_regset(&CLKCON, 0x20); /* enable LCD clock */
151 152
152 Setup_LCD_SPI(); 153 Setup_LCD_SPI();
153 154
@@ -204,7 +205,7 @@ void lcd_init_device(void)
204 SPI_Send_Bytes(initbuf, sizeof(initbuf)); 205 SPI_Send_Bytes(initbuf, sizeof(initbuf));
205 SPI_LCD_CS(false); 206 SPI_LCD_CS(false);
206 207
207 CLKCON &= ~0x40000; /* disable SPI clock */ 208 s3c_regclr(&CLKCON, 0x40000); /* disable SPI clock */
208} 209}
209 210
210/* Update a fraction of the display. */ 211/* Update a fraction of the display. */
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
index 00be543bb6..6014f4d3af 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/pcm-meg-fx.c
@@ -38,7 +38,7 @@ static struct
38} dma_play_lock = 38} dma_play_lock =
39{ 39{
40 .locked = 0, 40 .locked = 0,
41 .state = (0<<19) 41 .state = 0,
42}; 42};
43 43
44/* Last samplerate set by pcm_set_frequency */ 44/* Last samplerate set by pcm_set_frequency */
@@ -71,22 +71,18 @@ void pcm_apply_settings(void)
71 restore_fiq(status); 71 restore_fiq(status);
72} 72}
73 73
74/* For the locks, DMA interrupt must be disabled because the handler 74/* Mask the DMA interrupt */
75 manipulates INTMSK and the operation is not atomic */
76void pcm_play_lock(void) 75void pcm_play_lock(void)
77{ 76{
78 int status = disable_fiq_save();
79 if (++dma_play_lock.locked == 1) 77 if (++dma_play_lock.locked == 1)
80 INTMSK |= (1<<19); /* Mask the DMA interrupt */ 78 s3c_regset(&INTMSK, DMA2_MASK);
81 restore_fiq(status);
82} 79}
83 80
81/* Unmask the DMA interrupt if enabled */
84void pcm_play_unlock(void) 82void pcm_play_unlock(void)
85{ 83{
86 int status = disable_fiq_save();
87 if (--dma_play_lock.locked == 0) 84 if (--dma_play_lock.locked == 0)
88 INTMSK &= ~dma_play_lock.state; /* Unmask the DMA interrupt if enabled */ 85 s3c_regclr(&INTMSK, dma_play_lock.state);
89 restore_fiq(status);
90} 86}
91 87
92void pcm_play_dma_init(void) 88void pcm_play_dma_init(void)
@@ -110,11 +106,11 @@ void pcm_play_dma_init(void)
110 /* Do not service DMA requests, yet */ 106 /* Do not service DMA requests, yet */
111 107
112 /* clear any pending int and mask it */ 108 /* clear any pending int and mask it */
113 INTMSK |= (1<<19); 109 s3c_regset(&INTMSK, DMA2_MASK);
114 SRCPND = (1<<19); 110 SRCPND = DMA2_MASK;
115 111
116 /* connect to FIQ */ 112 /* connect to FIQ */
117 INTMOD |= (1<<19); 113 s3c_regset(&INTMOD, DMA2_MASK);
118} 114}
119 115
120void pcm_postinit(void) 116void pcm_postinit(void)
@@ -127,7 +123,7 @@ void pcm_postinit(void)
127static void play_start_pcm(void) 123static void play_start_pcm(void)
128{ 124{
129 /* clear pending DMA interrupt */ 125 /* clear pending DMA interrupt */
130 SRCPND = (1<<19); 126 SRCPND = DMA2_MASK;
131 127
132 _pcm_apply_settings(); 128 _pcm_apply_settings();
133 129
@@ -135,7 +131,7 @@ static void play_start_pcm(void)
135 clean_dcache_range((void*)DISRC2, (DCON2 & 0xFFFFF) * 2); 131 clean_dcache_range((void*)DISRC2, (DCON2 & 0xFFFFF) * 2);
136 132
137 /* unmask DMA interrupt when unlocking */ 133 /* unmask DMA interrupt when unlocking */
138 dma_play_lock.state = (1<<19); 134 dma_play_lock.state = DMA2_MASK;
139 135
140 /* turn on the request */ 136 /* turn on the request */
141 IISCON |= (1<<5); 137 IISCON |= (1<<5);
@@ -154,7 +150,7 @@ static void play_start_pcm(void)
154static void play_stop_pcm(void) 150static void play_stop_pcm(void)
155{ 151{
156 /* Mask DMA interrupt */ 152 /* Mask DMA interrupt */
157 INTMSK |= (1<<19); 153 s3c_regset(&INTMSK, DMA2_MASK);
158 154
159 /* De-Activate the DMA channel */ 155 /* De-Activate the DMA channel */
160 DMASKTRIG2 = 0x4; 156 DMASKTRIG2 = 0x4;
@@ -182,7 +178,7 @@ static void play_stop_pcm(void)
182void pcm_play_dma_start(const void *addr, size_t size) 178void pcm_play_dma_start(const void *addr, size_t size)
183{ 179{
184 /* Enable the IIS clock */ 180 /* Enable the IIS clock */
185 CLKCON |= (1<<17); 181 s3c_regset(&CLKCON, 1<<17);
186 182
187 /* stop any DMA in progress - idle IIS */ 183 /* stop any DMA in progress - idle IIS */
188 play_stop_pcm(); 184 play_stop_pcm();
@@ -217,7 +213,7 @@ void pcm_play_dma_stop(void)
217 play_stop_pcm(); 213 play_stop_pcm();
218 214
219 /* Disconnect the IIS clock */ 215 /* Disconnect the IIS clock */
220 CLKCON &= ~(1<<17); 216 s3c_regclr(&CLKCON, 1<<17);
221} 217}
222 218
223void pcm_play_dma_pause(bool pause) 219void pcm_play_dma_pause(bool pause)
@@ -245,7 +241,7 @@ void fiq_handler(void)
245 register pcm_more_callback_type get_more; /* No stack for this */ 241 register pcm_more_callback_type get_more; /* No stack for this */
246 242
247 /* clear any pending interrupt */ 243 /* clear any pending interrupt */
248 SRCPND = (1<<19); 244 SRCPND = DMA2_MASK;
249 245
250 /* Buffer empty. Try to get more. */ 246 /* Buffer empty. Try to get more. */
251 get_more = pcm_callback_for_more; 247 get_more = pcm_callback_for_more;
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c
index 19e9bed1e1..f789827d80 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/system-meg-fx.c
@@ -104,6 +104,24 @@ void memory_init(void) {
104 enable_mmu(); 104 enable_mmu();
105} 105}
106 106
107void s3c_regmod(volatile int *reg, unsigned int set, unsigned int clr)
108{
109 int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS);
110 unsigned int val = *reg;
111 *reg = (val | set) & ~clr;
112 restore_interrupt(oldstatus);
113}
114
115void s3c_regset(volatile int *reg, unsigned int mask)
116{
117 s3c_regmod(reg, mask, 0);
118}
119
120void s3c_regclr(volatile int *reg, unsigned int mask)
121{
122 s3c_regmod(reg, 0, mask);
123}
124
107void system_init(void) 125void system_init(void)
108{ 126{
109 /* Disable interrupts and set all to IRQ mode */ 127 /* Disable interrupts and set all to IRQ mode */
@@ -146,7 +164,7 @@ void system_init(void)
146 164
147 /* Turn off NAND flash controller */ 165 /* Turn off NAND flash controller */
148 | (1 << 4) 166 | (1 << 4)
149 167
150 ); 168 );
151 169
152 /* Turn off the USB PLL */ 170 /* Turn off the USB PLL */
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/system-target.h b/firmware/target/arm/s3c2440/gigabeat-fx/system-target.h
index 2fab652596..5df02effa9 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/system-target.h
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/system-target.h
@@ -26,6 +26,15 @@
26#define CPUFREQ_NORMAL 98784000 26#define CPUFREQ_NORMAL 98784000
27#define CPUFREQ_MAX 296352000 27#define CPUFREQ_MAX 296352000
28 28
29/* Functions to set and clear regiser bits atomically */
30
31/* Set and clear register bits */
32void s3c_regmod(volatile int *reg, unsigned int set, unsigned int clr);
33/* Set register bits */
34void s3c_regset(volatile int *reg, unsigned int mask);
35/* Clear register bits */
36void s3c_regclr(volatile int *reg, unsigned int mask);
37
29#define HAVE_INVALIDATE_ICACHE 38#define HAVE_INVALIDATE_ICACHE
30static inline void invalidate_icache(void) 39static inline void invalidate_icache(void)
31{ 40{
diff --git a/firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c b/firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c
index b59e95806d..574083373a 100644
--- a/firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c
+++ b/firmware/target/arm/s3c2440/gigabeat-fx/timer-meg-fx.c
@@ -89,7 +89,7 @@ bool __timer_register(void)
89{ 89{
90 bool retval = true; 90 bool retval = true;
91 91
92 int oldstatus = set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS); 92 int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS);
93 93
94 stop_timer(); 94 stop_timer();
95 95
@@ -115,14 +115,14 @@ bool __timer_register(void)
115 retval = false; 115 retval = false;
116 } 116 }
117 117
118 set_interrupt_status(oldstatus, IRQ_FIQ_STATUS); 118 restore_interrupt(oldstatus);
119 119
120 return retval; 120 return retval;
121} 121}
122 122
123void __timer_unregister(void) 123void __timer_unregister(void)
124{ 124{
125 int oldstatus = set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS); 125 int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS);
126 stop_timer(); 126 stop_timer();
127 set_interrupt_status(oldstatus, IRQ_FIQ_STATUS); 127 restore_interrupt(oldstatus);
128} 128}