summaryrefslogtreecommitdiffstats
path: root/firmware
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 /firmware
parent241fd0fbdb218518cabbc6430dc0159b348549bc (diff)
downloadrockbox-a65406e3f48daed80f4d1b8627fae38a683fecb6.tar.gz
rockbox-a65406e3f48daed80f4d1b8627fae38a683fecb6.tar.bz2
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
Diffstat (limited to 'firmware')
-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 @@
*
****************************************************************************/
#include "cpu.h"
+#include "system.h"
#include "adc-target.h"
#include "kernel.h"
@@ -35,7 +36,7 @@ void adc_init(void)
int i;
/* Turn on the ADC PCLK */
- CLKCON |= (1<<15);
+ s3c_regset(&CLKCON, 1<<15);
/* Set channel 0, normal mode, disable "start by read" */
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)
mutex_lock(&i2c_mtx);
/* Turn on I2C clock */
- CLKCON |= (1 << 16);
+ s3c_regset(&CLKCON, 1 << 16);
/* Set mode to master transmitter and enable lines */
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)
IICSTAT = 0;
/* Turn off I2C clock */
- CLKCON &= ~(1 << 16);
+ s3c_regclr(&CLKCON, 1 << 16);
mutex_unlock(&i2c_mtx);
}
@@ -90,11 +90,11 @@ void i2c_init(void)
INTPND = IIC_MASK;
/* Enable i2c interrupt in controller */
- INTMOD &= ~IIC_MASK;
- INTMSK &= ~IIC_MASK;
+ s3c_regclr(&INTMOD, IIC_MASK);
+ s3c_regclr(&INTMSK, IIC_MASK);
/* Turn on I2C clock */
- CLKCON |= (1 << 16);
+ s3c_regset(&CLKCON, 1 << 16);
/* Set GPE15 (IICSDA) and GPE14 (IICSCL) to IIC */
GPECON = (GPECON & ~((3 << 30) | (3 << 28))) |
@@ -108,7 +108,7 @@ void i2c_init(void)
IICLC = (0 << 0);
/* Turn off I2C clock */
- CLKCON &= ~(1 << 16);
+ s3c_regclr(&CLKCON, 1 << 16);
}
void 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 @@
#include "config.h"
+#include "system.h"
#include "cpu.h"
#include "string.h"
#include "lcd.h"
@@ -81,7 +82,7 @@ void SPI_Send_Bytes(const unsigned char *array, int count)
void Setup_LCD_SPI(void)
{
- CLKCON|=0x40000;
+ s3c_regset(&CLKCON, 0x40000);
SPI_LCD_CS(false);
SPCON0=0x3E;
SPPRE0=24;
@@ -146,8 +147,8 @@ void lcd_init_device(void)
#if !defined(BOOTLOADER)
lcd_poweroff = false;
#endif
-
- CLKCON |= 0x20; /* enable LCD clock */
+
+ s3c_regset(&CLKCON, 0x20); /* enable LCD clock */
Setup_LCD_SPI();
@@ -204,7 +205,7 @@ void lcd_init_device(void)
SPI_Send_Bytes(initbuf, sizeof(initbuf));
SPI_LCD_CS(false);
- CLKCON &= ~0x40000; /* disable SPI clock */
+ s3c_regclr(&CLKCON, 0x40000); /* disable SPI clock */
}
/* 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
} dma_play_lock =
{
.locked = 0,
- .state = (0<<19)
+ .state = 0,
};
/* Last samplerate set by pcm_set_frequency */
@@ -71,22 +71,18 @@ void pcm_apply_settings(void)
restore_fiq(status);
}
-/* For the locks, DMA interrupt must be disabled because the handler
- manipulates INTMSK and the operation is not atomic */
+/* Mask the DMA interrupt */
void pcm_play_lock(void)
{
- int status = disable_fiq_save();
if (++dma_play_lock.locked == 1)
- INTMSK |= (1<<19); /* Mask the DMA interrupt */
- restore_fiq(status);
+ s3c_regset(&INTMSK, DMA2_MASK);
}
+/* Unmask the DMA interrupt if enabled */
void pcm_play_unlock(void)
{
- int status = disable_fiq_save();
if (--dma_play_lock.locked == 0)
- INTMSK &= ~dma_play_lock.state; /* Unmask the DMA interrupt if enabled */
- restore_fiq(status);
+ s3c_regclr(&INTMSK, dma_play_lock.state);
}
void pcm_play_dma_init(void)
@@ -110,11 +106,11 @@ void pcm_play_dma_init(void)
/* Do not service DMA requests, yet */
/* clear any pending int and mask it */
- INTMSK |= (1<<19);
- SRCPND = (1<<19);
+ s3c_regset(&INTMSK, DMA2_MASK);
+ SRCPND = DMA2_MASK;
/* connect to FIQ */
- INTMOD |= (1<<19);
+ s3c_regset(&INTMOD, DMA2_MASK);
}
void pcm_postinit(void)
@@ -127,7 +123,7 @@ void pcm_postinit(void)
static void play_start_pcm(void)
{
/* clear pending DMA interrupt */
- SRCPND = (1<<19);
+ SRCPND = DMA2_MASK;
_pcm_apply_settings();
@@ -135,7 +131,7 @@ static void play_start_pcm(void)
clean_dcache_range((void*)DISRC2, (DCON2 & 0xFFFFF) * 2);
/* unmask DMA interrupt when unlocking */
- dma_play_lock.state = (1<<19);
+ dma_play_lock.state = DMA2_MASK;
/* turn on the request */
IISCON |= (1<<5);
@@ -154,7 +150,7 @@ static void play_start_pcm(void)
static void play_stop_pcm(void)
{
/* Mask DMA interrupt */
- INTMSK |= (1<<19);
+ s3c_regset(&INTMSK, DMA2_MASK);
/* De-Activate the DMA channel */
DMASKTRIG2 = 0x4;
@@ -182,7 +178,7 @@ static void play_stop_pcm(void)
void pcm_play_dma_start(const void *addr, size_t size)
{
/* Enable the IIS clock */
- CLKCON |= (1<<17);
+ s3c_regset(&CLKCON, 1<<17);
/* stop any DMA in progress - idle IIS */
play_stop_pcm();
@@ -217,7 +213,7 @@ void pcm_play_dma_stop(void)
play_stop_pcm();
/* Disconnect the IIS clock */
- CLKCON &= ~(1<<17);
+ s3c_regclr(&CLKCON, 1<<17);
}
void pcm_play_dma_pause(bool pause)
@@ -245,7 +241,7 @@ void fiq_handler(void)
register pcm_more_callback_type get_more; /* No stack for this */
/* clear any pending interrupt */
- SRCPND = (1<<19);
+ SRCPND = DMA2_MASK;
/* Buffer empty. Try to get more. */
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) {
enable_mmu();
}
+void s3c_regmod(volatile int *reg, unsigned int set, unsigned int clr)
+{
+ int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS);
+ unsigned int val = *reg;
+ *reg = (val | set) & ~clr;
+ restore_interrupt(oldstatus);
+}
+
+void s3c_regset(volatile int *reg, unsigned int mask)
+{
+ s3c_regmod(reg, mask, 0);
+}
+
+void s3c_regclr(volatile int *reg, unsigned int mask)
+{
+ s3c_regmod(reg, 0, mask);
+}
+
void system_init(void)
{
/* Disable interrupts and set all to IRQ mode */
@@ -146,7 +164,7 @@ void system_init(void)
/* Turn off NAND flash controller */
| (1 << 4)
-
+
);
/* 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 @@
#define CPUFREQ_NORMAL 98784000
#define CPUFREQ_MAX 296352000
+/* Functions to set and clear regiser bits atomically */
+
+/* Set and clear register bits */
+void s3c_regmod(volatile int *reg, unsigned int set, unsigned int clr);
+/* Set register bits */
+void s3c_regset(volatile int *reg, unsigned int mask);
+/* Clear register bits */
+void s3c_regclr(volatile int *reg, unsigned int mask);
+
#define HAVE_INVALIDATE_ICACHE
static inline void invalidate_icache(void)
{
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)
{
bool retval = true;
- int oldstatus = set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS);
+ int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS);
stop_timer();
@@ -115,14 +115,14 @@ bool __timer_register(void)
retval = false;
}
- set_interrupt_status(oldstatus, IRQ_FIQ_STATUS);
+ restore_interrupt(oldstatus);
return retval;
}
void __timer_unregister(void)
{
- int oldstatus = set_interrupt_status(IRQ_FIQ_DISABLED, IRQ_FIQ_STATUS);
+ int oldstatus = disable_interrupt_save(IRQ_FIQ_STATUS);
stop_timer();
- set_interrupt_status(oldstatus, IRQ_FIQ_STATUS);
+ restore_interrupt(oldstatus);
}