diff options
author | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-09 21:10:34 -0400 |
---|---|---|
committer | Linus Torvalds <torvalds@linux-foundation.org> | 2014-06-09 21:10:34 -0400 |
commit | 82abb273d838318424644d8f02825db0fbbd400a (patch) | |
tree | e1ea8a92db4ba68f347249986ffe3a25ffbf8219 /arch/mips/pci | |
parent | 9b651cc2277b5e4883012ebab0fea2bcda4cbafa (diff) | |
parent | f8647b506d7116a1a3accd8d618184096e85f50b (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/Makefile | 2 | ||||
-rw-r--r-- | arch/mips/pci/fixup-malta.c | 6 | ||||
-rw-r--r-- | arch/mips/pci/msi-octeon.c | 6 | ||||
-rw-r--r-- | arch/mips/pci/msi-xlp.c | 184 | ||||
-rw-r--r-- | arch/mips/pci/ops-pmcmsp.c | 2 | ||||
-rw-r--r-- | arch/mips/pci/ops-tx3927.c | 2 | ||||
-rw-r--r-- | arch/mips/pci/ops-tx4927.c | 9 | ||||
-rw-r--r-- | arch/mips/pci/pci-virtio-guest.c | 131 |
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 \ | |||
21 | obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o | 21 | obj-$(CONFIG_MIPS_ALCHEMY) += pci-alchemy.o |
22 | obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o | 22 | obj-$(CONFIG_SOC_AR71XX) += pci-ar71xx.o |
23 | obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o | 23 | obj-$(CONFIG_PCI_AR724X) += pci-ar724x.o |
24 | 24 | obj-$(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, ®_val); | 108 | pci_read_config_byte(pdev, PIIX4_FUNC0_SERIRQC, ®_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, ®_val16); | ||
114 | pci_write_config_word(pdev, PCI_COMMAND, | ||
115 | reg_val16 | PCI_COMMAND_SPECIAL); | ||
110 | } | 116 | } |
111 | 117 | ||
112 | DECLARE_PCI_FIXUP_HEADER(PCI_VENDOR_ID_INTEL, PCI_DEVICE_ID_INTEL_82371AB_0, | 118 | DECLARE_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 */ |
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 = { |
@@ -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 | ||
448 | void nlm_dispatch_msi(int node, int lirq) | 526 | void 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 | |||
21 | union 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 | |||
33 | int pcibios_plat_dev_init(struct pci_dev *dev) | ||
34 | { | ||
35 | return 0; | ||
36 | } | ||
37 | |||
38 | int pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) | ||
39 | { | ||
40 | return ((pin + slot) % 4)+ MIPS_IRQ_PCIA; | ||
41 | } | ||
42 | |||
43 | static 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 | |||
56 | static 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 | |||
76 | static 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 | |||
95 | static struct pci_ops pci_virtio_guest_ops = { | ||
96 | .read = pci_virtio_guest_read_config, | ||
97 | .write = pci_virtio_guest_write_config, | ||
98 | }; | ||
99 | |||
100 | static struct resource pci_virtio_guest_mem_resource = { | ||
101 | .name = "Virtio MEM", | ||
102 | .flags = IORESOURCE_MEM, | ||
103 | .start = 0x10000000, | ||
104 | .end = 0x1dffffff | ||
105 | }; | ||
106 | |||
107 | static struct resource pci_virtio_guest_io_resource = { | ||
108 | .name = "Virtio IO", | ||
109 | .flags = IORESOURCE_IO, | ||
110 | .start = 0, | ||
111 | .end = 0xffff | ||
112 | }; | ||
113 | |||
114 | static 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 | |||
120 | static 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 | } | ||
131 | arch_initcall(pci_virtio_guest_setup); | ||