summaryrefslogtreecommitdiff
path: root/arch/arm/mach-exynos/pm.c
diff options
context:
space:
mode:
authorTomasz Figa <t.figa@samsung.com>2014-03-18 07:28:30 +0900
committerKukjin Kim <kgene.kim@samsung.com>2014-03-21 04:09:29 +0900
commitdd8ac696b20c1be5ca4728045df10e882e01e91d (patch)
treea7b4926f10ad997f4bd1d833f1d38b8405cfea18 /arch/arm/mach-exynos/pm.c
parentd710aa31874e2ff6e656dbd4807f4bd8d659eb93 (diff)
ARM: EXYNOS: Allow wake-up using GIC interrupts
This patch restores the ability to receive wake-up events from internal GIC interrupts, e.g. RTC tick or alarm interrupts. Signed-off-by: Tomasz Figa <t.figa@samsung.com> Acked-by: Kyungmin Park <kyungmin.park@samsung.com> Signed-off-by: Kukjin Kim <kgene.kim@samsung.com>
Diffstat (limited to 'arch/arm/mach-exynos/pm.c')
-rw-r--r--arch/arm/mach-exynos/pm.c53
1 files changed, 53 insertions, 0 deletions
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index ada1c8374b77..15af0ceb0a66 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -17,6 +17,7 @@
#include <linux/suspend.h>
#include <linux/syscore_ops.h>
#include <linux/io.h>
+#include <linux/irqchip/arm-gic.h>
#include <linux/err.h>
#include <linux/clk.h>
@@ -35,6 +36,16 @@
#include "common.h"
#include "regs-pmu.h"
+/**
+ * struct exynos_wkup_irq - Exynos GIC to PMU IRQ mapping
+ * @hwirq: Hardware IRQ signal of the GIC
+ * @mask: Mask in PMU wake-up mask register
+ */
+struct exynos_wkup_irq {
+ unsigned int hwirq;
+ u32 mask;
+};
+
static struct sleep_save exynos5_sys_save[] = {
SAVE_ITEM(EXYNOS5_SYS_I2C_CFG),
};
@@ -48,8 +59,47 @@ static struct sleep_save exynos_core_save[] = {
SAVE_ITEM(S5P_SROM_BC3),
};
+/*
+ * GIC wake-up support
+ */
+
static u32 exynos_irqwake_intmask = 0xffffffff;
+static const struct exynos_wkup_irq exynos4_wkup_irq[] = {
+ { 76, BIT(1) }, /* RTC alarm */
+ { 77, BIT(2) }, /* RTC tick */
+ { /* sentinel */ },
+};
+
+static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
+ { 75, BIT(1) }, /* RTC alarm */
+ { 76, BIT(2) }, /* RTC tick */
+ { /* sentinel */ },
+};
+
+static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
+{
+ const struct exynos_wkup_irq *wkup_irq;
+
+ if (soc_is_exynos5250())
+ wkup_irq = exynos5250_wkup_irq;
+ else
+ wkup_irq = exynos4_wkup_irq;
+
+ while (wkup_irq->mask) {
+ if (wkup_irq->hwirq == data->hwirq) {
+ if (!state)
+ exynos_irqwake_intmask |= wkup_irq->mask;
+ else
+ exynos_irqwake_intmask &= ~wkup_irq->mask;
+ return 0;
+ }
+ ++wkup_irq;
+ }
+
+ return -ENOENT;
+}
+
/* For Cortex-A9 Diagnostic and Power control register */
static unsigned int save_arm_register[2];
@@ -258,6 +308,9 @@ void __init exynos_pm_init(void)
{
u32 tmp;
+ /* Platform-specific GIC callback */
+ gic_arch_extn.irq_set_wake = exynos_irq_set_wake;
+
/* All wakeup disable */
tmp = __raw_readl(S5P_WAKEUP_MASK);
tmp |= ((0xFF << 8) | (0x1F << 1));