aboutsummaryrefslogtreecommitdiffstats
path: root/arch
diff options
context:
space:
mode:
authorBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-09-19 13:45:07 -0400
committerBenjamin Herrenschmidt <benh@kernel.crashing.org>2011-09-20 02:12:54 -0400
commit82ba129baeb1ff72e75d93e70534ba50312153f3 (patch)
treedcd3e60d80f8102c670cb3e6cd3d2e0c7c9deb57 /arch
parentc1a2562ac5edcb3965760f4a37368122d85657af (diff)
powerpc/powernv: Handle PCI-X/PCIe reset delay
The firmware doesn't wait after lifting the PCI reset. However it does timestamp it in the device tree. We use that to ensure we wait long enough (3s is our current arbitrary setting) from that timestamp to actually probing the bus. Signed-off-by: Benjamin Herrenschmidt <benh@kernel.crashing.org>
Diffstat (limited to 'arch')
-rw-r--r--arch/powerpc/platforms/powernv/pci.c32
1 files changed, 32 insertions, 0 deletions
diff --git a/arch/powerpc/platforms/powernv/pci.c b/arch/powerpc/platforms/powernv/pci.c
index 5c175519cf9e..85bb66d7f933 100644
--- a/arch/powerpc/platforms/powernv/pci.c
+++ b/arch/powerpc/platforms/powernv/pci.c
@@ -35,6 +35,8 @@
35#include "powernv.h" 35#include "powernv.h"
36#include "pci.h" 36#include "pci.h"
37 37
38/* Delay in usec */
39#define PCI_RESET_DELAY_US 3000000
38 40
39#define cfg_dbg(fmt...) do { } while(0) 41#define cfg_dbg(fmt...) do { } while(0)
40//#define cfg_dbg(fmt...) printk(fmt) 42//#define cfg_dbg(fmt...) printk(fmt)
@@ -354,6 +356,35 @@ static void __devinit pnv_pci_dma_dev_setup(struct pci_dev *pdev)
354 pnv_pci_dma_fallback_setup(hose, pdev); 356 pnv_pci_dma_fallback_setup(hose, pdev);
355} 357}
356 358
359static int pnv_pci_probe_mode(struct pci_bus *bus)
360{
361 struct pci_controller *hose = pci_bus_to_host(bus);
362 const __be64 *tstamp;
363 u64 now, target;
364
365
366 /* We hijack this as a way to ensure we have waited long
367 * enough since the reset was lifted on the PCI bus
368 */
369 if (bus != hose->bus)
370 return PCI_PROBE_NORMAL;
371 tstamp = of_get_property(hose->dn, "reset-clear-timestamp", NULL);
372 if (!tstamp || !*tstamp)
373 return PCI_PROBE_NORMAL;
374
375 now = mftb() / tb_ticks_per_usec;
376 target = (be64_to_cpup(tstamp) / tb_ticks_per_usec)
377 + PCI_RESET_DELAY_US;
378
379 pr_devel("pci %04d: Reset target: 0x%llx now: 0x%llx\n",
380 hose->global_number, target, now);
381
382 if (now < target)
383 msleep((target - now + 999) / 1000);
384
385 return PCI_PROBE_NORMAL;
386}
387
357void __init pnv_pci_init(void) 388void __init pnv_pci_init(void)
358{ 389{
359 struct device_node *np; 390 struct device_node *np;
@@ -384,6 +415,7 @@ void __init pnv_pci_init(void)
384 ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup; 415 ppc_md.pci_dma_dev_setup = pnv_pci_dma_dev_setup;
385 ppc_md.tce_build = pnv_tce_build; 416 ppc_md.tce_build = pnv_tce_build;
386 ppc_md.tce_free = pnv_tce_free; 417 ppc_md.tce_free = pnv_tce_free;
418 ppc_md.pci_probe_mode = pnv_pci_probe_mode;
387 set_pci_dma_ops(&dma_iommu_ops); 419 set_pci_dma_ops(&dma_iommu_ops);
388 420
389 /* Configure MSIs */ 421 /* Configure MSIs */