powerpc/mpic: Add "last-interrupt-source" property to override hardware
The FreeScale PowerQUICC-III-compatible (mpc85xx/mpc86xx) MPICs do not correctly report the number of hardware interrupt sources, so software needs to override the detected value with "256". To avoid needing to write custom board-specific code to detect that scenario, allow it to be easily overridden in the device-tree. Signed-off-by: Kyle Moffett <Kyle.D.Moffett@boeing.com> Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
This commit is contained in:
parent
5019609fce
commit
c1b8d45db4
3 changed files with 34 additions and 20 deletions
|
@ -70,6 +70,13 @@ PROPERTIES
|
||||||
If present the MPIC will be assumed to only be able to route
|
If present the MPIC will be assumed to only be able to route
|
||||||
non-IPI interrupts to a single CPU at a time (EG: Freescale MPIC).
|
non-IPI interrupts to a single CPU at a time (EG: Freescale MPIC).
|
||||||
|
|
||||||
|
- last-interrupt-source
|
||||||
|
Usage: optional
|
||||||
|
Value type: <u32>
|
||||||
|
Some MPICs do not correctly report the number of hardware sources
|
||||||
|
in the global feature registers. If specified, this field will
|
||||||
|
override the value read from MPIC_GREG_FEATURE_LAST_SRC.
|
||||||
|
|
||||||
INTERRUPT SPECIFIER DEFINITION
|
INTERRUPT SPECIFIER DEFINITION
|
||||||
|
|
||||||
Interrupt specifiers consists of 4 cells encoded as
|
Interrupt specifiers consists of 4 cells encoded as
|
||||||
|
|
|
@ -41,6 +41,7 @@ mpic: pic@40000 {
|
||||||
device_type = "open-pic";
|
device_type = "open-pic";
|
||||||
big-endian;
|
big-endian;
|
||||||
single-cpu-affinity;
|
single-cpu-affinity;
|
||||||
|
last-interrupt-source = <255>;
|
||||||
};
|
};
|
||||||
|
|
||||||
timer@41100 {
|
timer@41100 {
|
||||||
|
|
|
@ -1149,6 +1149,7 @@ struct mpic * __init mpic_alloc(struct device_node *node,
|
||||||
u32 greg_feature;
|
u32 greg_feature;
|
||||||
const char *vers;
|
const char *vers;
|
||||||
const u32 *psrc;
|
const u32 *psrc;
|
||||||
|
u32 last_irq;
|
||||||
|
|
||||||
/* Default MPIC search parameters */
|
/* Default MPIC search parameters */
|
||||||
static const struct of_device_id __initconst mpic_device_id[] = {
|
static const struct of_device_id __initconst mpic_device_id[] = {
|
||||||
|
@ -1220,7 +1221,6 @@ struct mpic * __init mpic_alloc(struct device_node *node,
|
||||||
mpic->hc_tm = mpic_tm_chip;
|
mpic->hc_tm = mpic_tm_chip;
|
||||||
mpic->hc_tm.name = name;
|
mpic->hc_tm.name = name;
|
||||||
|
|
||||||
mpic->isu_size = isu_size;
|
|
||||||
mpic->num_sources = 0; /* so far */
|
mpic->num_sources = 0; /* so far */
|
||||||
|
|
||||||
if (mpic->flags & MPIC_LARGE_VECTORS)
|
if (mpic->flags & MPIC_LARGE_VECTORS)
|
||||||
|
@ -1307,20 +1307,6 @@ struct mpic * __init mpic_alloc(struct device_node *node,
|
||||||
mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
|
mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
|
||||||
| MPIC_GREG_GCONF_MCK);
|
| MPIC_GREG_GCONF_MCK);
|
||||||
|
|
||||||
/*
|
|
||||||
* Read feature register. For non-ISU MPICs, num sources as well. On
|
|
||||||
* ISU MPICs, sources are counted as ISUs are added
|
|
||||||
*/
|
|
||||||
greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
|
|
||||||
if (isu_size == 0) {
|
|
||||||
if (irq_count)
|
|
||||||
mpic->num_sources = irq_count;
|
|
||||||
else
|
|
||||||
mpic->num_sources =
|
|
||||||
((greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
|
|
||||||
>> MPIC_GREG_FEATURE_LAST_SRC_SHIFT) + 1;
|
|
||||||
}
|
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* The MPIC driver will crash if there are more cores than we
|
* The MPIC driver will crash if there are more cores than we
|
||||||
* can initialize, so we may as well catch that problem here.
|
* can initialize, so we may as well catch that problem here.
|
||||||
|
@ -1336,18 +1322,38 @@ struct mpic * __init mpic_alloc(struct device_node *node,
|
||||||
0x1000);
|
0x1000);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
/*
|
||||||
|
* Read feature register. For non-ISU MPICs, num sources as well. On
|
||||||
|
* ISU MPICs, sources are counted as ISUs are added
|
||||||
|
*/
|
||||||
|
greg_feature = mpic_read(mpic->gregs, MPIC_INFO(GREG_FEATURE_0));
|
||||||
|
|
||||||
|
/*
|
||||||
|
* By default, the last source number comes from the MPIC, but the
|
||||||
|
* device-tree and board support code can override it on buggy hw.
|
||||||
|
*/
|
||||||
|
last_irq = (greg_feature & MPIC_GREG_FEATURE_LAST_SRC_MASK)
|
||||||
|
>> MPIC_GREG_FEATURE_LAST_SRC_SHIFT;
|
||||||
|
of_property_read_u32(mpic->node, "last-interrupt-source", &last_irq);
|
||||||
|
if (irq_count)
|
||||||
|
last_irq = irq_count - 1;
|
||||||
|
|
||||||
/* Initialize main ISU if none provided */
|
/* Initialize main ISU if none provided */
|
||||||
if (mpic->isu_size == 0) {
|
if (!isu_size) {
|
||||||
mpic->isu_size = mpic->num_sources;
|
isu_size = last_irq + 1;
|
||||||
|
mpic->num_sources = isu_size;
|
||||||
mpic_map(mpic, mpic->paddr, &mpic->isus[0],
|
mpic_map(mpic, mpic->paddr, &mpic->isus[0],
|
||||||
MPIC_INFO(IRQ_BASE), MPIC_INFO(IRQ_STRIDE) * mpic->isu_size);
|
MPIC_INFO(IRQ_BASE),
|
||||||
|
MPIC_INFO(IRQ_STRIDE) * isu_size);
|
||||||
}
|
}
|
||||||
|
|
||||||
|
mpic->isu_size = isu_size;
|
||||||
mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
|
mpic->isu_shift = 1 + __ilog2(mpic->isu_size - 1);
|
||||||
mpic->isu_mask = (1 << mpic->isu_shift) - 1;
|
mpic->isu_mask = (1 << mpic->isu_shift) - 1;
|
||||||
|
|
||||||
mpic->irqhost = irq_alloc_host(mpic->node, IRQ_HOST_MAP_LINEAR,
|
mpic->irqhost = irq_alloc_host(mpic->node, IRQ_HOST_MAP_LINEAR,
|
||||||
isu_size ? isu_size : mpic->num_sources,
|
mpic->isu_size, &mpic_host_ops,
|
||||||
&mpic_host_ops, intvec_top + 1);
|
intvec_top + 1);
|
||||||
|
|
||||||
/*
|
/*
|
||||||
* FIXME: The code leaks the MPIC object and mappings here; this
|
* FIXME: The code leaks the MPIC object and mappings here; this
|
||||||
|
|
Loading…
Add table
Reference in a new issue