* [PATCH 0/9] irqchip: gic: kill gic_arch_extn
@ 2014-11-28 17:26 Marc Zyngier
2014-11-28 17:26 ` [PATCH 1/9] ARM: tegra: irq: fix buggy usage of irq_data irq field Marc Zyngier
` (9 more replies)
0 siblings, 10 replies; 12+ messages in thread
From: Marc Zyngier @ 2014-11-28 17:26 UTC (permalink / raw)
To: linux-arm-kernel
The gic_arch_extn hack that Tegra uses has been nagging me for too
long. It is only there for the benefit of a single platform, and yet
it impacts all GIC users. Moreover, it gives people the wrong idea
("let's use it to put some new custom hack in there"...).
But now that stacked irq domains have landed in -next, the time has
come for gic_arch_extn to meet the Big Bit Bucket.
This patch series moves Tegra's legacy interrupt controller support to
drivers/irqchip, implementing a stacked domain on top of the standard
GIC. The GIC itself is cleaned up, and some other bits and bobs are
adjusted for a good measure.
It is worth realizing that:
- I haven't been able to test this as much as I would have wanted to
(suspend/resume seems to be broken on my Harmony, and I don't have
another platform at hand). But I haven't seen any regression from 3.17.
- I've relaxed quite a bit of the locking in the GIC code. I believe
this is safe, but someone else should give it a long hard look.
- This actively *breaks* existing setups. Once you boot a new kernel
with an old DT, suspend/resume *will* be broken. Old kernels on a new
DT won't even boot! You've been warned.
As for the patches, they are on top of 3.18-rc6 +
tip/irq/irqdomain-arm. Patch #1 is already queued for 3.18, and only
included here for completeness.
I've pushed the code to:
git://git.kernel.org/pub/scm/linux/kernel/git/maz/arm-platforms.git irq/tegra-lic
Comments welcome,
M.
Marc Zyngier (9):
ARM: tegra: irq: fix buggy usage of irq_data irq field
ARM: tegra: irq: nuke leftovers from non-DT support
irqchip: tegra: add DT-based support for legacy interrupt controller
ARM: tegra: skip gic_arch_extn setup if DT has a LIC node
ARM: tegra: update DTs to expose legacy interrupt controller
DT: tegra: add binding for the legacy interrupt controller
ARM: tegra: remove old LIC support
ARM: tegra: use DT to find the GIC distributor
irqchip: gic: Drop support for gic_arch_extn
.../interrupt-controller/nvdia,tegra-ictlr.txt | 39 +++
arch/arm/boot/dts/tegra114.dtsi | 16 +-
arch/arm/boot/dts/tegra124.dtsi | 16 +-
arch/arm/boot/dts/tegra20.dtsi | 15 +-
arch/arm/boot/dts/tegra30.dtsi | 16 +-
arch/arm/mach-tegra/iomap.h | 18 --
arch/arm/mach-tegra/irq.c | 228 ++------------
arch/arm/mach-tegra/irq.h | 6 -
arch/arm/mach-tegra/tegra.c | 1 -
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-gic.c | 46 +--
drivers/irqchip/irq-tegra.c | 335 +++++++++++++++++++++
include/linux/irqchip/arm-gic.h | 2 -
13 files changed, 461 insertions(+), 278 deletions(-)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/nvdia,tegra-ictlr.txt
create mode 100644 drivers/irqchip/irq-tegra.c
--
2.1.3
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 1/9] ARM: tegra: irq: fix buggy usage of irq_data irq field
2014-11-28 17:26 [PATCH 0/9] irqchip: gic: kill gic_arch_extn Marc Zyngier
@ 2014-11-28 17:26 ` Marc Zyngier
2014-11-28 17:26 ` [PATCH 2/9] ARM: tegra: irq: nuke leftovers from non-DT support Marc Zyngier
` (8 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Marc Zyngier @ 2014-11-28 17:26 UTC (permalink / raw)
To: linux-arm-kernel
The crazy gic_arch_extn thing that Tegra uses contains multiple
references to the irq field in struct irq_data, and uses this
to directly poke hardware register.
But irq is the *virtual* irq number, something that has nothing
to do with the actual HW irq (stored in the hwirq field). And once
we put the stacked domain code in action, the whole thing explodes,
as these two values are *very* different:
root at bacon-fat:~# cat /proc/interrupts
CPU0 CPU1
16: 25801 2075 GIC 29 twd
17: 0 0 GIC 73 timer0
112: 0 0 GPIO 58 c8000600.sdhci cd
123: 0 0 GPIO 69 c8000200.sdhci cd
279: 1126 0 GIC 122 serial
281: 0 0 GIC 70 7000c000.i2c
282: 0 0 GIC 116 7000c400.i2c
283: 0 0 GIC 124 7000c500.i2c
284: 300 0 GIC 85 7000d000.i2c
[...]
Just replacing all instances of irq with hwirq fixes the issue.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/mach-tegra/irq.c | 22 +++++++++++-----------
1 file changed, 11 insertions(+), 11 deletions(-)
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index da7be13..ab95f53 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -99,42 +99,42 @@ static inline void tegra_irq_write_mask(unsigned int irq, unsigned long reg)
static void tegra_mask(struct irq_data *d)
{
- if (d->irq < FIRST_LEGACY_IRQ)
+ if (d->hwirq < FIRST_LEGACY_IRQ)
return;
- tegra_irq_write_mask(d->irq, ICTLR_CPU_IER_CLR);
+ tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_CLR);
}
static void tegra_unmask(struct irq_data *d)
{
- if (d->irq < FIRST_LEGACY_IRQ)
+ if (d->hwirq < FIRST_LEGACY_IRQ)
return;
- tegra_irq_write_mask(d->irq, ICTLR_CPU_IER_SET);
+ tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_SET);
}
static void tegra_ack(struct irq_data *d)
{
- if (d->irq < FIRST_LEGACY_IRQ)
+ if (d->hwirq < FIRST_LEGACY_IRQ)
return;
- tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_CLR);
+ tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR);
}
static void tegra_eoi(struct irq_data *d)
{
- if (d->irq < FIRST_LEGACY_IRQ)
+ if (d->hwirq < FIRST_LEGACY_IRQ)
return;
- tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_CLR);
+ tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR);
}
static int tegra_retrigger(struct irq_data *d)
{
- if (d->irq < FIRST_LEGACY_IRQ)
+ if (d->hwirq < FIRST_LEGACY_IRQ)
return 0;
- tegra_irq_write_mask(d->irq, ICTLR_CPU_IEP_FIR_SET);
+ tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_SET);
return 1;
}
@@ -142,7 +142,7 @@ static int tegra_retrigger(struct irq_data *d)
#ifdef CONFIG_PM_SLEEP
static int tegra_set_wake(struct irq_data *d, unsigned int enable)
{
- u32 irq = d->irq;
+ u32 irq = d->hwirq;
u32 index, mask;
if (irq < FIRST_LEGACY_IRQ ||
--
2.1.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 2/9] ARM: tegra: irq: nuke leftovers from non-DT support
2014-11-28 17:26 [PATCH 0/9] irqchip: gic: kill gic_arch_extn Marc Zyngier
2014-11-28 17:26 ` [PATCH 1/9] ARM: tegra: irq: fix buggy usage of irq_data irq field Marc Zyngier
@ 2014-11-28 17:26 ` Marc Zyngier
2014-11-28 17:26 ` [PATCH 3/9] irqchip: tegra: add DT-based support for legacy interrupt controller Marc Zyngier
` (7 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Marc Zyngier @ 2014-11-28 17:26 UTC (permalink / raw)
To: linux-arm-kernel
The GIC is now always initialized from DT on tegra, and there is
no point in keeping non-DT init code.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/mach-tegra/irq.c | 8 --------
1 file changed, 8 deletions(-)
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index ab95f53..7f87a50 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -283,13 +283,5 @@ void __init tegra_init_irq(void)
gic_arch_extn.irq_set_wake = tegra_set_wake;
gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
- /*
- * Check if there is a devicetree present, since the GIC will be
- * initialized elsewhere under DT.
- */
- if (!of_have_populated_dt())
- gic_init(0, 29, distbase,
- IO_ADDRESS(TEGRA_ARM_PERIF_BASE + 0x100));
-
tegra114_gic_cpu_pm_registration();
}
--
2.1.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 3/9] irqchip: tegra: add DT-based support for legacy interrupt controller
2014-11-28 17:26 [PATCH 0/9] irqchip: gic: kill gic_arch_extn Marc Zyngier
2014-11-28 17:26 ` [PATCH 1/9] ARM: tegra: irq: fix buggy usage of irq_data irq field Marc Zyngier
2014-11-28 17:26 ` [PATCH 2/9] ARM: tegra: irq: nuke leftovers from non-DT support Marc Zyngier
@ 2014-11-28 17:26 ` Marc Zyngier
2014-11-28 17:26 ` [PATCH 4/9] ARM: tegra: skip gic_arch_extn setup if DT has a LIC node Marc Zyngier
` (6 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Marc Zyngier @ 2014-11-28 17:26 UTC (permalink / raw)
To: linux-arm-kernel
Tegra's LIC (Legacy Interrupt Controller) has been so far only
supported as a weird extension of the GIC, which is not exactly
pretty.
The stacked irq domain framework fits this pretty well, and allows
the LIC code to be turned into a standalone irqchip. In the process,
make the driver DT aware, something that was sorely missing from
the mach-tegra implementation.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/irqchip/Makefile | 1 +
drivers/irqchip/irq-tegra.c | 335 ++++++++++++++++++++++++++++++++++++++++++++
2 files changed, 336 insertions(+)
create mode 100644 drivers/irqchip/irq-tegra.c
diff --git a/drivers/irqchip/Makefile b/drivers/irqchip/Makefile
index 983634d..0fd9c7d 100644
--- a/drivers/irqchip/Makefile
+++ b/drivers/irqchip/Makefile
@@ -6,6 +6,7 @@ obj-$(CONFIG_ARCH_HIP04) += irq-hip04.o
obj-$(CONFIG_ARCH_MMP) += irq-mmp.o
obj-$(CONFIG_ARCH_MVEBU) += irq-armada-370-xp.o
obj-$(CONFIG_ARCH_MXS) += irq-mxs.o
+obj-$(CONFIG_ARCH_TEGRA) += irq-tegra.o
obj-$(CONFIG_ARCH_S3C24XX) += irq-s3c24xx.o
obj-$(CONFIG_DW_APB_ICTL) += irq-dw-apb-ictl.o
obj-$(CONFIG_METAG) += irq-metag-ext.o
diff --git a/drivers/irqchip/irq-tegra.c b/drivers/irqchip/irq-tegra.c
new file mode 100644
index 0000000..b4fc2e3
--- /dev/null
+++ b/drivers/irqchip/irq-tegra.c
@@ -0,0 +1,335 @@
+/*
+ * Driver code for Tegra's Legacy Interrupt Controller
+ *
+ * Author: Marc Zyngier <marc.zyngier@arm.com>
+ *
+ * Heavily based on the original arch/arm/mach-tegra/irq.c code:
+ * Copyright (C) 2011 Google, Inc.
+ *
+ * Author:
+ * Colin Cross <ccross@android.com>
+ *
+ * Copyright (C) 2010,2013, NVIDIA Corporation
+ *
+ * This software is licensed under the terms of the GNU General Public
+ * License version 2, as published by the Free Software Foundation, and
+ * may be copied, distributed, and modified under those terms.
+ *
+ * This program is distributed in the hope that it will be useful,
+ * but WITHOUT ANY WARRANTY; without even the implied warranty of
+ * MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
+ * GNU General Public License for more details.
+ *
+ */
+
+#include <linux/io.h>
+#include <linux/irq.h>
+#include <linux/irqdomain.h>
+#include <linux/of_address.h>
+#include <linux/slab.h>
+#include <linux/syscore_ops.h>
+
+#include "irqchip.h"
+
+#define ICTLR_CPU_IEP_VFIQ 0x08
+#define ICTLR_CPU_IEP_FIR 0x14
+#define ICTLR_CPU_IEP_FIR_SET 0x18
+#define ICTLR_CPU_IEP_FIR_CLR 0x1c
+
+#define ICTLR_CPU_IER 0x20
+#define ICTLR_CPU_IER_SET 0x24
+#define ICTLR_CPU_IER_CLR 0x28
+#define ICTLR_CPU_IEP_CLASS 0x2C
+
+#define ICTLR_COP_IER 0x30
+#define ICTLR_COP_IER_SET 0x34
+#define ICTLR_COP_IER_CLR 0x38
+#define ICTLR_COP_IEP_CLASS 0x3c
+
+#define TEGRA_MAX_NUM_ICTLRS 5
+
+static int num_ictlrs;
+
+struct tegra_ictlr_info {
+ void __iomem *ictlr_reg_base[TEGRA_MAX_NUM_ICTLRS];
+#ifdef CONFIG_PM_SLEEP
+ u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
+ u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
+ u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
+ u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
+
+ u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
+#endif
+};
+
+static struct tegra_ictlr_info *tegra_ictlr_info;
+
+static inline void tegra_ictlr_write_mask(struct irq_data *d, unsigned long reg)
+{
+ void __iomem *base = d->chip_data;
+ u32 mask;
+
+ mask = BIT(d->hwirq % 32);
+ writel_relaxed(mask, base + reg);
+}
+
+static void tegra_mask(struct irq_data *d)
+{
+ tegra_ictlr_write_mask(d, ICTLR_CPU_IER_CLR);
+ irq_chip_mask_parent(d);
+}
+
+static void tegra_unmask(struct irq_data *d)
+{
+ tegra_ictlr_write_mask(d, ICTLR_CPU_IER_SET);
+ irq_chip_unmask_parent(d);
+}
+
+static void tegra_eoi(struct irq_data *d)
+{
+ tegra_ictlr_write_mask(d, ICTLR_CPU_IEP_FIR_CLR);
+ irq_chip_eoi_parent(d);
+}
+
+static int tegra_retrigger(struct irq_data *d)
+{
+ tegra_ictlr_write_mask(d, ICTLR_CPU_IEP_FIR_SET);
+ return irq_chip_retrigger_hierarchy(d);
+}
+
+#ifdef CONFIG_PM_SLEEP
+static int tegra_set_wake(struct irq_data *d, unsigned int enable)
+{
+ u32 irq = d->hwirq;
+ u32 index, mask;
+
+ index = (irq / 32);
+ mask = BIT(irq % 32);
+ if (enable)
+ tegra_ictlr_info->ictlr_wake_mask[index] |= mask;
+ else
+ tegra_ictlr_info->ictlr_wake_mask[index] &= ~mask;
+
+ /*
+ * Do *not* call into the parent, as the GIC doesn't have any
+ * wake-up facility...
+ */
+ return 0;
+}
+
+static int tegra_ictlr_suspend(void)
+{
+ unsigned long flags;
+ int i;
+
+ local_irq_save(flags);
+ for (i = 0; i < num_ictlrs; i++) {
+ void __iomem *ictlr = tegra_ictlr_info->ictlr_reg_base[i];
+ /* Save interrupt state */
+ tegra_ictlr_info->cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
+ tegra_ictlr_info->cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
+ tegra_ictlr_info->cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
+ tegra_ictlr_info->cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
+
+ /* Disable COP interrupts */
+ writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
+
+ /* Disable CPU interrupts */
+ writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+
+ /* Enable the wakeup sources of ictlr */
+ writel_relaxed(tegra_ictlr_info->ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
+ }
+ local_irq_restore(flags);
+
+ return 0;
+}
+
+static void tegra_ictlr_resume(void)
+{
+ unsigned long flags;
+ int i;
+
+ local_irq_save(flags);
+ for (i = 0; i < num_ictlrs; i++) {
+ void __iomem *ictlr = tegra_ictlr_info->ictlr_reg_base[i];
+ writel_relaxed(tegra_ictlr_info->cpu_iep[i],
+ ictlr + ICTLR_CPU_IEP_CLASS);
+ writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
+ writel_relaxed(tegra_ictlr_info->cpu_ier[i],
+ ictlr + ICTLR_CPU_IER_SET);
+ writel_relaxed(tegra_ictlr_info->cop_iep[i],
+ ictlr + ICTLR_COP_IEP_CLASS);
+ writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
+ writel_relaxed(tegra_ictlr_info->cop_ier[i],
+ ictlr + ICTLR_COP_IER_SET);
+ }
+ local_irq_restore(flags);
+}
+
+static struct syscore_ops tegra_ictlr_syscore_ops = {
+ .suspend = tegra_ictlr_suspend,
+ .resume = tegra_ictlr_resume,
+};
+
+static int tegra_ictlr_syscore_init(void)
+{
+ register_syscore_ops(&tegra_ictlr_syscore_ops);
+
+ return 0;
+}
+#else
+#define tegra_set_wake NULL
+static inline void tegra_ictlr_syscore_init(void) {}
+#endif
+
+static struct irq_chip tegra_ictlr_chip = {
+ .name = "ICTLR",
+ .irq_eoi = tegra_eoi,
+ .irq_mask = tegra_mask,
+ .irq_unmask = tegra_unmask,
+ .irq_retrigger = tegra_retrigger,
+ .irq_set_wake = tegra_set_wake,
+ .flags = IRQCHIP_MASK_ON_SUSPEND,
+};
+
+static int tegra_ictlr_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 tegra_ictlr_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;
+ struct tegra_ictlr_info *info = domain->host_data;
+ 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];
+ if (hwirq >= (num_ictlrs * 32))
+ return -EINVAL; /* Can't deal with this */
+
+ for (i = 0; i < nr_irqs; i++) {
+ int ictlr = (hwirq + i) / 32;
+
+ irq_domain_set_hwirq_and_chip(domain, virq + i, hwirq + i,
+ &tegra_ictlr_chip,
+ &info->ictlr_reg_base[ictlr]);
+ }
+
+ parent_args = *args;
+ parent_args.np = domain->parent->of_node;
+ return irq_domain_alloc_irqs_parent(domain, virq, nr_irqs, &parent_args);
+}
+
+
+static void tegra_ictlr_domain_free(struct irq_domain *domain,
+ unsigned int virq,
+ unsigned int nr_irqs)
+{
+ int i;
+
+ for (i = 0; i < nr_irqs; i++) {
+ struct irq_data *d = irq_domain_get_irq_data(domain, virq + i);
+ irq_domain_reset_irq_data(d);
+ }
+}
+
+static struct irq_domain_ops tegra_ictlr_domain_ops = {
+ .xlate = tegra_ictlr_domain_xlate,
+ .alloc = tegra_ictlr_domain_alloc,
+ .free = tegra_ictlr_domain_free,
+};
+
+static int __init tegra_ictlr_init(struct device_node *node,
+ struct device_node *parent)
+{
+ struct irq_domain *parent_domain, *domain;
+ int err;
+ int i;
+
+ 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;
+ }
+
+ tegra_ictlr_info = kzalloc(sizeof(*tegra_ictlr_info), GFP_KERNEL);
+ if (!tegra_ictlr_info)
+ return -ENOMEM;
+
+ for (i = 0; i < TEGRA_MAX_NUM_ICTLRS; i++) {
+ void __iomem *base;
+
+ base = of_iomap(node, i);
+ if (!base)
+ break;
+
+ tegra_ictlr_info->ictlr_reg_base[i] = base;
+
+ /* Disable all interrupts */
+ writel_relaxed(~0, base + ICTLR_CPU_IER_CLR);
+ /* All interrupts target IRQ */
+ writel_relaxed(0, base + ICTLR_CPU_IEP_CLASS);
+
+ num_ictlrs++;
+ }
+
+ if (!num_ictlrs) {
+ pr_err("%s: no valid regions, giving up\n", node->full_name);
+ err = -ENOMEM;
+ goto out_free;
+ }
+
+ domain = irq_domain_add_hierarchy(parent_domain, 0, num_ictlrs * 32,
+ node, &tegra_ictlr_domain_ops,
+ tegra_ictlr_info);
+ if (!domain) {
+ pr_err("%s: failed to allocated domain\n", node->full_name);
+ err = -ENOMEM;
+ goto out_unmap;
+ }
+
+ tegra_ictlr_syscore_init();
+
+ pr_info("%s: %d interrupts forwarded to %s\n",
+ node->full_name, num_ictlrs * 32, parent->full_name);
+
+ return 0;
+
+out_unmap:
+ for (i = 0; i < num_ictlrs; i++)
+ iounmap(tegra_ictlr_info->ictlr_reg_base[i]);
+out_free:
+ kfree(tegra_ictlr_info);
+ return err;
+}
+
+IRQCHIP_DECLARE(tegra_ictlr, "nvidia,tegra-ictlr", tegra_ictlr_init);
--
2.1.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 4/9] ARM: tegra: skip gic_arch_extn setup if DT has a LIC node
2014-11-28 17:26 [PATCH 0/9] irqchip: gic: kill gic_arch_extn Marc Zyngier
` (2 preceding siblings ...)
2014-11-28 17:26 ` [PATCH 3/9] irqchip: tegra: add DT-based support for legacy interrupt controller Marc Zyngier
@ 2014-11-28 17:26 ` Marc Zyngier
2014-11-28 17:26 ` [PATCH 5/9] ARM: tegra: update DTs to expose legacy interrupt controller Marc Zyngier
` (5 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Marc Zyngier @ 2014-11-28 17:26 UTC (permalink / raw)
To: linux-arm-kernel
If we detect that our DT has a LIC node, don't setup gic_arch_extn,
and skip tegra_legacy_irq_syscore_init as well.
This is only a temporary measure until that code is removed for good.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/mach-tegra/irq.c | 11 +++++++++++
arch/arm/mach-tegra/tegra.c | 1 -
2 files changed, 11 insertions(+), 1 deletion(-)
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index 7f87a50..b37141d 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -255,11 +255,21 @@ static void tegra114_gic_cpu_pm_registration(void)
static void tegra114_gic_cpu_pm_registration(void) { }
#endif
+static const struct of_device_id tegra_ictlr_match[] __initconst = {
+ { .compatible = "nvidia,tegra-ictlr" },
+ { }
+};
+
void __init tegra_init_irq(void)
{
int i;
void __iomem *distbase;
+ if (of_find_matching_node(NULL, tegra_ictlr_match))
+ goto skip_extn_setup;
+
+ tegra_legacy_irq_syscore_init();
+
distbase = IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE);
num_ictlrs = readl_relaxed(distbase + GIC_DIST_CTR) & 0x1f;
@@ -283,5 +293,6 @@ void __init tegra_init_irq(void)
gic_arch_extn.irq_set_wake = tegra_set_wake;
gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
+skip_extn_setup:
tegra114_gic_cpu_pm_registration();
}
diff --git a/arch/arm/mach-tegra/tegra.c b/arch/arm/mach-tegra/tegra.c
index ef016af..c33fba7 100644
--- a/arch/arm/mach-tegra/tegra.c
+++ b/arch/arm/mach-tegra/tegra.c
@@ -82,7 +82,6 @@ static void __init tegra_dt_init_irq(void)
{
tegra_init_irq();
irqchip_init();
- tegra_legacy_irq_syscore_init();
}
static void __init tegra_dt_init(void)
--
2.1.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 5/9] ARM: tegra: update DTs to expose legacy interrupt controller
2014-11-28 17:26 [PATCH 0/9] irqchip: gic: kill gic_arch_extn Marc Zyngier
` (3 preceding siblings ...)
2014-11-28 17:26 ` [PATCH 4/9] ARM: tegra: skip gic_arch_extn setup if DT has a LIC node Marc Zyngier
@ 2014-11-28 17:26 ` Marc Zyngier
2014-11-28 17:26 ` [PATCH 6/9] DT: tegra: add binding for the " Marc Zyngier
` (4 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Marc Zyngier @ 2014-11-28 17:26 UTC (permalink / raw)
To: linux-arm-kernel
Describe the legacy interrupt controller in every tegra DTSI files,
and make it the parent of most interrupts.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/boot/dts/tegra114.dtsi | 16 +++++++++++++++-
arch/arm/boot/dts/tegra124.dtsi | 16 +++++++++++++++-
arch/arm/boot/dts/tegra20.dtsi | 15 ++++++++++++++-
arch/arm/boot/dts/tegra30.dtsi | 16 +++++++++++++++-
4 files changed, 59 insertions(+), 4 deletions(-)
diff --git a/arch/arm/boot/dts/tegra114.dtsi b/arch/arm/boot/dts/tegra114.dtsi
index 222f3b3..b89454d 100644
--- a/arch/arm/boot/dts/tegra114.dtsi
+++ b/arch/arm/boot/dts/tegra114.dtsi
@@ -7,7 +7,7 @@
/ {
compatible = "nvidia,tegra114";
- interrupt-parent = <&gic>;
+ interrupt-parent = <&ictlr>;
host1x at 50000000 {
compatible = "nvidia,tegra114-host1x", "simple-bus";
@@ -129,6 +129,19 @@
<0x50046000 0x2000>;
interrupts = <GIC_PPI 9
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ interrupt-parent = <&gic>;
+ };
+
+ ictlr: interrupt-controller at 60004000 {
+ compatible = "nvidia,tegra114-ictlr", "nvidia,tegra-ictlr";
+ reg = <0x60004000 64>,
+ <0x60004100 64>,
+ <0x60004200 64>,
+ <0x60004300 64>,
+ <0x60004400 64>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&gic>;
};
timer at 60005000 {
@@ -761,5 +774,6 @@
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-parent = <&gic>;
};
};
diff --git a/arch/arm/boot/dts/tegra124.dtsi b/arch/arm/boot/dts/tegra124.dtsi
index df2b06b..e428655 100644
--- a/arch/arm/boot/dts/tegra124.dtsi
+++ b/arch/arm/boot/dts/tegra124.dtsi
@@ -8,7 +8,7 @@
/ {
compatible = "nvidia,tegra124";
- interrupt-parent = <&gic>;
+ interrupt-parent = <&ictlr>;
#address-cells = <2>;
#size-cells = <2>;
@@ -167,6 +167,7 @@
<0x0 0x50046000 0x0 0x2000>;
interrupts = <GIC_PPI 9
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
+ interrupt-parent = <&gic>;
};
gpu at 0,57000000 {
@@ -184,6 +185,18 @@
status = "disabled";
};
+ ictlr: interrupt-controller at 60004000 {
+ compatible = "nvidia,tegra124-ictlr", "nvidia,tegra-ictlr";
+ reg = <0x0 0x60004000 0x0 0x40>,
+ <0x0 0x60004100 0x0 0x40>,
+ <0x0 0x60004200 0x0 0x40>,
+ <0x0 0x60004300 0x0 0x40>,
+ <0x0 0x60004400 0x0 0x40>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&gic>;
+ };
+
timer at 0,60005000 {
compatible = "nvidia,tegra124-timer", "nvidia,tegra20-timer";
reg = <0x0 0x60005000 0x0 0x400>;
@@ -891,5 +904,6 @@
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>,
<GIC_PPI 10
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_LOW)>;
+ interrupt-parent = <&gic>;
};
};
diff --git a/arch/arm/boot/dts/tegra20.dtsi b/arch/arm/boot/dts/tegra20.dtsi
index 8acf5d8..ab2f004 100644
--- a/arch/arm/boot/dts/tegra20.dtsi
+++ b/arch/arm/boot/dts/tegra20.dtsi
@@ -7,7 +7,7 @@
/ {
compatible = "nvidia,tegra20";
- interrupt-parent = <&intc>;
+ interrupt-parent = <&ictlr>;
host1x at 50000000 {
compatible = "nvidia,tegra20-host1x", "simple-bus";
@@ -142,6 +142,7 @@
timer at 50004600 {
compatible = "arm,cortex-a9-twd-timer";
+ interrupt-parent = <&intc>;
reg = <0x50040600 0x20>;
interrupts = <GIC_PPI 13
(GIC_CPU_MASK_SIMPLE(2) | IRQ_TYPE_LEVEL_HIGH)>;
@@ -154,6 +155,7 @@
0x50040100 0x0100>;
interrupt-controller;
#interrupt-cells = <3>;
+ interrupt-parent = <&intc>;
};
cache-controller at 50043000 {
@@ -165,6 +167,17 @@
cache-level = <2>;
};
+ ictlr: interrupt-controller at 60004000 {
+ compatible = "nvidia,tegra20-ictlr", "nvidia,tegra-ictlr";
+ reg = <0x60004000 64>,
+ <0x60004100 64>,
+ <0x60004200 64>,
+ <0x60004300 64>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&intc>;
+ };
+
timer at 60005000 {
compatible = "nvidia,tegra20-timer";
reg = <0x60005000 0x60>;
diff --git a/arch/arm/boot/dts/tegra30.dtsi b/arch/arm/boot/dts/tegra30.dtsi
index b270b9e..4490f8c 100644
--- a/arch/arm/boot/dts/tegra30.dtsi
+++ b/arch/arm/boot/dts/tegra30.dtsi
@@ -7,7 +7,7 @@
/ {
compatible = "nvidia,tegra30";
- interrupt-parent = <&intc>;
+ interrupt-parent = <&ictlr>;
pcie-controller at 00003000 {
compatible = "nvidia,tegra30-pcie";
@@ -223,6 +223,7 @@
timer at 50004600 {
compatible = "arm,cortex-a9-twd-timer";
reg = <0x50040600 0x20>;
+ interrupt-parent = <&intc>;
interrupts = <GIC_PPI 13
(GIC_CPU_MASK_SIMPLE(4) | IRQ_TYPE_LEVEL_HIGH)>;
clocks = <&tegra_car TEGRA30_CLK_TWD>;
@@ -234,6 +235,7 @@
0x50040100 0x0100>;
interrupt-controller;
#interrupt-cells = <3>;
+ interrupt-parent = <&intc>;
};
cache-controller at 50043000 {
@@ -245,6 +247,18 @@
cache-level = <2>;
};
+ ictlr: interrupt-controller at 60004000 {
+ compatible = "nvidia,tegra30-ictlr", "nvidia,tegra-ictlr";
+ reg = <0x60004000 64>,
+ <0x60004100 64>,
+ <0x60004200 64>,
+ <0x60004300 64>,
+ <0x60004400 64>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&intc>;
+ };
+
timer at 60005000 {
compatible = "nvidia,tegra30-timer", "nvidia,tegra20-timer";
reg = <0x60005000 0x400>;
--
2.1.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 6/9] DT: tegra: add binding for the legacy interrupt controller
2014-11-28 17:26 [PATCH 0/9] irqchip: gic: kill gic_arch_extn Marc Zyngier
` (4 preceding siblings ...)
2014-11-28 17:26 ` [PATCH 5/9] ARM: tegra: update DTs to expose legacy interrupt controller Marc Zyngier
@ 2014-11-28 17:26 ` Marc Zyngier
2014-11-28 17:26 ` [PATCH 7/9] ARM: tegra: remove old LIC support Marc Zyngier
` (3 subsequent siblings)
9 siblings, 0 replies; 12+ messages in thread
From: Marc Zyngier @ 2014-11-28 17:26 UTC (permalink / raw)
To: linux-arm-kernel
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
.../interrupt-controller/nvdia,tegra-ictlr.txt | 39 ++++++++++++++++++++++
1 file changed, 39 insertions(+)
create mode 100644 Documentation/devicetree/bindings/interrupt-controller/nvdia,tegra-ictlr.txt
diff --git a/Documentation/devicetree/bindings/interrupt-controller/nvdia,tegra-ictlr.txt b/Documentation/devicetree/bindings/interrupt-controller/nvdia,tegra-ictlr.txt
new file mode 100644
index 0000000..4de6a2c
--- /dev/null
+++ b/Documentation/devicetree/bindings/interrupt-controller/nvdia,tegra-ictlr.txt
@@ -0,0 +1,39 @@
+NVIDIA Legacy Interrupt Controller
+
+All Tegra SoCs contain a legacy interrupt controller that routes
+interrupts to the GIC, and also serves as a wakeup source. It is also
+refered to as "ictlr", hence the name of the binding.
+
+The HW block exposes a number of frames, each implementing a set of 32
+interrupts.
+
+Reguired properties:
+
+- compatible : should contain at least "nvidia,tegra-ictlr".
+- reg : Specifies base physical address and size of the registers.
+ Each frame must be described separately.
+- interrupt-controller : Identifies the node as an interrupt controller.
+- #interrupt-cells : Specifies the number of cells needed to encode an
+ interrupt source. The value must be 3.
+- interrupt-parent : a phandle to the GIC these interrupts are routed
+ to.
+
+Notes:
+
+- Because this HW ultimately routes interrupts to the GIC, the
+ interrupt specifier must be that of the GIC.
+- Only SPIs can use the ictlr as an interrupt parent. SGIs and PPIs
+ are excplicitely forbiden.
+
+Example:
+
+ ictlr: interrupt-controller at 60004000 {
+ compatible = "nvidia,tegra20-ictlr", "nvidia,tegra-ictlr";
+ reg = <0x60004000 64>,
+ <0x60004100 64>,
+ <0x60004200 64>,
+ <0x60004300 64>;
+ interrupt-controller;
+ #interrupt-cells = <3>;
+ interrupt-parent = <&intc>;
+ };
--
2.1.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 7/9] ARM: tegra: remove old LIC support
2014-11-28 17:26 [PATCH 0/9] irqchip: gic: kill gic_arch_extn Marc Zyngier
` (5 preceding siblings ...)
2014-11-28 17:26 ` [PATCH 6/9] DT: tegra: add binding for the " Marc Zyngier
@ 2014-11-28 17:26 ` Marc Zyngier
2014-12-01 18:14 ` Stephen Warren
2014-11-28 17:26 ` [PATCH 8/9] ARM: tegra: use DT to find the GIC distributor Marc Zyngier
` (2 subsequent siblings)
9 siblings, 1 reply; 12+ messages in thread
From: Marc Zyngier @ 2014-11-28 17:26 UTC (permalink / raw)
To: linux-arm-kernel
Now that all DTs have been updated, entierely drop support for
the non-DT code.
This is likely to break platforms that do not update their DT,
so print a warning at boot time.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/mach-tegra/iomap.h | 15 ----
arch/arm/mach-tegra/irq.c | 201 +-------------------------------------------
arch/arm/mach-tegra/irq.h | 6 --
3 files changed, 2 insertions(+), 220 deletions(-)
diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h
index ee79808..81dc950 100644
--- a/arch/arm/mach-tegra/iomap.h
+++ b/arch/arm/mach-tegra/iomap.h
@@ -31,21 +31,6 @@
#define TEGRA_ARM_INT_DIST_BASE 0x50041000
#define TEGRA_ARM_INT_DIST_SIZE SZ_4K
-#define TEGRA_PRIMARY_ICTLR_BASE 0x60004000
-#define TEGRA_PRIMARY_ICTLR_SIZE SZ_64
-
-#define TEGRA_SECONDARY_ICTLR_BASE 0x60004100
-#define TEGRA_SECONDARY_ICTLR_SIZE SZ_64
-
-#define TEGRA_TERTIARY_ICTLR_BASE 0x60004200
-#define TEGRA_TERTIARY_ICTLR_SIZE SZ_64
-
-#define TEGRA_QUATERNARY_ICTLR_BASE 0x60004300
-#define TEGRA_QUATERNARY_ICTLR_SIZE SZ_64
-
-#define TEGRA_QUINARY_ICTLR_BASE 0x60004400
-#define TEGRA_QUINARY_ICTLR_SIZE SZ_64
-
#define TEGRA_TMR1_BASE 0x60005000
#define TEGRA_TMR1_SIZE SZ_8
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index b37141d..a1befd3 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -30,43 +30,9 @@
#include "board.h"
#include "iomap.h"
-#define ICTLR_CPU_IEP_VFIQ 0x08
-#define ICTLR_CPU_IEP_FIR 0x14
-#define ICTLR_CPU_IEP_FIR_SET 0x18
-#define ICTLR_CPU_IEP_FIR_CLR 0x1c
-
-#define ICTLR_CPU_IER 0x20
-#define ICTLR_CPU_IER_SET 0x24
-#define ICTLR_CPU_IER_CLR 0x28
-#define ICTLR_CPU_IEP_CLASS 0x2C
-
-#define ICTLR_COP_IER 0x30
-#define ICTLR_COP_IER_SET 0x34
-#define ICTLR_COP_IER_CLR 0x38
-#define ICTLR_COP_IEP_CLASS 0x3c
-
-#define FIRST_LEGACY_IRQ 32
-#define TEGRA_MAX_NUM_ICTLRS 5
-
#define SGI_MASK 0xFFFF
-static int num_ictlrs;
-
-static void __iomem *ictlr_reg_base[] = {
- IO_ADDRESS(TEGRA_PRIMARY_ICTLR_BASE),
- IO_ADDRESS(TEGRA_SECONDARY_ICTLR_BASE),
- IO_ADDRESS(TEGRA_TERTIARY_ICTLR_BASE),
- IO_ADDRESS(TEGRA_QUATERNARY_ICTLR_BASE),
- IO_ADDRESS(TEGRA_QUINARY_ICTLR_BASE),
-};
-
#ifdef CONFIG_PM_SLEEP
-static u32 cop_ier[TEGRA_MAX_NUM_ICTLRS];
-static u32 cop_iep[TEGRA_MAX_NUM_ICTLRS];
-static u32 cpu_ier[TEGRA_MAX_NUM_ICTLRS];
-static u32 cpu_iep[TEGRA_MAX_NUM_ICTLRS];
-
-static u32 ictlr_wake_mask[TEGRA_MAX_NUM_ICTLRS];
static void __iomem *tegra_gic_cpu_base;
#endif
@@ -83,140 +49,7 @@ bool tegra_pending_sgi(void)
return false;
}
-static inline void tegra_irq_write_mask(unsigned int irq, unsigned long reg)
-{
- void __iomem *base;
- u32 mask;
-
- BUG_ON(irq < FIRST_LEGACY_IRQ ||
- irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32);
-
- base = ictlr_reg_base[(irq - FIRST_LEGACY_IRQ) / 32];
- mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);
-
- __raw_writel(mask, base + reg);
-}
-
-static void tegra_mask(struct irq_data *d)
-{
- if (d->hwirq < FIRST_LEGACY_IRQ)
- return;
-
- tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_CLR);
-}
-
-static void tegra_unmask(struct irq_data *d)
-{
- if (d->hwirq < FIRST_LEGACY_IRQ)
- return;
-
- tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IER_SET);
-}
-
-static void tegra_ack(struct irq_data *d)
-{
- if (d->hwirq < FIRST_LEGACY_IRQ)
- return;
-
- tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR);
-}
-
-static void tegra_eoi(struct irq_data *d)
-{
- if (d->hwirq < FIRST_LEGACY_IRQ)
- return;
-
- tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_CLR);
-}
-
-static int tegra_retrigger(struct irq_data *d)
-{
- if (d->hwirq < FIRST_LEGACY_IRQ)
- return 0;
-
- tegra_irq_write_mask(d->hwirq, ICTLR_CPU_IEP_FIR_SET);
-
- return 1;
-}
-
#ifdef CONFIG_PM_SLEEP
-static int tegra_set_wake(struct irq_data *d, unsigned int enable)
-{
- u32 irq = d->hwirq;
- u32 index, mask;
-
- if (irq < FIRST_LEGACY_IRQ ||
- irq >= FIRST_LEGACY_IRQ + num_ictlrs * 32)
- return -EINVAL;
-
- index = ((irq - FIRST_LEGACY_IRQ) / 32);
- mask = BIT((irq - FIRST_LEGACY_IRQ) % 32);
- if (enable)
- ictlr_wake_mask[index] |= mask;
- else
- ictlr_wake_mask[index] &= ~mask;
-
- return 0;
-}
-
-static int tegra_legacy_irq_suspend(void)
-{
- unsigned long flags;
- int i;
-
- local_irq_save(flags);
- for (i = 0; i < num_ictlrs; i++) {
- void __iomem *ictlr = ictlr_reg_base[i];
- /* Save interrupt state */
- cpu_ier[i] = readl_relaxed(ictlr + ICTLR_CPU_IER);
- cpu_iep[i] = readl_relaxed(ictlr + ICTLR_CPU_IEP_CLASS);
- cop_ier[i] = readl_relaxed(ictlr + ICTLR_COP_IER);
- cop_iep[i] = readl_relaxed(ictlr + ICTLR_COP_IEP_CLASS);
-
- /* Disable COP interrupts */
- writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
-
- /* Disable CPU interrupts */
- writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
-
- /* Enable the wakeup sources of ictlr */
- writel_relaxed(ictlr_wake_mask[i], ictlr + ICTLR_CPU_IER_SET);
- }
- local_irq_restore(flags);
-
- return 0;
-}
-
-static void tegra_legacy_irq_resume(void)
-{
- unsigned long flags;
- int i;
-
- local_irq_save(flags);
- for (i = 0; i < num_ictlrs; i++) {
- void __iomem *ictlr = ictlr_reg_base[i];
- writel_relaxed(cpu_iep[i], ictlr + ICTLR_CPU_IEP_CLASS);
- writel_relaxed(~0ul, ictlr + ICTLR_CPU_IER_CLR);
- writel_relaxed(cpu_ier[i], ictlr + ICTLR_CPU_IER_SET);
- writel_relaxed(cop_iep[i], ictlr + ICTLR_COP_IEP_CLASS);
- writel_relaxed(~0ul, ictlr + ICTLR_COP_IER_CLR);
- writel_relaxed(cop_ier[i], ictlr + ICTLR_COP_IER_SET);
- }
- local_irq_restore(flags);
-}
-
-static struct syscore_ops tegra_legacy_irq_syscore_ops = {
- .suspend = tegra_legacy_irq_suspend,
- .resume = tegra_legacy_irq_resume,
-};
-
-int tegra_legacy_irq_syscore_init(void)
-{
- register_syscore_ops(&tegra_legacy_irq_syscore_ops);
-
- return 0;
-}
-
static int tegra_gic_notifier(struct notifier_block *self,
unsigned long cmd, void *v)
{
@@ -251,7 +84,6 @@ static void tegra114_gic_cpu_pm_registration(void)
cpu_pm_register_notifier(&tegra_gic_notifier_block);
}
#else
-#define tegra_set_wake NULL
static void tegra114_gic_cpu_pm_registration(void) { }
#endif
@@ -262,37 +94,8 @@ static const struct of_device_id tegra_ictlr_match[] __initconst = {
void __init tegra_init_irq(void)
{
- int i;
- void __iomem *distbase;
-
- if (of_find_matching_node(NULL, tegra_ictlr_match))
- goto skip_extn_setup;
-
- tegra_legacy_irq_syscore_init();
-
- distbase = IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE);
- num_ictlrs = readl_relaxed(distbase + GIC_DIST_CTR) & 0x1f;
-
- if (num_ictlrs > ARRAY_SIZE(ictlr_reg_base)) {
- WARN(1, "Too many (%d) interrupt controllers found. Maximum is %d.",
- num_ictlrs, ARRAY_SIZE(ictlr_reg_base));
- num_ictlrs = ARRAY_SIZE(ictlr_reg_base);
- }
-
- for (i = 0; i < num_ictlrs; i++) {
- void __iomem *ictlr = ictlr_reg_base[i];
- writel(~0, ictlr + ICTLR_CPU_IER_CLR);
- writel(0, ictlr + ICTLR_CPU_IEP_CLASS);
- }
-
- gic_arch_extn.irq_ack = tegra_ack;
- gic_arch_extn.irq_eoi = tegra_eoi;
- gic_arch_extn.irq_mask = tegra_mask;
- gic_arch_extn.irq_unmask = tegra_unmask;
- gic_arch_extn.irq_retrigger = tegra_retrigger;
- gic_arch_extn.irq_set_wake = tegra_set_wake;
- gic_arch_extn.flags = IRQCHIP_MASK_ON_SUSPEND;
+ if (!of_find_matching_node(NULL, tegra_ictlr_match))
+ pr_warn("Outdated DT detected, suspend/resume will NOT work\n");
-skip_extn_setup:
tegra114_gic_cpu_pm_registration();
}
diff --git a/arch/arm/mach-tegra/irq.h b/arch/arm/mach-tegra/irq.h
index bc05ce5..5142649 100644
--- a/arch/arm/mach-tegra/irq.h
+++ b/arch/arm/mach-tegra/irq.h
@@ -19,10 +19,4 @@
bool tegra_pending_sgi(void);
-#ifdef CONFIG_PM_SLEEP
-int tegra_legacy_irq_syscore_init(void);
-#else
-static inline int tegra_legacy_irq_syscore_init(void) { return 0; }
-#endif
-
#endif
--
2.1.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 8/9] ARM: tegra: use DT to find the GIC distributor
2014-11-28 17:26 [PATCH 0/9] irqchip: gic: kill gic_arch_extn Marc Zyngier
` (6 preceding siblings ...)
2014-11-28 17:26 ` [PATCH 7/9] ARM: tegra: remove old LIC support Marc Zyngier
@ 2014-11-28 17:26 ` Marc Zyngier
2014-11-28 17:26 ` [PATCH 9/9] irqchip: gic: Drop support for gic_arch_extn Marc Zyngier
2014-11-28 17:52 ` [PATCH 0/9] irqchip: gic: kill gic_arch_extn Marc Zyngier
9 siblings, 0 replies; 12+ messages in thread
From: Marc Zyngier @ 2014-11-28 17:26 UTC (permalink / raw)
To: linux-arm-kernel
Tegra likes to peek at the distributor to find out if SGIs are
pending. This looks odd, but I'm sure there's a good reason.
But instead of hardcoding everything, let's use the DT instead.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
arch/arm/mach-tegra/iomap.h | 3 ---
arch/arm/mach-tegra/irq.c | 20 +++++++++++++++++++-
2 files changed, 19 insertions(+), 4 deletions(-)
diff --git a/arch/arm/mach-tegra/iomap.h b/arch/arm/mach-tegra/iomap.h
index 81dc950..52bbb5c 100644
--- a/arch/arm/mach-tegra/iomap.h
+++ b/arch/arm/mach-tegra/iomap.h
@@ -28,9 +28,6 @@
#define TEGRA_ARM_PERIF_BASE 0x50040000
#define TEGRA_ARM_PERIF_SIZE SZ_8K
-#define TEGRA_ARM_INT_DIST_BASE 0x50041000
-#define TEGRA_ARM_INT_DIST_SIZE SZ_4K
-
#define TEGRA_TMR1_BASE 0x60005000
#define TEGRA_TMR1_SIZE SZ_8
diff --git a/arch/arm/mach-tegra/irq.c b/arch/arm/mach-tegra/irq.c
index a1befd3..37b17d5 100644
--- a/arch/arm/mach-tegra/irq.c
+++ b/arch/arm/mach-tegra/irq.c
@@ -36,10 +36,28 @@
static void __iomem *tegra_gic_cpu_base;
#endif
+static const struct of_device_id dt_gic_match[] __initconst = {
+ { .compatible = "arm,cortex-a9-gic" },
+ { .compatible = "arm,cortex-a15-gic" },
+ { }
+};
+
bool tegra_pending_sgi(void)
{
u32 pending_set;
- void __iomem *distbase = IO_ADDRESS(TEGRA_ARM_INT_DIST_BASE);
+ static void __iomem *distbase;
+
+ if (unlikely(!distbase)) {
+ struct device_node *dn;
+
+ dn = of_find_matching_node(NULL, dt_gic_match);
+ if (WARN_ONCE(!dn, "No GIC node????\n"))
+ return false;
+
+ distbase = of_iomap(dn, 0);
+ if (WARN_ONCE(!distbase, "Unable to map distributor????\n"))
+ return false;
+ }
pending_set = readl_relaxed(distbase + GIC_DIST_PENDING_SET);
--
2.1.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 9/9] irqchip: gic: Drop support for gic_arch_extn
2014-11-28 17:26 [PATCH 0/9] irqchip: gic: kill gic_arch_extn Marc Zyngier
` (7 preceding siblings ...)
2014-11-28 17:26 ` [PATCH 8/9] ARM: tegra: use DT to find the GIC distributor Marc Zyngier
@ 2014-11-28 17:26 ` Marc Zyngier
2014-11-28 17:52 ` [PATCH 0/9] irqchip: gic: kill gic_arch_extn Marc Zyngier
9 siblings, 0 replies; 12+ messages in thread
From: Marc Zyngier @ 2014-11-28 17:26 UTC (permalink / raw)
To: linux-arm-kernel
Now that the only user of gic_arch_extn has been fixed, drop the
"feature" for good. This leads to the removal of some now useless
locking.
Signed-off-by: Marc Zyngier <marc.zyngier@arm.com>
---
drivers/irqchip/irq-gic.c | 46 +----------------------------------------
include/linux/irqchip/arm-gic.h | 2 --
2 files changed, 1 insertion(+), 47 deletions(-)
diff --git a/drivers/irqchip/irq-gic.c b/drivers/irqchip/irq-gic.c
index 5a71be7..663dca9 100644
--- a/drivers/irqchip/irq-gic.c
+++ b/drivers/irqchip/irq-gic.c
@@ -80,19 +80,6 @@ static DEFINE_RAW_SPINLOCK(irq_controller_lock);
#define NR_GIC_CPU_IF 8
static u8 gic_cpu_map[NR_GIC_CPU_IF] __read_mostly;
-/*
- * Supported arch specific GIC irq extension.
- * Default make them NULL.
- */
-struct irq_chip gic_arch_extn = {
- .irq_eoi = NULL,
- .irq_mask = NULL,
- .irq_unmask = NULL,
- .irq_retrigger = NULL,
- .irq_set_type = NULL,
- .irq_set_wake = NULL,
-};
-
#ifndef MAX_GIC_NR
#define MAX_GIC_NR 1
#endif
@@ -155,32 +142,18 @@ static void gic_mask_irq(struct irq_data *d)
{
u32 mask = 1 << (gic_irq(d) % 32);
- raw_spin_lock(&irq_controller_lock);
writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_CLEAR + (gic_irq(d) / 32) * 4);
- if (gic_arch_extn.irq_mask)
- gic_arch_extn.irq_mask(d);
- raw_spin_unlock(&irq_controller_lock);
}
static void gic_unmask_irq(struct irq_data *d)
{
u32 mask = 1 << (gic_irq(d) % 32);
- raw_spin_lock(&irq_controller_lock);
- if (gic_arch_extn.irq_unmask)
- gic_arch_extn.irq_unmask(d);
writel_relaxed(mask, gic_dist_base(d) + GIC_DIST_ENABLE_SET + (gic_irq(d) / 32) * 4);
- raw_spin_unlock(&irq_controller_lock);
}
static void gic_eoi_irq(struct irq_data *d)
{
- if (gic_arch_extn.irq_eoi) {
- raw_spin_lock(&irq_controller_lock);
- gic_arch_extn.irq_eoi(d);
- raw_spin_unlock(&irq_controller_lock);
- }
-
writel_relaxed(gic_irq(d), gic_cpu_base(d) + GIC_CPU_EOI);
}
@@ -196,23 +169,13 @@ static int gic_set_type(struct irq_data *d, unsigned int type)
if (type != IRQ_TYPE_LEVEL_HIGH && type != IRQ_TYPE_EDGE_RISING)
return -EINVAL;
- raw_spin_lock(&irq_controller_lock);
-
- if (gic_arch_extn.irq_set_type)
- gic_arch_extn.irq_set_type(d, type);
-
gic_configure_irq(gicirq, type, base, NULL);
- raw_spin_unlock(&irq_controller_lock);
-
return 0;
}
static int gic_retrigger(struct irq_data *d)
{
- if (gic_arch_extn.irq_retrigger)
- return gic_arch_extn.irq_retrigger(d);
-
/* the genirq layer expects 0 if we can't retrigger in hardware */
return 0;
}
@@ -247,14 +210,8 @@ static int gic_set_affinity(struct irq_data *d, const struct cpumask *mask_val,
#ifdef CONFIG_PM
static int gic_set_wake(struct irq_data *d, unsigned int on)
{
- int ret = -ENXIO;
-
- if (gic_arch_extn.irq_set_wake)
- ret = gic_arch_extn.irq_set_wake(d, on);
-
- return ret;
+ return -ENXIO;
}
-
#else
#define gic_set_wake NULL
#endif
@@ -1029,7 +986,6 @@ void __init gic_init_bases(unsigned int gic_nr, int irq_start,
set_handle_irq(gic_handle_irq);
}
- gic_chip.flags |= gic_arch_extn.flags;
gic_dist_init(gic);
gic_cpu_init(gic);
gic_pm_init(gic);
diff --git a/include/linux/irqchip/arm-gic.h b/include/linux/irqchip/arm-gic.h
index 60b09ed..1911f06 100644
--- a/include/linux/irqchip/arm-gic.h
+++ b/include/linux/irqchip/arm-gic.h
@@ -93,8 +93,6 @@
struct device_node;
-extern struct irq_chip gic_arch_extn;
-
void gic_init_bases(unsigned int, int, void __iomem *, void __iomem *,
u32 offset, struct device_node *);
void gic_cascade_irq(unsigned int gic_nr, unsigned int irq);
--
2.1.3
^ permalink raw reply related [flat|nested] 12+ messages in thread
* [PATCH 0/9] irqchip: gic: kill gic_arch_extn
2014-11-28 17:26 [PATCH 0/9] irqchip: gic: kill gic_arch_extn Marc Zyngier
` (8 preceding siblings ...)
2014-11-28 17:26 ` [PATCH 9/9] irqchip: gic: Drop support for gic_arch_extn Marc Zyngier
@ 2014-11-28 17:52 ` Marc Zyngier
9 siblings, 0 replies; 12+ messages in thread
From: Marc Zyngier @ 2014-11-28 17:52 UTC (permalink / raw)
To: linux-arm-kernel
On 28/11/14 17:26, Marc Zyngier wrote:
> The gic_arch_extn hack that Tegra uses has been nagging me for too
> long. It is only there for the benefit of a single platform, and yet
> it impacts all GIC users. Moreover, it gives people the wrong idea
> ("let's use it to put some new custom hack in there"...).
Of course, just after sending this I realised that quite a lot of
platform are now using this crap:
arch/arm/mach-exynos/pm.c
arch/arm/mach-imx/gpc.c
arch/arm/mach-omap2/omap-wakeupgen.c
arch/arm/mach-shmobile/intc-sh73a0.c
arch/arm/mach-shmobile/setup-r8a7779.c
arch/arm/mach-ux500/cpu.c
arch/arm/mach-zynq/common.c
Yes, I intend to address them as well...
Thanks,
M.
--
Jazz is not dead. It just smells funny...
^ permalink raw reply [flat|nested] 12+ messages in thread
* [PATCH 7/9] ARM: tegra: remove old LIC support
2014-11-28 17:26 ` [PATCH 7/9] ARM: tegra: remove old LIC support Marc Zyngier
@ 2014-12-01 18:14 ` Stephen Warren
0 siblings, 0 replies; 12+ messages in thread
From: Stephen Warren @ 2014-12-01 18:14 UTC (permalink / raw)
To: linux-arm-kernel
On 11/28/2014 10:26 AM, Marc Zyngier wrote:
> Now that all DTs have been updated, entierely drop support for
> the non-DT code.
>
> This is likely to break platforms that do not update their DT,
> so print a warning at boot time.
That seems to imply that yet again we're ignoring DT-is-an-ABI...
^ permalink raw reply [flat|nested] 12+ messages in thread
end of thread, other threads:[~2014-12-01 18:14 UTC | newest]
Thread overview: 12+ messages (download: mbox.gz follow: Atom feed
-- links below jump to the message on this page --
2014-11-28 17:26 [PATCH 0/9] irqchip: gic: kill gic_arch_extn Marc Zyngier
2014-11-28 17:26 ` [PATCH 1/9] ARM: tegra: irq: fix buggy usage of irq_data irq field Marc Zyngier
2014-11-28 17:26 ` [PATCH 2/9] ARM: tegra: irq: nuke leftovers from non-DT support Marc Zyngier
2014-11-28 17:26 ` [PATCH 3/9] irqchip: tegra: add DT-based support for legacy interrupt controller Marc Zyngier
2014-11-28 17:26 ` [PATCH 4/9] ARM: tegra: skip gic_arch_extn setup if DT has a LIC node Marc Zyngier
2014-11-28 17:26 ` [PATCH 5/9] ARM: tegra: update DTs to expose legacy interrupt controller Marc Zyngier
2014-11-28 17:26 ` [PATCH 6/9] DT: tegra: add binding for the " Marc Zyngier
2014-11-28 17:26 ` [PATCH 7/9] ARM: tegra: remove old LIC support Marc Zyngier
2014-12-01 18:14 ` Stephen Warren
2014-11-28 17:26 ` [PATCH 8/9] ARM: tegra: use DT to find the GIC distributor Marc Zyngier
2014-11-28 17:26 ` [PATCH 9/9] irqchip: gic: Drop support for gic_arch_extn Marc Zyngier
2014-11-28 17:52 ` [PATCH 0/9] irqchip: gic: kill gic_arch_extn Marc Zyngier
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).