diff options
Diffstat (limited to 'arch')
-rw-r--r-- | arch/powerpc/platforms/powernv/pci.c | 32 |
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 | ||
359 | static 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 | |||
357 | void __init pnv_pci_init(void) | 388 | void __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 */ |