From 1f4fd0a0d28fabf965815755f1a74ef91dfb5ca6 Mon Sep 17 00:00:00 2001 From: Andrew Victor Date: Thu, 30 Nov 2006 10:01:47 +0100 Subject: [PATCH] [ARM] 3946/1: AT91: at91_arch_reset and at91_extern_irq The external interrupt sources are different on the various AT91 processors. This patch introduces the global 'at91_extern_irq' variable that contains a bitset of the available external interrupt sources. The processor reset mechanism also differs on the various AT91 processors. This patch also adds a global 'at91_arch_reset' callback (from system.h) into the processor-specific code to perform the reset. Signed-off-by: Andrew Victor Signed-off-by: Russell King --- arch/arm/mach-at91rm9200/at91rm9200.c | 17 +++++++++++++++++ arch/arm/mach-at91rm9200/generic.h | 3 +++ arch/arm/mach-at91rm9200/irq.c | 14 ++++++++++---- arch/arm/mach-at91rm9200/pm.c | 9 +-------- include/asm-arm/arch-at91rm9200/system.h | 12 +++++++----- 5 files changed, 38 insertions(+), 17 deletions(-) diff --git a/arch/arm/mach-at91rm9200/at91rm9200.c b/arch/arm/mach-at91rm9200/at91rm9200.c index dcf6136fed..0422593032 100644 --- a/arch/arm/mach-at91rm9200/at91rm9200.c +++ b/arch/arm/mach-at91rm9200/at91rm9200.c @@ -14,6 +14,7 @@ #include #include +#include #include #include "generic.h" @@ -222,6 +223,16 @@ static struct at91_gpio_bank at91rm9200_gpio[] = { } }; +static void at91rm9200_reset(void) +{ + /* + * Perform a hardware reset with the use of the Watchdog timer. + */ + at91_sys_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1); + at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); +} + + /* -------------------------------------------------------------------- * AT91RM9200 processor initialization * -------------------------------------------------------------------- */ @@ -230,6 +241,12 @@ void __init at91rm9200_initialize(unsigned long main_clock, unsigned short banks /* Map peripherals */ iotable_init(at91rm9200_io_desc, ARRAY_SIZE(at91rm9200_io_desc)); + at91_arch_reset = at91rm9200_reset; + at91_extern_irq = (1 << AT91RM9200_ID_IRQ0) | (1 << AT91RM9200_ID_IRQ1) + | (1 << AT91RM9200_ID_IRQ2) | (1 << AT91RM9200_ID_IRQ3) + | (1 << AT91RM9200_ID_IRQ4) | (1 << AT91RM9200_ID_IRQ5) + | (1 << AT91RM9200_ID_IRQ6); + /* Init clock subsystem */ at91_clock_init(main_clock); diff --git a/arch/arm/mach-at91rm9200/generic.h b/arch/arm/mach-at91rm9200/generic.h index 694e411e28..fd98e353c5 100644 --- a/arch/arm/mach-at91rm9200/generic.h +++ b/arch/arm/mach-at91rm9200/generic.h @@ -39,3 +39,6 @@ struct at91_gpio_bank { }; extern void __init at91_gpio_init(struct at91_gpio_bank *, int nr_banks); extern void __init at91_gpio_irq_setup(void); + +extern void (*at91_arch_reset)(void); +extern int at91_extern_irq; diff --git a/arch/arm/mach-at91rm9200/irq.c b/arch/arm/mach-at91rm9200/irq.c index 3e488117ca..2cea07a34a 100644 --- a/arch/arm/mach-at91rm9200/irq.c +++ b/arch/arm/mach-at91rm9200/irq.c @@ -47,6 +47,10 @@ static void at91_aic_unmask_irq(unsigned int irq) at91_sys_write(AT91_AIC_IECR, 1 << irq); } +unsigned int at91_extern_irq; + +#define is_extern_irq(irq) ((1 << (irq)) & at91_extern_irq) + static int at91_aic_set_type(unsigned irq, unsigned type) { unsigned int smr, srctype; @@ -59,14 +63,16 @@ static int at91_aic_set_type(unsigned irq, unsigned type) srctype = AT91_AIC_SRCTYPE_RISING; break; case IRQT_LOW: - if ((irq > AT91_ID_FIQ) && (irq < AT91RM9200_ID_IRQ0)) /* only supported on external interrupts */ + if ((irq == AT91_ID_FIQ) || is_extern_irq(irq)) /* only supported on external interrupts */ + srctype = AT91_AIC_SRCTYPE_LOW; + else return -EINVAL; - srctype = AT91_AIC_SRCTYPE_LOW; break; case IRQT_FALLING: - if ((irq > AT91_ID_FIQ) && (irq < AT91RM9200_ID_IRQ0)) /* only supported on external interrupts */ + if ((irq == AT91_ID_FIQ) || is_extern_irq(irq)) /* only supported on external interrupts */ + srctype = AT91_AIC_SRCTYPE_FALLING; + else return -EINVAL; - srctype = AT91_AIC_SRCTYPE_FALLING; break; default: return -EINVAL; diff --git a/arch/arm/mach-at91rm9200/pm.c b/arch/arm/mach-at91rm9200/pm.c index 32c95d8eaa..5e3b6e306f 100644 --- a/arch/arm/mach-at91rm9200/pm.c +++ b/arch/arm/mach-at91rm9200/pm.c @@ -112,7 +112,6 @@ EXPORT_SYMBOL(at91_suspend_entering_slow_clock); static void (*slow_clock)(void); - static int at91_pm_enter(suspend_state_t state) { at91_gpio_suspend(); @@ -123,13 +122,7 @@ static int at91_pm_enter(suspend_state_t state) (at91_sys_read(AT91_PMC_PCSR) | (1 << AT91_ID_FIQ) | (1 << AT91_ID_SYS) - | (1 << AT91RM9200_ID_IRQ0) - | (1 << AT91RM9200_ID_IRQ1) - | (1 << AT91RM9200_ID_IRQ2) - | (1 << AT91RM9200_ID_IRQ3) - | (1 << AT91RM9200_ID_IRQ4) - | (1 << AT91RM9200_ID_IRQ5) - | (1 << AT91RM9200_ID_IRQ6)) + | (at91_extern_irq)) & at91_sys_read(AT91_AIC_IMR), state); diff --git a/include/asm-arm/arch-at91rm9200/system.h b/include/asm-arm/arch-at91rm9200/system.h index 8a2ff472e4..1d54185e03 100644 --- a/include/asm-arm/arch-at91rm9200/system.h +++ b/include/asm-arm/arch-at91rm9200/system.h @@ -39,13 +39,15 @@ static inline void arch_idle(void) cpu_do_idle(); } +void (*at91_arch_reset)(void); + static inline void arch_reset(char mode) { - /* - * Perform a hardware reset with the use of the Watchdog timer. - */ - at91_sys_write(AT91_ST_WDMR, AT91_ST_RSTEN | AT91_ST_EXTEN | 1); - at91_sys_write(AT91_ST_CR, AT91_ST_WDRST); + /* call the CPU-specific reset function */ + if (at91_arch_reset) + (at91_arch_reset)(); + + for (;;) {} /* wait fovever */ } #define ARCH_ID_AT91RM9200 0x09200080 -- 2.39.5