From: marc.zyngier@arm.com (Marc Zyngier)
To: linux-arm-kernel@lists.infradead.org
Subject: [PATCH 10/16] ARM: exynos4/5: convert pmu wakeup to stacked domains
Date: Tue, 2 Dec 2014 16:58:11 +0000 [thread overview]
Message-ID: <1417539497-20101-11-git-send-email-marc.zyngier@arm.com> (raw)
In-Reply-To: <1417539497-20101-1-git-send-email-marc.zyngier@arm.com>
Exynos has been (ab)using the gic_arch_extn to provide
wakeup from suspend, and it makes a lot of sense to convert
this code to use stacked domains instead.
This patch does just this, updating the DT files to actually
reflect what the HW provides.
BIG FAT WARNING: because the DTs were so far lying by not
exposing the fact that the PMU block is actually the first
interrupt controller in the chain for RTC, kernels with this patch
applied wont have any suspend-resume facility when booted
with old DTs, and old kernels with updated DTs may not even boot.
Also, I stronly suspect that there is more than two wake-up
interrupts on these platforms, but I leave it to the maintainers
to fix their mess.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/boot/dts/exynos4.dtsi | 3 +
arch/arm/boot/dts/exynos5250.dtsi | 3 +
arch/arm/mach-exynos/exynos.c | 12 ++--
arch/arm/mach-exynos/pm.c | 116 +++++++++++++++++++++++++++++++++++---
4 files changed, 119 insertions(+), 15 deletions(-)
diff --git a/arch/arm/boot/dts/exynos4.dtsi b/arch/arm/boot/dts/exynos4.dtsi
index e0278ec..04decb9 100644
--- a/arch/arm/boot/dts/exynos4.dtsi
+++ b/arch/arm/boot/dts/exynos4.dtsi
@@ -141,6 +141,8 @@
pmu_system_controller: system-controller at 10020000 {
compatible = "samsung,exynos4210-pmu", "syscon";
reg = <0x10020000 0x4000>;
+ interrupt-controller;
+ interrupt-parent = <&gic>;
};
dsi_0: dsi at 11C80000 {
@@ -253,6 +255,7 @@
rtc at 10070000 {
compatible = "samsung,s3c6410-rtc";
reg = <0x10070000 0x100>;
+ interrupt-parent = <&pmu_system_controller>;
interrupts = <0 44 0>, <0 45 0>;
clocks = <&clock CLK_RTC>;
clock-names = "rtc";
diff --git a/arch/arm/boot/dts/exynos5250.dtsi b/arch/arm/boot/dts/exynos5250.dtsi
index d55c1a2..b937e7b 100644
--- a/arch/arm/boot/dts/exynos5250.dtsi
+++ b/arch/arm/boot/dts/exynos5250.dtsi
@@ -194,6 +194,8 @@
clock-names = "clkout16";
clocks = <&clock CLK_FIN_PLL>;
#clock-cells = <1>;
+ interrupt-controller;
+ interrupt-parent = <&gic>;
};
sysreg_system_controller: syscon at 10050000 {
@@ -230,6 +232,7 @@
rtc at 101E0000 {
clocks = <&clock CLK_RTC>;
clock-names = "rtc";
+ interrupt-parent = <&pmu_system_controller>;
status = "disabled";
};
diff --git a/arch/arm/mach-exynos/exynos.c b/arch/arm/mach-exynos/exynos.c
index 6b283eb..a4d2f65 100644
--- a/arch/arm/mach-exynos/exynos.c
+++ b/arch/arm/mach-exynos/exynos.c
@@ -247,12 +247,13 @@ static void __init exynos_init_io(void)
exynos_map_io();
}
+/*
+ * Apparently, these SoCs are not able to wake-up from suspend using
+ * the PMU. Too bad. Should they suddenly become capable of such a
+ * feat, the matches below should be moved to pm.c.
+ */
static const struct of_device_id exynos_dt_pmu_match[] = {
{ .compatible = "samsung,exynos3250-pmu" },
- { .compatible = "samsung,exynos4210-pmu" },
- { .compatible = "samsung,exynos4212-pmu" },
- { .compatible = "samsung,exynos4412-pmu" },
- { .compatible = "samsung,exynos5250-pmu" },
{ .compatible = "samsung,exynos5260-pmu" },
{ .compatible = "samsung,exynos5410-pmu" },
{ .compatible = "samsung,exynos5420-pmu" },
@@ -266,9 +267,6 @@ static void exynos_map_pmu(void)
np = of_find_matching_node(NULL, exynos_dt_pmu_match);
if (np)
pmu_base_addr = of_iomap(np, 0);
-
- if (!pmu_base_addr)
- panic("failed to find exynos pmu register\n");
}
static void __init exynos_init_irq(void)
diff --git a/arch/arm/mach-exynos/pm.c b/arch/arm/mach-exynos/pm.c
index abefacb..418e405 100644
--- a/arch/arm/mach-exynos/pm.c
+++ b/arch/arm/mach-exynos/pm.c
@@ -18,7 +18,9 @@
#include <linux/syscore_ops.h>
#include <linux/cpu_pm.h>
#include <linux/io.h>
-#include <linux/irqchip/arm-gic.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
#include <linux/err.h>
#include <linux/clk.h>
@@ -66,14 +68,14 @@ static struct sleep_save exynos_core_save[] = {
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 */
+ { 44, BIT(1) }, /* RTC alarm */
+ { 45, BIT(2) }, /* RTC tick */
{ /* sentinel */ },
};
static const struct exynos_wkup_irq exynos5250_wkup_irq[] = {
- { 75, BIT(1) }, /* RTC alarm */
- { 76, BIT(2) }, /* RTC tick */
+ { 43, BIT(1) }, /* RTC alarm */
+ { 44, BIT(2) }, /* RTC tick */
{ /* sentinel */ },
};
@@ -100,6 +102,107 @@ static int exynos_irq_set_wake(struct irq_data *data, unsigned int state)
return -ENOENT;
}
+static struct irq_chip exynos_pmu_chip = {
+ .name = "PMU",
+ .irq_eoi = irq_chip_eoi_parent,
+ .irq_mask = irq_chip_mask_parent,
+ .irq_unmask = irq_chip_unmask_parent,
+ .irq_retrigger = irq_chip_retrigger_hierarchy,
+ .irq_set_wake = exynos_irq_set_wake,
+};
+
+static int exynos_pmu_domain_xlate(struct irq_domain *domain,
+ struct device_node *controller,
+ const u32 *intspec,
+ unsigned int intsize,
+ unsigned long *out_hwirq,
+ unsigned int *out_type)
+{
+ if (domain->of_node != controller)
+ return -EINVAL; /* Shouldn't happen, really... */
+ if (intsize != 3)
+ return -EINVAL; /* Not GIC compliant */
+ if (intspec[0] != 0)
+ return -EINVAL; /* No PPI should point to this domain */
+
+ *out_hwirq = intspec[1];
+ *out_type = intspec[2];
+ return 0;
+}
+
+static int exynos_pmu_domain_alloc(struct irq_domain *domain,
+ unsigned int virq,
+ unsigned int nr_irqs, void *data)
+{
+ struct of_phandle_args *args = data;
+ struct of_phandle_args parent_args;
+ irq_hw_number_t hwirq;
+ int i;
+
+ if (args->args_count != 3)
+ return -EINVAL; /* Not GIC compliant */
+ if (args->args[0] != 0)
+ return -EINVAL; /* No PPI should point to this domain */
+
+ hwirq = args->args[1];
+
+ for (i = 0; i < nr_irqs; i++)
+ irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+ &exynos_pmu_chip, NULL);
+
+ parent_args = *args;
+ parent_args.np = domain->parent->of_node;
+ return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+}
+
+static struct irq_domain_ops exynos_pmu_domain_ops = {
+ .xlate = exynos_pmu_domain_xlate,
+ .alloc = exynos_pmu_domain_alloc,
+ .free = irq_domain_free_irqs_common,
+};
+
+static int __init exynos_pmu_irq_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct irq_domain *parent_domain, *domain;
+
+ if (!parent) {
+ pr_err("%s: no parent, giving up\n", node->full_name);
+ return -ENODEV;
+ }
+
+ parent_domain = irq_find_host(parent);
+ if (!parent_domain) {
+ pr_err("%s: unable to obtain parent domain\n", node->full_name);
+ return -ENXIO;
+ }
+
+ pmu_base_addr = of_iomap(node, 0);
+
+ if (!pmu_base_addr) {
+ pr_err("%s: failed to find exynos pmu register\n",
+ node->full_name);
+ return -ENOMEM;
+ }
+
+ domain = irq_domain_add_hierarchy(parent_domain, 0, 0,
+ node, &exynos_pmu_domain_ops,
+ NULL);
+ if (!domain) {
+ iounmap(pmu_base_addr);
+ return -ENOMEM;
+ }
+
+ return 0;
+}
+
+#define EXYNOS_PMU_IRQ(symbol,name) OF_DECLARE_2(irqchip, symbol, name, exynos_pmu_irq_init)
+
+EXYNOS_PMU_IRQ(exynos4210_pmu_irq, "samsung,exynos4210-pmu");
+EXYNOS_PMU_IRQ(exynos4212_pmu_irq, "samsung,exynos4212-pmu");
+EXYNOS_PMU_IRQ(exynos4412_pmu_irq, "samsung,exynos4412-pmu");
+EXYNOS_PMU_IRQ(exynos5250_pmu_irq, "samsung,exynos5250-pmu");
+
#define EXYNOS_BOOT_VECTOR_ADDR (samsung_rev() == EXYNOS4210_REV_1_1 ? \
pmu_base_addr + S5P_INFORM7 : \
(samsung_rev() == EXYNOS4210_REV_1_0 ? \
@@ -396,9 +499,6 @@ 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 = pmu_raw_readl(S5P_WAKEUP_MASK);
tmp |= ((0xFF << 8) | (0x1F << 1));
--
2.1.3
next prev parent reply other threads:[~2014-12-02 16:58 UTC|newest]
Thread overview: 26+ messages / expand[flat|nested] mbox.gz Atom feed top
2014-12-02 16:58 [PATCH 00/16] irqchip: gic: killing gic_arch_extn, slowly Marc Zyngier
2014-12-02 16:58 ` [PATCH 01/16] ARM: tegra: irq: nuke leftovers from non-DT support Marc Zyngier
2014-12-02 16:58 ` [PATCH 02/16] irqchip: tegra: add DT-based support for legacy interrupt controller Marc Zyngier
2014-12-02 16:58 ` [PATCH 03/16] ARM: tegra: skip gic_arch_extn setup if DT has a LIC node Marc Zyngier
2014-12-02 16:58 ` [PATCH 04/16] ARM: tegra: update DTs to expose legacy interrupt controller Marc Zyngier
2014-12-02 16:58 ` [PATCH 05/16] DT: tegra: add binding for the " Marc Zyngier
2014-12-02 16:58 ` [PATCH 06/16] ARM: tegra: remove old LIC support Marc Zyngier
2014-12-02 16:58 ` [PATCH 07/16] ARM: omap: convert wakeupgen to stacked domains Marc Zyngier
2014-12-02 16:58 ` [PATCH 08/16] DT: omap4/5: add binding for the wake-up generator Marc Zyngier
2014-12-02 16:58 ` [PATCH 09/16] ARM: imx6: convert wakeupgen to stacked domains Marc Zyngier
2014-12-06 16:08 ` Stefan Agner
2014-12-08 11:18 ` Marc Zyngier
2014-12-02 16:58 ` Marc Zyngier [this message]
2014-12-02 16:58 ` [PATCH 11/16] DT: exynos: update PMU binding Marc Zyngier
2014-12-02 16:58 ` [PATCH 12/16] irqchip: gic: add an entry point to set up irqchip flags Marc Zyngier
2014-12-02 16:58 ` [PATCH 13/16] ARM: shmobile: remove use of gic_arch_extn.irq_set_wake Marc Zyngier
2014-12-04 6:39 ` Simon Horman
2014-12-04 8:57 ` Marc Zyngier
2014-12-04 11:46 ` Simon Horman
2014-12-02 16:58 ` [PATCH 14/16] ARM: ux500: switch from gic_arch_extn to gic_set_irqchip_flags Marc Zyngier
2014-12-03 13:52 ` Linus Walleij
2014-12-02 16:58 ` [PATCH 15/16] ARM: zynq: " Marc Zyngier
2014-12-02 16:58 ` [PATCH 16/16] irqchip: gic: Drop support for gic_arch_extn Marc Zyngier
2014-12-03 14:30 ` [PATCH 00/16] irqchip: gic: killing gic_arch_extn, slowly Arnd Bergmann
2014-12-03 14:59 ` Marc Zyngier
2014-12-03 20:32 ` Arnd Bergmann
Reply instructions:
You may reply publicly to this message via plain-text email
using any one of the following methods:
* Save the following mbox file, import it into your mail client,
and reply-to-all from there: mbox
Avoid top-posting and favor interleaved quoting:
https://en.wikipedia.org/wiki/Posting_style#Interleaved_style
* Reply using the --to, --cc, and --in-reply-to
switches of git-send-email(1):
git send-email \
--in-reply-to=1417539497-20101-11-git-send-email-marc.zyngier@arm.com \
--to=marc.zyngier@arm.com \
--cc=linux-arm-kernel@lists.infradead.org \
/path/to/YOUR_REPLY
https://kernel.org/pub/software/scm/git/docs/git-send-email.html
* If your mail client supports setting the In-Reply-To header
via mailto: links, try the mailto: link
Be sure your reply has a Subject: header at the top and a blank line
before the message body.
This is a public inbox, see mirroring instructions
for how to clone and mirror all data and code used for this inbox;
as well as URLs for NNTP newsgroup(s).