aboutsummaryrefslogtreecommitdiff
path: root/cpu
diff options
context:
space:
mode:
authorwdenk <wdenk>2004-07-11 22:19:26 +0000
committerwdenk <wdenk>2004-07-11 22:19:26 +0000
commita1f4a3dd0592ef982017a50a7cfe749823114203 (patch)
tree5cb47632f587600559b20ad5ca644e1867fc9f2c /cpu
parentb9283e2dbedae4492ec0efdf683d51a00566a477 (diff)
* Patch by George G. Davis, 06 Jul 2004:
- update mach-types.h to latest arm.linux.org.uk master list - Set correct OMAP1610 bi_arch_number for build target * Patch by Curt Brune, 06 Jul 2004: evb4510: add support for timer interrupt; cleanup
Diffstat (limited to 'cpu')
-rw-r--r--cpu/arm720t/interrupts.c121
1 files changed, 91 insertions, 30 deletions
diff --git a/cpu/arm720t/interrupts.c b/cpu/arm720t/interrupts.c
index 485443f63..842a44384 100644
--- a/cpu/arm720t/interrupts.c
+++ b/cpu/arm720t/interrupts.c
@@ -46,6 +46,15 @@ extern void reset_cpu(ulong addr);
#define READ_TIMER (TM2STAT & NETARM_GEN_TSTAT_CTC_MASK)
#endif
+#ifdef CONFIG_S3C4510B
+/* require interrupts for the S3C4510B */
+# ifndef CONFIG_USE_IRQ
+# error CONFIG_USE_IRQ _must_ be defined when using CONFIG_S3C4510B
+# else
+static struct _irq_handler IRQ_HANDLER[N_IRQS];
+# endif
+#endif /* CONFIG_S3C4510B */
+
#ifdef CONFIG_USE_IRQ
/* enable IRQ/FIQ interrupts */
void enable_interrupts (void)
@@ -75,7 +84,7 @@ int disable_interrupts (void)
: "memory");
return (old & 0x80) == 0;
}
-#else
+#else /* CONFIG_USE_IRQ */
void enable_interrupts (void)
{
return;
@@ -86,7 +95,6 @@ int disable_interrupts (void)
}
#endif
-
void bad_mode (void)
{
panic ("Resetting CPU ...\n");
@@ -174,11 +182,42 @@ void do_fiq (struct pt_regs *pt_regs)
void do_irq (struct pt_regs *pt_regs)
{
+#if defined(CONFIG_IMPA7) || defined(CONFIG_EP7312) || defined(CONFIG_NETARM)
printf ("interrupt request\n");
show_regs (pt_regs);
bad_mode ();
+#elif defined(CONFIG_S3C4510B)
+ unsigned int pending;
+
+ while ( (pending = GET_REG( REG_INTOFFSET)) != 0x54) { /* sentinal value for no pending interrutps */
+ IRQ_HANDLER[pending>>2].m_func( IRQ_HANDLER[pending>>2].m_data);
+
+ /* clear pending interrupt */
+ PUT_REG( REG_INTPEND, (1<<(pending>>2)));
+ }
+#else
+#error do_irq() not defined for this CPU type
+#endif
+}
+
+
+#ifdef CONFIG_S3C4510B
+static void default_isr( void *data) {
+ printf ("default_isr(): called for IRQ %d\n", (int)data);
}
+static void timer_isr( void *data) {
+ unsigned int *pTime = (unsigned int *)data;
+
+ (*pTime)++;
+ if ( !(*pTime % (CFG_HZ/4))) {
+ /* toggle LED 0 */
+ PUT_REG( REG_IOPDATA, GET_REG(REG_IOPDATA) ^ 0x1);
+ }
+
+}
+#endif
+
static ulong timestamp;
static ulong lastdec;
@@ -209,8 +248,48 @@ int interrupt_init (void)
/* set timer 1 counter */
lastdec = IO_TC1D = TIMER_LOAD_VAL;
#elif defined(CONFIG_S3C4510B)
- /* Nothing to do, interrupts not supported */
+ int i;
+
+ /* install default interrupt handlers */
+ for ( i = 0; i < N_IRQS; i++) {
+ IRQ_HANDLER[i].m_data = (void *)i;
+ IRQ_HANDLER[i].m_func = default_isr;
+ }
+
+ /* configure interrupts for IRQ mode */
+ PUT_REG( REG_INTMODE, 0x0);
+ /* clear any pending interrupts */
+ PUT_REG( REG_INTPEND, 0x1FFFFF);
+
lastdec = 0;
+
+ /* install interrupt handler for timer */
+ IRQ_HANDLER[INT_TIMER0].m_data = (void *)&timestamp;
+ IRQ_HANDLER[INT_TIMER0].m_func = timer_isr;
+
+ /* configure free running timer 0 */
+ PUT_REG( REG_TMOD, 0x0);
+ /* Stop timer 0 */
+ CLR_REG( REG_TMOD, TM0_RUN);
+
+ /* Configure for interval mode */
+ CLR_REG( REG_TMOD, TM1_TOGGLE);
+
+ /*
+ * Load Timer data register with count down value.
+ * count_down_val = CFG_SYS_CLK_FREQ/CFG_HZ
+ */
+ PUT_REG( REG_TDATA0, (CFG_SYS_CLK_FREQ / CFG_HZ));
+
+ /*
+ * Enable global interrupt
+ * Enable timer0 interrupt
+ */
+ CLR_REG( REG_INTMASK, ((1<<INT_GLOBAL) | (1<<INT_TIMER0)));
+
+ /* Start timer */
+ SET_REG( REG_TMOD, TM0_RUN);
+
#else
#error No interrupt_init() defined for this CPU type
#endif
@@ -294,40 +373,22 @@ void udelay_masked (unsigned long usec)
#elif defined(CONFIG_S3C4510B)
-#define TMR_OFFSET (0x1000)
+ulong get_timer (ulong base)
+{
+ return timestamp - base;
+}
void udelay (unsigned long usec)
{
- u32 rDATA;
+ u32 ticks;
- rDATA = t_data_us(usec);
+ ticks = (usec * CFG_HZ) / 1000000;
- /* Stop timer 0 */
- CLR_REG( REG_TMOD, TM0_RUN);
+ ticks += get_timer (0);
- /* Configure for toggle mode */
- SET_REG( REG_TMOD, TM0_TOGGLE);
-
- /* Load Timer data register with count down value plus offset */
- PUT_REG( REG_TDATA0, rDATA + TMR_OFFSET);
-
- /* Clear timer counter register */
- PUT_REG( REG_TCNT0, 0x0);
-
- /* Start timer -- count down timer */
- SET_REG( REG_TMOD, TM0_RUN);
-
- /* spin during count down */
- while ( GET_REG( REG_TCNT0) > TMR_OFFSET);
-
- /* Stop timer */
- CLR_REG( REG_TMOD, TM0_RUN);
-
-}
+ while (get_timer (0) < ticks)
+ /*NOP*/;
-ulong get_timer (ulong base)
-{
- return (0xFFFFFFFF - GET_REG( REG_TCNT1)) - base;
}
#else