aboutsummaryrefslogtreecommitdiffstats
path: root/arch/mips/pci/pci-xlp.c
diff options
context:
space:
mode:
Diffstat (limited to 'arch/mips/pci/pci-xlp.c')
-rw-r--r--arch/mips/pci/pci-xlp.c110
1 files changed, 79 insertions, 31 deletions
diff --git a/arch/mips/pci/pci-xlp.c b/arch/mips/pci/pci-xlp.c
index 653d2db9e0c5..7babf01600cb 100644
--- a/arch/mips/pci/pci-xlp.c
+++ b/arch/mips/pci/pci-xlp.c
@@ -47,10 +47,11 @@
47#include <asm/netlogic/interrupt.h> 47#include <asm/netlogic/interrupt.h>
48#include <asm/netlogic/haldefs.h> 48#include <asm/netlogic/haldefs.h>
49#include <asm/netlogic/common.h> 49#include <asm/netlogic/common.h>
50#include <asm/netlogic/mips-extns.h>
50 51
51#include <asm/netlogic/xlp-hal/iomap.h> 52#include <asm/netlogic/xlp-hal/iomap.h>
52#include <asm/netlogic/xlp-hal/pic.h>
53#include <asm/netlogic/xlp-hal/xlp.h> 53#include <asm/netlogic/xlp-hal/xlp.h>
54#include <asm/netlogic/xlp-hal/pic.h>
54#include <asm/netlogic/xlp-hal/pcibus.h> 55#include <asm/netlogic/xlp-hal/pcibus.h>
55#include <asm/netlogic/xlp-hal/bridge.h> 56#include <asm/netlogic/xlp-hal/bridge.h>
56 57
@@ -66,9 +67,22 @@ static inline u32 pci_cfg_read_32bit(struct pci_bus *bus, unsigned int devfn,
66 u32 *cfgaddr; 67 u32 *cfgaddr;
67 68
68 where &= ~3; 69 where &= ~3;
69 if (bus->number == 0 && PCI_SLOT(devfn) == 1 && where == 0x954) 70 if (cpu_is_xlp9xx()) {
71 /* be very careful on SoC buses */
72 if (bus->number == 0) {
73 /* Scan only existing nodes - uboot bug? */
74 if (PCI_SLOT(devfn) != 0 ||
75 !nlm_node_present(PCI_FUNC(devfn)))
76 return 0xffffffff;
77 } else if (bus->parent->number == 0) { /* SoC bus */
78 if (PCI_SLOT(devfn) == 0) /* b.0.0 hangs */
79 return 0xffffffff;
80 if (devfn == 44) /* b.5.4 hangs */
81 return 0xffffffff;
82 }
83 } else if (bus->number == 0 && PCI_SLOT(devfn) == 1 && where == 0x954) {
70 return 0xffffffff; 84 return 0xffffffff;
71 85 }
72 cfgaddr = (u32 *)(pci_config_base + 86 cfgaddr = (u32 *)(pci_config_base +
73 pci_cfg_addr(bus->number, devfn, where)); 87 pci_cfg_addr(bus->number, devfn, where));
74 data = *cfgaddr; 88 data = *cfgaddr;
@@ -162,27 +176,39 @@ struct pci_controller nlm_pci_controller = {
162 .io_offset = 0x00000000UL, 176 .io_offset = 0x00000000UL,
163}; 177};
164 178
165static struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev) 179struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev)
166{ 180{
167 struct pci_bus *bus, *p; 181 struct pci_bus *bus, *p;
168 182
169 /* Find the bridge on bus 0 */
170 bus = dev->bus; 183 bus = dev->bus;
171 for (p = bus->parent; p && p->number != 0; p = p->parent)
172 bus = p;
173 184
174 return p ? bus->self : NULL; 185 if (cpu_is_xlp9xx()) {
186 /* find bus with grand parent number == 0 */
187 for (p = bus->parent; p && p->parent && p->parent->number != 0;
188 p = p->parent)
189 bus = p;
190 return (p && p->parent) ? bus->self : NULL;
191 } else {
192 /* Find the bridge on bus 0 */
193 for (p = bus->parent; p && p->number != 0; p = p->parent)
194 bus = p;
195
196 return p ? bus->self : NULL;
197 }
175} 198}
176 199
177static inline int nlm_pci_link_to_irq(int link) 200int xlp_socdev_to_node(const struct pci_dev *lnkdev)
178{ 201{
179 return PIC_PCIE_LINK_0_IRQ + link; 202 if (cpu_is_xlp9xx())
203 return PCI_FUNC(lnkdev->bus->self->devfn);
204 else
205 return PCI_SLOT(lnkdev->devfn) / 8;
180} 206}
181 207
182int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin) 208int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
183{ 209{
184 struct pci_dev *lnkdev; 210 struct pci_dev *lnkdev;
185 int lnkslot, lnkfunc; 211 int lnkfunc, node;
186 212
187 /* 213 /*
188 * For XLP PCIe, there is an IRQ per Link, find out which 214 * For XLP PCIe, there is an IRQ per Link, find out which
@@ -191,9 +217,11 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
191 lnkdev = xlp_get_pcie_link(dev); 217 lnkdev = xlp_get_pcie_link(dev);
192 if (lnkdev == NULL) 218 if (lnkdev == NULL)
193 return 0; 219 return 0;
220
194 lnkfunc = PCI_FUNC(lnkdev->devfn); 221 lnkfunc = PCI_FUNC(lnkdev->devfn);
195 lnkslot = PCI_SLOT(lnkdev->devfn); 222 node = xlp_socdev_to_node(lnkdev);
196 return nlm_irq_to_xirq(lnkslot / 8, nlm_pci_link_to_irq(lnkfunc)); 223
224 return nlm_irq_to_xirq(node, PIC_PCIE_LINK_LEGACY_IRQ(lnkfunc));
197} 225}
198 226
199/* Do platform specific device initialization at pci_enable_device() time */ 227/* Do platform specific device initialization at pci_enable_device() time */
@@ -220,17 +248,38 @@ static void xlp_config_pci_bswap(int node, int link)
220 * Enable byte swap in hardware. Program each link's PCIe SWAP regions 248 * Enable byte swap in hardware. Program each link's PCIe SWAP regions
221 * from the link's address ranges. 249 * from the link's address ranges.
222 */ 250 */
223 reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_BASE0 + link); 251 if (cpu_is_xlp9xx()) {
224 nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_BASE, reg); 252 reg = nlm_read_bridge_reg(nbubase,
225 253 BRIDGE_9XX_PCIEMEM_BASE0 + link);
226 reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_LIMIT0 + link); 254 nlm_write_pci_reg(lnkbase, PCIE_9XX_BYTE_SWAP_MEM_BASE, reg);
227 nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_LIM, reg | 0xfff); 255
228 256 reg = nlm_read_bridge_reg(nbubase,
229 reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_BASE0 + link); 257 BRIDGE_9XX_PCIEMEM_LIMIT0 + link);
230 nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_BASE, reg); 258 nlm_write_pci_reg(lnkbase,
231 259 PCIE_9XX_BYTE_SWAP_MEM_LIM, reg | 0xfff);
232 reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_LIMIT0 + link); 260
233 nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_LIM, reg | 0xfff); 261 reg = nlm_read_bridge_reg(nbubase,
262 BRIDGE_9XX_PCIEIO_BASE0 + link);
263 nlm_write_pci_reg(lnkbase, PCIE_9XX_BYTE_SWAP_IO_BASE, reg);
264
265 reg = nlm_read_bridge_reg(nbubase,
266 BRIDGE_9XX_PCIEIO_LIMIT0 + link);
267 nlm_write_pci_reg(lnkbase,
268 PCIE_9XX_BYTE_SWAP_IO_LIM, reg | 0xfff);
269 } else {
270 reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_BASE0 + link);
271 nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_BASE, reg);
272
273 reg = nlm_read_bridge_reg(nbubase,
274 BRIDGE_PCIEMEM_LIMIT0 + link);
275 nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_LIM, reg | 0xfff);
276
277 reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_BASE0 + link);
278 nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_BASE, reg);
279
280 reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_LIMIT0 + link);
281 nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_LIM, reg | 0xfff);
282 }
234} 283}
235#else 284#else
236/* Swap configuration not needed in little-endian mode */ 285/* Swap configuration not needed in little-endian mode */
@@ -239,7 +288,6 @@ static inline void xlp_config_pci_bswap(int node, int link) {}
239 288
240static int __init pcibios_init(void) 289static int __init pcibios_init(void)
241{ 290{
242 struct nlm_soc_info *nodep;
243 uint64_t pciebase; 291 uint64_t pciebase;
244 int link, n; 292 int link, n;
245 u32 reg; 293 u32 reg;
@@ -253,20 +301,20 @@ static int __init pcibios_init(void)
253 ioport_resource.end = ~0; 301 ioport_resource.end = ~0;
254 302
255 for (n = 0; n < NLM_NR_NODES; n++) { 303 for (n = 0; n < NLM_NR_NODES; n++) {
256 nodep = nlm_get_node(n); 304 if (!nlm_node_present(n))
257 if (!nodep->coremask) 305 continue;
258 continue; /* node does not exist */
259 306
260 for (link = 0; link < 4; link++) { 307 for (link = 0; link < PCIE_NLINKS; link++) {
261 pciebase = nlm_get_pcie_base(n, link); 308 pciebase = nlm_get_pcie_base(n, link);
262 if (nlm_read_pci_reg(pciebase, 0) == 0xffffffff) 309 if (nlm_read_pci_reg(pciebase, 0) == 0xffffffff)
263 continue; 310 continue;
264 xlp_config_pci_bswap(n, link); 311 xlp_config_pci_bswap(n, link);
312 xlp_init_node_msi_irqs(n, link);
265 313
266 /* put in intpin and irq - u-boot does not */ 314 /* put in intpin and irq - u-boot does not */
267 reg = nlm_read_pci_reg(pciebase, 0xf); 315 reg = nlm_read_pci_reg(pciebase, 0xf);
268 reg &= ~0x1fu; 316 reg &= ~0x1ffu;
269 reg |= (1 << 8) | nlm_pci_link_to_irq(link); 317 reg |= (1 << 8) | PIC_PCIE_LINK_LEGACY_IRQ(link);
270 nlm_write_pci_reg(pciebase, 0xf, reg); 318 nlm_write_pci_reg(pciebase, 0xf, reg);
271 pr_info("XLP PCIe: Link %d-%d initialized.\n", n, link); 319 pr_info("XLP PCIe: Link %d-%d initialized.\n", n, link);
272 } 320 }