2 * Support Hypertransport IRQ
4 * Copyright (C) 1997, 1998, 1999, 2000, 2009 Ingo Molnar, Hajnalka Szabo
5 * Moved from arch/x86/kernel/apic/io_apic.c.
7 * This program is free software; you can redistribute it and/or modify
8 * it under the terms of the GNU General Public License version 2 as
9 * published by the Free Software Foundation.
12 #include <linux/interrupt.h>
13 #include <linux/init.h>
14 #include <linux/device.h>
15 #include <linux/pci.h>
16 #include <linux/htirq.h>
17 #include <asm/hw_irq.h>
19 #include <asm/hypertransport.h>
22 * Hypertransport interrupt support
24 static void target_ht_irq(unsigned int irq
, unsigned int dest
, u8 vector
)
26 struct ht_irq_msg msg
;
28 fetch_ht_irq_msg(irq
, &msg
);
30 msg
.address_lo
&= ~(HT_IRQ_LOW_VECTOR_MASK
| HT_IRQ_LOW_DEST_ID_MASK
);
31 msg
.address_hi
&= ~(HT_IRQ_HIGH_DEST_ID_MASK
);
33 msg
.address_lo
|= HT_IRQ_LOW_VECTOR(vector
) | HT_IRQ_LOW_DEST_ID(dest
);
34 msg
.address_hi
|= HT_IRQ_HIGH_DEST_ID(dest
);
36 write_ht_irq_msg(irq
, &msg
);
40 ht_set_affinity(struct irq_data
*data
, const struct cpumask
*mask
, bool force
)
42 struct irq_cfg
*cfg
= irqd_cfg(data
);
46 ret
= apic_set_affinity(data
, mask
, &dest
);
50 target_ht_irq(data
->irq
, dest
, cfg
->vector
);
51 return IRQ_SET_MASK_OK_NOCOPY
;
54 static struct irq_chip ht_irq_chip
= {
56 .irq_mask
= mask_ht_irq
,
57 .irq_unmask
= unmask_ht_irq
,
58 .irq_ack
= apic_ack_edge
,
59 .irq_set_affinity
= ht_set_affinity
,
60 .irq_retrigger
= apic_retrigger_irq
,
61 .flags
= IRQCHIP_SKIP_SET_WAKE
,
64 int arch_setup_ht_irq(unsigned int irq
, struct pci_dev
*dev
)
67 struct ht_irq_msg msg
;
75 err
= assign_irq_vector(irq
, cfg
, apic
->target_cpus());
79 err
= apic
->cpu_mask_to_apicid_and(cfg
->domain
,
80 apic
->target_cpus(), &dest
);
84 msg
.address_hi
= HT_IRQ_HIGH_DEST_ID(dest
);
88 HT_IRQ_LOW_DEST_ID(dest
) |
89 HT_IRQ_LOW_VECTOR(cfg
->vector
) |
90 ((apic
->irq_dest_mode
== 0) ?
91 HT_IRQ_LOW_DM_PHYSICAL
:
92 HT_IRQ_LOW_DM_LOGICAL
) |
93 HT_IRQ_LOW_RQEOI_EDGE
|
94 ((apic
->irq_delivery_mode
!= dest_LowestPrio
) ?
96 HT_IRQ_LOW_MT_ARBITRATED
) |
97 HT_IRQ_LOW_IRQ_MASKED
;
99 write_ht_irq_msg(irq
, &msg
);
101 irq_set_chip_and_handler_name(irq
, &ht_irq_chip
,
102 handle_edge_irq
, "edge");
104 dev_dbg(&dev
->dev
, "irq %d for HT\n", irq
);