aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
-rw-r--r--drivers/pci/host/pci-imx6.c44
1 files changed, 27 insertions, 17 deletions
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index fdb95367721e..c93bcdf58a56 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -352,6 +352,23 @@ static int imx6_pcie_wait_for_link(struct pcie_port *pp)
352 return 0; 352 return 0;
353} 353}
354 354
355static int imx6_pcie_wait_for_speed_change(struct pcie_port *pp)
356{
357 uint32_t tmp;
358 unsigned int retries;
359
360 for (retries = 0; retries < 200; retries++) {
361 tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
362 /* Test if the speed change finished. */
363 if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
364 return 0;
365 usleep_range(100, 1000);
366 }
367
368 dev_err(pp->dev, "Speed change timeout\n");
369 return -EINVAL;
370}
371
355static irqreturn_t imx6_pcie_msi_handler(int irq, void *arg) 372static irqreturn_t imx6_pcie_msi_handler(int irq, void *arg)
356{ 373{
357 struct pcie_port *pp = arg; 374 struct pcie_port *pp = arg;
@@ -363,7 +380,7 @@ static int imx6_pcie_start_link(struct pcie_port *pp)
363{ 380{
364 struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); 381 struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
365 uint32_t tmp; 382 uint32_t tmp;
366 int ret, count; 383 int ret;
367 384
368 /* 385 /*
369 * Force Gen1 operation when starting the link. In case the link is 386 * Force Gen1 operation when starting the link. In case the link is
@@ -397,29 +414,22 @@ static int imx6_pcie_start_link(struct pcie_port *pp)
397 tmp |= PORT_LOGIC_SPEED_CHANGE; 414 tmp |= PORT_LOGIC_SPEED_CHANGE;
398 writel(tmp, pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); 415 writel(tmp, pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
399 416
400 count = 200; 417 ret = imx6_pcie_wait_for_speed_change(pp);
401 while (count--) { 418 if (ret) {
402 tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); 419 dev_err(pp->dev, "Failed to bring link up!\n");
403 /* Test if the speed change finished. */ 420 return ret;
404 if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
405 break;
406 usleep_range(100, 1000);
407 } 421 }
408 422
409 /* Make sure link training is finished as well! */ 423 /* Make sure link training is finished as well! */
410 if (count) 424 ret = imx6_pcie_wait_for_link(pp);
411 ret = imx6_pcie_wait_for_link(pp);
412 else
413 ret = -EINVAL;
414
415 if (ret) { 425 if (ret) {
416 dev_err(pp->dev, "Failed to bring link up!\n"); 426 dev_err(pp->dev, "Failed to bring link up!\n");
417 } else { 427 return ret;
418 tmp = readl(pp->dbi_base + 0x80);
419 dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf);
420 } 428 }
421 429
422 return ret; 430 tmp = readl(pp->dbi_base + 0x80);
431 dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf);
432 return 0;
423} 433}
424 434
425static void imx6_pcie_host_init(struct pcie_port *pp) 435static void imx6_pcie_host_init(struct pcie_port *pp)