aboutsummaryrefslogtreecommitdiffstats
diff options
context:
space:
mode:
authorMarek Vasut <marex@denx.de>2013-12-12 16:50:02 -0500
committerBjorn Helgaas <bhelgaas@google.com>2013-12-19 13:00:04 -0500
commitfa33a6d87eac1ab1457e632d32b7b4b74172e699 (patch)
tree15b852fc3c88f1fbb7846dce61ff9da5682f6925
parent66a60f934701e282e596c97a3df22e4e5a7c2d68 (diff)
PCI: imx6: Start link in Gen1 before negotiating for Gen2 mode
This patch first forces the link into Gen1 mode before starting up the link and, only after the link is up, start negotiating possible Gen2 mode operation. This is because without such sequence, some PCIe switches are not detected at all. Signed-off-by: Marek Vasut <marex@denx.de> Signed-off-by: Bjorn Helgaas <bhelgaas@google.com> Acked-by: Shawn Guo <shawn.guo@linaro.org> Cc: Frank Li <lznuaa@gmail.com> Cc: Harro Haan <hrhaan@gmail.com> Cc: Jingoo Han <jg1.han@samsung.com> Cc: Mohit KUMAR <Mohit.KUMAR@st.com> Cc: Pratyush Anand <pratyush.anand@st.com> Cc: Richard Zhu <r65037@freescale.com> Cc: Sascha Hauer <s.hauer@pengutronix.de> Cc: Sean Cross <xobs@kosagi.com> Cc: Siva Reddy Kallam <siva.kallam@samsung.com> Cc: Srikanth T Shivanand <ts.srikanth@samsung.com> Cc: Tim Harvey <tharvey@gateworks.com> Cc: Troy Kisky <troy.kisky@boundarydevices.com> Cc: Yinghai Lu <yinghai@kernel.org>
-rw-r--r--drivers/pci/host/pci-imx6.c78
1 files changed, 72 insertions, 6 deletions
diff --git a/drivers/pci/host/pci-imx6.c b/drivers/pci/host/pci-imx6.c
index d81da4556c19..d34678dc5a14 100644
--- a/drivers/pci/host/pci-imx6.c
+++ b/drivers/pci/host/pci-imx6.c
@@ -44,6 +44,12 @@ 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)
@@ -61,6 +67,9 @@ struct imx6_pcie {
61#define PCIE_PHY_STAT (PL_OFFSET + 0x110) 67#define PCIE_PHY_STAT (PL_OFFSET + 0x110)
62#define PCIE_PHY_STAT_ACK_LOC 16 68#define PCIE_PHY_STAT_ACK_LOC 16
63 69
70#define PCIE_LINK_WIDTH_SPEED_CONTROL 0x80C
71#define PORT_LOGIC_SPEED_CHANGE (0x1 << 17)
72
64/* PHY registers (not memory-mapped) */ 73/* PHY registers (not memory-mapped) */
65#define PCIE_PHY_RX_ASIC_OUT 0x100D 74#define PCIE_PHY_RX_ASIC_OUT 0x100D
66 75
@@ -323,11 +332,71 @@ static int imx6_pcie_wait_for_link(struct pcie_port *pp)
323 return 0; 332 return 0;
324} 333}
325 334
326static void imx6_pcie_host_init(struct pcie_port *pp) 335static int imx6_pcie_start_link(struct pcie_port *pp)
327{ 336{
328 int count = 0;
329 struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp); 337 struct imx6_pcie *imx6_pcie = to_imx6_pcie(pp);
338 uint32_t tmp;
339 int ret, count;
340
341 /*
342 * Force Gen1 operation when starting the link. In case the link is
343 * started in Gen2 mode, there is a possibility the devices on the
344 * bus will not be detected at all. This happens with PCIe switches.
345 */
346 tmp = readl(pp->dbi_base + PCIE_RC_LCR);
347 tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
348 tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN1;
349 writel(tmp, pp->dbi_base + PCIE_RC_LCR);
350
351 /* Start LTSSM. */
352 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12,
353 IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
354
355 ret = imx6_pcie_wait_for_link(pp);
356 if (ret)
357 return ret;
358
359 /* Allow Gen2 mode after the link is up. */
360 tmp = readl(pp->dbi_base + PCIE_RC_LCR);
361 tmp &= ~PCIE_RC_LCR_MAX_LINK_SPEEDS_MASK;
362 tmp |= PCIE_RC_LCR_MAX_LINK_SPEEDS_GEN2;
363 writel(tmp, pp->dbi_base + PCIE_RC_LCR);
364
365 /*
366 * Start Directed Speed Change so the best possible speed both link
367 * partners support can be negotiated.
368 */
369 tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
370 tmp |= PORT_LOGIC_SPEED_CHANGE;
371 writel(tmp, pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
372
373 count = 200;
374 while (count--) {
375 tmp = readl(pp->dbi_base + PCIE_LINK_WIDTH_SPEED_CONTROL);
376 /* Test if the speed change finished. */
377 if (!(tmp & PORT_LOGIC_SPEED_CHANGE))
378 break;
379 usleep_range(100, 1000);
380 }
381
382 /* Make sure link training is finished as well! */
383 if (count)
384 ret = imx6_pcie_wait_for_link(pp);
385 else
386 ret = -EINVAL;
330 387
388 if (ret) {
389 dev_err(pp->dev, "Failed to bring link up!\n");
390 } else {
391 tmp = readl(pp->dbi_base + 0x80);
392 dev_dbg(pp->dev, "Link up, Gen=%i\n", (tmp >> 16) & 0xf);
393 }
394
395 return ret;
396}
397
398static void imx6_pcie_host_init(struct pcie_port *pp)
399{
331 imx6_pcie_assert_core_reset(pp); 400 imx6_pcie_assert_core_reset(pp);
332 401
333 imx6_pcie_init_phy(pp); 402 imx6_pcie_init_phy(pp);
@@ -336,10 +405,7 @@ static void imx6_pcie_host_init(struct pcie_port *pp)
336 405
337 dw_pcie_setup_rc(pp); 406 dw_pcie_setup_rc(pp);
338 407
339 regmap_update_bits(imx6_pcie->iomuxc_gpr, IOMUXC_GPR12, 408 imx6_pcie_start_link(pp);
340 IMX6Q_GPR12_PCIE_CTL_2, 1 << 10);
341
342 imx6_pcie_wait_for_link(pp);
343} 409}
344 410
345static void imx6_pcie_reset_phy(struct pcie_port *pp) 411static void imx6_pcie_reset_phy(struct pcie_port *pp)