summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorMichael Sevakis <jethead71@rockbox.org>2007-04-13 20:55:48 +0000
committerMichael Sevakis <jethead71@rockbox.org>2007-04-13 20:55:48 +0000
commitd95c39072ace1a7aeaad3ee49ed668399b4862bd (patch)
tree7f8c8e41e5e793daa64051f153bbbd52ccbe8fc9 /firmware
parente10f455fbd3149a034e35d30be333f958d773d92 (diff)
downloadrockbox-d95c39072ace1a7aeaad3ee49ed668399b4862bd.tar.gz
rockbox-d95c39072ace1a7aeaad3ee49ed668399b4862bd.tar.bz2
rockbox-d95c39072ace1a7aeaad3ee49ed668399b4862bd.zip
Portal Player: Add invalidate_icache and flush_icache. Flush the cache on the core for newborn threads. In doing so, move more ARM stuff to the target tree and organize it to make a clean job of it. If anything isn't appropriate for some particular device give a hollar or even just fix it by some added #ifdefing. I was informed that the PP targets are register compatible so I'm going off that advice. The Sansa likes it though.
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@13144 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/system.h165
-rw-r--r--firmware/rolo.c6
-rw-r--r--firmware/target/arm/gigabeat/meg-fx/system-meg-fx.h (renamed from firmware/target/arm/gigabeat/meg-fx/system-target.h)1
-rw-r--r--firmware/target/arm/sandisk/sansa-e200/lcd-e200.c14
-rw-r--r--firmware/target/arm/system-pp.h49
-rw-r--r--firmware/target/arm/system-target.h155
-rw-r--r--firmware/target/coldfire/system-target.h4
-rw-r--r--firmware/thread.c47
8 files changed, 262 insertions, 179 deletions
diff --git a/firmware/export/system.h b/firmware/export/system.h
index b32d1d3a21..19ce7a4d6a 100644
--- a/firmware/export/system.h
+++ b/firmware/export/system.h
@@ -29,24 +29,6 @@ extern void system_init(void);
extern long cpu_frequency;
-#ifdef CPU_PP
-#define inl(a) (*(volatile unsigned long *) (a))
-#define outl(a,b) (*(volatile unsigned long *) (b) = (a))
-#define inb(a) (*(volatile unsigned char *) (a))
-#define outb(a,b) (*(volatile unsigned char *) (b) = (a))
-#define inw(a) (*(volatile unsigned short *) (a))
-#define outw(a,b) (*(volatile unsigned short *) (b) = (a))
-extern unsigned int ipod_hw_rev;
-
-static inline void udelay(unsigned usecs)
-{
- unsigned stop = USEC_TIMER + usecs;
- while (TIME_BEFORE(USEC_TIMER, stop));
-}
-
-unsigned int current_core(void);
-#endif
-
struct flash_header {
unsigned long magic;
unsigned long length;
@@ -173,10 +155,6 @@ int get_cpu_boost_counter(void);
#define H_TO_BE32(x) (x)
#endif
-
-#define nop \
- asm volatile ("nop")
-
/* gcc 3.4 changed the format of the constraints */
#if (__GNUC__ >= 3) && (__GNUC_MINOR__ > 3) || (__GNUC__ >= 4)
#define I_CONSTRAINT "I08"
@@ -196,141 +174,7 @@ enum {
};
#ifndef SIMULATOR
-#if defined(CPU_COLDFIRE) || (CONFIG_CPU == S3C2440) || (CONFIG_CPU == SH7034)
#include "system-target.h"
-#endif
-#endif
-
-#ifndef SIMULATOR
-
-#if defined(CPU_ARM)
-
-/* TODO: Implement set_irq_level and check CPU frequencies */
-
-#if CONFIG_CPU == S3C2440
-
-#define CPUFREQ_DEFAULT 98784000
-#define CPUFREQ_NORMAL 98784000
-#define CPUFREQ_MAX 296352000
-
-#elif CONFIG_CPU == PNX0101
-
-#define CPUFREQ_DEFAULT 12000000
-#define CPUFREQ_NORMAL 48000000
-#define CPUFREQ_MAX 60000000
-
-#else
-
-#define CPUFREQ_DEFAULT_MULT 8
-#define CPUFREQ_DEFAULT 24000000
-#define CPUFREQ_NORMAL_MULT 10
-#define CPUFREQ_NORMAL 30000000
-#define CPUFREQ_MAX_MULT 25
-#define CPUFREQ_MAX 75000000
-
-#endif
-
-static inline uint16_t swap16(uint16_t value)
- /*
- result[15..8] = value[ 7..0];
- result[ 7..0] = value[15..8];
- */
-{
- return (value >> 8) | (value << 8);
-}
-
-static inline uint32_t swap32(uint32_t value)
- /*
- result[31..24] = value[ 7.. 0];
- result[23..16] = value[15.. 8];
- result[15.. 8] = value[23..16];
- result[ 7.. 0] = value[31..24];
- */
-{
- uint32_t tmp;
-
- asm volatile (
- "eor %1, %0, %0, ror #16 \n\t"
- "bic %1, %1, #0xff0000 \n\t"
- "mov %0, %0, ror #8 \n\t"
- "eor %0, %0, %1, lsr #8 \n\t"
- : "+r" (value), "=r" (tmp)
- );
- return value;
-}
-
-static inline uint32_t swap_odd_even32(uint32_t value)
-{
- /*
- result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
- result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
- */
- uint32_t tmp;
-
- asm volatile ( /* ABCD */
- "bic %1, %0, #0x00ff00 \n\t" /* AB.D */
- "bic %0, %0, #0xff0000 \n\t" /* A.CD */
- "mov %0, %0, lsr #8 \n\t" /* .A.C */
- "orr %0, %0, %1, lsl #8 \n\t" /* B.D.|.A.C */
- : "+r" (value), "=r" (tmp) /* BADC */
- );
- return value;
-}
-
-#define HIGHEST_IRQ_LEVEL (1)
-
-static inline int set_irq_level(int level)
-{
- unsigned long cpsr;
- /* Read the old level and set the new one */
- asm volatile ("mrs %0,cpsr" : "=r" (cpsr));
- asm volatile ("msr cpsr_c,%0"
- : : "r" ((cpsr & ~0x80) | (level << 7)));
- return (cpsr >> 7) & 1;
-}
-
-static inline void set_fiq_handler(void(*fiq_handler)(void))
-{
- /* Install the FIQ handler */
- *((unsigned int*)(15*4)) = (unsigned int)fiq_handler;
-}
-
-static inline void enable_fiq(void)
-{
- /* Clear FIQ disable bit */
- asm volatile (
- "mrs r0, cpsr \n"\
- "bic r0, r0, #0x40 \n"\
- "msr cpsr_c, r0 "
- : : : "r0"
- );
-}
-
-static inline void disable_fiq(void)
-{
- /* Set FIQ disable bit */
- asm volatile (
- "mrs r0, cpsr \n"\
- "orr r0, r0, #0x40 \n"\
- "msr cpsr_c, r0 "
- : : : "r0"
- );
-}
-
-#if CONFIG_CPU != S3C2440
-#define invalidate_icache()
-#endif
-
-#if CONFIG_CPU == PNX0101
-typedef void (*interrupt_handler_t)(void);
-
-void irq_set_int_handler(int n, interrupt_handler_t handler);
-void irq_enable_int(int n);
-void irq_disable_int(int n);
-#endif
-
-#endif
-
#else /* SIMULATOR */
static inline uint16_t swap16(uint16_t value)
@@ -365,8 +209,15 @@ static inline uint32_t swap_odd_even32(uint32_t value)
return (t >> 8) | ((t ^ value) << 8);
}
+#endif /* !SIMULATOR */
+
+/* Just define these as empty if not declared */
+#ifndef HAVE_INVALIDATE_ICACHE
#define invalidate_icache()
+#endif
-#endif /* !SIMULATOR */
+#ifndef HAVE_FLUSH_ICACHE
+#define flush_icache()
+#endif
#endif /* __SYSTEM_H__ */
diff --git a/firmware/rolo.c b/firmware/rolo.c
index 0689e8be5b..0375a7ac82 100644
--- a/firmware/rolo.c
+++ b/firmware/rolo.c
@@ -49,8 +49,7 @@ void rolo_restart_cop(void) ICODE_ATTR;
void rolo_restart_cop(void)
{
/* Invalidate cache */
- outl(inl(0xf000f044) | 0x6, 0xf000f044);
- while ((CACHE_CTL & 0x8000) != 0) {}
+ invalidate_icache();
/* Disable cache */
CACHE_CTL = CACHE_DISABLE;
@@ -119,8 +118,7 @@ void rolo_restart(const unsigned char* source, unsigned char* dest,
cpu_message = 0;
/* Flush cache */
- outl(inl(0xf000f044) | 0x2, 0xf000f044);
- while ((CACHE_CTL & 0x8000) != 0) {}
+ flush_icache();
/* Disable cache */
CACHE_CTL = CACHE_DISABLE;
diff --git a/firmware/target/arm/gigabeat/meg-fx/system-target.h b/firmware/target/arm/gigabeat/meg-fx/system-meg-fx.h
index e5d15d643e..7d598af360 100644
--- a/firmware/target/arm/gigabeat/meg-fx/system-target.h
+++ b/firmware/target/arm/gigabeat/meg-fx/system-meg-fx.h
@@ -19,6 +19,7 @@
#include "mmu-meg-fx.h"
+#define HAVE_INVALIDATE_ICACHE
static inline void invalidate_icache(void)
{
clean_dcache();
diff --git a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
index 3e8246b367..93d79633b1 100644
--- a/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
+++ b/firmware/target/arm/sandisk/sansa-e200/lcd-e200.c
@@ -112,16 +112,6 @@ static inline void lcd_write_reg(unsigned int reg, unsigned int data)
lcd_send_msg(0x72, data);
}
-static inline void cache_flush(void)
-{
-#ifndef BOOTLOADER
- outl(inl(0xf000f044) | 0x2, 0xf000f044);
- while ((CACHE_CTL & 0x8000) != 0)
- {
- }
-#endif
-}
-
/* The LCD controller gets passed the address of the framebuffer, but can only
use the physical, not the remapped, address. This is a quick and dirty way
of correcting it */
@@ -271,7 +261,7 @@ inline void lcd_update_rect(int x, int y, int width, int height)
memcpy(((char*)&lcd_driver_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH),
((char *)&lcd_framebuffer)+(y * sizeof(fb_data) * LCD_WIDTH),
((height * sizeof(fb_data) * LCD_WIDTH)));
- cache_flush();
+ flush_icache();
/* Restart DMA */
LCD_REG_6 |= 1;
@@ -287,7 +277,7 @@ inline void lcd_update(void)
/* Copy the Rockbox framebuffer to the second framebuffer */
memcpy(lcd_driver_framebuffer, lcd_framebuffer, sizeof(fb_data) * LCD_WIDTH * LCD_HEIGHT);
- cache_flush();
+ flush_icache();
/* Restart DMA */
LCD_REG_6 |= 1;
diff --git a/firmware/target/arm/system-pp.h b/firmware/target/arm/system-pp.h
new file mode 100644
index 0000000000..05fd8b6edf
--- /dev/null
+++ b/firmware/target/arm/system-pp.h
@@ -0,0 +1,49 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 by Alan Korr
+ * Copyright (C) 2007 by Michael Sevakis
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+
+#define inl(a) (*(volatile unsigned long *) (a))
+#define outl(a,b) (*(volatile unsigned long *) (b) = (a))
+#define inb(a) (*(volatile unsigned char *) (a))
+#define outb(a,b) (*(volatile unsigned char *) (b) = (a))
+#define inw(a) (*(volatile unsigned short *) (a))
+#define outw(a,b) (*(volatile unsigned short *) (b) = (a))
+extern unsigned int ipod_hw_rev;
+
+static inline void udelay(unsigned usecs)
+{
+ unsigned stop = USEC_TIMER + usecs;
+ while (TIME_BEFORE(USEC_TIMER, stop));
+}
+
+unsigned int current_core(void);
+
+#define HAVE_INVALIDATE_ICACHE
+static inline void invalidate_icache(void)
+{
+ outl(inl(0xf000f044) | 0x6, 0xf000f044);
+ while ((CACHE_CTL & 0x8000) != 0);
+}
+
+#define HAVE_FLUSH_ICACHE
+static inline void flush_icache(void)
+{
+ outl(inl(0xf000f044) | 0x2, 0xf000f044);
+ while ((CACHE_CTL & 0x8000) != 0);
+}
diff --git a/firmware/target/arm/system-target.h b/firmware/target/arm/system-target.h
new file mode 100644
index 0000000000..ceb8be2079
--- /dev/null
+++ b/firmware/target/arm/system-target.h
@@ -0,0 +1,155 @@
+/***************************************************************************
+ * __________ __ ___.
+ * Open \______ \ ____ ____ | | _\_ |__ _______ ___
+ * Source | _// _ \_/ ___\| |/ /| __ \ / _ \ \/ /
+ * Jukebox | | ( <_> ) \___| < | \_\ ( <_> > < <
+ * Firmware |____|_ /\____/ \___ >__|_ \|___ /\____/__/\_ \
+ * \/ \/ \/ \/ \/
+ * $Id$
+ *
+ * Copyright (C) 2002 by Alan Korr
+ *
+ * All files in this archive are subject to the GNU General Public License.
+ * See the file COPYING in the source tree root for full license agreement.
+ *
+ * This software is distributed on an "AS IS" basis, WITHOUT WARRANTY OF ANY
+ * KIND, either express or implied.
+ *
+ ****************************************************************************/
+#ifndef SYSTEM_TARGET_H
+#define SYSTEM_TARGET_H
+
+#define nop \
+ asm volatile ("nop")
+
+/* This gets too complicated otherwise with all the ARM variation and would
+ have conflicts with another system-target.h elsewhere so include a
+ subheader from here. */
+
+#ifdef CPU_PP
+#include "system-pp.h"
+#elif CONFIG_CPU == S3C2440
+#include "system-meg-fx.h"
+#endif
+
+/* TODO: Implement set_irq_level and check CPU frequencies */
+
+#if CONFIG_CPU == S3C2440
+
+#define CPUFREQ_DEFAULT 98784000
+#define CPUFREQ_NORMAL 98784000
+#define CPUFREQ_MAX 296352000
+
+#elif CONFIG_CPU == PNX0101
+
+#define CPUFREQ_DEFAULT 12000000
+#define CPUFREQ_NORMAL 48000000
+#define CPUFREQ_MAX 60000000
+
+#else
+
+#define CPUFREQ_DEFAULT_MULT 8
+#define CPUFREQ_DEFAULT 24000000
+#define CPUFREQ_NORMAL_MULT 10
+#define CPUFREQ_NORMAL 30000000
+#define CPUFREQ_MAX_MULT 25
+#define CPUFREQ_MAX 75000000
+
+#endif
+
+static inline uint16_t swap16(uint16_t value)
+ /*
+ result[15..8] = value[ 7..0];
+ result[ 7..0] = value[15..8];
+ */
+{
+ return (value >> 8) | (value << 8);
+}
+
+static inline uint32_t swap32(uint32_t value)
+ /*
+ result[31..24] = value[ 7.. 0];
+ result[23..16] = value[15.. 8];
+ result[15.. 8] = value[23..16];
+ result[ 7.. 0] = value[31..24];
+ */
+{
+ uint32_t tmp;
+
+ asm volatile (
+ "eor %1, %0, %0, ror #16 \n\t"
+ "bic %1, %1, #0xff0000 \n\t"
+ "mov %0, %0, ror #8 \n\t"
+ "eor %0, %0, %1, lsr #8 \n\t"
+ : "+r" (value), "=r" (tmp)
+ );
+ return value;
+}
+
+static inline uint32_t swap_odd_even32(uint32_t value)
+{
+ /*
+ result[31..24],[15.. 8] = value[23..16],[ 7.. 0]
+ result[23..16],[ 7.. 0] = value[31..24],[15.. 8]
+ */
+ uint32_t tmp;
+
+ asm volatile ( /* ABCD */
+ "bic %1, %0, #0x00ff00 \n\t" /* AB.D */
+ "bic %0, %0, #0xff0000 \n\t" /* A.CD */
+ "mov %0, %0, lsr #8 \n\t" /* .A.C */
+ "orr %0, %0, %1, lsl #8 \n\t" /* B.D.|.A.C */
+ : "+r" (value), "=r" (tmp) /* BADC */
+ );
+ return value;
+}
+
+#define HIGHEST_IRQ_LEVEL (1)
+
+static inline int set_irq_level(int level)
+{
+ unsigned long cpsr;
+ /* Read the old level and set the new one */
+ asm volatile ("mrs %0,cpsr" : "=r" (cpsr));
+ asm volatile ("msr cpsr_c,%0"
+ : : "r" ((cpsr & ~0x80) | (level << 7)));
+ return (cpsr >> 7) & 1;
+}
+
+static inline void set_fiq_handler(void(*fiq_handler)(void))
+{
+ /* Install the FIQ handler */
+ *((unsigned int*)(15*4)) = (unsigned int)fiq_handler;
+}
+
+static inline void enable_fiq(void)
+{
+ /* Clear FIQ disable bit */
+ asm volatile (
+ "mrs r0, cpsr \n"\
+ "bic r0, r0, #0x40 \n"\
+ "msr cpsr_c, r0 "
+ : : : "r0"
+ );
+}
+
+static inline void disable_fiq(void)
+{
+ /* Set FIQ disable bit */
+ asm volatile (
+ "mrs r0, cpsr \n"\
+ "orr r0, r0, #0x40 \n"\
+ "msr cpsr_c, r0 "
+ : : : "r0"
+ );
+}
+
+#if CONFIG_CPU == PNX0101
+typedef void (*interrupt_handler_t)(void);
+
+void irq_set_int_handler(int n, interrupt_handler_t handler);
+void irq_enable_int(int n);
+void irq_disable_int(int n);
+#endif
+
+#endif /* SYSTEM_TARGET_H */
diff --git a/firmware/target/coldfire/system-target.h b/firmware/target/coldfire/system-target.h
index 40542353be..6f1b2eb4ae 100644
--- a/firmware/target/coldfire/system-target.h
+++ b/firmware/target/coldfire/system-target.h
@@ -19,6 +19,9 @@
#ifndef SYSTEM_TARGET_H
#define SYSTEM_TARGET_H
+#define nop \
+ asm volatile ("trapf")
+
#define or_l(mask, address) \
asm \
("or.l %0,(%1)" \
@@ -147,6 +150,7 @@ static inline uint32_t swap_odd_even32(uint32_t value)
return value;
}
+#define HAVE_INVALIDATE_ICACHE
static inline void invalidate_icache(void)
{
asm volatile ("move.l #0x01000000,%d0\n"
diff --git a/firmware/thread.c b/firmware/thread.c
index a803e4f78d..275f04d029 100644
--- a/firmware/thread.c
+++ b/firmware/thread.c
@@ -64,12 +64,15 @@ int *cop_stackend = stackend;
#endif
#if NUM_CORES > 1
+#if 0
static long cores_locked IBSS_ATTR;
#define LOCK(...) do { } while (test_and_set(&cores_locked, 1))
#define UNLOCK(...) cores_locked = 0
+#endif
#warning "Core locking mechanism should be fixed on H10/4G!"
+
inline void lock_cores(void)
{
#if 0
@@ -125,15 +128,47 @@ static inline void store_context(void* addr)
* Load non-volatile context.
*---------------------------------------------------------------------------
*/
+static void start_thread(void (*thread_func)(void), const void* addr) __attribute__((naked));
+static void start_thread(void (*thread_func)(void), const void* addr)
+{
+ /* r0 = thread_func, r1 = addr */
+#if NUM_CORES > 1
+ asm volatile (
+ "mov r2, #0 \n"
+ "str r2, [r1, #40] \n"
+ "ldr r1, =0xf000f044 \n" /* invalidate this core's cache */
+ "ldr r2, [r1] \n"
+ "orr r2, r2, #6 \n"
+ "str r2, [r1] \n"
+ "ldr r1, =0x6000c000 \n"
+ "1: \n"
+ "ldr r2, [r1] \n"
+ "tst r2, #0x8000 \n"
+ "bne 1b \n"
+ "mov pc, r0 \n"
+ : : : "r1", "r2"
+ );
+#else
+ asm volatile (
+ "mov r2, #0 \n"
+ "str r2, [r1, #40] \n"
+ "mov pc, r0 \n"
+ : : : "r1", "r2"
+ );
+#endif
+ (void)thread_func;
+ (void)addr;
+ (void)start_thread;
+}
+
static inline void load_context(const void* addr)
{
asm volatile(
- "ldmia %0, { r4-r11, sp, lr }\n" /* load regs r4 to r14 from context */
- "ldr r0, [%0, #40] \n" /* load start pointer */
- "mov r1, #0 \n"
- "cmp r0, r1 \n" /* check for NULL */
- "strne r1, [%0, #40] \n" /* if it's NULL, we're already running */
- "movne pc, r0 \n" /* not already running, so jump to start */
+ "ldmia %0, { r4-r11, sp, lr } \n" /* load regs r4 to r14 from context */
+ "ldr r0, [%0, #40] \n" /* load start pointer */
+ "cmp r0, #0 \n" /* check for NULL */
+ "movne r1, %0 \n" /* if not already running, jump to start */
+ "ldrne pc, =start_thread \n"
: : "r" (addr) : "r0", "r1"
);
}