aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/pci
diff options
context:
space:
mode:
authorLinus Torvalds <torvalds@linux-foundation.org>2014-06-09 21:10:34 -0400
committerLinus Torvalds <torvalds@linux-foundation.org>2014-06-09 21:10:34 -0400
commit82abb273d838318424644d8f02825db0fbbd400a (patch)
treee1ea8a92db4ba68f347249986ffe3a25ffbf8219 /arch/mips/pci
parent9b651cc2277b5e4883012ebab0fea2bcda4cbafa (diff)
parentf8647b506d7116a1a3accd8d618184096e85f50b (diff)
Merge branch 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus
Pull MIPS updates from Ralf Baechle: - three fixes for 3.15 that didn't make it in time - limited Octeon 3 support. - paravirtualization support - improvment to platform support for Netlogix SOCs. - add support for powering down the Malta eval board in software - add many instructions to the in-kernel microassembler. - add support for the BPF JIT. - minor cleanups of the BCM47xx code. - large cleanup of math emu code resulting in significant code size reduction, better readability of the code and more accurate emulation. - improvments to the MIPS CPS code. - support C3 power status for the R4k count/compare clock device. - improvments to the GIO support for older SGI workstations. - increase number of supported CPUs to 256; this can be reached on certain embedded multithreaded ccNUMA configurations. - various small cleanups, updates and fixes * 'upstream' of git://git.linux-mips.org/pub/scm/ralf/upstream-linus: (173 commits) MIPS: IP22/IP28: Improve GIO support MIPS: Octeon: Add twsi interrupt initialization for OCTEON 3XXX, 5XXX, 63XX DEC: Document the R4k MB ASIC mini interrupt controller DEC: Add self as the maintainer MIPS: Add microMIPS MSA support. MIPS: Replace calls to obsolete strict_strto call with kstrto* equivalents. MIPS: Replace obsolete strict_strto call with kstrto MIPS: BFP: Simplify code slightly. MIPS: Call find_vma with the mmap_sem held MIPS: Fix 'write_msa_##' inline macro. MIPS: Fix MSA toolchain support detection. mips: Update the email address of Geert Uytterhoeven MIPS: Add minimal defconfig for mips_paravirt MIPS: Enable build for new system 'paravirt' MIPS: paravirt: Add pci controller for virtio MIPS: Add code for new system 'paravirt' MIPS: Add functions for hypervisor call MIPS: OCTEON: Add OCTEON3 to __get_cpu_type MIPS: Add function get_ebase_cpunum MIPS: Add minimal support for OCTEON3 to c-r4k.c ...
Diffstat (limited to 'arch/mips/pci')
-rw-r--r--arch/mips/pci/Makefile2
-rw-r--r--arch/mips/pci/fixup-malta.c6
-rw-r--r--arch/mips/pci/msi-octeon.c6
-rw-r--r--arch/mips/pci/msi-xlp.c184
-rw-r--r--arch/mips/pci/ops-pmcmsp.c2
-rw-r--r--arch/mips/pci/ops-tx3927.c2
-rw-r--r--arch/mips/pci/ops-tx4927.c9
-rw-r--r--arch/mips/pci/pci-virtio-guest.c131
8 files changed, 287 insertions, 55 deletions
diff --git a/arch/mips/pci/Makefile b/arch/mips/pci/Makefile
index d61138a177cc..ff8a5539b363 100644
--- a/arch/mips/pci/Makefile
+++ b/arch/mips/pci/Makefile
@@ -21,7 +21,7 @@ obj-$(CONFIG_BCM63XX) += pci-bcm63xx.o fixup-bcm63xx.o \
21obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o 21obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o
22obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o 22obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o
23obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o 23obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o
24 24obj-$(CONFIG_MIPS_PCI_VIRTIO) += pci-virtio-guest.o
25# 25#
26# These are still pretty much in the old state, watch, go blind. 26# These are still pretty much in the old state, watch, go blind.
27# 27#
diff --git a/arch/mips/pci/fixup-malta.c b/arch/mips/pci/fixup-malta.c
index 2f9e52a1a750..40e920c653cc 100644
--- a/arch/mips/pci/fixup-malta.c
+++ b/arch/mips/pci/fixup-malta.c
@@ -68,6 +68,7 @@ static void malta_piix_func0_fixup(struct pci_dev *pdev)
68{ 68{
69 unsigned char reg_val; 69 unsigned char reg_val;
70 u32 reg_val32; 70 u32 reg_val32;
71 u16 reg_val16;
71 /* PIIX PIRQC[A:D] irq mappings */ 72 /* PIIX PIRQC[A:D] irq mappings */
72 static int piixirqmap[PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MAX] = { 73 static int piixirqmap[PIIX4_FUNC0_PIRQRC_IRQ_ROUTING_MAX] = {
73 0, 0, 0, 3, 74 0, 0, 0, 3,
@@ -107,6 +108,11 @@ static void malta_piix_func0_fixup(struct pci_dev *pdev)
107 pci_read_config_byte(pdev, PIIX4_FUNC0_SERIRQC, &reg_val); 108 pci_read_config_byte(pdev, PIIX4_FUNC0_SERIRQC, &reg_val);
108 reg_val |= PIIX4_FUNC0_SERIRQC_EN | PIIX4_FUNC0_SERIRQC_CONT; 109 reg_val |= PIIX4_FUNC0_SERIRQC_EN | PIIX4_FUNC0_SERIRQC_CONT;
109 pci_write_config_byte(pdev, PIIX4_FUNC0_SERIRQC, reg_val); 110 pci_write_config_byte(pdev, PIIX4_FUNC0_SERIRQC, reg_val);
111
112 /* Enable response to special cycles */
113 pci_read_config_word(pdev, PCI_COMMAND, &reg_val16);
114 pci_write_config_word(pdev, PCI_COMMAND,
115 reg_val16 | PCI_COMMAND_SPECIAL);
110} 116}
111 117
112DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, 118DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0,
diff --git a/arch/mips/pci/msi-octeon.c b/arch/mips/pci/msi-octeon.c
index 2b91b0e61566..ab0c5d14c6f7 100644
--- a/arch/mips/pci/msi-octeon.c
+++ b/arch/mips/pci/msi-octeon.c
@@ -15,6 +15,7 @@
15#include <asm/octeon/cvmx-npi-defs.h> 15#include <asm/octeon/cvmx-npi-defs.h>
16#include <asm/octeon/cvmx-pci-defs.h> 16#include <asm/octeon/cvmx-pci-defs.h>
17#include <asm/octeon/cvmx-npei-defs.h> 17#include <asm/octeon/cvmx-npei-defs.h>
18#include <asm/octeon/cvmx-sli-defs.h>
18#include <asm/octeon/cvmx-pexp-defs.h> 19#include <asm/octeon/cvmx-pexp-defs.h>
19#include <asm/octeon/pci-octeon.h> 20#include <asm/octeon/pci-octeon.h>
20 21
@@ -162,6 +163,11 @@ msi_irq_allocated:
162 msg.address_lo = (0 + CVMX_NPEI_PCIE_MSI_RCV) & 0xffffffff; 163 msg.address_lo = (0 + CVMX_NPEI_PCIE_MSI_RCV) & 0xffffffff;
163 msg.address_hi = (0 + CVMX_NPEI_PCIE_MSI_RCV) >> 32; 164 msg.address_hi = (0 + CVMX_NPEI_PCIE_MSI_RCV) >> 32;
164 break; 165 break;
166 case OCTEON_DMA_BAR_TYPE_PCIE2:
167 /* When using PCIe2, Bar 0 is based at 0 */
168 msg.address_lo = (0 + CVMX_SLI_PCIE_MSI_RCV) & 0xffffffff;
169 msg.address_hi = (0 + CVMX_SLI_PCIE_MSI_RCV) >> 32;
170 break;
165 default: 171 default:
166 panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type"); 172 panic("arch_setup_msi_irq: Invalid octeon_dma_bar_type");
167 } 173 }
diff --git a/arch/mips/pci/msi-xlp.c b/arch/mips/pci/msi-xlp.c
index 3249685e03ad..fa374fe3746b 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 */
63static inline int nlm_link_msiirq(int link, int msivec) 63static 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 */
68static inline int nlm_irq_msivec(int irq) 69static 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 */
73static inline int nlm_irq_msilink(int irq) 75static 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 */
84static inline int nlm_link_msixirq(int link, int bit) 91static 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 */
89static inline int nlm_irq_msixvec(int irq) 97static 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
94static inline int nlm_irq_msixlink(int irq) 102/* get the link from MSIX vec */
103static 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
166static struct irq_chip xlp_msi_chip = { 190static 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 */
184static void xlp_msix_mask_ack(struct irq_data *d) 212static 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
201static struct irq_chip xlp_msix_chip = { 240static struct irq_chip xlp_msix_chip = {
@@ -219,10 +258,18 @@ static void xlp_config_link_msi(uint64_t lnkbase, int lirq, uint64_t msiaddr)
219{ 258{
220 u32 val; 259 u32 val;
221 260
222 val = nlm_read_reg(lnkbase, PCIE_INT_EN0); 261 if (cpu_is_xlp9xx()) {
223 if ((val & 0x200) == 0) { 262 val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0);
224 val |= 0x200; /* MSI Interrupt enable */ 263 if ((val & 0x200) == 0) {
225 nlm_write_reg(lnkbase, PCIE_INT_EN0, val); 264 val |= 0x200; /* MSI Interrupt enable */
265 nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val);
266 }
267 } else {
268 val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
269 if ((val & 0x200) == 0) {
270 val |= 0x200;
271 nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
272 }
226 } 273 }
227 274
228 val = nlm_read_reg(lnkbase, 0x1); /* CMD */ 275 val = nlm_read_reg(lnkbase, 0x1); /* CMD */
@@ -269,9 +316,12 @@ static int xlp_setup_msi(uint64_t lnkbase, int node, int link,
269 316
270 spin_lock_irqsave(&md->msi_lock, flags); 317 spin_lock_irqsave(&md->msi_lock, flags);
271 if (md->msi_alloc_mask == 0) { 318 if (md->msi_alloc_mask == 0) {
272 /* switch the link IRQ to MSI range */
273 xlp_config_link_msi(lnkbase, lirq, msiaddr); 319 xlp_config_link_msi(lnkbase, lirq, msiaddr);
274 irt = PIC_IRT_PCIE_LINK_INDEX(link); 320 /* switch the link IRQ to MSI range */
321 if (cpu_is_xlp9xx())
322 irt = PIC_9XX_IRT_PCIE_LINK_INDEX(link);
323 else
324 irt = PIC_IRT_PCIE_LINK_INDEX(link);
275 nlm_setup_pic_irq(node, lirq, lirq, irt); 325 nlm_setup_pic_irq(node, lirq, lirq, irt);
276 nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq, 326 nlm_pic_init_irt(nlm_get_node(node)->picbase, irt, lirq,
277 node * nlm_threads_per_node(), 1 /*en */); 327 node * nlm_threads_per_node(), 1 /*en */);
@@ -311,10 +361,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr)
311 val |= 0x80000000U; 361 val |= 0x80000000U;
312 nlm_write_reg(lnkbase, 0x2C, val); 362 nlm_write_reg(lnkbase, 0x2C, val);
313 } 363 }
314 val = nlm_read_reg(lnkbase, PCIE_INT_EN0); 364
315 if ((val & 0x200) == 0) { 365 if (cpu_is_xlp9xx()) {
316 val |= 0x200; /* MSI Interrupt enable */ 366 val = nlm_read_reg(lnkbase, PCIE_9XX_INT_EN0);
317 nlm_write_reg(lnkbase, PCIE_INT_EN0, val); 367 if ((val & 0x200) == 0) {
368 val |= 0x200; /* MSI Interrupt enable */
369 nlm_write_reg(lnkbase, PCIE_9XX_INT_EN0, val);
370 }
371 } else {
372 val = nlm_read_reg(lnkbase, PCIE_INT_EN0);
373 if ((val & 0x200) == 0) {
374 val |= 0x200; /* MSI Interrupt enable */
375 nlm_write_reg(lnkbase, PCIE_INT_EN0, val);
376 }
318 } 377 }
319 378
320 val = nlm_read_reg(lnkbase, 0x1); /* CMD */ 379 val = nlm_read_reg(lnkbase, 0x1); /* CMD */
@@ -329,10 +388,19 @@ static void xlp_config_link_msix(uint64_t lnkbase, int lirq, uint64_t msixaddr)
329 val |= (1 << 8) | lirq; 388 val |= (1 << 8) | lirq;
330 nlm_write_pci_reg(lnkbase, 0xf, val); 389 nlm_write_pci_reg(lnkbase, 0xf, val);
331 390
332 /* MSI-X addresses */ 391 if (cpu_is_xlp9xx()) {
333 nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE, msixaddr >> 8); 392 /* MSI-X addresses */
334 nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT, 393 nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_BASE,
335 (msixaddr + MSI_ADDR_SZ) >> 8); 394 msixaddr >> 8);
395 nlm_write_reg(lnkbase, PCIE_9XX_BRIDGE_MSIX_ADDR_LIMIT,
396 (msixaddr + MSI_ADDR_SZ) >> 8);
397 } else {
398 /* MSI-X addresses */
399 nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_BASE,
400 msixaddr >> 8);
401 nlm_write_reg(lnkbase, PCIE_BRIDGE_MSIX_ADDR_LIMIT,
402 (msixaddr + MSI_ADDR_SZ) >> 8);
403 }
336} 404}
337 405
338/* 406/*
@@ -369,6 +437,7 @@ static int xlp_setup_msix(uint64_t lnkbase, int node, int link,
369 437
370 xirq += t; 438 xirq += t;
371 msixvec = nlm_irq_msixvec(xirq); 439 msixvec = nlm_irq_msixvec(xirq);
440
372 msg.address_hi = msixaddr >> 32; 441 msg.address_hi = msixaddr >> 32;
373 msg.address_lo = msixaddr & 0xffffffff; 442 msg.address_lo = msixaddr & 0xffffffff;
374 msg.data = 0xc00 | msixvec; 443 msg.data = 0xc00 | msixvec;
@@ -409,7 +478,7 @@ void __init xlp_init_node_msi_irqs(int node, int link)
409{ 478{
410 struct nlm_soc_info *nodep; 479 struct nlm_soc_info *nodep;
411 struct xlp_msi_data *md; 480 struct xlp_msi_data *md;
412 int irq, i, irt, msixvec; 481 int irq, i, irt, msixvec, val;
413 482
414 pr_info("[%d %d] Init node PCI IRT\n", node, link); 483 pr_info("[%d %d] Init node PCI IRT\n", node, link);
415 nodep = nlm_get_node(node); 484 nodep = nlm_get_node(node);
@@ -430,19 +499,28 @@ void __init xlp_init_node_msi_irqs(int node, int link)
430 irq_set_handler_data(i, md); 499 irq_set_handler_data(i, md);
431 } 500 }
432 501
433 for (i = 0; i < XLP_MSIXVEC_PER_LINK; i++) { 502 for (i = 0; i < XLP_MSIXVEC_PER_LINK ; i++) {
434 /* Initialize MSI-X irts to generate one interrupt per link */ 503 if (cpu_is_xlp9xx()) {
435 msixvec = link * XLP_MSIXVEC_PER_LINK + i; 504 val = ((node * nlm_threads_per_node()) << 7 |
436 irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec); 505 PIC_PCIE_MSIX_IRQ(link) << 1 | 0 << 0);
437 nlm_pic_init_irt(nodep->picbase, irt, PIC_PCIE_MSIX_IRQ(link), 506 nlm_write_pcie_reg(md->lnkbase, PCIE_9XX_MSIX_VECX(i +
438 node * nlm_threads_per_node(), 1 /* enable */); 507 (link * XLP_MSIXVEC_PER_LINK)), val);
508 } else {
509 /* Initialize MSI-X irts to generate one interrupt
510 * per link
511 */
512 msixvec = link * XLP_MSIXVEC_PER_LINK + i;
513 irt = PIC_IRT_PCIE_MSIX_INDEX(msixvec);
514 nlm_pic_init_irt(nodep->picbase, irt,
515 PIC_PCIE_MSIX_IRQ(link),
516 node * nlm_threads_per_node(), 1);
517 }
439 518
440 /* Initialize MSI-X extended irq space for the link */ 519 /* Initialize MSI-X extended irq space for the link */
441 irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i)); 520 irq = nlm_irq_to_xirq(node, nlm_link_msixirq(link, i));
442 irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq); 521 irq_set_chip_and_handler(irq, &xlp_msix_chip, handle_level_irq);
443 irq_set_handler_data(irq, md); 522 irq_set_handler_data(irq, md);
444 } 523 }
445
446} 524}
447 525
448void nlm_dispatch_msi(int node, int lirq) 526void nlm_dispatch_msi(int node, int lirq)
@@ -454,7 +532,11 @@ void nlm_dispatch_msi(int node, int lirq)
454 link = lirq - PIC_PCIE_LINK_MSI_IRQ_BASE; 532 link = lirq - PIC_PCIE_LINK_MSI_IRQ_BASE;
455 irqbase = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0)); 533 irqbase = nlm_irq_to_xirq(node, nlm_link_msiirq(link, 0));
456 md = irq_get_handler_data(irqbase); 534 md = irq_get_handler_data(irqbase);
457 status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) & 535 if (cpu_is_xlp9xx())
536 status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSI_STATUS) &
537 md->msi_enabled_mask;
538 else
539 status = nlm_read_reg(md->lnkbase, PCIE_MSI_STATUS) &
458 md->msi_enabled_mask; 540 md->msi_enabled_mask;
459 while (status) { 541 while (status) {
460 i = __ffs(status); 542 i = __ffs(status);
@@ -472,10 +554,14 @@ void nlm_dispatch_msix(int node, int lirq)
472 link = lirq - PIC_PCIE_MSIX_IRQ_BASE; 554 link = lirq - PIC_PCIE_MSIX_IRQ_BASE;
473 irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0)); 555 irqbase = nlm_irq_to_xirq(node, nlm_link_msixirq(link, 0));
474 md = irq_get_handler_data(irqbase); 556 md = irq_get_handler_data(irqbase);
475 status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS); 557 if (cpu_is_xlp9xx())
558 status = nlm_read_reg(md->lnkbase, PCIE_9XX_MSIX_STATUSX(link));
559 else
560 status = nlm_read_reg(md->lnkbase, PCIE_MSIX_STATUS);
476 561
477 /* narrow it down to the MSI-x vectors for our link */ 562 /* narrow it down to the MSI-x vectors for our link */
478 status = (status >> (link * XLP_MSIXVEC_PER_LINK)) & 563 if (!cpu_is_xlp9xx())
564 status = (status >> (link * XLP_MSIXVEC_PER_LINK)) &
479 ((1 << XLP_MSIXVEC_PER_LINK) - 1); 565 ((1 << XLP_MSIXVEC_PER_LINK) - 1);
480 566
481 while (status) { 567 while (status) {
diff --git a/arch/mips/pci/ops-pmcmsp.c b/arch/mips/pci/ops-pmcmsp.c
index 3d27800edba2..50034f985be1 100644
--- a/arch/mips/pci/ops-pmcmsp.c
+++ b/arch/mips/pci/ops-pmcmsp.c
@@ -7,7 +7,7 @@
7 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net 7 * Author: Jun Sun, jsun@mvista.com or jsun@junsun.net
8 * 8 *
9 * Much of the code is derived from the original DDB5074 port by 9 * Much of the code is derived from the original DDB5074 port by
10 * Geert Uytterhoeven <geert@sonycom.com> 10 * Geert Uytterhoeven <geert@linux-m68k.org>
11 * 11 *
12 * This program is free software; you can redistribute it and/or modify it 12 * This program is free software; you can redistribute it and/or modify it
13 * under the terms of the GNU General Public License as published by the 13 * under the terms of the GNU General Public License as published by the
diff --git a/arch/mips/pci/ops-tx3927.c b/arch/mips/pci/ops-tx3927.c
index 02d64f77e967..d35dc9c9ab9d 100644
--- a/arch/mips/pci/ops-tx3927.c
+++ b/arch/mips/pci/ops-tx3927.c
@@ -11,7 +11,7 @@
11 * Define the pci_ops for TX3927. 11 * Define the pci_ops for TX3927.
12 * 12 *
13 * Much of the code is derived from the original DDB5074 port by 13 * Much of the code is derived from the original DDB5074 port by
14 * Geert Uytterhoeven <geert@sonycom.com> 14 * Geert Uytterhoeven <geert@linux-m68k.org>
15 * 15 *
16 * This program is free software; you can redistribute it and/or modify it 16 * This program is free software; you can redistribute it and/or modify it
17 * under the terms of the GNU General Public License as published by the 17 * under the terms of the GNU General Public License as published by the
diff --git a/arch/mips/pci/ops-tx4927.c b/arch/mips/pci/ops-tx4927.c
index 3d5df514d024..0e046d82e4e3 100644
--- a/arch/mips/pci/ops-tx4927.c
+++ b/arch/mips/pci/ops-tx4927.c
@@ -202,17 +202,20 @@ char *tx4927_pcibios_setup(char *str)
202 unsigned long val; 202 unsigned long val;
203 203
204 if (!strncmp(str, "trdyto=", 7)) { 204 if (!strncmp(str, "trdyto=", 7)) {
205 if (strict_strtoul(str + 7, 0, &val) == 0) 205 u8 val = 0;
206 if (kstrtou8(str + 7, 0, &val) == 0)
206 tx4927_pci_opts.trdyto = val; 207 tx4927_pci_opts.trdyto = val;
207 return NULL; 208 return NULL;
208 } 209 }
209 if (!strncmp(str, "retryto=", 8)) { 210 if (!strncmp(str, "retryto=", 8)) {
210 if (strict_strtoul(str + 8, 0, &val) == 0) 211 u8 val = 0;
212 if (kstrtou8(str + 8, 0, &val) == 0)
211 tx4927_pci_opts.retryto = val; 213 tx4927_pci_opts.retryto = val;
212 return NULL; 214 return NULL;
213 } 215 }
214 if (!strncmp(str, "gbwc=", 5)) { 216 if (!strncmp(str, "gbwc=", 5)) {
215 if (strict_strtoul(str + 5, 0, &val) == 0) 217 u16 val;
218 if (kstrtou16(str + 5, 0, &val) == 0)
216 tx4927_pci_opts.gbwc = val; 219 tx4927_pci_opts.gbwc = val;
217 return NULL; 220 return NULL;
218 } 221 }
diff --git a/arch/mips/pci/pci-virtio-guest.c b/arch/mips/pci/pci-virtio-guest.c
new file mode 100644
index 000000000000..40a078bc4617
--- /dev/null
+++ b/arch/mips/pci/pci-virtio-guest.c
@@ -0,0 +1,131 @@
1/*
2 * This file is subject to the terms and conditions of the GNU General Public
3 * License. See the file "COPYING" in the main directory of this archive
4 * for more details.
5 *
6 * Copyright (C) 2013 Cavium, Inc.
7 */
8
9#include <linux/kernel.h>
10#include <linux/init.h>
11#include <linux/interrupt.h>
12#include <linux/pci.h>
13
14#include <uapi/asm/bitfield.h>
15#include <asm/byteorder.h>
16#include <asm/io.h>
17
18#define PCI_CONFIG_ADDRESS 0xcf8
19#define PCI_CONFIG_DATA 0xcfc
20
21union pci_config_address {
22 struct {
23 __BITFIELD_FIELD(unsigned enable_bit : 1, /* 31 */
24 __BITFIELD_FIELD(unsigned reserved : 7, /* 30 .. 24 */
25 __BITFIELD_FIELD(unsigned bus_number : 8, /* 23 .. 16 */
26 __BITFIELD_FIELD(unsigned devfn_number : 8, /* 15 .. 8 */
27 __BITFIELD_FIELD(unsigned register_number : 8, /* 7 .. 0 */
28 )))));
29 };
30 u32 w;
31};
32
33int pcibios_plat_dev_init(struct pci_dev *dev)
34{
35 return 0;
36}
37
38int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
39{
40 return ((pin + slot) % 4)+ MIPS_IRQ_PCIA;
41}
42
43static void pci_virtio_guest_write_config_addr(struct pci_bus *bus,
44 unsigned int devfn, int reg)
45{
46 union pci_config_address pca = { .w = 0 };
47
48 pca.register_number = reg;
49 pca.devfn_number = devfn;
50 pca.bus_number = bus->number;
51 pca.enable_bit = 1;
52
53 outl(pca.w, PCI_CONFIG_ADDRESS);
54}
55
56static int pci_virtio_guest_write_config(struct pci_bus *bus,
57 unsigned int devfn, int reg, int size, u32 val)
58{
59 pci_virtio_guest_write_config_addr(bus, devfn, reg);
60
61 switch (size) {
62 case 1:
63 outb(val, PCI_CONFIG_DATA + (reg & 3));
64 break;
65 case 2:
66 outw(val, PCI_CONFIG_DATA + (reg & 2));
67 break;
68 case 4:
69 outl(val, PCI_CONFIG_DATA);
70 break;
71 }
72
73 return PCIBIOS_SUCCESSFUL;
74}
75
76static int pci_virtio_guest_read_config(struct pci_bus *bus, unsigned int devfn,
77 int reg, int size, u32 *val)
78{
79 pci_virtio_guest_write_config_addr(bus, devfn, reg);
80
81 switch (size) {
82 case 1:
83 *val = inb(PCI_CONFIG_DATA + (reg & 3));
84 break;
85 case 2:
86 *val = inw(PCI_CONFIG_DATA + (reg & 2));
87 break;
88 case 4:
89 *val = inl(PCI_CONFIG_DATA);
90 break;
91 }
92 return PCIBIOS_SUCCESSFUL;
93}
94
95static struct pci_ops pci_virtio_guest_ops = {
96 .read = pci_virtio_guest_read_config,
97 .write = pci_virtio_guest_write_config,
98};
99
100static struct resource pci_virtio_guest_mem_resource = {
101 .name = "Virtio MEM",
102 .flags = IORESOURCE_MEM,
103 .start = 0x10000000,
104 .end = 0x1dffffff
105};
106
107static struct resource pci_virtio_guest_io_resource = {
108 .name = "Virtio IO",
109 .flags = IORESOURCE_IO,
110 .start = 0,
111 .end = 0xffff
112};
113
114static struct pci_controller pci_virtio_guest_controller = {
115 .pci_ops = &pci_virtio_guest_ops,
116 .mem_resource = &pci_virtio_guest_mem_resource,
117 .io_resource = &pci_virtio_guest_io_resource,
118};
119
120static int __init pci_virtio_guest_setup(void)
121{
122 pr_err("pci_virtio_guest_setup\n");
123
124 /* Virtio comes pre-assigned */
125 pci_set_flags(PCI_PROBE_ONLY);
126
127 pci_virtio_guest_controller.io_map_base = mips_io_port_base;
128 register_pci_controller(&pci_virtio_guest_controller);
129 return 0;
130}
131arch_initcall(pci_virtio_guest_setup);