summaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorMeador Inge <meador_inge@mentor.com>2011-03-14 11:01:06 +0100
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-03-21 01:01:32 +0100
commitdfec2202729e2460d67649a04756f0c3d8dcd8a6 (patch)
tree276d05c28bb7b1f8c170b118a6e81c37e86ea6fb /arch
parentpowerpc: Document the Open PIC device tree binding (diff)
downloadlinux-dfec2202729e2460d67649a04756f0c3d8dcd8a6.tar.xz
linux-dfec2202729e2460d67649a04756f0c3d8dcd8a6.zip
powerpc: Make MPIC honor the "pic-no-reset" device tree property
This property, defined in the Open PIC binding, tells the kernel not to use the reset bit in the global configuration register. Additionally, its presence mandates that only sources which are actually used (i.e. appear in the device tree) should have their VECPRI bits initialized. Although, "pic-no-reset" can be used for the same use cases that "protected-sources" is covering, the "protected-sources" implementation was left completely intact. This is a more pragmatic approach as there are already several existing systems which use protected sources. If "pic-no-reset" *and* "protected-sources" are both used, however, then "pic-no-reset" takes precedence in terms of the init behavior and the sanity checks done by protected sources will still take place. Signed-off-by: Meador Inge <meador_inge@mentor.com> Cc: Hollis Blanchard <hollis_blanchard@mentor.com> Cc: Benjamin Herrenschmidt <benh@kernel.crashing.org> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/include/asm/mpic.h4
-rw-r--r--arch/powerpc/sysdev/mpic.c66
2 files changed, 59 insertions, 11 deletions
diff --git a/arch/powerpc/include/asm/mpic.h b/arch/powerpc/include/asm/mpic.h
index 946ec4947da2..7005ee0b074d 100644
--- a/arch/powerpc/include/asm/mpic.h
+++ b/arch/powerpc/include/asm/mpic.h
@@ -367,6 +367,10 @@ struct mpic
#define MPIC_SINGLE_DEST_CPU 0x00001000
/* Enable CoreInt delivery of interrupts */
#define MPIC_ENABLE_COREINT 0x00002000
+/* Disable resetting of the MPIC.
+ * NOTE: This flag trumps MPIC_WANTS_RESET.
+ */
+#define MPIC_NO_RESET 0x00004000
/* MPIC HW modification ID */
#define MPIC_REGSET_MASK 0xf0000000
diff --git a/arch/powerpc/sysdev/mpic.c b/arch/powerpc/sysdev/mpic.c
index eb7021815e2d..3bf71035ff50 100644
--- a/arch/powerpc/sysdev/mpic.c
+++ b/arch/powerpc/sysdev/mpic.c
@@ -913,6 +913,20 @@ void mpic_set_vector(unsigned int virq, unsigned int vector)
mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
}
+void mpic_set_destination(unsigned int virq, unsigned int cpuid)
+{
+ struct mpic *mpic = mpic_from_irq(virq);
+ unsigned int src = mpic_irq_to_hw(virq);
+
+ DBG("mpic: set_destination(mpic:@%p,virq:%d,src:%d,cpuid:0x%x)\n",
+ mpic, virq, src, cpuid);
+
+ if (src >= mpic->irq_count)
+ return;
+
+ mpic_irq_write(src, MPIC_INFO(IRQ_DESTINATION), 1 << cpuid);
+}
+
static struct irq_chip mpic_irq_chip = {
.irq_mask = mpic_mask_irq,
.irq_unmask = mpic_unmask_irq,
@@ -993,6 +1007,21 @@ static int mpic_host_map(struct irq_host *h, unsigned int virq,
/* Set default irq type */
set_irq_type(virq, IRQ_TYPE_NONE);
+ /* If the MPIC was reset, then all vectors have already been
+ * initialized. Otherwise, a per source lazy initialization
+ * is done here.
+ */
+ if (!mpic_is_ipi(mpic, hw) && (mpic->flags & MPIC_NO_RESET)) {
+ unsigned int cpu = 0;
+
+ if (mpic->flags & MPIC_PRIMARY)
+ cpu = hard_smp_processor_id();
+
+ mpic_set_vector(virq, hw);
+ mpic_set_destination(virq, cpu);
+ mpic_irq_set_priority(virq, 8);
+ }
+
return 0;
}
@@ -1040,6 +1069,11 @@ static struct irq_host_ops mpic_host_ops = {
.xlate = mpic_host_xlate,
};
+static int mpic_reset_prohibited(struct device_node *node)
+{
+ return node && of_get_property(node, "pic-no-reset", NULL);
+}
+
/*
* Exported functions
*/
@@ -1160,7 +1194,15 @@ struct mpic * __init mpic_alloc(struct device_node *node,
mpic_map(mpic, node, paddr, &mpic->tmregs, MPIC_INFO(TIMER_BASE), 0x1000);
/* Reset */
- if (flags & MPIC_WANTS_RESET) {
+
+ /* When using a device-node, reset requests are only honored if the MPIC
+ * is allowed to reset.
+ */
+ if (mpic_reset_prohibited(node))
+ mpic->flags |= MPIC_NO_RESET;
+
+ if ((flags & MPIC_WANTS_RESET) && !(mpic->flags & MPIC_NO_RESET)) {
+ printk(KERN_DEBUG "mpic: Resetting\n");
mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
| MPIC_GREG_GCONF_RESET);
@@ -1325,17 +1367,19 @@ void __init mpic_init(struct mpic *mpic)
else
cpu = 0;
- for (i = 0; i < mpic->num_sources; i++) {
- /* start with vector = source number, and masked */
- u32 vecpri = MPIC_VECPRI_MASK | i |
- (8 << MPIC_VECPRI_PRIORITY_SHIFT);
+ if (!(mpic->flags & MPIC_NO_RESET)) {
+ for (i = 0; i < mpic->num_sources; i++) {
+ /* start with vector = source number, and masked */
+ u32 vecpri = MPIC_VECPRI_MASK | i |
+ (8 << MPIC_VECPRI_PRIORITY_SHIFT);
- /* check if protected */
- if (mpic->protected && test_bit(i, mpic->protected))
- continue;
- /* init hw */
- mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
- mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
+ /* check if protected */
+ if (mpic->protected && test_bit(i, mpic->protected))
+ continue;
+ /* init hw */
+ mpic_irq_write(i, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
+ mpic_irq_write(i, MPIC_INFO(IRQ_DESTINATION), 1 << cpu);
+ }
}
/* Init spurious vector */