aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorJayachandran C <jchandra@broadcom.com>2013-12-21 06:22:27 -0500
committerRalf Baechle <ralf@linux-mips.org>2014-01-24 16:39:49 -0500
commitb6ba1c5294c3f51fd4cf8b0d60de4ba82ef2a1c9 (patch)
treef7d2f610de3852e8ded2d485c24bb52327039dea
parent98d4884ca55883e8b16180bd969a8bccaa885c80 (diff)
MIPS: PCI: Netlogic XLP9XX support
Add PCI support for Netlogic XLP9XX. The PCI registers and SoC bus numbers have changed in XLP9XX. Also skip a few (bus,dev,fn) combinations which have issues when read. Signed-off-by: Jayachandran C <jchandra@broadcom.com> Signed-off-by: John Crispin <blogic@openwrt.org> Patchwork: http://patchwork.linux-mips.org/patch/6284/
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/pcibus.h10
-rw-r--r--arch/mips/include/asm/netlogic/xlp-hal/xlp.h3
-rw-r--r--arch/mips/netlogic/xlp/nlm_hal.c5
-rw-r--r--arch/mips/pci/pci-xlp.c95
4 files changed, 90 insertions, 23 deletions
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
index 0fac32b1d8ba..d4deb87ad069 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/pcibus.h
@@ -63,6 +63,12 @@
63#define PCIE_INT_EN0 0x261 63#define PCIE_INT_EN0 0x261
64#define PCIE_INT_EN1 0x262 64#define PCIE_INT_EN1 0x262
65 65
66/* XLP9XX has basic changes */
67#define PCIE_9XX_BYTE_SWAP_MEM_BASE 0x25c
68#define PCIE_9XX_BYTE_SWAP_MEM_LIM 0x25d
69#define PCIE_9XX_BYTE_SWAP_IO_BASE 0x25e
70#define PCIE_9XX_BYTE_SWAP_IO_LIM 0x25f
71
66/* other */ 72/* other */
67#define PCIE_NLINKS 4 73#define PCIE_NLINKS 4
68 74
@@ -78,8 +84,8 @@
78 84
79#define nlm_read_pcie_reg(b, r) nlm_read_reg(b, r) 85#define nlm_read_pcie_reg(b, r) nlm_read_reg(b, r)
80#define nlm_write_pcie_reg(b, r, v) nlm_write_reg(b, r, v) 86#define nlm_write_pcie_reg(b, r, v) nlm_write_reg(b, r, v)
81#define nlm_get_pcie_base(node, inst) \ 87#define nlm_get_pcie_base(node, inst) nlm_pcicfg_base(cpu_is_xlp9xx() ? \
82 nlm_pcicfg_base(XLP_IO_PCIE_OFFSET(node, inst)) 88 XLP9XX_IO_PCIE_OFFSET(node, inst) : XLP_IO_PCIE_OFFSET(node, inst))
83 89
84#ifdef CONFIG_PCI_MSI 90#ifdef CONFIG_PCI_MSI
85void xlp_init_node_msi_irqs(int node, int link); 91void xlp_init_node_msi_irqs(int node, int link);
diff --git a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
index 9ccdb7d0f073..120c003c124d 100644
--- a/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
+++ b/arch/mips/include/asm/netlogic/xlp-hal/xlp.h
@@ -84,6 +84,9 @@ void xlp_mmu_init(void);
84void nlm_hal_init(void); 84void nlm_hal_init(void);
85int xlp_get_dram_map(int n, uint64_t *dram_map); 85int xlp_get_dram_map(int n, uint64_t *dram_map);
86 86
87struct pci_dev;
88int xlp_socdev_to_node(const struct pci_dev *dev);
89
87/* Device tree related */ 90/* Device tree related */
88void xlp_early_init_devtree(void); 91void xlp_early_init_devtree(void);
89void *xlp_dt_init(void *fdtp); 92void *xlp_dt_init(void *fdtp);
diff --git a/arch/mips/netlogic/xlp/nlm_hal.c b/arch/mips/netlogic/xlp/nlm_hal.c
index efd64ac1f407..e7ff2d37a464 100644
--- a/arch/mips/netlogic/xlp/nlm_hal.c
+++ b/arch/mips/netlogic/xlp/nlm_hal.c
@@ -76,6 +76,11 @@ int nlm_irq_to_irt(int irq)
76 return 133; 76 return 133;
77 case PIC_UART_1_IRQ: 77 case PIC_UART_1_IRQ:
78 return 134; 78 return 134;
79 case PIC_PCIE_LINK_LEGACY_IRQ(0):
80 case PIC_PCIE_LINK_LEGACY_IRQ(1):
81 case PIC_PCIE_LINK_LEGACY_IRQ(2):
82 case PIC_PCIE_LINK_LEGACY_IRQ(3):
83 return 191 + irq - PIC_PCIE_LINK_LEGACY_IRQ_BASE;
79 } 84 }
80 return -1; 85 return -1;
81 } 86 }
diff --git a/arch/mips/pci/pci-xlp.c b/arch/mips/pci/pci-xlp.c
index f390aa9970e6..7babf01600cb 100644
--- a/arch/mips/pci/pci-xlp.c
+++ b/arch/mips/pci/pci-xlp.c
@@ -67,9 +67,22 @@ static inline u32 pci_cfg_read_32bit(struct pci_bus *bus, unsigned int devfn,
67 u32 *cfgaddr; 67 u32 *cfgaddr;
68 68
69 where &= ~3; 69 where &= ~3;
70 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) {
71 return 0xffffffff; 84 return 0xffffffff;
72 85 }
73 cfgaddr = (u32 *)(pci_config_base + 86 cfgaddr = (u32 *)(pci_config_base +
74 pci_cfg_addr(bus->number, devfn, where)); 87 pci_cfg_addr(bus->number, devfn, where));
75 data = *cfgaddr; 88 data = *cfgaddr;
@@ -167,18 +180,35 @@ struct pci_dev *xlp_get_pcie_link(const struct pci_dev *dev)
167{ 180{
168 struct pci_bus *bus, *p; 181 struct pci_bus *bus, *p;
169 182
170 /* Find the bridge on bus 0 */
171 bus = dev->bus; 183 bus = dev->bus;
172 for (p = bus->parent; p && p->number != 0; p = p->parent)
173 bus = p;
174 184
175 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 }
198}
199
200int xlp_socdev_to_node(const struct pci_dev *lnkdev)
201{
202 if (cpu_is_xlp9xx())
203 return PCI_FUNC(lnkdev->bus->self->devfn);
204 else
205 return PCI_SLOT(lnkdev->devfn) / 8;
176} 206}
177 207
178int __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)
179{ 209{
180 struct pci_dev *lnkdev; 210 struct pci_dev *lnkdev;
181 int lnkslot, lnkfunc; 211 int lnkfunc, node;
182 212
183 /* 213 /*
184 * 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
@@ -187,9 +217,11 @@ int __init pcibios_map_irq(const struct pci_dev *dev, u8 slot, u8 pin)
187 lnkdev = xlp_get_pcie_link(dev); 217 lnkdev = xlp_get_pcie_link(dev);
188 if (lnkdev == NULL) 218 if (lnkdev == NULL)
189 return 0; 219 return 0;
220
190 lnkfunc = PCI_FUNC(lnkdev->devfn); 221 lnkfunc = PCI_FUNC(lnkdev->devfn);
191 lnkslot = PCI_SLOT(lnkdev->devfn); 222 node = xlp_socdev_to_node(lnkdev);
192 return nlm_irq_to_xirq(lnkslot / 8, PIC_PCIE_LINK_LEGACY_IRQ(lnkfunc)); 223
224 return nlm_irq_to_xirq(node, PIC_PCIE_LINK_LEGACY_IRQ(lnkfunc));
193} 225}
194 226
195/* Do platform specific device initialization at pci_enable_device() time */ 227/* Do platform specific device initialization at pci_enable_device() time */
@@ -216,17 +248,38 @@ static void xlp_config_pci_bswap(int node, int link)
216 * 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
217 * from the link's address ranges. 249 * from the link's address ranges.
218 */ 250 */
219 reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_BASE0 + link); 251 if (cpu_is_xlp9xx()) {
220 nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_BASE, reg); 252 reg = nlm_read_bridge_reg(nbubase,
221 253 BRIDGE_9XX_PCIEMEM_BASE0 + link);
222 reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEMEM_LIMIT0 + link); 254 nlm_write_pci_reg(lnkbase, PCIE_9XX_BYTE_SWAP_MEM_BASE, reg);
223 nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_MEM_LIM, reg | 0xfff); 255
224 256 reg = nlm_read_bridge_reg(nbubase,
225 reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_BASE0 + link); 257 BRIDGE_9XX_PCIEMEM_LIMIT0 + link);
226 nlm_write_pci_reg(lnkbase, PCIE_BYTE_SWAP_IO_BASE, reg); 258 nlm_write_pci_reg(lnkbase,
227 259 PCIE_9XX_BYTE_SWAP_MEM_LIM, reg | 0xfff);
228 reg = nlm_read_bridge_reg(nbubase, BRIDGE_PCIEIO_LIMIT0 + link); 260
229 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 }
230} 283}
231#else 284#else
232/* Swap configuration not needed in little-endian mode */ 285/* Swap configuration not needed in little-endian mode */
@@ -260,7 +313,7 @@ static int __init pcibios_init(void)
260 313
261 /* put in intpin and irq - u-boot does not */ 314 /* put in intpin and irq - u-boot does not */
262 reg = nlm_read_pci_reg(pciebase, 0xf); 315 reg = nlm_read_pci_reg(pciebase, 0xf);
263 reg &= ~0x1fu; 316 reg &= ~0x1ffu;
264 reg |= (1 << 8) | PIC_PCIE_LINK_LEGACY_IRQ(link); 317 reg |= (1 << 8) | PIC_PCIE_LINK_LEGACY_IRQ(link);
265 nlm_write_pci_reg(pciebase, 0xf, reg); 318 nlm_write_pci_reg(pciebase, 0xf, reg);
266 pr_info("XLP PCIe: Link %d-%d initialized.\n", n, link); 319 pr_info("XLP PCIe: Link %d-%d initialized.\n", n, link);