MPIC_CPU_WHOAMI,
MPIC_CPU_INTACK,
MPIC_CPU_EOI,
+ MPIC_CPU_MCACK,
MPIC_IRQ_BASE,
MPIC_IRQ_STRIDE,
TSI108_CPU_WHOAMI,
TSI108_CPU_INTACK,
TSI108_CPU_EOI,
+ TSI108_CPU_MCACK,
TSI108_IRQ_BASE,
TSI108_IRQ_STRIDE,
switch(type) {
#ifdef CONFIG_PPC_DCR
case mpic_access_dcr:
- return dcr_read(rb->dhost,
- rb->dbase + reg + rb->doff);
+ return dcr_read(rb->dhost, reg);
#endif
case mpic_access_mmio_be:
return in_be32(rb->base + (reg >> 2));
switch(type) {
#ifdef CONFIG_PPC_DCR
case mpic_access_dcr:
- return dcr_write(rb->dhost,
- rb->dbase + reg + rb->doff, value);
+ return dcr_write(rb->dhost, reg, value);
#endif
case mpic_access_mmio_be:
return out_be32(rb->base + (reg >> 2), value);
unsigned int isu = src_no >> mpic->isu_shift;
unsigned int idx = src_no & mpic->isu_mask;
- return _mpic_read(mpic->reg_type, &mpic->isus[isu],
- reg + (idx * MPIC_INFO(IRQ_STRIDE)));
+#ifdef CONFIG_MPIC_BROKEN_REGREAD
+ if (reg == 0)
+ return mpic->isu_reg0_shadow[idx];
+ else
+#endif
+ return _mpic_read(mpic->reg_type, &mpic->isus[isu],
+ reg + (idx * MPIC_INFO(IRQ_STRIDE)));
}
static inline void _mpic_irq_write(struct mpic *mpic, unsigned int src_no,
_mpic_write(mpic->reg_type, &mpic->isus[isu],
reg + (idx * MPIC_INFO(IRQ_STRIDE)), value);
+
+#ifdef CONFIG_MPIC_BROKEN_REGREAD
+ if (reg == 0)
+ mpic->isu_reg0_shadow[idx] = value;
+#endif
}
#define mpic_read(b,r) _mpic_read(mpic->reg_type,&(b),(r))
static void _mpic_map_dcr(struct mpic *mpic, struct mpic_reg_bank *rb,
unsigned int offset, unsigned int size)
{
- rb->dbase = mpic->dcr_base;
- rb->doff = offset;
- rb->dhost = dcr_map(mpic->of_node, rb->dbase + rb->doff, size);
+ const u32 *dbasep;
+
+ dbasep = of_get_property(mpic->irqhost->of_node, "dcr-reg", NULL);
+
+ rb->dhost = dcr_map(mpic->irqhost->of_node, *dbasep + offset, size);
BUG_ON(!DCR_MAP_OK(rb->dhost));
}
}
#ifdef CONFIG_SMP
-static irqreturn_t mpic_ipi_action(int irq, void *dev_id)
+static irqreturn_t mpic_ipi_action(int irq, void *data)
{
- struct mpic *mpic;
+ long ipi = (long)data;
- mpic = mpic_find(irq, NULL);
- smp_message_recv(mpic_irq_to_hw(irq) - mpic->ipi_vecs[0]);
+ smp_message_recv(ipi);
return IRQ_HANDLED;
}
#endif /* CONFIG_SMP */
-static void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
+void mpic_set_affinity(unsigned int irq, cpumask_t cpumask)
{
struct mpic *mpic = mpic_from_irq(irq);
unsigned int src = mpic_irq_to_hw(irq);
return 0;
}
+void mpic_set_vector(unsigned int virq, unsigned int vector)
+{
+ struct mpic *mpic = mpic_from_irq(virq);
+ unsigned int src = mpic_irq_to_hw(virq);
+ unsigned int vecpri;
+
+ DBG("mpic: set_vector(mpic:@%p,virq:%d,src:%d,vector:0x%x)\n",
+ mpic, virq, src, vector);
+
+ if (src >= mpic->irq_count)
+ return;
+
+ vecpri = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
+ vecpri = vecpri & ~MPIC_INFO(VECPRI_VECTOR_MASK);
+ vecpri |= vector;
+ mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vecpri);
+}
+
static struct irq_chip mpic_irq_chip = {
.mask = mpic_mask_irq,
.unmask = mpic_unmask_irq,
static int mpic_host_match(struct irq_host *h, struct device_node *node)
{
- struct mpic *mpic = h->host_data;
-
/* Exact match, unless mpic node is NULL */
- return mpic->of_node == NULL || mpic->of_node == node;
+ return h->of_node == NULL || h->of_node == node;
}
static int mpic_host_map(struct irq_host *h, unsigned int virq,
memset(mpic, 0, sizeof(struct mpic));
mpic->name = name;
- mpic->of_node = of_node_get(node);
- mpic->irqhost = irq_alloc_host(IRQ_HOST_MAP_LINEAR, isu_size,
- &mpic_host_ops,
+ mpic->irqhost = irq_alloc_host(of_node_get(node), IRQ_HOST_MAP_LINEAR,
+ isu_size, &mpic_host_ops,
flags & MPIC_LARGE_VECTORS ? 2048 : 256);
if (mpic->irqhost == NULL) {
of_node_put(node);
BUG_ON(paddr == 0 && node == NULL);
/* If no physical address passed in, check if it's dcr based */
- if (paddr == 0 && of_get_property(node, "dcr-reg", NULL) != NULL)
- mpic->flags |= MPIC_USES_DCR;
-
+ if (paddr == 0 && of_get_property(node, "dcr-reg", NULL) != NULL) {
#ifdef CONFIG_PPC_DCR
- if (mpic->flags & MPIC_USES_DCR) {
- const u32 *dbasep;
- dbasep = of_get_property(node, "dcr-reg", NULL);
- BUG_ON(dbasep == NULL);
- mpic->dcr_base = *dbasep;
+ mpic->flags |= MPIC_USES_DCR;
mpic->reg_type = mpic_access_dcr;
- }
#else
- BUG_ON (mpic->flags & MPIC_USES_DCR);
+ BUG();
#endif /* CONFIG_PPC_DCR */
+ }
/* If the MPIC is not DCR based, and no physical address was passed
* in, try to obtain one
mb();
}
+ if (flags & MPIC_ENABLE_MCK)
+ mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
+ mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
+ | MPIC_GREG_GCONF_MCK);
+
/* Read feature register, calculate num CPUs and, for non-ISU
* MPICs, num sources as well. On ISU MPICs, sources are counted
* as ISUs are added
mpic_u3msi_init(mpic);
}
+ mpic_pasemi_msi_init(mpic);
+
for (i = 0; i < mpic->num_sources; i++) {
/* start with vector = source number, and masked */
u32 vecpri = MPIC_VECPRI_MASK | i |
mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
| MPIC_GREG_GCONF_8259_PTHROU_DIS);
+ if (mpic->flags & MPIC_NO_BIAS)
+ mpic_write(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0),
+ mpic_read(mpic->gregs, MPIC_INFO(GREG_GLOBAL_CONF_0))
+ | MPIC_GREG_GCONF_NO_BIAS);
+
/* Set current processor priority to 0 */
mpic_cpu_write(MPIC_INFO(CPU_CURRENT_TASK_PRI), 0);
mpic_physmask(cpu_mask & cpus_addr(cpu_online_map)[0]));
}
-unsigned int mpic_get_one_irq(struct mpic *mpic)
+static unsigned int _mpic_get_one_irq(struct mpic *mpic, int reg)
{
u32 src;
- src = mpic_cpu_read(MPIC_INFO(CPU_INTACK)) & MPIC_INFO(VECPRI_VECTOR_MASK);
+ src = mpic_cpu_read(reg) & MPIC_INFO(VECPRI_VECTOR_MASK);
#ifdef DEBUG_LOW
- DBG("%s: get_one_irq(): %d\n", mpic->name, src);
+ DBG("%s: get_one_irq(reg 0x%x): %d\n", mpic->name, reg, src);
#endif
if (unlikely(src == mpic->spurious_vec)) {
if (mpic->flags & MPIC_SPV_EOI)
return irq_linear_revmap(mpic->irqhost, src);
}
+unsigned int mpic_get_one_irq(struct mpic *mpic)
+{
+ return _mpic_get_one_irq(mpic, MPIC_INFO(CPU_INTACK));
+}
+
unsigned int mpic_get_irq(void)
{
struct mpic *mpic = mpic_primary;
return mpic_get_one_irq(mpic);
}
+unsigned int mpic_get_mcirq(void)
+{
+ struct mpic *mpic = mpic_primary;
+
+ BUG_ON(mpic == NULL);
+
+ return _mpic_get_one_irq(mpic, MPIC_INFO(CPU_MCACK));
+}
#ifdef CONFIG_SMP
void mpic_request_ipis(void)
{
struct mpic *mpic = mpic_primary;
- int i, err;
+ long i, err;
static char *ipi_names[] = {
"IPI0 (call function)",
"IPI1 (reschedule)",
unsigned int vipi = irq_create_mapping(mpic->irqhost,
mpic->ipi_vecs[0] + i);
if (vipi == NO_IRQ) {
- printk(KERN_ERR "Failed to map IPI %d\n", i);
+ printk(KERN_ERR "Failed to map IPI %ld\n", i);
break;
}
err = request_irq(vipi, mpic_ipi_action,
IRQF_DISABLED|IRQF_PERCPU,
- ipi_names[i], mpic);
+ ipi_names[i], (void *)i);
if (err) {
- printk(KERN_ERR "Request of irq %d for IPI %d failed\n",
+ printk(KERN_ERR "Request of irq %d for IPI %ld failed\n",
vipi, i);
break;
}