diff options
author | Ganesan Ramalingam <ganesanr@broadcom.com> | 2014-05-09 07:05:49 -0400 |
---|---|---|
committer | Ralf Baechle <ralf@linux-mips.org> | 2014-05-30 10:51:02 -0400 |
commit | d66f3f0e10b49df8d0cc0d8eb5bf2ef9863a33cf (patch) | |
tree | 39f0d8fa0dacfd9f7ab7794bbdd330160af173c9 /arch | |
parent | 1c98398662c9b4e2f03f64344f83dd6cb14e0420 (diff) |
MIPS: Add MSI support for XLP9XX
In XLP9XX, the interrupt routing table for MSI-X has been moved to the
PCIe controller's config space from PIC. There are also 32 MSI-X
interrupts available per link on XLP9XX.
Update XLP MSI/MSI-X code to handle this.
Signed-off-by: Ganesan Ramalingam <ganesanr@broadcom.com>
Signed-off-by: Jayachandran C <jchandra@broadcom.com>
Cc: g@linux-mips.org
Cc: linux-mips@linux-mips.org
Patchwork: https://patchwork.linux-mips.org/patch/6912/
Signed-off-by: Ralf Baechle <ralf@linux-mips.org>
Diffstat (limited to 'arch')
-rw-r--r-- | arch/mips/include/asm/netlogic/xlp-hal/pcibus.h | 14 | ||||
-rw-r--r-- | arch/mips/include/asm/netlogic/xlp-hal/pic.h | 4 | ||||
-rw-r--r-- | arch/mips/include/asm/netlogic/xlp-hal/xlp.h | 5 | ||||
-rw-r--r-- | arch/mips/pci/msi-xlp.c | 184 |
4 files changed, 156 insertions, 51 deletions
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h index d4deb87ad069..91540f41e1e4 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h | |||
@@ -69,6 +69,20 @@ | |||
69 | #define PCIE_9XX_BYTE_SWAP_IO_BASE 0x25e | 69 | #define PCIE_9XX_BYTE_SWAP_IO_BASE 0x25e |
70 | #define PCIE_9XX_BYTE_SWAP_IO_LIM 0x25f | 70 | #define PCIE_9XX_BYTE_SWAP_IO_LIM 0x25f |
71 | 71 | ||
72 | #define PCIE_9XX_BRIDGE_MSIX_ADDR_BASE 0x264 | ||
73 | #define PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT 0x265 | ||
74 | #define PCIE_9XX_MSI_STATUS 0x283 | ||
75 | #define PCIE_9XX_MSI_EN 0x284 | ||
76 | /* 128 MSIX vectors available in 9xx */ | ||
77 | #define PCIE_9XX_MSIX_STATUS0 0x286 | ||
78 | #define PCIE_9XX_MSIX_STATUSX(n) (n + 0x286) | ||
79 | #define PCIE_9XX_MSIX_VEC 0x296 | ||
80 | #define PCIE_9XX_MSIX_VECX(n) (n + 0x296) | ||
81 | #define PCIE_9XX_INT_STATUS0 0x397 | ||
82 | #define PCIE_9XX_INT_STATUS1 0x398 | ||
83 | #define PCIE_9XX_INT_EN0 0x399 | ||
84 | #define PCIE_9XX_INT_EN1 0x39a | ||
85 | |||
72 | /* other */ | 86 | /* other */ |
73 | #define PCIE_NLINKS 4 | 87 | #define PCIE_NLINKS 4 |
74 | 88 | ||
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pic.h b/arch/mips/include/asm/netlogic/xlp-hal/pic.h index f10bf3bba58f..41cefe94f0c9 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/pic.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/pic.h | |||
@@ -199,6 +199,10 @@ | |||
199 | #define PIC_IRT_PCIE_LINK_3_INDEX 81 | 199 | #define PIC_IRT_PCIE_LINK_3_INDEX 81 |
200 | #define PIC_IRT_PCIE_LINK_INDEX(num) ((num) + PIC_IRT_PCIE_LINK_0_INDEX) | 200 | #define PIC_IRT_PCIE_LINK_INDEX(num) ((num) + PIC_IRT_PCIE_LINK_0_INDEX) |
201 | 201 | ||
202 | #define PIC_9XX_IRT_PCIE_LINK_0_INDEX 191 | ||
203 | #define PIC_9XX_IRT_PCIE_LINK_INDEX(num) \ | ||
204 | ((num) + PIC_9XX_IRT_PCIE_LINK_0_INDEX) | ||
205 | |||
202 | #define PIC_CLOCK_TIMER 7 | 206 | #define PIC_CLOCK_TIMER 7 |
203 | 207 | ||
204 | #if !defined(LOCORE) && !defined(__ASSEMBLY__) | 208 | #if !defined(LOCORE) && !defined(__ASSEMBLY__) |
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h index 62d19871b983..a862b93223cc 100644 --- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h +++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h | |||
@@ -70,8 +70,9 @@ | |||
70 | #define PIC_PCIE_MSIX_IRQ_BASE 48 /* 48 - 51 MSI-X IRQ */ | 70 | #define PIC_PCIE_MSIX_IRQ_BASE 48 /* 48 - 51 MSI-X IRQ */ |
71 | #define PIC_PCIE_MSIX_IRQ(i) (48 + (i)) | 71 | #define PIC_PCIE_MSIX_IRQ(i) (48 + (i)) |
72 | 72 | ||
73 | #define NLM_MSIX_VEC_BASE 96 /* 96 - 127 - MSIX mapped */ | 73 | /* XLP9xx and XLP8xx has 128 and 32 MSIX vectors respectively */ |
74 | #define NLM_MSI_VEC_BASE 128 /* 128 -255 - MSI mapped */ | 74 | #define NLM_MSIX_VEC_BASE 96 /* 96 - 223 - MSIX mapped */ |
75 | #define NLM_MSI_VEC_BASE 224 /* 224 -351 - MSI mapped */ | ||
75 | 76 | ||
76 | #define NLM_PIC_INDIRECT_VEC_BASE 512 | 77 | #define NLM_PIC_INDIRECT_VEC_BASE 512 |
77 | #define NLM_GPIO_VEC_BASE 768 | 78 | #define NLM_GPIO_VEC_BASE 768 |
diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c index afd8405e0188..1ef3ed607f47 100644 --- a/arch/mips/pci/msi-xlp.c +++ b/arch/mips/pci/msi-xlp.c | |||
@@ -56,8 +56,8 @@ | |||
56 | #include <asm/netlogic/xlp-hal/bridge.h> | 56 | #include <asm/netlogic/xlp-hal/bridge.h> |
57 | 57 | ||
58 | #define XLP_MSIVEC_PER_LINK 32 | 58 | #define XLP_MSIVEC_PER_LINK 32 |
59 | #define XLP_MSIXVEC_TOTAL 32 | 59 | #define XLP_MSIXVEC_TOTAL (cpu_is_xlp9xx() ? 128 : 32) |
60 | #define XLP_MSIXVEC_PER_LINK 8 | 60 | #define XLP_MSIXVEC_PER_LINK (cpu_is_xlp9xx() ? 32 : 8) |
61 | 61 | ||
62 | /* 128 MSI irqs per node, mapped starting at NLM_MSI_VEC_BASE */ | 62 | /* 128 MSI irqs per node, mapped starting at NLM_MSI_VEC_BASE */ |
63 | static inline int nlm_link_msiirq(int link, int msivec) | 63 | static inline int nlm_link_msiirq(int link, int msivec) |
@@ -65,35 +65,44 @@ static inline int nlm_link_msiirq(int link, int msivec) | |||
65 | return NLM_MSI_VEC_BASE + link * XLP_MSIVEC_PER_LINK + msivec; | 65 | return NLM_MSI_VEC_BASE + link * XLP_MSIVEC_PER_LINK + msivec; |
66 | } | 66 | } |
67 | 67 | ||
68 | /* get the link MSI vector from irq number */ | ||
68 | static inline int nlm_irq_msivec(int irq) | 69 | static inline int nlm_irq_msivec(int irq) |
69 | { | 70 | { |
70 | return irq % XLP_MSIVEC_PER_LINK; | 71 | return (irq - NLM_MSI_VEC_BASE) % XLP_MSIVEC_PER_LINK; |
71 | } | 72 | } |
72 | 73 | ||
74 | /* get the link from the irq number */ | ||
73 | static inline int nlm_irq_msilink(int irq) | 75 | static inline int nlm_irq_msilink(int irq) |
74 | { | 76 | { |
75 | return (irq % (XLP_MSIVEC_PER_LINK * PCIE_NLINKS)) / | 77 | int total_msivec = XLP_MSIVEC_PER_LINK * PCIE_NLINKS; |
76 | XLP_MSIVEC_PER_LINK; | 78 | |
79 | return ((irq - NLM_MSI_VEC_BASE) % total_msivec) / | ||
80 | XLP_MSIVEC_PER_LINK; | ||
77 | } | 81 | } |
78 | 82 | ||
79 | /* | 83 | /* |
80 | * Only 32 MSI-X vectors are possible because there are only 32 PIC | 84 | * For XLP 8xx/4xx/3xx/2xx, only 32 MSI-X vectors are possible because |
81 | * interrupts for MSI. We split them statically and use 8 MSI-X vectors | 85 | * there are only 32 PIC interrupts for MSI. We split them statically |
82 | * per link - this keeps the allocation and lookup simple. | 86 | * and use 8 MSI-X vectors per link - this keeps the allocation and |
87 | * lookup simple. | ||
88 | * On XLP 9xx, there are 32 vectors per link, and the interrupts are | ||
89 | * not routed thru PIC, so we can use all 128 MSI-X vectors. | ||
83 | */ | 90 | */ |
84 | static inline int nlm_link_msixirq(int link, int bit) | 91 | static inline int nlm_link_msixirq(int link, int bit) |
85 | { | 92 | { |
86 | return NLM_MSIX_VEC_BASE + link * XLP_MSIXVEC_PER_LINK + bit; | 93 | return NLM_MSIX_VEC_BASE + link * XLP_MSIXVEC_PER_LINK + bit; |
87 | } | 94 | } |
88 | 95 | ||
96 | /* get the link MSI vector from irq number */ | ||
89 | static inline int nlm_irq_msixvec(int irq) | 97 | static inline int nlm_irq_msixvec(int irq) |
90 | { | 98 | { |
91 | return irq % XLP_MSIXVEC_TOTAL; /* works when given xirq */ | 99 | return (irq - NLM_MSIX_VEC_BASE) % XLP_MSIXVEC_TOTAL; |
92 | } | 100 | } |
93 | 101 | ||
94 | static inline int nlm_irq_msixlink(int irq) | 102 | /* get the link from MSIX vec */ |
103 | static inline int nlm_irq_msixlink(int msixvec) | ||
95 | { | 104 | { |
96 | return nlm_irq_msixvec(irq) / XLP_MSIXVEC_PER_LINK; | 105 | return msixvec / XLP_MSIXVEC_PER_LINK; |
97 | } | 106 | } |
98 | 107 | ||
99 | /* | 108 | /* |
@@ -129,7 +138,11 @@ static void xlp_msi_enable(struct irq_data *d) | |||
129 | vec = nlm_irq_msivec(d->irq); | 138 | vec = nlm_irq_msivec(d->irq); |
130 | spin_lock_irqsave(&md->msi_lock, flags); | 139 | spin_lock_irqsave(&md->msi_lock, flags); |
131 | md->msi_enabled_mask |= 1u << vec; | 140 | md->msi_enabled_mask |= 1u << vec; |
132 | nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); | 141 | if (cpu_is_xlp9xx()) |
142 | nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN, | ||
143 | md->msi_enabled_mask); | ||
144 | else | ||
145 | nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); | ||
133 | spin_unlock_irqrestore(&md->msi_lock, flags); | 146 | spin_unlock_irqrestore(&md->msi_lock, flags); |
134 | } | 147 | } |
135 | 148 | ||
@@ -142,7 +155,11 @@ static void xlp_msi_disable(struct irq_data *d) | |||
142 | vec = nlm_irq_msivec(d->irq); | 155 | vec = nlm_irq_msivec(d->irq); |
143 | spin_lock_irqsave(&md->msi_lock, flags); | 156 | spin_lock_irqsave(&md->msi_lock, flags); |
144 | md->msi_enabled_mask &= ~(1u << vec); | 157 | md->msi_enabled_mask &= ~(1u << vec); |
145 | nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); | 158 | if (cpu_is_xlp9xx()) |
159 | nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_EN, | ||
160 | md->msi_enabled_mask); | ||
161 | else | ||
162 | nlm_write_reg(md->lnkbase, PCIE_MSI_EN, md->msi_enabled_mask); | ||
146 | spin_unlock_irqrestore(&md->msi_lock, flags); | 163 | spin_unlock_irqrestore(&md->msi_lock, flags); |
147 | } | 164 | } |
148 | 165 | ||
@@ -156,11 +173,18 @@ static void xlp_msi_mask_ack(struct irq_data *d) | |||
156 | xlp_msi_disable(d); | 173 | xlp_msi_disable(d); |
157 | 174 | ||
158 | /* Ack MSI on bridge */ | 175 | /* Ack MSI on bridge */ |
159 | nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec); | 176 | if (cpu_is_xlp9xx()) |
177 | nlm_write_reg(md->lnkbase, PCIE_9XX_MSI_STATUS, 1u << vec); | ||
178 | else | ||
179 | nlm_write_reg(md->lnkbase, PCIE_MSI_STATUS, 1u << vec); | ||
160 | 180 | ||
161 | /* Ack at eirr and PIC */ | 181 | /* Ack at eirr and PIC */ |
162 | ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link)); | 182 | ack_c0_eirr(PIC_PCIE_LINK_MSI_IRQ(link)); |
163 | nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link)); | 183 | if (cpu_is_xlp9xx()) |
184 | nlm_pic_ack(md->node->picbase, | ||
185 | PIC_9XX_IRT_PCIE_LINK_INDEX(link)); | ||
186 | else | ||
187 | nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_LINK_INDEX(link)); | ||
164 | } | 188 | } |
165 | 189 | ||
166 | static struct irq_chip xlp_msi_chip = { | 190 | static struct irq_chip xlp_msi_chip = { |
@@ -172,30 +196,45 @@ static struct irq_chip xlp_msi_chip = { | |||
172 | }; | 196 | }; |
173 | 197 | ||
174 | /* | 198 | /* |
175 | * The MSI-X interrupt handling is different from MSI, there are 32 | 199 | * XLP8XX/4XX/3XX/2XX: |
176 | * MSI-X interrupts generated by the PIC and each of these correspond | 200 | * The MSI-X interrupt handling is different from MSI, there are 32 MSI-X |
177 | * to a MSI-X vector (0-31) that can be assigned. | 201 | * interrupts generated by the PIC and each of these correspond to a MSI-X |
202 | * vector (0-31) that can be assigned. | ||
178 | * | 203 | * |
179 | * We divide the MSI-X vectors to 8 per link and do a per-link | 204 | * We divide the MSI-X vectors to 8 per link and do a per-link allocation |
180 | * allocation | 205 | * |
206 | * XLP9XX: | ||
207 | * 32 MSI-X vectors are available per link, and the interrupts are not routed | ||
208 | * thru the PIC. PIC ack not needed. | ||
181 | * | 209 | * |
182 | * Enable and disable done using standard MSI functions. | 210 | * Enable and disable done using standard MSI functions. |
183 | */ | 211 | */ |
184 | static void xlp_msix_mask_ack(struct irq_data *d) | 212 | static void xlp_msix_mask_ack(struct irq_data *d) |
185 | { | 213 | { |
186 | struct xlp_msi_data *md = irq_data_get_irq_handler_data(d); | 214 | struct xlp_msi_data *md; |
187 | int link, msixvec; | 215 | int link, msixvec; |
216 | uint32_t status_reg, bit; | ||
188 | 217 | ||
189 | msixvec = nlm_irq_msixvec(d->irq); | 218 | msixvec = nlm_irq_msixvec(d->irq); |
190 | link = nlm_irq_msixlink(d->irq); | 219 | link = nlm_irq_msixlink(msixvec); |
191 | mask_msi_irq(d); | 220 | mask_msi_irq(d); |
221 | md = irq_data_get_irq_handler_data(d); | ||
192 | 222 | ||
193 | /* Ack MSI on bridge */ | 223 | /* Ack MSI on bridge */ |
194 | nlm_write_reg(md->lnkbase, PCIE_MSIX_STATUS, 1u << msixvec); | 224 | if (cpu_is_xlp9xx()) { |
225 | status_reg = PCIE_9XX_MSIX_STATUSX(link); | ||
226 | bit = msixvec % XLP_MSIXVEC_PER_LINK; | ||
227 | } else { | ||
228 | status_reg = PCIE_MSIX_STATUS; | ||
229 | bit = msixvec; | ||
230 | } | ||
231 | nlm_write_reg(md->lnkbase, status_reg, 1u << bit); | ||
195 | 232 | ||
196 | /* Ack at eirr and PIC */ | 233 | /* Ack at eirr and PIC */ |
197 | ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link)); | 234 | ack_c0_eirr(PIC_PCIE_MSIX_IRQ(link)); |
198 | nlm_pic_ack(md->node->picbase, PIC_IRT_PCIE_MSIX_INDEX(msixvec)); | 235 | if (!cpu_is_xlp9xx()) |
236 | nlm_pic_ack(md->node->picbase, | ||
237 | PIC_IRT_PCIE_MSIX_INDEX(msixvec)); | ||
199 | } | 238 | } |
200 | 239 | ||
201 | static struct irq_chip xlp_msix_chip = { | 240 | static struct irq_chip xlp_msix_chip = { |
@@ -225,10 +264,18 @@ static void xlp_config_link_msi(uint64_t lnkbase, int lirq, uint64_t msiaddr) | |||
225 | { | 264 | { |
226 | u32 val; | 265 | u32 val; |
227 | 266 | ||
228 | val = nlm_read_reg(lnkbase, PCIE_INT_EN0); | 267 | if (cpu_is_xlp9xx()) { |
229 | if ((val & 0x200) == 0) { | 268 | val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0); |
230 | val |= 0x200; /* MSI Interrupt enable */ | 269 | if ((val & 0x200) == 0) { |
231 | nlm_write_reg(lnkbase, PCIE_INT_EN0, val); | 270 | val |= 0x200; /* MSI Interrupt enable */ |
271 | nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val); | ||
272 | } | ||
273 | } else { | ||
274 | val = nlm_read_reg(lnkbase, PCIE_INT_EN0); | ||
275 | if ((val & 0x200) == 0) { | ||
276 | val |= 0x200; | ||
277 | nlm_write_reg(lnkbase, PCIE_INT_EN0, val); | ||
278 | } | ||
232 | } | 279 | } |
233 | 280 | ||
234 | val = nlm_read_reg(lnkbase, 0x1); /* CMD */ | 281 | val = nlm_read_reg(lnkbase, 0x1); /* CMD */ |
@@ -275,9 +322,12 @@ static int xlp_setup_msi(uint64_t lnkbase, int node, int link, | |||
275 | 322 | ||
276 | spin_lock_irqsave(&md->msi_lock, flags); | 323 | spin_lock_irqsave(&md->msi_lock, flags); |
277 | if (md->msi_alloc_mask == 0) { | 324 | if (md->msi_alloc_mask == 0) { |
278 | /* switch the link IRQ to MSI range */ | ||
279 | xlp_config_link_msi(lnkbase, lirq, msiaddr); | 325 | xlp_config_link_msi(lnkbase, lirq, msiaddr); |
280 | irt = PIC_IRT_PCIE_LINK_INDEX(link); | 326 | /* switch the link IRQ to MSI range */ |
327 | if (cpu_is_xlp9xx()) | ||
328 | irt = PIC_9XX_IRT_PCIE_LINK_INDEX(link); | ||
329 | else | ||
330 | irt = PIC_IRT_PCIE_LINK_INDEX(link); | ||
281 | nlm_setup_pic_irq(node, lirq, lirq, irt); | 331 | nlm_setup_pic_irq(node, lirq, lirq, irt); |
282 | nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq, | 332 | nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq, |
283 | node * nlm_threads_per_node(), 1 /*en */); | 333 | node * nlm_threads_per_node(), 1 /*en */); |
@@ -319,10 +369,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr) | |||
319 | val |= 0x80000000U; | 369 | val |= 0x80000000U; |
320 | nlm_write_reg(lnkbase, 0x2C, val); | 370 | nlm_write_reg(lnkbase, 0x2C, val); |
321 | } | 371 | } |
322 | val = nlm_read_reg(lnkbase, PCIE_INT_EN0); | 372 | |
323 | if ((val & 0x200) == 0) { | 373 | if (cpu_is_xlp9xx()) { |
324 | val |= 0x200; /* MSI Interrupt enable */ | 374 | val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0); |
325 | nlm_write_reg(lnkbase, PCIE_INT_EN0, val); | 375 | if ((val & 0x200) == 0) { |
376 | val |= 0x200; /* MSI Interrupt enable */ | ||
377 | nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val); | ||
378 | } | ||
379 | } else { | ||
380 | val = nlm_read_reg(lnkbase, PCIE_INT_EN0); | ||
381 | if ((val & 0x200) == 0) { | ||
382 | val |= 0x200; /* MSI Interrupt enable */ | ||
383 | nlm_write_reg(lnkbase, PCIE_INT_EN0, val); | ||
384 | } | ||
326 | } | 385 | } |
327 | 386 | ||
328 | val = nlm_read_reg(lnkbase, 0x1); /* CMD */ | 387 | val = nlm_read_reg(lnkbase, 0x1); /* CMD */ |
@@ -337,10 +396,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr) | |||
337 | val |= (1 << 8) | lirq; | 396 | val |= (1 << 8) | lirq; |
338 | nlm_write_pci_reg(lnkbase, 0xf, val); | 397 | nlm_write_pci_reg(lnkbase, 0xf, val); |
339 | 398 | ||
340 | /* MSI-X addresses */ | 399 | if (cpu_is_xlp9xx()) { |
341 | nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE, msixaddr >> 8); | 400 | /* MSI-X addresses */ |
342 | nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT, | 401 | nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_BASE, |
343 | (msixaddr + MSI_ADDR_SZ) >> 8); | 402 | msixaddr >> 8); |
403 | nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT, | ||
404 | (msixaddr + MSI_ADDR_SZ) >> 8); | ||
405 | } else { | ||
406 | /* MSI-X addresses */ | ||
407 | nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE, | ||
408 | msixaddr >> 8); | ||
409 | nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT, | ||
410 | (msixaddr + MSI_ADDR_SZ) >> 8); | ||
411 | } | ||
344 | } | 412 | } |
345 | 413 | ||
346 | /* | 414 | /* |
@@ -377,6 +445,7 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link, | |||
377 | 445 | ||
378 | xirq += t; | 446 | xirq += t; |
379 | msixvec = nlm_irq_msixvec(xirq); | 447 | msixvec = nlm_irq_msixvec(xirq); |
448 | |||
380 | msg.address_hi = msixaddr >> 32; | 449 | msg.address_hi = msixaddr >> 32; |
381 | msg.address_lo = msixaddr & 0xffffffff; | 450 | msg.address_lo = msixaddr & 0xffffffff; |
382 | msg.data = 0xc00 | msixvec; | 451 | msg.data = 0xc00 | msixvec; |
@@ -417,7 +486,7 @@ void __init xlp_init_node_msi_irqs(int node, int link) | |||
417 | { | 486 | { |
418 | struct nlm_soc_info *nodep; | 487 | struct nlm_soc_info *nodep; |
419 | struct xlp_msi_data *md; | 488 | struct xlp_msi_data *md; |
420 | int irq, i, irt, msixvec; | 489 | int irq, i, irt, msixvec, val; |
421 | 490 | ||
422 | pr_info("[%d %d] Init node PCI IRT\n", node, link); | 491 | pr_info("[%d %d] Init node PCI IRT\n", node, link); |
423 | nodep = nlm_get_node(node); | 492 | nodep = nlm_get_node(node); |
@@ -438,19 +507,28 @@ void __init xlp_init_node_msi_irqs(int node, int link) | |||
438 | irq_set_handler_data(i, md); | 507 | irq_set_handler_data(i, md); |
439 | } | 508 | } |
440 | 509 | ||
441 | for (i = 0; i < XLP_MSIXVEC_PER_LINK; i++) { | 510 | for (i = 0; i < XLP_MSIXVEC_PER_LINK ; i++) { |
442 | /* Initialize MSI-X irts to generate one interrupt per link */ | 511 | if (cpu_is_xlp9xx()) { |
443 | msixvec = link * XLP_MSIXVEC_PER_LINK + i; | 512 | val = ((node * nlm_threads_per_node()) << 7 | |
444 | irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec); | 513 | PIC_PCIE_MSIX_IRQ(link) << 1 | 0 << 0); |
445 | nlm_pic_init_irt(nodep->picbase, irt, PIC_PCIE_MSIX_IRQ(link), | 514 | nlm_write_pcie_reg(md->lnkbase, PCIE_9XX_MSIX_VECX(i + |
446 | node * nlm_threads_per_node(), 1 /* enable */); | 515 | (link * XLP_MSIXVEC_PER_LINK)), val); |
516 | } else { | ||
517 | /* Initialize MSI-X irts to generate one interrupt | ||
518 | * per link | ||
519 | */ | ||
520 | msixvec = link * XLP_MSIXVEC_PER_LINK + i; | ||
521 | irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec); | ||
522 | nlm_pic_init_irt(nodep->picbase, irt, | ||
523 | PIC_PCIE_MSIX_IRQ(link), | ||
524 | node * nlm_threads_per_node(), 1); | ||
525 | } | ||
447 | 526 | ||
448 | /* Initialize MSI-X extended irq space for the link */ | 527 | /* Initialize MSI-X extended irq space for the link */ |
449 | irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i)); | 528 | irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i)); |
450 | irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq); | 529 | irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq); |
451 | irq_set_handler_data(irq, md); | 530 | irq_set_handler_data(irq, md); |
452 | } | 531 | } |
453 | |||
454 | } | 532 | } |
455 | 533 | ||
456 | void nlm_dispatch_msi(int node, int lirq) | 534 | void nlm_dispatch_msi(int node, int lirq) |
@@ -462,7 +540,11 @@ void nlm_dispatch_msi(int node, int lirq) | |||
462 | link = lirq - PIC_PCIE_LINK_MSI_IRQ_BASE; | 540 | link = lirq - PIC_PCIE_LINK_MSI_IRQ_BASE; |
463 | irqbase = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0)); | 541 | irqbase = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0)); |
464 | md = irq_get_handler_data(irqbase); | 542 | md = irq_get_handler_data(irqbase); |
465 | status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) & | 543 | if (cpu_is_xlp9xx()) |
544 | status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSI_STATUS) & | ||
545 | md->msi_enabled_mask; | ||
546 | else | ||
547 | status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) & | ||
466 | md->msi_enabled_mask; | 548 | md->msi_enabled_mask; |
467 | while (status) { | 549 | while (status) { |
468 | i = __ffs(status); | 550 | i = __ffs(status); |
@@ -480,10 +562,14 @@ void nlm_dispatch_msix(int node, int lirq) | |||
480 | link = lirq - PIC_PCIE_MSIX_IRQ_BASE; | 562 | link = lirq - PIC_PCIE_MSIX_IRQ_BASE; |
481 | irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0)); | 563 | irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0)); |
482 | md = irq_get_handler_data(irqbase); | 564 | md = irq_get_handler_data(irqbase); |
483 | status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS); | 565 | if (cpu_is_xlp9xx()) |
566 | status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSIX_STATUSX(link)); | ||
567 | else | ||
568 | status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS); | ||
484 | 569 | ||
485 | /* narrow it down to the MSI-x vectors for our link */ | 570 | /* narrow it down to the MSI-x vectors for our link */ |
486 | status = (status >> (link * XLP_MSIXVEC_PER_LINK)) & | 571 | if (!cpu_is_xlp9xx()) |
572 | status = (status >> (link * XLP_MSIXVEC_PER_LINK)) & | ||
487 | ((1 << XLP_MSIXVEC_PER_LINK) - 1); | 573 | ((1 << XLP_MSIXVEC_PER_LINK) - 1); |
488 | 574 | ||
489 | while (status) { | 575 | while (status) { |