summaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--arch/arm/mach-at91/Makefile2
-rw-r--r--arch/arm/mach-at91/at91sam9260_devices.c8
-rw-r--r--arch/arm/mach-at91/at91sam9261_devices.c8
-rw-r--r--arch/arm/mach-at91/at91sam9263_devices.c8
-rw-r--r--arch/arm/mach-at91/at91sam9g45_devices.c7
-rw-r--r--arch/arm/mach-at91/generic.h2
-rw-r--r--arch/arm/mach-at91/include/mach/at91_rtt.h35
-rw-r--r--arch/arm/mach-at91/irq_fixup.c22
8 files changed, 91 insertions, 1 deletions
diff --git a/arch/arm/mach-at91/Makefile b/arch/arm/mach-at91/Makefile
index f098e0eabb..ab80e5f0aa 100644
--- a/arch/arm/mach-at91/Makefile
+++ b/arch/arm/mach-at91/Makefile
@@ -1,4 +1,4 @@
-obj-y += setup.o clock.o gpio.o
+obj-y += setup.o clock.o gpio.o irq_fixup.o
obj-$(CONFIG_CMD_AT91_BOOT_TEST) += boot_test_cmd.o
obj-$(CONFIG_AT91_BOOTSTRAP) += bootstrap.o
diff --git a/arch/arm/mach-at91/at91sam9260_devices.c b/arch/arm/mach-at91/at91sam9260_devices.c
index 84a03296ea..bf2b5b7402 100644
--- a/arch/arm/mach-at91/at91sam9260_devices.c
+++ b/arch/arm/mach-at91/at91sam9260_devices.c
@@ -10,6 +10,7 @@
*
*/
#include <common.h>
+#include <init.h>
#include <sizes.h>
#include <gpio.h>
#include <asm/armlinux.h>
@@ -398,3 +399,10 @@ void at91_add_device_mci(short mmc_id, struct atmel_mci_platform_data *data)
#else
void at91_add_device_mci(short mmc_id, struct atmel_mci_platform_data *data) {}
#endif
+
+static int at91_fixup_device(void)
+{
+ at91_rtt_irq_fixup(IOMEM(AT91SAM9260_BASE_RTT));
+ return 0;
+}
+late_initcall(at91_fixup_device);
diff --git a/arch/arm/mach-at91/at91sam9261_devices.c b/arch/arm/mach-at91/at91sam9261_devices.c
index b522afb76a..9ac9f20b84 100644
--- a/arch/arm/mach-at91/at91sam9261_devices.c
+++ b/arch/arm/mach-at91/at91sam9261_devices.c
@@ -10,6 +10,7 @@
*
*/
#include <common.h>
+#include <init.h>
#include <sizes.h>
#include <gpio.h>
#include <asm/armlinux.h>
@@ -351,3 +352,10 @@ void at91_add_device_mci(short mmc_id, struct atmel_mci_platform_data *data)
#else
void at91_add_device_mci(short mmc_id, struct atmel_mci_platform_data *data) {}
#endif
+
+static int at91_fixup_device(void)
+{
+ at91_rtt_irq_fixup(IOMEM(AT91SAM9261_BASE_RTT));
+ return 0;
+}
+late_initcall(at91_fixup_device);
diff --git a/arch/arm/mach-at91/at91sam9263_devices.c b/arch/arm/mach-at91/at91sam9263_devices.c
index 9d8bc32dc6..6860ad09d3 100644
--- a/arch/arm/mach-at91/at91sam9263_devices.c
+++ b/arch/arm/mach-at91/at91sam9263_devices.c
@@ -10,6 +10,7 @@
*
*/
#include <common.h>
+#include <init.h>
#include <sizes.h>
#include <gpio.h>
#include <asm/armlinux.h>
@@ -426,3 +427,10 @@ void at91_add_device_mci(short mmc_id, struct atmel_mci_platform_data *data)
void at91_add_device_mci(short mmc_id, struct atmel_mci_platform_data *data) {}
#endif
+static int at91_fixup_device(void)
+{
+ at91_rtt_irq_fixup(IOMEM(AT91SAM9263_BASE_RTT0));
+ at91_rtt_irq_fixup(IOMEM(AT91SAM9263_BASE_RTT1));
+ return 0;
+}
+late_initcall(at91_fixup_device);
diff --git a/arch/arm/mach-at91/at91sam9g45_devices.c b/arch/arm/mach-at91/at91sam9g45_devices.c
index 3e0bc100bb..bd7ab9333b 100644
--- a/arch/arm/mach-at91/at91sam9g45_devices.c
+++ b/arch/arm/mach-at91/at91sam9g45_devices.c
@@ -10,6 +10,7 @@
*
*/
#include <common.h>
+#include <init.h>
#include <sizes.h>
#include <gpio.h>
#include <asm/armlinux.h>
@@ -451,3 +452,9 @@ void __init at91_add_device_lcdc(struct atmel_lcdfb_platform_data *data)
void __init at91_add_device_lcdc(struct atmel_lcdfb_platform_data *data) {}
#endif
+static int at91_fixup_device(void)
+{
+ at91_rtt_irq_fixup(IOMEM(AT91SAM9G45_BASE_RTT));
+ return 0;
+}
+late_initcall(at91_fixup_device);
diff --git a/arch/arm/mach-at91/generic.h b/arch/arm/mach-at91/generic.h
index deba019243..a47bcb2c57 100644
--- a/arch/arm/mach-at91/generic.h
+++ b/arch/arm/mach-at91/generic.h
@@ -35,3 +35,5 @@ static inline struct device_d *at91_add_sam9_smc(int id, resource_size_t start,
return add_generic_device("at91sam9-smc", id, NULL, start, size,
IORESOURCE_MEM, NULL);
}
+
+void at91_rtt_irq_fixup(void *base);
diff --git a/arch/arm/mach-at91/include/mach/at91_rtt.h b/arch/arm/mach-at91/include/mach/at91_rtt.h
new file mode 100644
index 0000000000..7ec75de8bb
--- /dev/null
+++ b/arch/arm/mach-at91/include/mach/at91_rtt.h
@@ -0,0 +1,35 @@
+/*
+ * arch/arm/mach-at91/include/mach/at91_rtt.h
+ *
+ * Copyright (C) 2007 Andrew Victor
+ * Copyright (C) 2007 Atmel Corporation.
+ *
+ * Real-time Timer (RTT) - System peripherals regsters.
+ * Based on AT91SAM9261 datasheet revision D.
+ *
+ * This program is free software; you can redistribute it and/or modify
+ * it under the terms of the GNU General Public License as published by
+ * the Free Software Foundation; either version 2 of the License, or
+ * (at your option) any later version.
+ */
+
+#ifndef AT91_RTT_H
+#define AT91_RTT_H
+
+#define AT91_RTT_MR 0x00 /* Real-time Mode Register */
+#define AT91_RTT_RTPRES (0xffff << 0) /* Real-time Timer Prescaler Value */
+#define AT91_RTT_ALMIEN (1 << 16) /* Alarm Interrupt Enable */
+#define AT91_RTT_RTTINCIEN (1 << 17) /* Real Time Timer Increment Interrupt Enable */
+#define AT91_RTT_RTTRST (1 << 18) /* Real Time Timer Restart */
+
+#define AT91_RTT_AR 0x04 /* Real-time Alarm Register */
+#define AT91_RTT_ALMV (0xffffffff) /* Alarm Value */
+
+#define AT91_RTT_VR 0x08 /* Real-time Value Register */
+#define AT91_RTT_CRTV (0xffffffff) /* Current Real-time Value */
+
+#define AT91_RTT_SR 0x0c /* Real-time Status Register */
+#define AT91_RTT_ALMS (1 << 0) /* Real-time Alarm Status */
+#define AT91_RTT_RTTINC (1 << 1) /* Real-time Timer Increment */
+
+#endif
diff --git a/arch/arm/mach-at91/irq_fixup.c b/arch/arm/mach-at91/irq_fixup.c
new file mode 100644
index 0000000000..a9eebd785b
--- /dev/null
+++ b/arch/arm/mach-at91/irq_fixup.c
@@ -0,0 +1,22 @@
+/*
+ * Copyright (C) 2013 Jean-Christophe PLAGNIOL-VILLARD <plagnioj@jcrosoft.com>
+ *
+ * Under GPLv2 only
+ */
+
+#include <io.h>
+#include <mach/at91_rtt.h>
+
+/*
+ * As the RTT is powered by the backup power so if the interrupt
+ * is still on when the kernel start, the kernel will end up with
+ * dead lock interrupt that it can not clear. Because the interrupt line is
+ * shared with the basic timer (PIT) on AT91_ID_SYS.
+ */
+void at91_rtt_irq_fixup(void *base)
+{
+ void *reg = base + AT91_RTT_MR;
+ u32 mr = readl(reg);
+
+ writel(mr & ~(AT91_RTT_ALMIEN | AT91_RTT_RTTINCIEN), reg);
+}