-static unsigned int mpic_type_to_vecpri(struct mpic *mpic, unsigned int type)
-{
- /* Now convert sense value */
- switch(type & IRQ_TYPE_SENSE_MASK) {
- case IRQ_TYPE_EDGE_RISING:
- return MPIC_INFO(VECPRI_SENSE_EDGE) |
- MPIC_INFO(VECPRI_POLARITY_POSITIVE);
- case IRQ_TYPE_EDGE_FALLING:
- case IRQ_TYPE_EDGE_BOTH:
- return MPIC_INFO(VECPRI_SENSE_EDGE) |
- MPIC_INFO(VECPRI_POLARITY_NEGATIVE);
- case IRQ_TYPE_LEVEL_HIGH:
- return MPIC_INFO(VECPRI_SENSE_LEVEL) |
- MPIC_INFO(VECPRI_POLARITY_POSITIVE);
- case IRQ_TYPE_LEVEL_LOW:
- default:
- return MPIC_INFO(VECPRI_SENSE_LEVEL) |
- MPIC_INFO(VECPRI_POLARITY_NEGATIVE);
- }
-}
-
-static int mpic_set_irq_type(unsigned int virq, unsigned int flow_type)
-{
- struct mpic *mpic = mpic_from_irq(virq);
- unsigned int src = mpic_irq_to_hw(virq);
- struct irq_desc *desc = get_irq_desc(virq);
- unsigned int vecpri, vold, vnew;
-
- DBG("mpic: set_irq_type(mpic:@%p,virq:%d,src:0x%x,type:0x%x)\n",
- mpic, virq, src, flow_type);
-
- if (src >= mpic->irq_count)
- return -EINVAL;
-
- if (flow_type == IRQ_TYPE_NONE)
- if (mpic->senses && src < mpic->senses_count)
- flow_type = mpic->senses[src];
- if (flow_type == IRQ_TYPE_NONE)
- flow_type = IRQ_TYPE_LEVEL_LOW;
-
- desc->status &= ~(IRQ_TYPE_SENSE_MASK | IRQ_LEVEL);
- desc->status |= flow_type & IRQ_TYPE_SENSE_MASK;
- if (flow_type & (IRQ_TYPE_LEVEL_HIGH | IRQ_TYPE_LEVEL_LOW))
- desc->status |= IRQ_LEVEL;
-
- if (mpic_is_ht_interrupt(mpic, src))
- vecpri = MPIC_VECPRI_POLARITY_POSITIVE |
- MPIC_VECPRI_SENSE_EDGE;
- else
- vecpri = mpic_type_to_vecpri(mpic, flow_type);
-
- vold = mpic_irq_read(src, MPIC_INFO(IRQ_VECTOR_PRI));
- vnew = vold & ~(MPIC_INFO(VECPRI_POLARITY_MASK) |
- MPIC_INFO(VECPRI_SENSE_MASK));
- vnew |= vecpri;
- if (vold != vnew)
- mpic_irq_write(src, MPIC_INFO(IRQ_VECTOR_PRI), vnew);
-
- return 0;
-}
-
-static struct irq_chip mpic_irq_chip = {
- .mask = mpic_mask_irq,
- .unmask = mpic_unmask_irq,
- .eoi = mpic_end_irq,
- .set_type = mpic_set_irq_type,
-};
-
-#ifdef CONFIG_SMP
-static struct irq_chip mpic_ipi_chip = {
- .mask = mpic_mask_ipi,
- .unmask = mpic_unmask_ipi,
- .eoi = mpic_end_ipi,
-};
-#endif /* CONFIG_SMP */
-
-#ifdef CONFIG_MPIC_BROKEN_U3
-static struct irq_chip mpic_irq_ht_chip = {
- .startup = mpic_startup_ht_irq,
- .shutdown = mpic_shutdown_ht_irq,
- .mask = mpic_mask_irq,
- .unmask = mpic_unmask_ht_irq,
- .eoi = mpic_end_ht_irq,
- .set_type = mpic_set_irq_type,
-};
-#endif /* CONFIG_MPIC_BROKEN_U3 */
-
-
-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;
-}
-
-static int mpic_host_map(struct irq_host *h, unsigned int virq,
- irq_hw_number_t hw)
-{
- struct mpic *mpic = h->host_data;
- struct irq_chip *chip;
-
- DBG("mpic: map virq %d, hwirq 0x%lx\n", virq, hw);
-
- if (hw == MPIC_VEC_SPURRIOUS)
- return -EINVAL;
-
-#ifdef CONFIG_SMP
- else if (hw >= MPIC_VEC_IPI_0) {
- WARN_ON(!(mpic->flags & MPIC_PRIMARY));
-
- DBG("mpic: mapping as IPI\n");
- set_irq_chip_data(virq, mpic);
- set_irq_chip_and_handler(virq, &mpic->hc_ipi,
- handle_percpu_irq);
- return 0;
- }
-#endif /* CONFIG_SMP */
-
- if (hw >= mpic->irq_count)
- return -EINVAL;
-
- /* Default chip */
- chip = &mpic->hc_irq;
-
-#ifdef CONFIG_MPIC_BROKEN_U3
- /* Check for HT interrupts, override vecpri */
- if (mpic_is_ht_interrupt(mpic, hw))
- chip = &mpic->hc_ht_irq;
-#endif /* CONFIG_MPIC_BROKEN_U3 */
-
- DBG("mpic: mapping to irq chip @%p\n", chip);
-
- set_irq_chip_data(virq, mpic);
- set_irq_chip_and_handler(virq, chip, handle_fasteoi_irq);
-
- /* Set default irq type */
- set_irq_type(virq, IRQ_TYPE_NONE);
-
- return 0;
-}
-
-static int mpic_host_xlate(struct irq_host *h, struct device_node *ct,
- u32 *intspec, unsigned int intsize,
- irq_hw_number_t *out_hwirq, unsigned int *out_flags)
-
-{
- static unsigned char map_mpic_senses[4] = {
- IRQ_TYPE_EDGE_RISING,
- IRQ_TYPE_LEVEL_LOW,
- IRQ_TYPE_LEVEL_HIGH,
- IRQ_TYPE_EDGE_FALLING,
- };
-
- *out_hwirq = intspec[0];
- if (intsize > 1) {
- u32 mask = 0x3;
-
- /* Apple invented a new race of encoding on machines with
- * an HT APIC. They encode, among others, the index within
- * the HT APIC. We don't care about it here since thankfully,
- * it appears that they have the APIC already properly
- * configured, and thus our current fixup code that reads the
- * APIC config works fine. However, we still need to mask out
- * bits in the specifier to make sure we only get bit 0 which
- * is the level/edge bit (the only sense bit exposed by Apple),
- * as their bit 1 means something else.
- */
- if (machine_is(powermac))
- mask = 0x1;
- *out_flags = map_mpic_senses[intspec[1] & mask];
- } else
- *out_flags = IRQ_TYPE_NONE;
-
- DBG("mpic: xlate (%d cells: 0x%08x 0x%08x) to line 0x%lx sense 0x%x\n",
- intsize, intspec[0], intspec[1], *out_hwirq, *out_flags);
-
- return 0;
-}
-
-static struct irq_host_ops mpic_host_ops = {
- .match = mpic_host_match,
- .map = mpic_host_map,
- .xlate = mpic_host_xlate,
-};