aboutsummaryrefslogtreecommitdiffstats
path: root/drivers/pci/host/pci-imx6.c
diff options
context:
space:
mode:
Diffstat (limited to 'drivers/pci/host/pci-imx6.c')
-rw-r--r--drivers/pci/host/pci-imx6.c47
1 files changed, 34 insertions, 13 deletions
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index e8663a8c3406..ee082509b0ba 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -424,20 +424,40 @@ static void imx6_pcie_reset_phy(struct pcie_port *pp)
424 424
425static int imx6_pcie_link_up(struct pcie_port *pp) 425static int imx6_pcie_link_up(struct pcie_port *pp)
426{ 426{
427 u32 rc, ltssm, rx_valid; 427 u32 rc, debug_r0, rx_valid;
428 int count = 5;
428 429
429 /* 430 /*
430 * Test if the PHY reports that the link is up and also that 431 * Test if the PHY reports that the link is up and also that the LTSSM
431 * the link training finished. It might happen that the PHY 432 * training finished. There are three possible states of the link when
432 * reports the link is already up, but the link training bit 433 * this code is called:
433 * is still set, so make sure to check the training is done 434 * 1) The link is DOWN (unlikely)
434 * as well here. 435 * The link didn't come up yet for some reason. This usually means
436 * we have a real problem somewhere. Reset the PHY and exit. This
437 * state calls for inspection of the DEBUG registers.
438 * 2) The link is UP, but still in LTSSM training
439 * Wait for the training to finish, which should take a very short
440 * time. If the training does not finish, we have a problem and we
441 * need to inspect the DEBUG registers. If the training does finish,
442 * the link is up and operating correctly.
443 * 3) The link is UP and no longer in LTSSM training
444 * The link is up and operating correctly.
435 */ 445 */
436 rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1); 446 while (1) {
437 if ((rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP) && 447 rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1);
438 !(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING)) 448 if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP))
439 return 1; 449 break;
440 450 if (!(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING))
451 return 1;
452 if (!count--)
453 break;
454 dev_dbg(pp->dev, "Link is up, but still in training\n");
455 /*
456 * Wait a little bit, then re-check if the link finished
457 * the training.
458 */
459 usleep_range(1000, 2000);
460 }
441 /* 461 /*
442 * From L0, initiate MAC entry to gen2 if EP/RC supports gen2. 462 * From L0, initiate MAC entry to gen2 if EP/RC supports gen2.
443 * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2). 463 * Wait 2ms (LTSSM timeout is 24ms, PHY lock is ~5us in gen2).
@@ -446,15 +466,16 @@ static int imx6_pcie_link_up(struct pcie_port *pp)
446 * to gen2 is stuck 466 * to gen2 is stuck
447 */ 467 */
448 pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid); 468 pcie_phy_read(pp->dbi_base, PCIE_PHY_RX_ASIC_OUT, &rx_valid);
449 ltssm = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0) & 0x3F; 469 debug_r0 = readl(pp->dbi_base + PCIE_PHY_DEBUG_R0);
450 470
451 if (rx_valid & 0x01) 471 if (rx_valid & 0x01)
452 return 0; 472 return 0;
453 473
454 if (ltssm != 0x0d) 474 if ((debug_r0 & 0x3f) != 0x0d)
455 return 0; 475 return 0;
456 476
457 dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n"); 477 dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n");
478 dev_dbg(pp->dev, "debug_r0=%08x debug_r1=%08x\n", debug_r0, rc);
458 479
459 imx6_pcie_reset_phy(pp); 480 imx6_pcie_reset_phy(pp);
460 481