aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJohan Hovold <jhovold@gmail.com>2013-10-16 05:56:15 -0400
committerNicolas Ferre <nicolas.ferre@atmel.com>2013-11-15 06:13:33 -0500
commit94c4c79f2f1acca6e69a50bff5a7d9027509c16b (patch)
tree85b5fdb02f99edb8b8f4368ea932c4d149fc9e1f
parent6de714c21a8ea315fffba6a93bbe537f4c1bf4f0 (diff)
ARM: at91: fix hanged boot due to early rtt-interrupt
Make sure the RTT-interrupts are masked at boot by adding a new helper function to be used at SOC-init. This fixes hanged boot on all AT91 SOCs with an RTT, for example, if an RTT-alarm goes off after a non-clean shutdown (e.g. when using RTC wakeup). The RTC and RTT-peripherals are powered by backup power (VDDBU) (on all AT91 SOCs but RM9200) and are not reset on wake-up, user, watchdog or software reset. This means that their interrupts may be enabled during early boot if, for example, they where not disabled during a previous shutdown (e.g. due to a buggy driver or a non-clean shutdown such as a user reset). Furthermore, an RTC or RTT-alarm may also be active. The RTC and RTT-interrupts use the shared system-interrupt line, which is also used by the PIT, and if an interrupt occurs before a handler (e.g. RTC-driver) has been installed this leads to the system interrupt being disabled and prevents the system from booting. Note that when boot hangs due to an early RTC or RTT-interrupt, the only way to get the system to start again is to remove the backup power (e.g. battery) or to disable the interrupt manually from the bootloader. In particular, a user reset is not sufficient. Signed-off-by: Johan Hovold <jhovold@gmail.com> Signed-off-by: Nicolas Ferre <nicolas.ferre@atmel.com> Cc: stable@vger.kernel.org # 3.11.x
-rw-r--r--arch/arm/mach-at91/at91sam9260.c2
-rw-r--r--arch/arm/mach-at91/at91sam9261.c2
-rw-r--r--arch/arm/mach-at91/at91sam9263.c3
-rw-r--r--arch/arm/mach-at91/at91sam9g45.c1
-rw-r--r--arch/arm/mach-at91/at91sam9rl.c1
-rw-r--r--arch/arm/mach-at91/generic.h1
-rw-r--r--arch/arm/mach-at91/sysirq_mask.c24
7 files changed, 34 insertions, 0 deletions
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 ff662af77fee..9f7a97c84c12 100644
--- a/arch/arm/mach-at91/at91sam9g45.c
+++ b/arch/arm/mach-at91/at91sam9g45.c
@@ -378,6 +378,7 @@ static void __init at91sam9g45_initialize(void)
378 arm_pm_restart = at91sam9g45_restart; 378 arm_pm_restart = at91sam9g45_restart;
379 379
380 at91_sysirq_mask_rtc(AT91SAM9G45_BASE_RTC); 380 at91_sysirq_mask_rtc(AT91SAM9G45_BASE_RTC);
381 at91_sysirq_mask_rtt(AT91SAM9G45_BASE_RTT);
381 382
382 /* Register GPIO subsystem */ 383 /* Register GPIO subsystem */
383 at91_gpio_init(at91sam9g45_gpio, 5); 384 at91_gpio_init(at91sam9g45_gpio, 5);
diff --git a/arch/arm/mach-at91/at91sam9rl.c b/arch/arm/mach-at91/at91sam9rl.c
index b5a8c9d81bc8..301e1728d353 100644
--- a/arch/arm/mach-at91/at91sam9rl.c
+++ b/arch/arm/mach-at91/at91sam9rl.c
@@ -295,6 +295,7 @@ static void __init at91sam9rl_initialize(void)
295 arm_pm_restart = at91sam9_alt_restart; 295 arm_pm_restart = at91sam9_alt_restart;
296 296
297 at91_sysirq_mask_rtc(AT91SAM9RL_BASE_RTC); 297 at91_sysirq_mask_rtc(AT91SAM9RL_BASE_RTC);
298 at91_sysirq_mask_rtt(AT91SAM9RL_BASE_RTT);
298 299
299 /* Register GPIO subsystem */ 300 /* Register GPIO subsystem */
300 at91_gpio_init(at91sam9rl_gpio, 4); 301 at91_gpio_init(at91sam9rl_gpio, 4);
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index 80269bda0dd7..26dee3ce9397 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -35,6 +35,7 @@ extern int __init at91_aic_of_init(struct device_node *node,
35extern int __init at91_aic5_of_init(struct device_node *node, 35extern int __init at91_aic5_of_init(struct device_node *node,
36 struct device_node *parent); 36 struct device_node *parent);
37extern void __init at91_sysirq_mask_rtc(u32 rtc_base); 37extern void __init at91_sysirq_mask_rtc(u32 rtc_base);
38extern void __init at91_sysirq_mask_rtt(u32 rtt_base);
38 39
39 40
40 /* Timer */ 41 /* Timer */
diff --git a/arch/arm/mach-at91/sysirq_mask.c b/arch/arm/mach-at91/sysirq_mask.c
index ee3e22c66ce8..2ba694f9626b 100644
--- a/arch/arm/mach-at91/sysirq_mask.c
+++ b/arch/arm/mach-at91/sysirq_mask.c
@@ -21,6 +21,7 @@
21 */ 21 */
22 22
23#include <linux/io.h> 23#include <linux/io.h>
24#include <mach/at91_rtt.h>
24 25
25#include "generic.h" 26#include "generic.h"
26 27
@@ -45,3 +46,26 @@ void __init at91_sysirq_mask_rtc(u32 rtc_base)
45 46
46 iounmap(base); 47 iounmap(base);
47} 48}
49
50void __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}