summaryrefslogtreecommitdiffstats
path: root/firmware
diff options
context:
space:
mode:
authorRafaël Carré <rafael.carre@gmail.com>2008-11-06 02:31:32 +0000
committerRafaël Carré <rafael.carre@gmail.com>2008-11-06 02:31:32 +0000
commitc3e667c1981c0596aff2429904450d9aa9511747 (patch)
treef006f8e7a6e6a3397bfbb55a5765fb367da98be1 /firmware
parent7384454665b7984dbb81d22274004bdcc59c454c (diff)
downloadrockbox-c3e667c1981c0596aff2429904450d9aa9511747.tar.gz
rockbox-c3e667c1981c0596aff2429904450d9aa9511747.zip
AS3525: timer support
git-svn-id: svn://svn.rockbox.org/rockbox/trunk@19025 a1c6a512-1295-4272-9138-f99709370657
Diffstat (limited to 'firmware')
-rw-r--r--firmware/export/as3525.h13
-rw-r--r--firmware/target/arm/as3525/system-as3525.c7
-rw-r--r--firmware/timer.c55
3 files changed, 59 insertions, 16 deletions
diff --git a/firmware/export/as3525.h b/firmware/export/as3525.h
index 9bd4b19a20..8d81997b94 100644
--- a/firmware/export/as3525.h
+++ b/firmware/export/as3525.h
@@ -275,12 +275,13 @@ interface */
-#define TIMER_LOAD (*(volatile unsigned long*)(TIMER_BASE + 0x00)) /* 32-bit width */
-#define TIMER_VALUE (*(volatile unsigned long*)(TIMER_BASE + 0x04)) /* 32 bit width */
-#define TIMER_CONTROL (*(volatile unsigned long*)(TIMER_BASE + 0x08)) /* 8 bit width */
-#define TIMER_INTCLR (*(volatile unsigned long*)(TIMER_BASE + 0x0C)) /* clears ir by write access */
-#define TIMER_RIS (*(volatile unsigned long*)(TIMER_BASE + 0x10)) /* 1 bit width */
-#define TIMER_MIS (*(volatile unsigned long*)(TIMER_BASE + 0x14)) /* 1 bit width */
+#define TIMER1_LOAD (*(volatile unsigned long*)(TIMER_BASE + 0x00)) /* 32-bit width */
+#define TIMER1_VALUE (*(volatile unsigned long*)(TIMER_BASE + 0x04)) /* 32 bit width */
+#define TIMER1_CONTROL (*(volatile unsigned long*)(TIMER_BASE + 0x08)) /* 8 bit width */
+#define TIMER1_INTCLR (*(volatile unsigned long*)(TIMER_BASE + 0x0C)) /* clears ir by write access */
+#define TIMER1_RIS (*(volatile unsigned long*)(TIMER_BASE + 0x10)) /* 1 bit width */
+#define TIMER1_MIS (*(volatile unsigned long*)(TIMER_BASE + 0x14)) /* 1 bit width */
+#define TIMER1_BGLOAD (*(volatile unsigned long*)(TIMER_BASE + 0x18)) /* 32-bit width */
/**
* Counter/Timer control register bits
diff --git a/firmware/target/arm/as3525/system-as3525.c b/firmware/target/arm/as3525/system-as3525.c
index d2729b7ec6..05c9b200a2 100644
--- a/firmware/target/arm/as3525/system-as3525.c
+++ b/firmware/target/arm/as3525/system-as3525.c
@@ -215,7 +215,7 @@ void system_init(void)
asm volatile(
"mrs r0, cpsr \n"
- "orr r0, r0, #0x80 \n" /* disable interrupts */
+ "bic r0, r0, #0x80 \n" /* enable interrupts */
"msr cpsr, r0 \n"
"mov r0, #0 \n"
"mcr p15, 0, r0, c7, c7 \n" /* invalidate icache & dcache */
@@ -229,11 +229,12 @@ void system_init(void)
CGU_PERI |= (5<<2)|0x01; /* pclk = PLLA / 6 = 64 MHz */
-#if 0 /* we don't use interrupts at the moment */
+ /* enable timer interface for TIMER1 & TIMER2 */
+ CGU_PERI |= CGU_TIMERIF_CLOCK_ENABLE;
+
/* enable VIC */
CGU_PERI |= CGU_VIC_CLOCK_ENABLE;
VIC_INT_SELECT = 0; /* only IRQ, no FIQ */
-#endif
}
void system_reboot(void)
diff --git a/firmware/timer.c b/firmware/timer.c
index aeb0ee142b..0746b05e46 100644
--- a/firmware/timer.c
+++ b/firmware/timer.c
@@ -52,6 +52,14 @@ void TIMER1(void)
pfn_timer();
TER1 = 0xff; /* clear all events */
}
+#elif CONFIG_CPU == AS3525
+void INT_TIMER1(void)
+{
+ if (pfn_timer != NULL)
+ pfn_timer();
+
+ TIMER1_INTCLR = 0; /* clear interrupt */
+}
#elif defined(CPU_PP)
void TIMER2(void)
{
@@ -92,17 +100,23 @@ void TIMER1_ISR(void)
static bool timer_set(long cycles, bool start)
{
-#if (CONFIG_CPU == SH7034) || defined(CPU_COLDFIRE)
+#if CONFIG_CPU == SH7034 || defined(CPU_COLDFIRE) || CONFIG_CPU == AS3525
int phi = 0; /* bits for the prescaler */
int prescale = 1;
+#if CONFIG_CPU == SH7034 || defined(CPU_COLDFIRE)
+#define PRESCALE_STEP 1
+#else /* CONFIG_CPU == AS3525 */
+#define PRESCALE_STEP 4
+#endif
+
while (cycles > 0x10000)
{ /* work out the smallest prescaler that makes it fit */
-#if CONFIG_CPU == SH7034
+#if CONFIG_CPU == SH7034 || CONFIG_CPU == AS3525
phi++;
#endif
- prescale *= 2;
- cycles >>= 1;
+ prescale <<= PRESCALE_STEP;
+ cycles >>= PRESCALE_STEP;
}
#endif
@@ -154,6 +168,25 @@ static bool timer_set(long cycles, bool start)
and_b(~0x01, &TSR4); /* clear an eventual interrupt */
return true;
+#elif CONFIG_CPU == AS3525
+ /* XXX: 32 bits cycles could be used */
+ if (prescale > 256 || cycles > 0x10000)
+ return false;
+
+ if (start)
+ {
+ if (pfn_unregister != NULL)
+ {
+ pfn_unregister();
+ pfn_unregister = NULL;
+ }
+ }
+
+ TIMER1_LOAD = TIMER1_BGLOAD = cycles;
+ /* /!\ bit 4 (reserved) must not be modified
+ * periodic mode, interrupt enabled, 16 bits counter */
+ TIMER1_CONTROL = (TIMER1_CONTROL & (1<<4)) | 0xe0 | (phi<<2);
+ return true;
#elif defined CPU_COLDFIRE
if (prescale > 4096/CPUFREQ_MAX_MULT)
return false;
@@ -165,7 +198,7 @@ static bool timer_set(long cycles, bool start)
}
else
phi = 0x03; /* prescale sysclk, timer enabled */
-
+
base_prescale = prescale;
prescale *= (cpu_frequency / CPU_FREQ);
@@ -255,7 +288,7 @@ bool timer_register(int reg_prio, void (*unregister_callback)(void),
if (!timer_set(cycles, true))
return false;
-
+
pfn_timer = timer_callback;
pfn_unregister = unregister_callback;
timer_prio = reg_prio;
@@ -282,6 +315,10 @@ bool timer_register(int reg_prio, void (*unregister_callback)(void),
irq_set_int_handler(IRQ_TIMER1, TIMER1_ISR);
irq_enable_int(IRQ_TIMER1);
return true;
+#elif CONFIG_CPU == AS3525
+ CGU_PERI |= CGU_TIMER1_CLOCK_ENABLE; /* enable peripheral */
+ VIC_INT_ENABLE |= INTERRUPT_TIMER1;
+ return true;
#elif CONFIG_CPU == IMX31L
/* TODO */
return false;
@@ -295,7 +332,7 @@ bool timer_register(int reg_prio, void (*unregister_callback)(void),
(void)cycles;
/* TODO: Implement for PortalPlayer and iFP (if possible) */
(void)int_prio;
- (void)timer_callback;
+ (void)timer_callback;
}
bool timer_set_period(long cycles)
@@ -318,6 +355,10 @@ void timer_unregister(void)
#elif CONFIG_CPU == PNX0101
TIMER1.ctrl &= ~0x80; /* disable timer 1 */
irq_disable_int(IRQ_TIMER1);
+#elif CONFIG_CPU == AS3525
+ TIMER1_CONTROL &= 0x10; /* disable timer 1 (don't modify bit 4) */
+ VIC_INT_EN_CLEAR |= INTERRUPT_TIMER1; /* disable interrupt */
+ CGU_PERI &= ~CGU_TIMER1_CLOCK_ENABLE; /* disable peripheral */
#elif CONFIG_CPU == S3C2440 || CONFIG_CPU == DM320
__TIMER_UNREGISTER();
#endif