diff options
author | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2007-10-10 14:58:29 +0200 |
---|---|---|
committer | Haavard Skinnemoen <hskinnemoen@atmel.com> | 2008-01-25 08:31:43 +0100 |
commit | e7ba176b47db2ed53f258a6b4fe9d9fc6fa437a9 (patch) | |
tree | beb9ffab7da0c24f11c04b6eb4ca29b23b1dd07b /arch/avr32/mach-at32ap | |
parent | f6135d12db4bed3b992052020f1c50d749cd8dc6 (diff) |
[AVR32] NMI debugging
Change the NMI handler to use the die notifier chain to signal anyone
who cares. Add a simple "nmi debugger" which hooks into this chain and
that may dump registers, task state, etc. when it happens.
Signed-off-by: Haavard Skinnemoen <hskinnemoen@atmel.com>
Diffstat (limited to 'arch/avr32/mach-at32ap')
-rw-r--r-- | arch/avr32/mach-at32ap/at32ap700x.c | 1 | ||||
-rw-r--r-- | arch/avr32/mach-at32ap/extint.c | 39 |
2 files changed, 33 insertions, 7 deletions
diff --git a/arch/avr32/mach-at32ap/at32ap700x.c b/arch/avr32/mach-at32ap/at32ap700x.c index 9386e1f82fb8..14e61f05e1f6 100644 --- a/arch/avr32/mach-at32ap/at32ap700x.c +++ b/arch/avr32/mach-at32ap/at32ap700x.c @@ -13,6 +13,7 @@ #include <linux/spi/spi.h> #include <asm/io.h> +#include <asm/irq.h> #include <asm/arch/at32ap700x.h> #include <asm/arch/board.h> diff --git a/arch/avr32/mach-at32ap/extint.c b/arch/avr32/mach-at32ap/extint.c index f5bfd4c81fe7..e108e7bba8c0 100644 --- a/arch/avr32/mach-at32ap/extint.c +++ b/arch/avr32/mach-at32ap/extint.c @@ -26,16 +26,10 @@ #define EIC_MODE 0x0014 #define EIC_EDGE 0x0018 #define EIC_LEVEL 0x001c -#define EIC_TEST 0x0020 #define EIC_NMIC 0x0024 -/* Bitfields in TEST */ -#define EIC_TESTEN_OFFSET 31 -#define EIC_TESTEN_SIZE 1 - /* Bitfields in NMIC */ -#define EIC_EN_OFFSET 0 -#define EIC_EN_SIZE 1 +#define EIC_NMIC_ENABLE (1 << 0) /* Bit manipulation macros */ #define EIC_BIT(name) \ @@ -63,6 +57,9 @@ struct eic { unsigned int first_irq; }; +static struct eic *nmi_eic; +static bool nmi_enabled; + static void eic_ack_irq(unsigned int irq) { struct eic *eic = get_irq_chip_data(irq); @@ -174,6 +171,24 @@ static void demux_eic_irq(unsigned int irq, struct irq_desc *desc) } } +int nmi_enable(void) +{ + nmi_enabled = true; + + if (nmi_eic) + eic_writel(nmi_eic, NMIC, EIC_NMIC_ENABLE); + + return 0; +} + +void nmi_disable(void) +{ + if (nmi_eic) + eic_writel(nmi_eic, NMIC, 0); + + nmi_enabled = false; +} + static int __init eic_probe(struct platform_device *pdev) { struct eic *eic; @@ -230,6 +245,16 @@ static int __init eic_probe(struct platform_device *pdev) set_irq_chained_handler(int_irq, demux_eic_irq); set_irq_data(int_irq, eic); + if (pdev->id == 0) { + nmi_eic = eic; + if (nmi_enabled) + /* + * Someone tried to enable NMI before we were + * ready. Do it now. + */ + nmi_enable(); + } + dev_info(&pdev->dev, "External Interrupt Controller at 0x%p, IRQ %u\n", eic->regs, int_irq); |