diff options
author | wdenk <wdenk> | 2004-07-11 22:19:26 +0000 |
---|---|---|
committer | wdenk <wdenk> | 2004-07-11 22:19:26 +0000 |
commit | a1f4a3dd0592ef982017a50a7cfe749823114203 (patch) | |
tree | 5cb47632f587600559b20ad5ca644e1867fc9f2c /cpu/arm720t/interrupts.c | |
parent | b9283e2dbedae4492ec0efdf683d51a00566a477 (diff) | |
download | u-boot-a1f4a3dd0592ef982017a50a7cfe749823114203.tar.gz u-boot-a1f4a3dd0592ef982017a50a7cfe749823114203.tar.xz u-boot-a1f4a3dd0592ef982017a50a7cfe749823114203.zip |
* 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/arm720t/interrupts.c')
-rw-r--r-- | cpu/arm720t/interrupts.c | 121 |
1 files changed, 91 insertions, 30 deletions
diff --git a/cpu/arm720t/interrupts.c b/cpu/arm720t/interrupts.c index 485443f63c..842a44384b 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 *)×tamp; + 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 |