aboutsummaryrefslogtreecommitdiffstats
path: root/arch/avr32/mach-at32ap/extint.c
diff options
context:
space:
mode:
authorHaavard Skinnemoen <hskinnemoen@atmel.com>2007-10-10 08:58:29 -0400
committerHaavard Skinnemoen <hskinnemoen@atmel.com>2008-01-25 02:31:43 -0500
commite7ba176b47db2ed53f258a6b4fe9d9fc6fa437a9 (patch)
treebeb9ffab7da0c24f11c04b6eb4ca29b23b1dd07b /arch/avr32/mach-at32ap/extint.c
parentf6135d12db4bed3b992052020f1c50d749cd8dc6 (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/extint.c')
-rw-r--r--arch/avr32/mach-at32ap/extint.c39
1 files changed, 32 insertions, 7 deletions
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 @@
26#define EIC_MODE 0x0014 26#define EIC_MODE 0x0014
27#define EIC_EDGE 0x0018 27#define EIC_EDGE 0x0018
28#define EIC_LEVEL 0x001c 28#define EIC_LEVEL 0x001c
29#define EIC_TEST 0x0020
30#define EIC_NMIC 0x0024 29#define EIC_NMIC 0x0024
31 30
32/* Bitfields in TEST */
33#define EIC_TESTEN_OFFSET 31
34#define EIC_TESTEN_SIZE 1
35
36/* Bitfields in NMIC */ 31/* Bitfields in NMIC */
37#define EIC_EN_OFFSET 0 32#define EIC_NMIC_ENABLE (1 << 0)
38#define EIC_EN_SIZE 1
39 33
40/* Bit manipulation macros */ 34/* Bit manipulation macros */
41#define EIC_BIT(name) \ 35#define EIC_BIT(name) \
@@ -63,6 +57,9 @@ struct eic {
63 unsigned int first_irq; 57 unsigned int first_irq;
64}; 58};
65 59
60static struct eic *nmi_eic;
61static bool nmi_enabled;
62
66static void eic_ack_irq(unsigned int irq) 63static void eic_ack_irq(unsigned int irq)
67{ 64{
68 struct eic *eic = get_irq_chip_data(irq); 65 struct eic *eic = get_irq_chip_data(irq);
@@ -174,6 +171,24 @@ static void demux_eic_irq(unsigned int irq, struct irq_desc *desc)
174 } 171 }
175} 172}
176 173
174int nmi_enable(void)
175{
176 nmi_enabled = true;
177
178 if (nmi_eic)
179 eic_writel(nmi_eic, NMIC, EIC_NMIC_ENABLE);
180
181 return 0;
182}
183
184void nmi_disable(void)
185{
186 if (nmi_eic)
187 eic_writel(nmi_eic, NMIC, 0);
188
189 nmi_enabled = false;
190}
191
177static int __init eic_probe(struct platform_device *pdev) 192static int __init eic_probe(struct platform_device *pdev)
178{ 193{
179 struct eic *eic; 194 struct eic *eic;
@@ -230,6 +245,16 @@ static int __init eic_probe(struct platform_device *pdev)
230 set_irq_chained_handler(int_irq, demux_eic_irq); 245 set_irq_chained_handler(int_irq, demux_eic_irq);
231 set_irq_data(int_irq, eic); 246 set_irq_data(int_irq, eic);
232 247
248 if (pdev->id == 0) {
249 nmi_eic = eic;
250 if (nmi_enabled)
251 /*
252 * Someone tried to enable NMI before we were
253 * ready. Do it now.
254 */
255 nmi_enable();
256 }
257
233 dev_info(&pdev->dev, 258 dev_info(&pdev->dev,
234 "External Interrupt Controller at 0x%p, IRQ %u\n", 259 "External Interrupt Controller at 0x%p, IRQ %u\n",
235 eic->regs, int_irq); 260 eic->regs, int_irq);