aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorAnton Vorontsov <avorontsov@ru.mvista.com>2009-01-08 16:55:39 -0500
committerKumar Gala <galak@kernel.crashing.org>2009-01-28 19:16:45 -0500
commit598804cd041c395ce87302af9088b2f227196185 (patch)
tree345914bdf8ee69ab0542f51c3ae421226a8bec27
parent18e352e4a73465349711a9324767e1b2453383e2 (diff)
powerpc/fsl_pci: Add MPC83xx PCI-E controller RC mode support
This patch adds support for PCI-Express controllers as found on the newer MPC83xx chips. The work is loosely based on the Tony Li's patch[1], but unlike the original patch, this patch implements sliding window for the Type 1 transactions using outbound window translations, so we don't have to ioremap the whole PCI-E configuration space. [1] http://ozlabs.org/pipermail/linuxppc-dev/2008-January/049028.html Signed-off-by: Tony Li <tony.li@freescale.com> Signed-off-by: Anton Vorontsov <avorontsov@ru.mvista.com> Signed-off-by: Kumar Gala <galak@kernel.crashing.org>
-rw-r--r--arch/powerpc/sysdev/fsl_pci.c244
-rw-r--r--include/linux/pci_ids.h8
2 files changed, 228 insertions, 24 deletions
diff --git a/arch/powerpc/sysdev/fsl_pci.c b/arch/powerpc/sysdev/fsl_pci.c
index 9817f63723dd..78021d8afc53 100644
--- a/arch/powerpc/sysdev/fsl_pci.c
+++ b/arch/powerpc/sysdev/fsl_pci.c
@@ -1,12 +1,16 @@
1/* 1/*
2 * MPC83xx/85xx/86xx PCI/PCIE support routing. 2 * MPC83xx/85xx/86xx PCI/PCIE support routing.
3 * 3 *
4 * Copyright 2007,2008 Freescale Semiconductor, Inc 4 * Copyright 2007-2009 Freescale Semiconductor, Inc.
5 * Copyright 2008-2009 MontaVista Software, Inc.
5 * 6 *
6 * Initial author: Xianghua Xiao <x.xiao@freescale.com> 7 * Initial author: Xianghua Xiao <x.xiao@freescale.com>
7 * Recode: ZHANG WEI <wei.zhang@freescale.com> 8 * Recode: ZHANG WEI <wei.zhang@freescale.com>
8 * Rewrite the routing for Frescale PCI and PCI Express 9 * Rewrite the routing for Frescale PCI and PCI Express
9 * Roy Zang <tie-fei.zang@freescale.com> 10 * Roy Zang <tie-fei.zang@freescale.com>
11 * MPC83xx PCI-Express support:
12 * Tony Li <tony.li@freescale.com>
13 * Anton Vorontsov <avorontsov@ru.mvista.com>
10 * 14 *
11 * This program is free software; you can redistribute it and/or modify it 15 * This program is free software; you can redistribute it and/or modify it
12 * under the terms of the GNU General Public License as published by the 16 * under the terms of the GNU General Public License as published by the
@@ -27,6 +31,29 @@
27#include <sysdev/fsl_soc.h> 31#include <sysdev/fsl_soc.h>
28#include <sysdev/fsl_pci.h> 32#include <sysdev/fsl_pci.h>
29 33
34static int fsl_pcie_bus_fixup;
35
36static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
37{
38 /* if we aren't a PCIe don't bother */
39 if (!pci_find_capability(dev, PCI_CAP_ID_EXP))
40 return;
41
42 dev->class = PCI_CLASS_BRIDGE_PCI << 8;
43 fsl_pcie_bus_fixup = 1;
44 return;
45}
46
47static int __init fsl_pcie_check_link(struct pci_controller *hose)
48{
49 u32 val;
50
51 early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
52 if (val < PCIE_LTSSM_L0)
53 return 1;
54 return 0;
55}
56
30#if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx) 57#if defined(CONFIG_PPC_85xx) || defined(CONFIG_PPC_86xx)
31static int __init setup_one_atmu(struct ccsr_pci __iomem *pci, 58static int __init setup_one_atmu(struct ccsr_pci __iomem *pci,
32 unsigned int index, const struct resource *res, 59 unsigned int index, const struct resource *res,
@@ -159,28 +186,6 @@ static void __init setup_pci_pcsrbar(struct pci_controller *hose)
159#endif 186#endif
160} 187}
161 188
162static int fsl_pcie_bus_fixup;
163
164static void __init quirk_fsl_pcie_header(struct pci_dev *dev)
165{
166 /* if we aren't a PCIe don't bother */
167 if (!pci_find_capability(dev, PCI_CAP_ID_EXP))
168 return ;
169
170 dev->class = PCI_CLASS_BRIDGE_PCI << 8;
171 fsl_pcie_bus_fixup = 1;
172 return ;
173}
174
175static int __init fsl_pcie_check_link(struct pci_controller *hose)
176{
177 u32 val;
178 early_read_config_dword(hose, 0, 0, PCIE_LTSSM, &val);
179 if (val < PCIE_LTSSM_L0)
180 return 1;
181 return 0;
182}
183
184void fsl_pcibios_fixup_bus(struct pci_bus *bus) 189void fsl_pcibios_fixup_bus(struct pci_bus *bus)
185{ 190{
186 struct pci_controller *hose = (struct pci_controller *) bus->sysdata; 191 struct pci_controller *hose = (struct pci_controller *) bus->sysdata;
@@ -294,8 +299,184 @@ DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8610, quirk_fsl_pcie_header);
294#endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */ 299#endif /* CONFIG_PPC_85xx || CONFIG_PPC_86xx */
295 300
296#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x) 301#if defined(CONFIG_PPC_83xx) || defined(CONFIG_PPC_MPC512x)
302DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314E, quirk_fsl_pcie_header);
303DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8314, quirk_fsl_pcie_header);
304DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8315E, quirk_fsl_pcie_header);
305DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8315, quirk_fsl_pcie_header);
306DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8377E, quirk_fsl_pcie_header);
307DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8377, quirk_fsl_pcie_header);
308DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8378E, quirk_fsl_pcie_header);
309DECLARE_PCI_FIXUP_HEADER(0x1957, PCI_DEVICE_ID_MPC8378, quirk_fsl_pcie_header);
310
311struct mpc83xx_pcie_priv {
312 void __iomem *cfg_type0;
313 void __iomem *cfg_type1;
314 u32 dev_base;
315};
316
317/*
318 * With the convention of u-boot, the PCIE outbound window 0 serves
319 * as configuration transactions outbound.
320 */
321#define PEX_OUTWIN0_BAR 0xCA4
322#define PEX_OUTWIN0_TAL 0xCA8
323#define PEX_OUTWIN0_TAH 0xCAC
324
325static int mpc83xx_pcie_exclude_device(struct pci_bus *bus, unsigned int devfn)
326{
327 struct pci_controller *hose = bus->sysdata;
328
329 if (hose->indirect_type & PPC_INDIRECT_TYPE_NO_PCIE_LINK)
330 return PCIBIOS_DEVICE_NOT_FOUND;
331 /*
332 * Workaround for the HW bug: for Type 0 configure transactions the
333 * PCI-E controller does not check the device number bits and just
334 * assumes that the device number bits are 0.
335 */
336 if (bus->number == hose->first_busno ||
337 bus->primary == hose->first_busno) {
338 if (devfn & 0xf8)
339 return PCIBIOS_DEVICE_NOT_FOUND;
340 }
341
342 if (ppc_md.pci_exclude_device) {
343 if (ppc_md.pci_exclude_device(hose, bus->number, devfn))
344 return PCIBIOS_DEVICE_NOT_FOUND;
345 }
346
347 return PCIBIOS_SUCCESSFUL;
348}
349
350static void __iomem *mpc83xx_pcie_remap_cfg(struct pci_bus *bus,
351 unsigned int devfn, int offset)
352{
353 struct pci_controller *hose = bus->sysdata;
354 struct mpc83xx_pcie_priv *pcie = hose->dn->data;
355 u8 bus_no = bus->number - hose->first_busno;
356 u32 dev_base = bus_no << 24 | devfn << 16;
357 int ret;
358
359 ret = mpc83xx_pcie_exclude_device(bus, devfn);
360 if (ret)
361 return NULL;
362
363 offset &= 0xfff;
364
365 /* Type 0 */
366 if (bus->number == hose->first_busno)
367 return pcie->cfg_type0 + offset;
368
369 if (pcie->dev_base == dev_base)
370 goto mapped;
371
372 out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAL, dev_base);
373
374 pcie->dev_base = dev_base;
375mapped:
376 return pcie->cfg_type1 + offset;
377}
378
379static int mpc83xx_pcie_read_config(struct pci_bus *bus, unsigned int devfn,
380 int offset, int len, u32 *val)
381{
382 void __iomem *cfg_addr;
383
384 cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset);
385 if (!cfg_addr)
386 return PCIBIOS_DEVICE_NOT_FOUND;
387
388 switch (len) {
389 case 1:
390 *val = in_8(cfg_addr);
391 break;
392 case 2:
393 *val = in_le16(cfg_addr);
394 break;
395 default:
396 *val = in_le32(cfg_addr);
397 break;
398 }
399
400 return PCIBIOS_SUCCESSFUL;
401}
402
403static int mpc83xx_pcie_write_config(struct pci_bus *bus, unsigned int devfn,
404 int offset, int len, u32 val)
405{
406 void __iomem *cfg_addr;
407
408 cfg_addr = mpc83xx_pcie_remap_cfg(bus, devfn, offset);
409 if (!cfg_addr)
410 return PCIBIOS_DEVICE_NOT_FOUND;
411
412 switch (len) {
413 case 1:
414 out_8(cfg_addr, val);
415 break;
416 case 2:
417 out_le16(cfg_addr, val);
418 break;
419 default:
420 out_le32(cfg_addr, val);
421 break;
422 }
423
424 return PCIBIOS_SUCCESSFUL;
425}
426
427static struct pci_ops mpc83xx_pcie_ops = {
428 .read = mpc83xx_pcie_read_config,
429 .write = mpc83xx_pcie_write_config,
430};
431
432static int __init mpc83xx_pcie_setup(struct pci_controller *hose,
433 struct resource *reg)
434{
435 struct mpc83xx_pcie_priv *pcie;
436 u32 cfg_bar;
437 int ret = -ENOMEM;
438
439 pcie = zalloc_maybe_bootmem(sizeof(*pcie), GFP_KERNEL);
440 if (!pcie)
441 return ret;
442
443 pcie->cfg_type0 = ioremap(reg->start, resource_size(reg));
444 if (!pcie->cfg_type0)
445 goto err0;
446
447 cfg_bar = in_le32(pcie->cfg_type0 + PEX_OUTWIN0_BAR);
448 if (!cfg_bar) {
449 /* PCI-E isn't configured. */
450 ret = -ENODEV;
451 goto err1;
452 }
453
454 pcie->cfg_type1 = ioremap(cfg_bar, 0x1000);
455 if (!pcie->cfg_type1)
456 goto err1;
457
458 WARN_ON(hose->dn->data);
459 hose->dn->data = pcie;
460 hose->ops = &mpc83xx_pcie_ops;
461
462 out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAH, 0);
463 out_le32(pcie->cfg_type0 + PEX_OUTWIN0_TAL, 0);
464
465 if (fsl_pcie_check_link(hose))
466 hose->indirect_type |= PPC_INDIRECT_TYPE_NO_PCIE_LINK;
467
468 return 0;
469err1:
470 iounmap(pcie->cfg_type0);
471err0:
472 kfree(pcie);
473 return ret;
474
475}
476
297int __init mpc83xx_add_bridge(struct device_node *dev) 477int __init mpc83xx_add_bridge(struct device_node *dev)
298{ 478{
479 int ret;
299 int len; 480 int len;
300 struct pci_controller *hose; 481 struct pci_controller *hose;
301 struct resource rsrc_reg; 482 struct resource rsrc_reg;
@@ -303,6 +484,11 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
303 const int *bus_range; 484 const int *bus_range;
304 int primary; 485 int primary;
305 486
487 if (!of_device_is_available(dev)) {
488 pr_warning("%s: disabled by the firmware.\n",
489 dev->full_name);
490 return -ENODEV;
491 }
306 pr_debug("Adding PCI host bridge %s\n", dev->full_name); 492 pr_debug("Adding PCI host bridge %s\n", dev->full_name);
307 493
308 /* Fetch host bridge registers address */ 494 /* Fetch host bridge registers address */
@@ -350,7 +536,14 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
350 hose->first_busno = bus_range ? bus_range[0] : 0; 536 hose->first_busno = bus_range ? bus_range[0] : 0;
351 hose->last_busno = bus_range ? bus_range[1] : 0xff; 537 hose->last_busno = bus_range ? bus_range[1] : 0xff;
352 538
353 setup_indirect_pci(hose, rsrc_cfg.start, rsrc_cfg.start + 4, 0); 539 if (of_device_is_compatible(dev, "fsl,mpc8314-pcie")) {
540 ret = mpc83xx_pcie_setup(hose, &rsrc_reg);
541 if (ret)
542 goto err0;
543 } else {
544 setup_indirect_pci(hose, rsrc_cfg.start,
545 rsrc_cfg.start + 4, 0);
546 }
354 547
355 printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. " 548 printk(KERN_INFO "Found FSL PCI host bridge at 0x%016llx. "
356 "Firmware bus number: %d->%d\n", 549 "Firmware bus number: %d->%d\n",
@@ -365,5 +558,8 @@ int __init mpc83xx_add_bridge(struct device_node *dev)
365 pci_process_bridge_OF_ranges(hose, dev, primary); 558 pci_process_bridge_OF_ranges(hose, dev, primary);
366 559
367 return 0; 560 return 0;
561err0:
562 pcibios_free_controller(hose);
563 return ret;
368} 564}
369#endif /* CONFIG_PPC_83xx */ 565#endif /* CONFIG_PPC_83xx */
diff --git a/include/linux/pci_ids.h b/include/linux/pci_ids.h
index febc10ed3858..ff9b7be2b791 100644
--- a/include/linux/pci_ids.h
+++ b/include/linux/pci_ids.h
@@ -2217,6 +2217,14 @@
2217#define PCI_DEVICE_ID_TDI_EHCI 0x0101 2217#define PCI_DEVICE_ID_TDI_EHCI 0x0101
2218 2218
2219#define PCI_VENDOR_ID_FREESCALE 0x1957 2219#define PCI_VENDOR_ID_FREESCALE 0x1957
2220#define PCI_DEVICE_ID_MPC8315E 0x00b4
2221#define PCI_DEVICE_ID_MPC8315 0x00b5
2222#define PCI_DEVICE_ID_MPC8314E 0x00b6
2223#define PCI_DEVICE_ID_MPC8314 0x00b7
2224#define PCI_DEVICE_ID_MPC8378E 0x00c4
2225#define PCI_DEVICE_ID_MPC8378 0x00c5
2226#define PCI_DEVICE_ID_MPC8377E 0x00c6
2227#define PCI_DEVICE_ID_MPC8377 0x00c7
2220#define PCI_DEVICE_ID_MPC8548E 0x0012 2228#define PCI_DEVICE_ID_MPC8548E 0x0012
2221#define PCI_DEVICE_ID_MPC8548 0x0013 2229#define PCI_DEVICE_ID_MPC8548 0x0013
2222#define PCI_DEVICE_ID_MPC8543E 0x0014 2230#define PCI_DEVICE_ID_MPC8543E 0x0014