Skip to content

Commit d0c6a34

Browse files
paliLorenzo Pieralisi
authored andcommitted
PCI: aardvark: Move PCIe reset card code to advk_pcie_train_link()
Move code which belongs to link training (delays and resets) into advk_pcie_train_link() function, so everything related to link training, including timings is at one place. After experiments it can be observed that link training in aardvark hardware is very sensitive to timings and delays, so it is a good idea to have this code at the same place as link training calls. This patch does not change behavior of aardvark initialization. Link: https://lore.kernel.org/r/[email protected] Tested-by: Marek Behún <[email protected]> Signed-off-by: Pali Rohár <[email protected]> Signed-off-by: Lorenzo Pieralisi <[email protected]>
1 parent 526a769 commit d0c6a34

File tree

1 file changed

+34
-30
lines changed

1 file changed

+34
-30
lines changed

drivers/pci/controller/pci-aardvark.c

Lines changed: 34 additions & 30 deletions
Original file line numberDiff line numberDiff line change
@@ -252,6 +252,25 @@ static void advk_pcie_wait_for_retrain(struct advk_pcie *pcie)
252252
}
253253
}
254254

255+
static void advk_pcie_issue_perst(struct advk_pcie *pcie)
256+
{
257+
u32 reg;
258+
259+
if (!pcie->reset_gpio)
260+
return;
261+
262+
/* PERST does not work for some cards when link training is enabled */
263+
reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
264+
reg &= ~LINK_TRAINING_EN;
265+
advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
266+
267+
/* 10ms delay is needed for some cards */
268+
dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n");
269+
gpiod_set_value_cansleep(pcie->reset_gpio, 1);
270+
usleep_range(10000, 11000);
271+
gpiod_set_value_cansleep(pcie->reset_gpio, 0);
272+
}
273+
255274
static int advk_pcie_train_at_gen(struct advk_pcie *pcie, int gen)
256275
{
257276
int ret, neg_gen;
@@ -299,6 +318,21 @@ static void advk_pcie_train_link(struct advk_pcie *pcie)
299318
struct device *dev = &pcie->pdev->dev;
300319
int neg_gen = -1, gen;
301320

321+
/*
322+
* Reset PCIe card via PERST# signal. Some cards are not detected
323+
* during link training when they are in some non-initial state.
324+
*/
325+
advk_pcie_issue_perst(pcie);
326+
327+
/*
328+
* PERST# signal could have been asserted by pinctrl subsystem before
329+
* probe() callback has been called or issued explicitly by reset gpio
330+
* function advk_pcie_issue_perst(), making the endpoint going into
331+
* fundamental reset. As required by PCI Express spec a delay for at
332+
* least 100ms after such a reset before link training is needed.
333+
*/
334+
msleep(PCI_PM_D3COLD_WAIT);
335+
302336
/*
303337
* Try link training at link gen specified by device tree property
304338
* 'max-link-speed'. If this fails, iteratively train at lower gen.
@@ -331,31 +365,10 @@ static void advk_pcie_train_link(struct advk_pcie *pcie)
331365
dev_err(dev, "link never came up\n");
332366
}
333367

334-
static void advk_pcie_issue_perst(struct advk_pcie *pcie)
335-
{
336-
u32 reg;
337-
338-
if (!pcie->reset_gpio)
339-
return;
340-
341-
/* PERST does not work for some cards when link training is enabled */
342-
reg = advk_readl(pcie, PCIE_CORE_CTRL0_REG);
343-
reg &= ~LINK_TRAINING_EN;
344-
advk_writel(pcie, reg, PCIE_CORE_CTRL0_REG);
345-
346-
/* 10ms delay is needed for some cards */
347-
dev_info(&pcie->pdev->dev, "issuing PERST via reset GPIO for 10ms\n");
348-
gpiod_set_value_cansleep(pcie->reset_gpio, 1);
349-
usleep_range(10000, 11000);
350-
gpiod_set_value_cansleep(pcie->reset_gpio, 0);
351-
}
352-
353368
static void advk_pcie_setup_hw(struct advk_pcie *pcie)
354369
{
355370
u32 reg;
356371

357-
advk_pcie_issue_perst(pcie);
358-
359372
/* Enable TX */
360373
reg = advk_readl(pcie, PCIE_CORE_REF_CLK_REG);
361374
reg |= PCIE_CORE_REF_CLK_TX_ENABLE;
@@ -432,15 +445,6 @@ static void advk_pcie_setup_hw(struct advk_pcie *pcie)
432445
reg |= PIO_CTRL_ADDR_WIN_DISABLE;
433446
advk_writel(pcie, reg, PIO_CTRL);
434447

435-
/*
436-
* PERST# signal could have been asserted by pinctrl subsystem before
437-
* probe() callback has been called or issued explicitly by reset gpio
438-
* function advk_pcie_issue_perst(), making the endpoint going into
439-
* fundamental reset. As required by PCI Express spec a delay for at
440-
* least 100ms after such a reset before link training is needed.
441-
*/
442-
msleep(PCI_PM_D3COLD_WAIT);
443-
444448
advk_pcie_train_link(pcie);
445449

446450
/*

0 commit comments

Comments
 (0)