diff options
author | Olof Johansson <olof@lixom.net> | 2013-11-15 14:10:41 -0500 |
---|---|---|
committer | Olof Johansson <olof@lixom.net> | 2013-11-15 14:10:41 -0500 |
commit | ca439c9b983ffa14e9eae6030e3ee80ad039388f (patch) | |
tree | 9ae38ed0b1e6559ffd79896d32248bda50f04839 /arch/arm/mach-at91 | |
parent | ba52b7d4afaec172073a4169e1d6522552b2979c (diff) | |
parent | 94c4c79f2f1acca6e69a50bff5a7d9027509c16b (diff) |
Merge tag 'at91-fixes-non-critical' of git://github.com/at91linux/linux-at91 into fixes
From Nicolas Ferre, fixes for early boot hangs on at91:
Fixes for RTT & RTC interrupts that can fire early during boot process
and kill the system.
* tag 'at91-fixes-non-critical' of git://github.com/at91linux/linux-at91:
ARM: at91: fix hanged boot due to early rtt-interrupt
ARM: at91: fix hanged boot due to early rtc-interrupt
Diffstat (limited to 'arch/arm/mach-at91')
-rw-r--r-- | arch/arm/mach-at91/Makefile | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9260.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9261.c | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9263.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9g45.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9n12.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9rl.c | 3 | ||||
-rw-r--r-- | arch/arm/mach-at91/at91sam9x5.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-at91/generic.h | 2 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/at91sam9n12.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/at91sam9x5.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-at91/include/mach/sama5d3.h | 5 | ||||
-rw-r--r-- | arch/arm/mach-at91/sama5d3.c | 6 | ||||
-rw-r--r-- | arch/arm/mach-at91/sysirq_mask.c | 71 |
14 files changed, 120 insertions, 1 deletions
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile index 3b0a9538093c..e0fda04e6aa1 100644 --- a/arch/arm/mach-at91/Makefile +++ b/arch/arm/mach-at91/Makefile | |||
@@ -2,7 +2,7 @@ | |||
2 | # Makefile for the linux kernel. | 2 | # Makefile for the linux kernel. |
3 | # | 3 | # |
4 | 4 | ||
5 | obj-y := irq.o gpio.o setup.o | 5 | obj-y := irq.o gpio.o setup.o sysirq_mask.o |
6 | obj-m := | 6 | obj-m := |
7 | obj-n := | 7 | obj-n := |
8 | obj- := | 8 | obj- := |
diff --git a/arch/arm/mach-at91/at91sam9260.c b/arch/arm/mach-at91/at91sam9260.c index 5de6074b4f4f..ae10d14de700 100644 --- a/arch/arm/mach-at91/at91sam9260.c +++ b/arch/arm/mach-at91/at91sam9260.c | |||
@@ -349,6 +349,8 @@ static void __init at91sam9260_initialize(void) | |||
349 | arm_pm_idle = at91sam9_idle; | 349 | arm_pm_idle = at91sam9_idle; |
350 | arm_pm_restart = at91sam9_alt_restart; | 350 | arm_pm_restart = at91sam9_alt_restart; |
351 | 351 | ||
352 | at91_sysirq_mask_rtt(AT91SAM9260_BASE_RTT); | ||
353 | |||
352 | /* Register GPIO subsystem */ | 354 | /* Register GPIO subsystem */ |
353 | at91_gpio_init(at91sam9260_gpio, 3); | 355 | at91_gpio_init(at91sam9260_gpio, 3); |
354 | } | 356 | } |
diff --git a/arch/arm/mach-at91/at91sam9261.c b/arch/arm/mach-at91/at91sam9261.c index 0e0793241ab7..e761e74ac64b 100644 --- a/arch/arm/mach-at91/at91sam9261.c +++ b/arch/arm/mach-at91/at91sam9261.c | |||
@@ -291,6 +291,8 @@ static void __init at91sam9261_initialize(void) | |||
291 | arm_pm_idle = at91sam9_idle; | 291 | arm_pm_idle = at91sam9_idle; |
292 | arm_pm_restart = at91sam9_alt_restart; | 292 | arm_pm_restart = at91sam9_alt_restart; |
293 | 293 | ||
294 | at91_sysirq_mask_rtt(AT91SAM9261_BASE_RTT); | ||
295 | |||
294 | /* Register GPIO subsystem */ | 296 | /* Register GPIO subsystem */ |
295 | at91_gpio_init(at91sam9261_gpio, 3); | 297 | at91_gpio_init(at91sam9261_gpio, 3); |
296 | } | 298 | } |
diff --git a/arch/arm/mach-at91/at91sam9263.c b/arch/arm/mach-at91/at91sam9263.c index 6ce7d1850893..e6fed6253a7f 100644 --- a/arch/arm/mach-at91/at91sam9263.c +++ b/arch/arm/mach-at91/at91sam9263.c | |||
@@ -328,6 +328,9 @@ static void __init at91sam9263_initialize(void) | |||
328 | arm_pm_idle = at91sam9_idle; | 328 | arm_pm_idle = at91sam9_idle; |
329 | arm_pm_restart = at91sam9_alt_restart; | 329 | arm_pm_restart = at91sam9_alt_restart; |
330 | 330 | ||
331 | at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT0); | ||
332 | at91_sysirq_mask_rtt(AT91SAM9263_BASE_RTT1); | ||
333 | |||
331 | /* Register GPIO subsystem */ | 334 | /* Register GPIO subsystem */ |
332 | at91_gpio_init(at91sam9263_gpio, 5); | 335 | at91_gpio_init(at91sam9263_gpio, 5); |
333 | } | 336 | } |
diff --git a/arch/arm/mach-at91/at91sam9g45.c b/arch/arm/mach-at91/at91sam9g45.c index 474ee04d24b9..9f7a97c84c12 100644 --- a/arch/arm/mach-at91/at91sam9g45.c +++ b/arch/arm/mach-at91/at91sam9g45.c | |||
@@ -377,6 +377,9 @@ static void __init at91sam9g45_initialize(void) | |||
377 | arm_pm_idle = at91sam9_idle; | 377 | arm_pm_idle = at91sam9_idle; |
378 | arm_pm_restart = at91sam9g45_restart; | 378 | arm_pm_restart = at91sam9g45_restart; |
379 | 379 | ||
380 | at91_sysirq_mask_rtc(AT91SAM9G45_BASE_RTC); | ||
381 | at91_sysirq_mask_rtt(AT91SAM9G45_BASE_RTT); | ||
382 | |||
380 | /* Register GPIO subsystem */ | 383 | /* Register GPIO subsystem */ |
381 | at91_gpio_init(at91sam9g45_gpio, 5); | 384 | at91_gpio_init(at91sam9g45_gpio, 5); |
382 | } | 385 | } |
diff --git a/arch/arm/mach-at91/at91sam9n12.c b/arch/arm/mach-at91/at91sam9n12.c index 2d895a297739..388ec3aec4b9 100644 --- a/arch/arm/mach-at91/at91sam9n12.c +++ b/arch/arm/mach-at91/at91sam9n12.c | |||
@@ -224,7 +224,13 @@ static void __init at91sam9n12_map_io(void) | |||
224 | at91_init_sram(0, AT91SAM9N12_SRAM_BASE, AT91SAM9N12_SRAM_SIZE); | 224 | at91_init_sram(0, AT91SAM9N12_SRAM_BASE, AT91SAM9N12_SRAM_SIZE); |
225 | } | 225 | } |
226 | 226 | ||
227 | static void __init at91sam9n12_initialize(void) | ||
228 | { | ||
229 | at91_sysirq_mask_rtc(AT91SAM9N12_BASE_RTC); | ||
230 | } | ||
231 | |||
227 | AT91_SOC_START(at91sam9n12) | 232 | AT91_SOC_START(at91sam9n12) |
228 | .map_io = at91sam9n12_map_io, | 233 | .map_io = at91sam9n12_map_io, |
229 | .register_clocks = at91sam9n12_register_clocks, | 234 | .register_clocks = at91sam9n12_register_clocks, |
235 | .init = at91sam9n12_initialize, | ||
230 | AT91_SOC_END | 236 | AT91_SOC_END |
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c index d4ec0d9a9872..301e1728d353 100644 --- a/arch/arm/mach-at91/at91sam9rl.c +++ b/arch/arm/mach-at91/at91sam9rl.c | |||
@@ -294,6 +294,9 @@ static void __init at91sam9rl_initialize(void) | |||
294 | arm_pm_idle = at91sam9_idle; | 294 | arm_pm_idle = at91sam9_idle; |
295 | arm_pm_restart = at91sam9_alt_restart; | 295 | arm_pm_restart = at91sam9_alt_restart; |
296 | 296 | ||
297 | at91_sysirq_mask_rtc(AT91SAM9RL_BASE_RTC); | ||
298 | at91_sysirq_mask_rtt(AT91SAM9RL_BASE_RTT); | ||
299 | |||
297 | /* Register GPIO subsystem */ | 300 | /* Register GPIO subsystem */ |
298 | at91_gpio_init(at91sam9rl_gpio, 4); | 301 | at91_gpio_init(at91sam9rl_gpio, 4); |
299 | } | 302 | } |
diff --git a/arch/arm/mach-at91/at91sam9x5.c b/arch/arm/mach-at91/at91sam9x5.c index 916e5a142917..e8a2e075a1b8 100644 --- a/arch/arm/mach-at91/at91sam9x5.c +++ b/arch/arm/mach-at91/at91sam9x5.c | |||
@@ -322,6 +322,11 @@ static void __init at91sam9x5_map_io(void) | |||
322 | at91_init_sram(0, AT91SAM9X5_SRAM_BASE, AT91SAM9X5_SRAM_SIZE); | 322 | at91_init_sram(0, AT91SAM9X5_SRAM_BASE, AT91SAM9X5_SRAM_SIZE); |
323 | } | 323 | } |
324 | 324 | ||
325 | static void __init at91sam9x5_initialize(void) | ||
326 | { | ||
327 | at91_sysirq_mask_rtc(AT91SAM9X5_BASE_RTC); | ||
328 | } | ||
329 | |||
325 | /* -------------------------------------------------------------------- | 330 | /* -------------------------------------------------------------------- |
326 | * Interrupt initialization | 331 | * Interrupt initialization |
327 | * -------------------------------------------------------------------- */ | 332 | * -------------------------------------------------------------------- */ |
@@ -329,4 +334,5 @@ static void __init at91sam9x5_map_io(void) | |||
329 | AT91_SOC_START(at91sam9x5) | 334 | AT91_SOC_START(at91sam9x5) |
330 | .map_io = at91sam9x5_map_io, | 335 | .map_io = at91sam9x5_map_io, |
331 | .register_clocks = at91sam9x5_register_clocks, | 336 | .register_clocks = at91sam9x5_register_clocks, |
337 | .init = at91sam9x5_initialize, | ||
332 | AT91_SOC_END | 338 | AT91_SOC_END |
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h index dc6e2f5f804d..26dee3ce9397 100644 --- a/arch/arm/mach-at91/generic.h +++ b/arch/arm/mach-at91/generic.h | |||
@@ -34,6 +34,8 @@ extern int __init at91_aic_of_init(struct device_node *node, | |||
34 | struct device_node *parent); | 34 | struct device_node *parent); |
35 | extern int __init at91_aic5_of_init(struct device_node *node, | 35 | extern int __init at91_aic5_of_init(struct device_node *node, |
36 | struct device_node *parent); | 36 | struct device_node *parent); |
37 | extern void __init at91_sysirq_mask_rtc(u32 rtc_base); | ||
38 | extern void __init at91_sysirq_mask_rtt(u32 rtt_base); | ||
37 | 39 | ||
38 | 40 | ||
39 | /* Timer */ | 41 | /* Timer */ |
diff --git a/arch/arm/mach-at91/include/mach/at91sam9n12.h b/arch/arm/mach-at91/include/mach/at91sam9n12.h index d374b87c0459..0151bcf6163c 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9n12.h +++ b/arch/arm/mach-at91/include/mach/at91sam9n12.h | |||
@@ -49,6 +49,11 @@ | |||
49 | #define AT91SAM9N12_BASE_USART3 0xf8028000 | 49 | #define AT91SAM9N12_BASE_USART3 0xf8028000 |
50 | 50 | ||
51 | /* | 51 | /* |
52 | * System Peripherals | ||
53 | */ | ||
54 | #define AT91SAM9N12_BASE_RTC 0xfffffeb0 | ||
55 | |||
56 | /* | ||
52 | * Internal Memory. | 57 | * Internal Memory. |
53 | */ | 58 | */ |
54 | #define AT91SAM9N12_SRAM_BASE 0x00300000 /* Internal SRAM base address */ | 59 | #define AT91SAM9N12_SRAM_BASE 0x00300000 /* Internal SRAM base address */ |
diff --git a/arch/arm/mach-at91/include/mach/at91sam9x5.h b/arch/arm/mach-at91/include/mach/at91sam9x5.h index c75ee19b58d3..2fc76c49e97c 100644 --- a/arch/arm/mach-at91/include/mach/at91sam9x5.h +++ b/arch/arm/mach-at91/include/mach/at91sam9x5.h | |||
@@ -55,6 +55,11 @@ | |||
55 | #define AT91SAM9X5_BASE_USART2 0xf8024000 | 55 | #define AT91SAM9X5_BASE_USART2 0xf8024000 |
56 | 56 | ||
57 | /* | 57 | /* |
58 | * System Peripherals | ||
59 | */ | ||
60 | #define AT91SAM9X5_BASE_RTC 0xfffffeb0 | ||
61 | |||
62 | /* | ||
58 | * Internal Memory. | 63 | * Internal Memory. |
59 | */ | 64 | */ |
60 | #define AT91SAM9X5_SRAM_BASE 0x00300000 /* Internal SRAM base address */ | 65 | #define AT91SAM9X5_SRAM_BASE 0x00300000 /* Internal SRAM base address */ |
diff --git a/arch/arm/mach-at91/include/mach/sama5d3.h b/arch/arm/mach-at91/include/mach/sama5d3.h index 31096a8aaf1d..25613d8c6dcd 100644 --- a/arch/arm/mach-at91/include/mach/sama5d3.h +++ b/arch/arm/mach-at91/include/mach/sama5d3.h | |||
@@ -73,6 +73,11 @@ | |||
73 | #define SAMA5D3_BASE_USART3 0xf8024000 | 73 | #define SAMA5D3_BASE_USART3 0xf8024000 |
74 | 74 | ||
75 | /* | 75 | /* |
76 | * System Peripherals | ||
77 | */ | ||
78 | #define SAMA5D3_BASE_RTC 0xfffffeb0 | ||
79 | |||
80 | /* | ||
76 | * Internal Memory | 81 | * Internal Memory |
77 | */ | 82 | */ |
78 | #define SAMA5D3_SRAM_BASE 0x00300000 /* Internal SRAM base address */ | 83 | #define SAMA5D3_SRAM_BASE 0x00300000 /* Internal SRAM base address */ |
diff --git a/arch/arm/mach-at91/sama5d3.c b/arch/arm/mach-at91/sama5d3.c index 401279715ab1..3ea86428ee09 100644 --- a/arch/arm/mach-at91/sama5d3.c +++ b/arch/arm/mach-at91/sama5d3.c | |||
@@ -371,7 +371,13 @@ static void __init sama5d3_map_io(void) | |||
371 | at91_init_sram(0, SAMA5D3_SRAM_BASE, SAMA5D3_SRAM_SIZE); | 371 | at91_init_sram(0, SAMA5D3_SRAM_BASE, SAMA5D3_SRAM_SIZE); |
372 | } | 372 | } |
373 | 373 | ||
374 | static void __init sama5d3_initialize(void) | ||
375 | { | ||
376 | at91_sysirq_mask_rtc(SAMA5D3_BASE_RTC); | ||
377 | } | ||
378 | |||
374 | AT91_SOC_START(sama5d3) | 379 | AT91_SOC_START(sama5d3) |
375 | .map_io = sama5d3_map_io, | 380 | .map_io = sama5d3_map_io, |
376 | .register_clocks = sama5d3_register_clocks, | 381 | .register_clocks = sama5d3_register_clocks, |
382 | .init = sama5d3_initialize, | ||
377 | AT91_SOC_END | 383 | AT91_SOC_END |
diff --git a/arch/arm/mach-at91/sysirq_mask.c b/arch/arm/mach-at91/sysirq_mask.c new file mode 100644 index 000000000000..2ba694f9626b --- /dev/null +++ b/arch/arm/mach-at91/sysirq_mask.c | |||
@@ -0,0 +1,71 @@ | |||
1 | /* | ||
2 | * sysirq_mask.c - System-interrupt masking | ||
3 | * | ||
4 | * Copyright (C) 2013 Johan Hovold <jhovold@gmail.com> | ||
5 | * | ||
6 | * Functions to disable system interrupts from backup-powered peripherals. | ||
7 | * | ||
8 | * The RTC and RTT-peripherals are generally powered by backup power (VDDBU) | ||
9 | * and are not reset on wake-up, user, watchdog or software reset. This means | ||
10 | * that their interrupts may be enabled during early boot (e.g. after a user | ||
11 | * reset). | ||
12 | * | ||
13 | * As the RTC and RTT share the system-interrupt line with the PIT, an | ||
14 | * interrupt occurring before a handler has been installed would lead to the | ||
15 | * system interrupt being disabled and prevent the system from booting. | ||
16 | * | ||
17 | * This program is free software; you can redistribute it and/or modify | ||
18 | * it under the terms of the GNU General Public License as published by | ||
19 | * the Free Software Foundation; either version 2 of the License, or | ||
20 | * (at your option) any later version. | ||
21 | */ | ||
22 | |||
23 | #include <linux/io.h> | ||
24 | #include <mach/at91_rtt.h> | ||
25 | |||
26 | #include "generic.h" | ||
27 | |||
28 | #define AT91_RTC_IDR 0x24 /* Interrupt Disable Register */ | ||
29 | #define AT91_RTC_IMR 0x28 /* Interrupt Mask Register */ | ||
30 | |||
31 | void __init at91_sysirq_mask_rtc(u32 rtc_base) | ||
32 | { | ||
33 | void __iomem *base; | ||
34 | u32 mask; | ||
35 | |||
36 | base = ioremap(rtc_base, 64); | ||
37 | if (!base) | ||
38 | return; | ||
39 | |||
40 | mask = readl_relaxed(base + AT91_RTC_IMR); | ||
41 | if (mask) { | ||
42 | pr_info("AT91: Disabling rtc irq\n"); | ||
43 | writel_relaxed(mask, base + AT91_RTC_IDR); | ||
44 | (void)readl_relaxed(base + AT91_RTC_IMR); /* flush */ | ||
45 | } | ||
46 | |||
47 | iounmap(base); | ||
48 | } | ||
49 | |||
50 | void __init at91_sysirq_mask_rtt(u32 rtt_base) | ||
51 | { | ||
52 | void __iomem *base; | ||
53 | void __iomem *reg; | ||
54 | u32 mode; | ||
55 | |||
56 | base = ioremap(rtt_base, 16); | ||
57 | if (!base) | ||
58 | return; | ||
59 | |||
60 | reg = base + AT91_RTT_MR; | ||
61 | |||
62 | mode = readl_relaxed(reg); | ||
63 | if (mode & (AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN)) { | ||
64 | pr_info("AT91: Disabling rtt irq\n"); | ||
65 | mode &= ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN); | ||
66 | writel_relaxed(mode, reg); | ||
67 | (void)readl_relaxed(reg); /* flush */ | ||
68 | } | ||
69 | |||
70 | iounmap(base); | ||
71 | } | ||