/* * Shared interrupt handling code for IPR and INTC2 types of IRQs. * * Copyright (C) 2007, 2008 Magnus Damm * Copyright (C) 2009 - 2012 Paul Mundt * * Based on intc2.c and ipr.c * * Copyright (C) 1999 Niibe Yutaka & Takeshi Yaegashi * Copyright (C) 2000 Kazumoto Kojima * Copyright (C) 2001 David J. Mckay (david.mckay@st.com) * Copyright (C) 2003 Takashi Kusuda <kusuda-takashi@hitachi-ul.co.jp> * Copyright (C) 2005, 2006 Paul Mundt * * This file is subject to the terms and conditions of the GNU General Public * License. See the file "COPYING" in the main directory of this archive * for more details.
*/ #define pr_fmt(fmt) "intc: " fmt
/* * Default priority level * - this needs to be at least 2 for 5-bit priorities on 7780
*/ staticunsignedint default_prio_level = 2; /* 2 - 16 */ staticunsignedint intc_prio_level[INTC_NR_IRQS]; /* for now */
/* * set priority level
*/
intc_set_prio_level(irq, intc_get_dfl_prio_level());
/* enable secondary masking method if present */ if (data[!primary])
_intc_enable(irq_data, data[!primary]);
/* add irq to d->prio list if priority is available */ if (data[1]) {
hp = d->prio + d->nr_prio;
hp->irq = irq;
hp->handle = data[1];
if (primary) { /* * only secondary priority should access registers, so * set _INTC_FN(h) = REG_FN_ERR for intc_set_priority()
*/
hp->handle &= ~_INTC_MK(0x0f, 0, 0, 0, 0, 0);
hp->handle |= _INTC_MK(REG_FN_ERR, 0, 0, 0, 0, 0);
}
d->nr_prio++;
}
/* add irq to d->sense list if sense is available */
data[0] = intc_get_sense_handle(desc, d, enum_id); if (data[0]) {
(d->sense + d->nr_sense)->irq = irq;
(d->sense + d->nr_sense)->handle = data[0];
d->nr_sense++;
}
/* irq should be disabled by default */
d->chip.irq_mask(irq_data);
d->reg = kcalloc(d->nr_reg, sizeof(*d->reg), GFP_NOWAIT); if (!d->reg) goto err2;
#ifdef CONFIG_SMP
d->smp = kcalloc(d->nr_reg, sizeof(*d->smp), GFP_NOWAIT); if (!d->smp) goto err3; #endif
k = 0;
if (hw->mask_regs) { for (i = 0; i < hw->nr_mask_regs; i++) {
smp = IS_SMP(hw->mask_regs[i]);
k += save_reg(d, k, hw->mask_regs[i].set_reg, smp);
k += save_reg(d, k, hw->mask_regs[i].clr_reg, smp); #ifdef CONFIG_INTC_BALANCING
k += save_reg(d, k, hw->mask_regs[i].dist_reg, 0); #endif
}
}
if (hw->prio_regs) {
d->prio = kcalloc(hw->nr_vectors, sizeof(*d->prio),
GFP_NOWAIT); if (!d->prio) goto err4;
for (i = 0; i < hw->nr_prio_regs; i++) {
smp = IS_SMP(hw->prio_regs[i]);
k += save_reg(d, k, hw->prio_regs[i].set_reg, smp);
k += save_reg(d, k, hw->prio_regs[i].clr_reg, smp);
}
if (hw->ack_regs) for (i = 0; i < hw->nr_ack_regs; i++)
k += save_reg(d, k, hw->ack_regs[i].set_reg, 0); else
d->chip.irq_mask_ack = d->chip.irq_disable;
/* disable bits matching force_disable before registering irqs */ if (desc->force_disable)
intc_enable_disable_enum(desc, d, desc->force_disable, 0);
/* disable bits matching force_enable before registering irqs */ if (desc->force_enable)
intc_enable_disable_enum(desc, d, desc->force_enable, 0);
BUG_ON(k > 256); /* _INTC_ADDR_E() and _INTC_ADDR_D() are 8 bits */
intc_irq_domain_init(d, hw);
/* register the vectors one by one */ for (i = 0; i < hw->nr_vectors; i++) { struct intc_vect *vect = hw->vectors + i; unsignedint irq = evt2irq(vect->vect);
for (k = i + 1; k < hw->nr_vectors; k++) { struct intc_vect *vect2 = hw->vectors + k; unsignedint irq2 = evt2irq(vect2->vect);
if (vect->enum_id != vect2->enum_id) continue;
/* * In the case of multi-evt handling and sparse * IRQ support, each vector still needs to have * its own backing irq_desc.
*/ if (!intc_map(d->domain, irq2)) continue;
vect2->enum_id = 0;
/* redirect this interrupts to the first one */
irq_set_chip(irq2, &dummy_irq_chip);
irq_set_chained_handler_and_data(irq2,
intc_redirect_irq,
(void *)irq);
}
}
intc_subgroup_init(desc, d);
/* enable bits matching force_enable after registering irqs */ if (desc->force_enable)
intc_enable_disable_enum(desc, d, desc->force_enable, 1);
data = irq_get_irq_data(irq);
chip = irq_data_get_irq_chip(data); /* * This will catch the redirect and VIRQ cases * due to the dummy_irq_chip being inserted.
*/ if (chip != &d->chip) continue; if (irqd_irq_disabled(data))
chip->irq_disable(data); else
chip->irq_enable(data);
}
}
}
Die Informationen auf dieser Webseite wurden
nach bestem Wissen sorgfältig zusammengestellt. Es wird jedoch weder Vollständigkeit, noch Richtigkeit,
noch Qualität der bereit gestellten Informationen zugesichert.
Bemerkung:
Die farbliche Syntaxdarstellung und die Messung sind noch experimentell.