|
@@ -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 */
|