summaryrefslogtreecommitdiffstats
path: root/arch/arm/mach-davinci/cp_intc.c
diff options
context:
space:
mode:
authorBartosz Golaszewski <bgolaszewski@baylibre.com>2019-02-14 15:51:58 +0100
committerSekhar Nori <nsekhar@ti.com>2019-02-19 15:10:30 +0100
commitd0064594f20a9d46ac55af02139c7022971ea8fd (patch)
treee9b9a64701b46fb8af132a4a4d5a0f05d08a8515 /arch/arm/mach-davinci/cp_intc.c
parentARM: davinci: aintc: use irq domain (diff)
downloadlinux-d0064594f20a9d46ac55af02139c7022971ea8fd.tar.xz
linux-d0064594f20a9d46ac55af02139c7022971ea8fd.zip
ARM: davinci: select GENERIC_IRQ_MULTI_HANDLER
In order to support SPARSE_IRQ we first need to make davinci use the generic irq handler for ARM. Translate the legacy assembly to C and put the irq handlers into their respective drivers (aintc and cp-intc). Signed-off-by: Bartosz Golaszewski <bgolaszewski@baylibre.com> Signed-off-by: Sekhar Nori <nsekhar@ti.com>
Diffstat (limited to 'arch/arm/mach-davinci/cp_intc.c')
-rw-r--r--arch/arm/mach-davinci/cp_intc.c28
1 files changed, 28 insertions, 0 deletions
diff --git a/arch/arm/mach-davinci/cp_intc.c b/arch/arm/mach-davinci/cp_intc.c
index 67805ca74ff8..4a372add8cf9 100644
--- a/arch/arm/mach-davinci/cp_intc.c
+++ b/arch/arm/mach-davinci/cp_intc.c
@@ -19,9 +19,13 @@
#include <linux/of_address.h>
#include <linux/of_irq.h>
+#include <asm/exception.h>
#include <mach/common.h>
#include "cp_intc.h"
+#define DAVINCI_CP_INTC_PRI_INDX_MASK GENMASK(9, 0)
+#define DAVINCI_CP_INTC_GPIR_NONE BIT(31)
+
static inline unsigned int cp_intc_read(unsigned offset)
{
return __raw_readl(davinci_intc_base + offset);
@@ -97,6 +101,28 @@ static struct irq_chip cp_intc_irq_chip = {
static struct irq_domain *cp_intc_domain;
+static asmlinkage void __exception_irq_entry
+cp_intc_handle_irq(struct pt_regs *regs)
+{
+ int gpir, irqnr, none;
+
+ /*
+ * The interrupt number is in first ten bits. The NONE field set to 1
+ * indicates a spurious irq.
+ */
+
+ gpir = cp_intc_read(CP_INTC_PRIO_IDX);
+ irqnr = gpir & DAVINCI_CP_INTC_PRI_INDX_MASK;
+ none = gpir & DAVINCI_CP_INTC_GPIR_NONE;
+
+ if (unlikely(none)) {
+ pr_err_once("%s: spurious irq!\n", __func__);
+ return;
+ }
+
+ handle_domain_irq(cp_intc_domain, irqnr, regs);
+}
+
static int cp_intc_host_map(struct irq_domain *h, unsigned int virq,
irq_hw_number_t hw)
{
@@ -196,6 +222,8 @@ int __init cp_intc_of_init(struct device_node *node, struct device_node *parent)
return -EINVAL;
}
+ set_handle_irq(cp_intc_handle_irq);
+
/* Enable global interrupt */
cp_intc_write(1, CP_INTC_GLOBAL_ENABLE);