diff options
author | Jayachandran C <jchandra@broadcom.com> | 2013-12-21 06:22:13 -0500 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-01-24 16:39:46 -0500 |
commit | c24a8a7a99885d5b986f38f6631f69e7794a3e5e (patch) | |
tree | a0d6702fc1c45cba157a5734215c509fa4b216c6 /arch/mips/netlogic | |
parent | 27547abf36af7964b53a8c9265e266df692d4806 (diff) |
MIPS: Netlogic: Add MSI support for XLP
Add MSI chip and MSIX chip definitions.
For MSI, we map the link interrupt to a MSI link IRQ which will
do a second level of dispatch based on the MSI status register.
The MSI chip definitions use the MSI enable register to enable
and disable the MSI irqs.
For MSI-X, we split the 32 available MSI-X vectors across the
four PCIe links (8 each). These PIC interrupts generate an IRQ
per link which uses a second level dispatch as well.
The MSI-X chip definition uses the standard functions to enable
and disable interrupts.
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
Signed-off-by: John Crispin <blogic@openwrt.org>
Patchwork: http://patchwork.linux-mips.org/patch/6270/
Diffstat (limited to 'arch/mips/netlogic')
-rw-r--r-- | arch/mips/netlogic/common/irq.c | 29 | ||||
-rw-r--r-- | arch/mips/netlogic/xlp/nlm_hal.c | 12 |
2 files changed, 31 insertions, 10 deletions
diff --git a/arch/mips/netlogic/common/irq.c b/arch/mips/netlogic/common/irq.c index 1c7e3a1b81ab..3800bf6551ab 100644 --- a/arch/mips/netlogic/common/irq.c +++ b/arch/mips/netlogic/common/irq.c | |||
@@ -180,6 +180,7 @@ static void __init nlm_init_percpu_irqs(void) | |||
180 | #endif | 180 | #endif |
181 | } | 181 | } |
182 | 182 | ||
183 | |||
183 | void nlm_setup_pic_irq(int node, int picirq, int irq, int irt) | 184 | void nlm_setup_pic_irq(int node, int picirq, int irq, int irt) |
184 | { | 185 | { |
185 | struct nlm_pic_irq *pic_data; | 186 | struct nlm_pic_irq *pic_data; |
@@ -207,24 +208,24 @@ void nlm_set_pic_extra_ack(int node, int irq, void (*xack)(struct irq_data *)) | |||
207 | 208 | ||
208 | static void nlm_init_node_irqs(int node) | 209 | static void nlm_init_node_irqs(int node) |
209 | { | 210 | { |
210 | int i, irt; | ||
211 | uint64_t irqmask; | ||
212 | struct nlm_soc_info *nodep; | 211 | struct nlm_soc_info *nodep; |
212 | int i, irt; | ||
213 | 213 | ||
214 | pr_info("Init IRQ for node %d\n", node); | 214 | pr_info("Init IRQ for node %d\n", node); |
215 | nodep = nlm_get_node(node); | 215 | nodep = nlm_get_node(node); |
216 | irqmask = PERCPU_IRQ_MASK; | 216 | nodep->irqmask = PERCPU_IRQ_MASK; |
217 | for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) { | 217 | for (i = PIC_IRT_FIRST_IRQ; i <= PIC_IRT_LAST_IRQ; i++) { |
218 | irt = nlm_irq_to_irt(i); | 218 | irt = nlm_irq_to_irt(i); |
219 | if (irt == -1) | 219 | if (irt == -1) /* unused irq */ |
220 | continue; | 220 | continue; |
221 | nlm_setup_pic_irq(node, i, i, irt); | 221 | nodep->irqmask |= 1ull << i; |
222 | /* set interrupts to first cpu in node */ | 222 | if (irt == -2) /* not a direct PIC irq */ |
223 | continue; | ||
224 | |||
223 | nlm_pic_init_irt(nodep->picbase, irt, i, | 225 | nlm_pic_init_irt(nodep->picbase, irt, i, |
224 | node * NLM_CPUS_PER_NODE, 0); | 226 | node * NLM_CPUS_PER_NODE, 0); |
225 | irqmask |= (1ull << i); | 227 | nlm_setup_pic_irq(node, i, i, irt); |
226 | } | 228 | } |
227 | nodep->irqmask = irqmask; | ||
228 | } | 229 | } |
229 | 230 | ||
230 | void nlm_smp_irq_init(int hwcpuid) | 231 | void nlm_smp_irq_init(int hwcpuid) |
@@ -256,6 +257,18 @@ asmlinkage void plat_irq_dispatch(void) | |||
256 | return; | 257 | return; |
257 | } | 258 | } |
258 | 259 | ||
260 | #if defined(CONFIG_PCI_MSI) && defined(CONFIG_CPU_XLP) | ||
261 | /* PCI interrupts need a second level dispatch for MSI bits */ | ||
262 | if (i >= PIC_PCIE_LINK_MSI_IRQ(0) && i <= PIC_PCIE_LINK_MSI_IRQ(3)) { | ||
263 | nlm_dispatch_msi(node, i); | ||
264 | return; | ||
265 | } | ||
266 | if (i >= PIC_PCIE_MSIX_IRQ(0) && i <= PIC_PCIE_MSIX_IRQ(3)) { | ||
267 | nlm_dispatch_msix(node, i); | ||
268 | return; | ||
269 | } | ||
270 | |||
271 | #endif | ||
259 | /* top level irq handling */ | 272 | /* top level irq handling */ |
260 | do_IRQ(nlm_irq_to_xirq(node, i)); | 273 | do_IRQ(nlm_irq_to_xirq(node, i)); |
261 | } | 274 | } |
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c index 56c50ba43c9b..56930219964b 100644 --- a/arch/mips/netlogic/xlp/nlm_hal.c +++ b/arch/mips/netlogic/xlp/nlm_hal.c | |||
@@ -135,9 +135,17 @@ int nlm_irq_to_irt(int irq) | |||
135 | case PIC_I2C_3_IRQ: | 135 | case PIC_I2C_3_IRQ: |
136 | irt = irt + 3; break; | 136 | irt = irt + 3; break; |
137 | } | 137 | } |
138 | } else if (irq >= PIC_PCIE_LINK_0_IRQ && irq <= PIC_PCIE_LINK_3_IRQ) { | 138 | } else if (irq >= PIC_PCIE_LINK_LEGACY_IRQ(0) && |
139 | irq <= PIC_PCIE_LINK_LEGACY_IRQ(3)) { | ||
139 | /* HW bug, PCI IRT entries are bad on early silicon, fix */ | 140 | /* HW bug, PCI IRT entries are bad on early silicon, fix */ |
140 | irt = PIC_IRT_PCIE_LINK_INDEX(irq - PIC_PCIE_LINK_0_IRQ); | 141 | irt = PIC_IRT_PCIE_LINK_INDEX(irq - |
142 | PIC_PCIE_LINK_LEGACY_IRQ_BASE); | ||
143 | } else if (irq >= PIC_PCIE_LINK_MSI_IRQ(0) && | ||
144 | irq <= PIC_PCIE_LINK_MSI_IRQ(3)) { | ||
145 | irt = -2; | ||
146 | } else if (irq >= PIC_PCIE_MSIX_IRQ(0) && | ||
147 | irq <= PIC_PCIE_MSIX_IRQ(3)) { | ||
148 | irt = -2; | ||
141 | } else { | 149 | } else { |
142 | irt = -1; | 150 | irt = -1; |
143 | } | 151 | } |