diff options
author | Bjorn Helgaas <bhelgaas@google.com> | 2013-12-20 14:38:07 -0500 |
---|---|---|
committer | Bjorn Helgaas <bhelgaas@google.com> | 2013-12-20 14:38:07 -0500 |
commit | 4bd70bc997afbc7d6a2f57739b34802611dfe455 (patch) | |
tree | 6a5a6484dc62d084649ed118e4124e29c5485109 | |
parent | 608235a30706814dfff5b23938dc5f14fdb7e7e3 (diff) | |
parent | bc9ef770047a931787e1b1e092dbe3993ce4e0fb (diff) |
Merge branch 'pci/host-imx6' into next
* pci/host-imx6:
PCI: imx6: Fix bugs in PCIe startup code
PCI: imx6: Start link in Gen1 before negotiating for Gen2 mode
PCI: imx6: Factor out link up wait loop
PCI: imx6: Factor out PHY reset
PCI: imx6: Report "link up" only after link training completes
PCI: imx6: Make reset-gpio optional
-rw-r--r-- | Documentation/devicetree/bindings/pci/designware-pcie.txt | 2 | ||||
-rw-r--r-- | drivers/pci/host/pci-imx6.c | 188 |
2 files changed, 136 insertions, 54 deletions
diff --git a/Documentation/devicetree/bindings/pci/designware-pcie.txt b/Documentation/devicetree/bindings/pci/designware-pcie.txt index d5d26d443693..d6fae13ff062 100644 --- a/Documentation/devicetree/bindings/pci/designware-pcie.txt +++ b/Documentation/devicetree/bindings/pci/designware-pcie.txt | |||
@@ -19,6 +19,8 @@ Required properties: | |||
19 | to define the mapping of the PCIe interface to interrupt | 19 | to define the mapping of the PCIe interface to interrupt |
20 | numbers. | 20 | numbers. |
21 | - num-lanes: number of lanes to use | 21 | - num-lanes: number of lanes to use |
22 | |||
23 | Optional properties: | ||
22 | - reset-gpio: gpio pin number of power good signal | 24 | - reset-gpio: gpio pin number of power good signal |
23 | 25 | ||
24 | Optional properties for fsl,imx6q-pcie | 26 | Optional properties for fsl,imx6q-pcie |
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c index 9fc1cb66c64e..e8663a8c3406 100644 --- a/drivers/pci/host/pci-imx6.c +++ b/drivers/pci/host/pci-imx6.c | |||
@@ -44,10 +44,18 @@ struct imx6_pcie { | |||
44 | void __iomem *mem_base; | 44 | void __iomem *mem_base; |
45 | }; | 45 | }; |
46 | 46 | ||
47 | /* PCIe Root Complex registers (memory-mapped) */ | ||
48 | #define PCIE_RC_LCR 0x7c | ||
49 | #define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1 0x1 | ||
50 | #define PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2 0x2 | ||
51 | #define PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK 0xf | ||
52 | |||
47 | /* PCIe Port Logic registers (memory-mapped) */ | 53 | /* PCIe Port Logic registers (memory-mapped) */ |
48 | #define PL_OFFSET 0x700 | 54 | #define PL_OFFSET 0x700 |
49 | #define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28) | 55 | #define PCIE_PHY_DEBUG_R0 (PL_OFFSET + 0x28) |
50 | #define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c) | 56 | #define PCIE_PHY_DEBUG_R1 (PL_OFFSET + 0x2c) |
57 | #define PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING (1 << 29) | ||
58 | #define PCIE_PHY_DEBUG_R1_XMLH_LINK_UP (1 << 4) | ||
51 | 59 | ||
52 | #define PCIE_PHY_CTRL (PL_OFFSET + 0x114) | 60 | #define PCIE_PHY_CTRL (PL_OFFSET + 0x114) |
53 | #define PCIE_PHY_CTRL_DATA_LOC 0 | 61 | #define PCIE_PHY_CTRL_DATA_LOC 0 |
@@ -59,6 +67,9 @@ struct imx6_pcie { | |||
59 | #define PCIE_PHY_STAT (PL_OFFSET + 0x110) | 67 | #define PCIE_PHY_STAT (PL_OFFSET + 0x110) |
60 | #define PCIE_PHY_STAT_ACK_LOC 16 | 68 | #define PCIE_PHY_STAT_ACK_LOC 16 |
61 | 69 | ||
70 | #define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C | ||
71 | #define PORT_LOGIC_SPEED_CHANGE (0x1 << 17) | ||
72 | |||
62 | /* PHY registers (not memory-mapped) */ | 73 | /* PHY registers (not memory-mapped) */ |
63 | #define PCIE_PHY_RX_ASIC_OUT 0x100D | 74 | #define PCIE_PHY_RX_ASIC_OUT 0x100D |
64 | 75 | ||
@@ -209,15 +220,9 @@ static int imx6_pcie_assert_core_reset(struct pcie_port *pp) | |||
209 | 220 | ||
210 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, | 221 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, |
211 | IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18); | 222 | IMX6Q_GPR1_PCIE_TEST_PD, 1 << 18); |
212 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, | ||
213 | IMX6Q_GPR12_PCIE_CTL_2, 1 << 10); | ||
214 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, | 223 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR1, |
215 | IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16); | 224 | IMX6Q_GPR1_PCIE_REF_CLK_EN, 0 << 16); |
216 | 225 | ||
217 | gpio_set_value(imx6_pcie->reset_gpio, 0); | ||
218 | msleep(100); | ||
219 | gpio_set_value(imx6_pcie->reset_gpio, 1); | ||
220 | |||
221 | return 0; | 226 | return 0; |
222 | } | 227 | } |
223 | 228 | ||
@@ -261,6 +266,12 @@ static int imx6_pcie_deassert_core_reset(struct pcie_port *pp) | |||
261 | /* allow the clocks to stabilize */ | 266 | /* allow the clocks to stabilize */ |
262 | usleep_range(200, 500); | 267 | usleep_range(200, 500); |
263 | 268 | ||
269 | /* Some boards don't have PCIe reset GPIO. */ | ||
270 | if (gpio_is_valid(imx6_pcie->reset_gpio)) { | ||
271 | gpio_set_value(imx6_pcie->reset_gpio, 0); | ||
272 | msleep(100); | ||
273 | gpio_set_value(imx6_pcie->reset_gpio, 1); | ||
274 | } | ||
264 | return 0; | 275 | return 0; |
265 | 276 | ||
266 | err_pcie_axi: | 277 | err_pcie_axi: |
@@ -299,11 +310,90 @@ static void imx6_pcie_init_phy(struct pcie_port *pp) | |||
299 | IMX6Q_GPR8_TX_SWING_LOW, 127 << 25); | 310 | IMX6Q_GPR8_TX_SWING_LOW, 127 << 25); |
300 | } | 311 | } |
301 | 312 | ||
302 | static void imx6_pcie_host_init(struct pcie_port *pp) | 313 | static int imx6_pcie_wait_for_link(struct pcie_port *pp) |
314 | { | ||
315 | int count = 200; | ||
316 | |||
317 | while (!dw_pcie_link_up(pp)) { | ||
318 | usleep_range(100, 1000); | ||
319 | if (--count) | ||
320 | continue; | ||
321 | |||
322 | dev_err(pp->dev, "phy link never came up\n"); | ||
323 | dev_dbg(pp->dev, "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", | ||
324 | readl(pp->dbi_base + PCIE_PHY_DEBUG_R0), | ||
325 | readl(pp->dbi_base + PCIE_PHY_DEBUG_R1)); | ||
326 | return -EINVAL; | ||
327 | } | ||
328 | |||
329 | return 0; | ||
330 | } | ||
331 | |||
332 | static int imx6_pcie_start_link(struct pcie_port *pp) | ||
303 | { | 333 | { |
304 | int count = 0; | ||
305 | struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); | 334 | struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); |
335 | uint32_t tmp; | ||
336 | int ret, count; | ||
337 | |||
338 | /* | ||
339 | * Force Gen1 operation when starting the link. In case the link is | ||
340 | * started in Gen2 mode, there is a possibility the devices on the | ||
341 | * bus will not be detected at all. This happens with PCIe switches. | ||
342 | */ | ||
343 | tmp = readl(pp->dbi_base + PCIE_RC_LCR); | ||
344 | tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; | ||
345 | tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1; | ||
346 | writel(tmp, pp->dbi_base + PCIE_RC_LCR); | ||
347 | |||
348 | /* Start LTSSM. */ | ||
349 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, | ||
350 | IMX6Q_GPR12_PCIE_CTL_2, 1 << 10); | ||
351 | |||
352 | ret = imx6_pcie_wait_for_link(pp); | ||
353 | if (ret) | ||
354 | return ret; | ||
355 | |||
356 | /* Allow Gen2 mode after the link is up. */ | ||
357 | tmp = readl(pp->dbi_base + PCIE_RC_LCR); | ||
358 | tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK; | ||
359 | tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2; | ||
360 | writel(tmp, pp->dbi_base + PCIE_RC_LCR); | ||
361 | |||
362 | /* | ||
363 | * Start Directed Speed Change so the best possible speed both link | ||
364 | * partners support can be negotiated. | ||
365 | */ | ||
366 | tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); | ||
367 | tmp |= PORT_LOGIC_SPEED_CHANGE; | ||
368 | writel(tmp, pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); | ||
369 | |||
370 | count = 200; | ||
371 | while (count--) { | ||
372 | tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL); | ||
373 | /* Test if the speed change finished. */ | ||
374 | if (!(tmp & PORT_LOGIC_SPEED_CHANGE)) | ||
375 | break; | ||
376 | usleep_range(100, 1000); | ||
377 | } | ||
306 | 378 | ||
379 | /* Make sure link training is finished as well! */ | ||
380 | if (count) | ||
381 | ret = imx6_pcie_wait_for_link(pp); | ||
382 | else | ||
383 | ret = -EINVAL; | ||
384 | |||
385 | if (ret) { | ||
386 | dev_err(pp->dev, "Failed to bring link up!\n"); | ||
387 | } else { | ||
388 | tmp = readl(pp->dbi_base + 0x80); | ||
389 | dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf); | ||
390 | } | ||
391 | |||
392 | return ret; | ||
393 | } | ||
394 | |||
395 | static void imx6_pcie_host_init(struct pcie_port *pp) | ||
396 | { | ||
307 | imx6_pcie_assert_core_reset(pp); | 397 | imx6_pcie_assert_core_reset(pp); |
308 | 398 | ||
309 | imx6_pcie_init_phy(pp); | 399 | imx6_pcie_init_phy(pp); |
@@ -312,33 +402,41 @@ static void imx6_pcie_host_init(struct pcie_port *pp) | |||
312 | 402 | ||
313 | dw_pcie_setup_rc(pp); | 403 | dw_pcie_setup_rc(pp); |
314 | 404 | ||
315 | regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, | 405 | imx6_pcie_start_link(pp); |
316 | IMX6Q_GPR12_PCIE_CTL_2, 1 << 10); | 406 | } |
317 | 407 | ||
318 | while (!dw_pcie_link_up(pp)) { | 408 | static void imx6_pcie_reset_phy(struct pcie_port *pp) |
319 | usleep_range(100, 1000); | 409 | { |
320 | count++; | 410 | uint32_t temp; |
321 | if (count >= 200) { | 411 | |
322 | dev_err(pp->dev, "phy link never came up\n"); | 412 | pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &temp); |
323 | dev_dbg(pp->dev, | 413 | temp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN | |
324 | "DEBUG_R0: 0x%08x, DEBUG_R1: 0x%08x\n", | 414 | PHY_RX_OVRD_IN_LO_RX_PLL_EN); |
325 | readl(pp->dbi_base + PCIE_PHY_DEBUG_R0), | 415 | pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, temp); |
326 | readl(pp->dbi_base + PCIE_PHY_DEBUG_R1)); | 416 | |
327 | break; | 417 | usleep_range(2000, 3000); |
328 | } | ||
329 | } | ||
330 | 418 | ||
331 | return; | 419 | pcie_phy_read(pp->dbi_base, PHY_RX_OVRD_IN_LO, &temp); |
420 | temp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN | | ||
421 | PHY_RX_OVRD_IN_LO_RX_PLL_EN); | ||
422 | pcie_phy_write(pp->dbi_base, PHY_RX_OVRD_IN_LO, temp); | ||
332 | } | 423 | } |
333 | 424 | ||
334 | static int imx6_pcie_link_up(struct pcie_port *pp) | 425 | static int imx6_pcie_link_up(struct pcie_port *pp) |
335 | { | 426 | { |
336 | u32 rc, ltssm, rx_valid, temp; | 427 | u32 rc, ltssm, rx_valid; |
337 | 428 | ||
338 | /* link is debug bit 36, debug register 1 starts at bit 32 */ | 429 | /* |
339 | rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1) & (0x1 << (36 - 32)); | 430 | * Test if the PHY reports that the link is up and also that |
340 | if (rc) | 431 | * the link training finished. It might happen that the PHY |
341 | return -EAGAIN; | 432 | * reports the link is already up, but the link training bit |
433 | * is still set, so make sure to check the training is done | ||
434 | * as well here. | ||
435 | */ | ||
436 | rc = readl(pp->dbi_base + PCIE_PHY_DEBUG_R1); | ||
437 | if ((rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_UP) && | ||
438 | !(rc & PCIE_PHY_DEBUG_R1_XMLH_LINK_IN_TRAINING)) | ||
439 | return 1; | ||
342 | 440 | ||
343 | /* | 441 | /* |
344 | * From L0, initiate MAC entry to gen2 if EP/RC supports gen2. | 442 | * From L0, initiate MAC entry to gen2 if EP/RC supports gen2. |
@@ -358,21 +456,7 @@ static int imx6_pcie_link_up(struct pcie_port *pp) | |||
358 | 456 | ||
359 | dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n"); | 457 | dev_err(pp->dev, "transition to gen2 is stuck, reset PHY!\n"); |
360 | 458 | ||
361 | pcie_phy_read(pp->dbi_base, | 459 | imx6_pcie_reset_phy(pp); |
362 | PHY_RX_OVRD_IN_LO, &temp); | ||
363 | temp |= (PHY_RX_OVRD_IN_LO_RX_DATA_EN | ||
364 | | PHY_RX_OVRD_IN_LO_RX_PLL_EN); | ||
365 | pcie_phy_write(pp->dbi_base, | ||
366 | PHY_RX_OVRD_IN_LO, temp); | ||
367 | |||
368 | usleep_range(2000, 3000); | ||
369 | |||
370 | pcie_phy_read(pp->dbi_base, | ||
371 | PHY_RX_OVRD_IN_LO, &temp); | ||
372 | temp &= ~(PHY_RX_OVRD_IN_LO_RX_DATA_EN | ||
373 | | PHY_RX_OVRD_IN_LO_RX_PLL_EN); | ||
374 | pcie_phy_write(pp->dbi_base, | ||
375 | PHY_RX_OVRD_IN_LO, temp); | ||
376 | 460 | ||
377 | return 0; | 461 | return 0; |
378 | } | 462 | } |
@@ -432,17 +516,13 @@ static int __init imx6_pcie_probe(struct platform_device *pdev) | |||
432 | 516 | ||
433 | /* Fetch GPIOs */ | 517 | /* Fetch GPIOs */ |
434 | imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); | 518 | imx6_pcie->reset_gpio = of_get_named_gpio(np, "reset-gpio", 0); |
435 | if (!gpio_is_valid(imx6_pcie->reset_gpio)) { | 519 | if (gpio_is_valid(imx6_pcie->reset_gpio)) { |
436 | dev_err(&pdev->dev, "no reset-gpio defined\n"); | 520 | ret = devm_gpio_request_one(&pdev->dev, imx6_pcie->reset_gpio, |
437 | ret = -ENODEV; | 521 | GPIOF_OUT_INIT_LOW, "PCIe reset"); |
438 | } | 522 | if (ret) { |
439 | ret = devm_gpio_request_one(&pdev->dev, | 523 | dev_err(&pdev->dev, "unable to get reset gpio\n"); |
440 | imx6_pcie->reset_gpio, | 524 | return ret; |
441 | GPIOF_OUT_INIT_LOW, | 525 | } |
442 | "PCIe reset"); | ||
443 | if (ret) { | ||
444 | dev_err(&pdev->dev, "unable to get reset gpio\n"); | ||
445 | return ret; | ||
446 | } | 526 | } |
447 | 527 | ||
448 | imx6_pcie->power_on_gpio = of_get_named_gpio(np, "power-on-gpio", 0); | 528 | imx6_pcie->power_on_gpio = of_get_named_gpio(np, "power-on-gpio", 0); |