aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorStefano Stabellini <stefano.stabellini@eu.citrix.com>2012-02-09 11:33:30 +0000
committerStefano Stabellini <stefano.stabellini@eu.citrix.com>2012-02-09 11:33:30 +0000
commit666bf69521d9622e674a5c6277acc7b7c9128bbd (patch)
tree9c482fb7c47f03f63555ea1897e8b6868d2f5301
parenta5dcd99502c0d2343fe75989522d71bebae0053a (diff)
downloadxen-666bf69521d9622e674a5c6277acc7b7c9128bbd.tar.gz
xen-666bf69521d9622e674a5c6277acc7b7c9128bbd.tar.bz2
xen-666bf69521d9622e674a5c6277acc7b7c9128bbd.zip
arm: irq
A simple do_IRQ and request_irq implementation for ARM. Signed-off-by: Stefano Stabellini <stefano.stabellini@eu.citrix.com> Signed-off-by: Ian Campbell <ian.campbell@citrix.com> Signed-off-by: Tim Deegan <Tim.Deegan@citrix.com> Committed-by: Ian Campbell <ian.campbell@citrix.com>
-rw-r--r--xen/arch/arm/irq.c179
-rw-r--r--xen/include/asm-arm/irq.h30
-rw-r--r--xen/include/asm-arm/setup.h2
-rw-r--r--xen/include/xen/irq.h13
4 files changed, 224 insertions, 0 deletions
diff --git a/xen/arch/arm/irq.c b/xen/arch/arm/irq.c
new file mode 100644
index 0000000000..17c939c35e
--- /dev/null
+++ b/xen/arch/arm/irq.c
@@ -0,0 +1,179 @@
+/*
+ * xen/arch/arm/irq.c
+ *
+ * ARM Interrupt support
+ *
+ * Ian Campbell <ian.campbell@citrix.com>
+ * Copyright (c) 2011 Citrix Systems.
+ *
+ * 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.
+ *
+ * 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 <xen/config.h>
+#include <xen/lib.h>
+#include <xen/spinlock.h>
+#include <xen/irq.h>
+#include <xen/init.h>
+#include <xen/errno.h>
+#include <xen/sched.h>
+
+#include "gic.h"
+
+static void enable_none(struct irq_desc *irq) { }
+static unsigned int startup_none(struct irq_desc *irq) { return 0; }
+static void disable_none(struct irq_desc *irq) { }
+static void ack_none(struct irq_desc *irq)
+{
+ printk("unexpected IRQ trap at irq %02x\n", irq->irq);
+}
+
+#define shutdown_none disable_none
+#define end_none enable_none
+
+hw_irq_controller no_irq_type = {
+ .typename = "none",
+ .startup = startup_none,
+ .shutdown = shutdown_none,
+ .enable = enable_none,
+ .disable = disable_none,
+ .ack = ack_none,
+ .end = end_none
+};
+
+int __init arch_init_one_irq_desc(struct irq_desc *desc)
+{
+ return 0;
+}
+
+
+static int __init init_irq_data(void)
+{
+ int irq;
+
+ for (irq = 0; irq < NR_IRQS; irq++) {
+ struct irq_desc *desc = irq_to_desc(irq);
+ init_one_irq_desc(desc);
+ desc->irq = irq;
+ desc->action = NULL;
+ }
+ return 0;
+}
+
+void __init init_IRQ(void)
+{
+ BUG_ON(init_irq_data() < 0);
+}
+
+int __init request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct cpu_user_regs *),
+ unsigned long irqflags, const char * devname, void *dev_id)
+{
+ struct irqaction *action;
+ int retval;
+
+ /*
+ * Sanity-check: shared interrupts must pass in a real dev-ID,
+ * otherwise we'll have trouble later trying to figure out
+ * which interrupt is which (messes up the interrupt freeing
+ * logic etc).
+ */
+ if (irq >= nr_irqs)
+ return -EINVAL;
+ if (!handler)
+ return -EINVAL;
+
+ action = xmalloc(struct irqaction);
+ if (!action)
+ return -ENOMEM;
+
+ action->handler = handler;
+ action->name = devname;
+ action->dev_id = dev_id;
+ action->free_on_release = 1;
+
+ retval = setup_irq(irq, action);
+ if (retval)
+ xfree(action);
+
+ return retval;
+}
+
+/* Dispatch an interrupt */
+void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq)
+{
+ struct irq_desc *desc = irq_to_desc(irq);
+ struct irqaction *action = desc->action;
+
+ /* TODO: perfc_incr(irqs); */
+
+ /* TODO: this_cpu(irq_count)++; */
+
+ irq_enter();
+
+ spin_lock(&desc->lock);
+ desc->handler->ack(desc);
+
+ if ( action == NULL )
+ {
+ printk("Unknown %s %#3.3x\n",
+ is_fiq ? "FIQ" : "IRQ", irq);
+ goto out;
+ }
+
+ if ( desc->status & IRQ_GUEST )
+ {
+ struct domain *d = action->dev_id;
+
+ desc->handler->end(desc);
+
+ desc->status |= IRQ_INPROGRESS;
+
+ /* XXX: inject irq into the guest */
+ goto out_no_end;
+ }
+
+ desc->status |= IRQ_PENDING;
+
+ /*
+ * Since we set PENDING, if another processor is handling a different
+ * instance of this same irq, the other processor will take care of it.
+ */
+ if ( desc->status & (IRQ_DISABLED | IRQ_INPROGRESS) )
+ goto out;
+
+ desc->status |= IRQ_INPROGRESS;
+
+ action = desc->action;
+ while ( desc->status & IRQ_PENDING )
+ {
+ desc->status &= ~IRQ_PENDING;
+ spin_unlock_irq(&desc->lock);
+ action->handler(irq, action->dev_id, regs);
+ spin_lock_irq(&desc->lock);
+ }
+
+ desc->status &= ~IRQ_INPROGRESS;
+
+out:
+ desc->handler->end(desc);
+out_no_end:
+ spin_unlock(&desc->lock);
+ irq_exit();
+}
+
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/irq.h b/xen/include/asm-arm/irq.h
new file mode 100644
index 0000000000..8e65a2e499
--- /dev/null
+++ b/xen/include/asm-arm/irq.h
@@ -0,0 +1,30 @@
+#ifndef _ASM_HW_IRQ_H
+#define _ASM_HW_IRQ_H
+
+#include <xen/config.h>
+
+#define NR_VECTORS 256 /* XXX */
+
+typedef struct {
+ DECLARE_BITMAP(_bits,NR_VECTORS);
+} vmask_t;
+
+struct arch_pirq
+{
+};
+
+struct irq_cfg {
+#define arch_irq_desc irq_cfg
+};
+
+void do_IRQ(struct cpu_user_regs *regs, unsigned int irq, int is_fiq);
+
+#endif /* _ASM_HW_IRQ_H */
+/*
+ * Local variables:
+ * mode: C
+ * c-set-style: "BSD"
+ * c-basic-offset: 4
+ * indent-tabs-mode: nil
+ * End:
+ */
diff --git a/xen/include/asm-arm/setup.h b/xen/include/asm-arm/setup.h
index 1dc3f972a8..2041f068db 100644
--- a/xen/include/asm-arm/setup.h
+++ b/xen/include/asm-arm/setup.h
@@ -7,6 +7,8 @@ void arch_get_xen_caps(xen_capabilities_info_t *info);
int construct_dom0(struct domain *d);
+void init_IRQ(void);
+
#endif
/*
* Local variables:
diff --git a/xen/include/xen/irq.h b/xen/include/xen/irq.h
index 7afc64ab26..61a155967a 100644
--- a/xen/include/xen/irq.h
+++ b/xen/include/xen/irq.h
@@ -106,6 +106,19 @@ extern irq_desc_t irq_desc[NR_VECTORS];
#define request_irq(irq, handler, irqflags, devname, devid) \
request_irq_vector(irq_to_vector(irq), handler, irqflags, devname, devid)
+
+#elif defined(__arm__)
+
+#define NR_IRQS 1024
+#define nr_irqs NR_IRQS
+extern irq_desc_t irq_desc[NR_IRQS];
+
+extern int setup_irq(unsigned int irq, struct irqaction *);
+extern void release_irq(unsigned int irq);
+extern int request_irq(unsigned int irq,
+ void (*handler)(int, void *, struct cpu_user_regs *),
+ unsigned long irqflags, const char * devname, void *dev_id);
+
#else
extern int setup_irq(unsigned int irq, struct irqaction *);
extern void release_irq(unsigned int irq);